IOS

From WiiUBrew
Jump to navigation Jump to search

IOS (historically unofficially known as IOSU for distinguishing between the Wii and Wii U variants but officially sometimes called CAFE-IOS) is the operating system running on the Starbuck coprocessor in Wii U mode. It is the Wii U equivalent of the IOS on the Wii and, while similar in some aspects due to it being based on it, is a complete rewrite with many changes.

While the kernel implements memory, process and thread management, device drivers and security handlers run as processes in the ARM user mode. These processes, called resource managers (RMs), can register as request handlers for resources, which are represented as nodes under "/dev" in a virtual filesystem. They communicate with each other through the kernel, using standard Unix file operations (open/close/read/write/seek/ioctl/ioctlv).

The IOSU firmware image file ("fw.img") is stored as a boot image image which, when decrypted, contains three regions: a header, an ELF loader and the actual operating system image as an ELF binary.

Retail and debug IOSU are identical aside from being signed by different keys. That is, all development and evaluation console functionality (on an ARM level) is technically available on all Wii U consoles if you disregard permissions. Retail consoles are prohibited from accessing debug features due to their keyset.

Pages

Architecture

IOSU is a Nintendo-proprietary, embedded operating system. Many of its core components are directly built off of the Wii's IOS, as well as its overall architecture. Despite its Wii-rooting, IOSU is still one of the most unique and complex Nintendo operating systems. IOS-MCP handles nearly all critical system functionality and other system related operations. It and IOS-BSP are the earliest known modules in IOSU, existing extremely early into development.

The Wii treats IOS as part of the game's runtime environment, whereas the Wii U treats the operating system (including IOSU) as part of the console's platform environment.

IOS on the Wii U can include CAFE-IOS, SRAM-IOS (cafe2wii and cafe2wii_hai), and boot1writer.

Modules

Similarly to the Wii, IOS modules map to processes and drivers inside the kernel.

IOS-CRYPTO

Cryptography services.

IOS-MCP

Master title operations such as title launching and cafe2wii booting.

IOS-USB

USB controllers and devices.

IOS-FS

File system services.

IOS-PAD

Gamepad controllers and devices.

IOS-NET

Network services.

IOS-ACP

User level application management.

IOS-NSEC

Network security services. This uses OpenSSL, "OpenSSL 1.0.0f 4 Jan 2012".

IOS-NIM-BOSS

Nintendo's proprietary online services such as update installations. This uses statically-linked libcurl.

IOS-FPD

Nintendo's proprietary friend system. This uses statically-linked libcurl.

IOS-TEST

Debugging and testing services.

IOS-AUXIL

Auxiliary services

IOS-BSP

Hardware.

  • /dev/bsp - Board support package (hardware interface)

Others

These are not real /dev nodes. Instead, they represent internal mappings of system volumes created by the IOS-FS process as part of the virtual file system API's initialization.
The virtual file system API is able to map more than one instance of such volumes, whence why the final node name always has an integer representing it's instance (e.g.: 01).

Header

This just contains the 0x100-byte struct BootOSImageHeader.

BootOSImageHeader

Offset Size Description
0x0 0x4 HdrSize (always 0x100)
0x4 0x4 LoaderSize
0x8 0x4 ImageSize
0xC 0x4 DdrInit
0x10 0xF0 Pad

Auxiliary Vectors

The IOSU elf has a PH_NOTES section which contains a so called "mrg file". This "mrg file" contains auxiliary vectors for IOSU modules.

The vectors are parsed by IOS-KERNEL, before launching the modules.

The first 0xc bytes of the notes section make up a Elf32_Nhdr. After that there are 6 auxv_t for each module (14 in 5.5.X).

The following auxiliary vector types are used:

Value Name Description
0x09 AT_ENTRY Entry point address
0x0B AT_UID Module ID
0x7D AT_PRIORITY Main thread priority
0x7E AT_STACK_SIZE Main thread stack size
0x7F AT_STACK_ADDR Main thread stack address
0x80 AT_MEM_PERM_MASK Memory permission mask

Auxiliary vectors from 5.5.X:

 AT_UID:                0
 AT_ENTRY:              0xFFFF0000
 AT_PRIORITY:           0x0
 AT_STACK_SIZE:         0x0
 AT_STACK_ADDR:         0x00000000
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                1
 AT_ENTRY:              0x05056718
 AT_PRIORITY:           0x7C
 AT_STACK_SIZE:         0x2000
 AT_STACK_ADDR:         0x050BA4A0
 AT_MEM_PERM_MASK:      0x000C0030
 AT_UID:                2
 AT_ENTRY:              0xE600F848
 AT_PRIORITY:           0x7D
 AT_STACK_SIZE:         0x1000
 AT_STACK_ADDR:         0xE7000000
 AT_MEM_PERM_MASK:      0x00100000
 AT_UID:                3
 AT_ENTRY:              0x04015EA4
 AT_PRIORITY:           0x7B
 AT_STACK_SIZE:         0x1000
 AT_STACK_ADDR:         0x04028628
 AT_MEM_PERM_MASK:      0x000C0030
 AT_UID:                4
 AT_ENTRY:              0x1012E9E8
 AT_PRIORITY:           0x6B
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0x104B92C8
 AT_MEM_PERM_MASK:      0x00038600
 AT_UID:                5
 AT_ENTRY:              0x107F6830
 AT_PRIORITY:           0x55
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0x1114117C
 AT_MEM_PERM_MASK:      0x001C5870
 AT_UID:                6
 AT_ENTRY:              0x11F82D94
 AT_PRIORITY:           0x75
 AT_STACK_SIZE:         0x2000
 AT_STACK_ADDR:         0x1214AB4C
 AT_MEM_PERM_MASK:      0x00008180
 AT_UID:                7
 AT_ENTRY:              0x123E4174
 AT_PRIORITY:           0x50
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0x12804498
 AT_MEM_PERM_MASK:      0x00002000
 AT_UID:                11
 AT_ENTRY:              0xE22602FC
 AT_PRIORITY:           0x32
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0xE22CB000
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                9
 AT_ENTRY:              0xE108E930
 AT_PRIORITY:           0x32
 AT_STACK_SIZE:         0x1000
 AT_STACK_ADDR:         0xE12E71A4
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                12
 AT_ENTRY:              0xE3166B34
 AT_PRIORITY:           0x32
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0xE31AF000
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                8
 AT_ENTRY:              0xE00D8290
 AT_PRIORITY:           0x32
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0xE0125390
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                10
 AT_ENTRY:              0xE500D720
 AT_PRIORITY:           0x46
 AT_STACK_SIZE:         0x4000
 AT_STACK_ADDR:         0xE506A900
 AT_MEM_PERM_MASK:      0x00000000
 AT_UID:                13
 AT_ENTRY:              0xE40168A4
 AT_PRIORITY:           0x4B
 AT_STACK_SIZE:         0x2000
 AT_STACK_ADDR:         0xE415623C
 AT_MEM_PERM_MASK:      0x00000000

Exception Handling

The data-abort and prefetch-abort exception handlers will first check whether a certain flag is clear(flagsfield & (1<<PID)). When that bit is clear and the PID is <=13(highest IOSU PID value that exists), it will just return from the function then do a context-switch. Otherwise, iosPanic() is called.

IPC

PowerPC code is able to call IOSU drivers through an IPC interface. It uses the same call interface as IOSU does internally. Userspace code submits IOSU requests with the IPCKDriver_SubmitRequest() syscall in the Cafe OS kernel. The kernel includes information to identify which Cafe OS process sent the request, allowing IOSU to check permissions on a per-app basis. Requests are contained in a struct, sent through a hardware interface, and marshalled by the IOSU kernel to a target process. An example of IOSU IPC from the PowerPC can be found here.

IPC request struct (size = 0x48, align = 0x20)

0x00: CMD (1=open, 2=close, 3=read, 4=write, 5=seek, 6=ioctl, 7=ioctlv)
0x04: Reply to client
0x08: Client FD
0x0C: Flags (always 0)
0x10: Client CPU (0=ARM internal, 1-3=PPC cores 0-2)
0x14: Client PID (PFID in older versions, RAMPID more recently?)
0x18: Client group ID (Title ID, upper)
0x1C: Client group ID (Title ID, lower)
0x20: Server handle (written by IOSU)
0x24: Arg0
0x28: Arg1
0x2C: Arg2
0x30: Arg3
0x34: Arg4
0x38: CMD (previous)
0x3C: Client FD (previous)
0x40: Virt0 (PPC virtual addresses to be translated)
0x44: Virt1 (PPC virtual addresses to be translated)
IPC commands

0x00 -> IOS_COMMAND_INVALID
0x01 -> IOS_OPEN
0x02 -> IOS_CLOSE
0x03 -> IOS_READ
0x04 -> IOS_WRITE
0x05 -> IOS_SEEK
0x06 -> IOS_IOCTL
0x07 -> IOS_IOCTLV
0x08 -> IOS_REPLY (internal to IOSU)
0x09 -> IOS_IPC_MSG0 (internal to IOSU)
0x0A -> IOS_IPC_MSG1 (internal to IOSU)
0x0B -> IOS_IPC_MSG2 (internal to IOSU)
0x0C -> IOS_SUSPEND (internal to IOSU)
0x0D -> IOS_RESUME (internal to IOSU)
0x0E -> IOS_SVCMSG (internal to IOSU)
IPC client PIDs

On older versions of IOSU, it seems to match the PFID list. More recently, it appears to use the RAMPID. See the Cafe OS PID tables.
IPC arguments

Open CMD:   Client FD == 0
            Arg0 = name
            Arg1 = name_size
            Arg2 = mode (0 = none, 1 = read, 2 = write)
            Arg3-Arg4 = u64 permissions_bitmask for the target IOSU process, loaded by the target IOSU process during fd init. With PPC this originates from the cos.xml of the source process.

Close CMD:  Client FD != 0

Read CMD:   Client FD != 0
            Arg0 = outPtr
            Arg1 = outLen

Write CMD:  Client FD != 0
            Arg0 = inPtr
            Arg1 = inLen

Seek CMD:   Client FD != 0
            Arg0 = where
            Arg1 = whence

IOCtl CMD:  Client FD != 0
            Arg0 = cmd
            Arg1 = inPtr
            Arg2 = inLen
            Arg3 = outPtr
            Arg4 = outLen

IOCtlv CMD: Client FD != 0
            Arg0 = cmd
            Arg1 = readCount
            Arg2 = writeCount
            Arg3 = vector

Virtual Memory Map

Virtual memory map for latest version of IOSU (5.5.0 onwards).

Virtual address range Physical address range Size Description
0x04000000 - 0x04030000 0x08280000 - 0x082B0000 0x30000 IOS-CRYPTO
0x05000000 - 0x050C0000 0x081C0000 - 0x08280000 0xC0000 IOS-MCP
0x05100000 - 0x05120000 0x13D80000 - 0x13DA0000 0x20000 IOS-MCP (development and recovery mode)
0x08120000 - 0x081C0000 0x08120000 - 0x081C0000 0xA0000 IOS-KERNEL
0x10000000 - 0x10100000 0x10000000 - 0x10100000 0x100000 PRSH/PRST
0x10100000 - 0x104D0000 0x10100000 - 0x104D0000 0x3D0000 IOS-USB
0x10700000 - 0x11C40000 0x10700000 - 0x11C40000 0x1540000 IOS-FS
0x11F00000 - 0x12160000 0x11F00000 - 0x12160000 0x260000 IOS-PAD
0x12300000 - 0x12890000 0x12300000 - 0x12890000 0x590000 IOS-NET
0x1D000000 - 0x1FB00000 0x1D000000 - 0x1FB00000 0x2B00000 Global heap
0x1FB00000 - 0x1FE00000 0x1FB00000 - 0x1FE00000 0x300000 Global IOB (input/output block)
0x1FE00000 - 0x1FE20000 0x1FE00000 - 0x1FE20000 0x40000 IOS-MCP (shared region)
0x1FE40000 - 0x20000000 0x1FE40000 - 0x20000000 0x1C0000 IOS-MCP (setup region)
0x20000000 - 0x28000000 0x20000000 - 0x28000000 0x8000000 RAMDISK
0xE0000000 - 0xE0270000 0x12900000 - 0x12B70000 0x270000 IOS-ACP
0xE1000000 - 0xE12F0000 0x12BC0000 - 0x12EB0000 0x2F0000 IOS-NSEC
0xE2000000 - 0xE26D0000 0x12EC0000 - 0x13590000 0x6D0000 IOS-NIM-BOSS
0xE3000000 - 0xE3300000 0x13640000 - 0x13940000 0x300000 IOS-FPD
0xE4000000 - 0xE4160000 0x13A40000 - 0x13BA0000 0x160000 IOS-TEST
0xE5000000 - 0xE5070000 0x13C00000 - 0x13C70000 0x70000 IOS-AUXIL
0xE6000000 - 0xE6050000 0x13CC0000 - 0x13D80000 0xC0000 IOS-BSP
0xE7000000 - 0xE7001000
0xEFF00000 - 0xEFF08000 0xFFF00000 - 0xFFF08000 0x8000 C2W (cafe2wii) boot heap
0xFFFF0000 - 0xFFFFFFFF 0xFFFF0000 - 0xFFFFFFFF 0x10000 Kernel SRAM / C2W (cafe2wii)

The Starbuck MMU itself only has R/W permissions for data/instruction memory access, no XN. However, there is XN implemented via separate hardware registers at 0x0d8b0XXX. The register relative-offset is calculated with the physaddr of the memory being protected. Each u32 register corresponds to a different block of physical memory. Among other things, this controls whether the ARM is allowed to access the memory for instruction-access, and in what ARM-mode(userland/privileged) the instruction-access is permitted.

Hence, userland .text is only executable from userland. From userland, the only executable memory is the process .text. In privileged-mode, the only executable memory is the main kernel .text(0x08120000) and 0xffff0000(the latter is also RWX).

Other Info

IOSIpcServer

Offset Size Description
0x0 0x4 IsEnabled
0x4 0x4 NodeId
0x8 0x4 ClientNodeIdx
0xC 0x4 Event
0x10 0x4 Message
0x14 0x34
0x48 0x4 IpcIopCtrlReg
0x4C 0x4 IpcPpcMsgReg
0x50 0x4 IpcIopMsgReg
0x54 0x4 ActiveReplies
0x58 0x4
0x5C 0x4 CurrentReplyIdx
0x60 0x38 * 128 Replies
0x260 0x4 ActiveRequests
0x264 0x4 IsInAckPending
0x268 0x4 HasPendingRequests
0x26C 0x4 InvalidRequestAddressErrors
0x270 0x4 InvalidRequestClientPidErrors
0x274 0x4 ReadErrors
0x278 0x4 WriteErrors
0x27C 0x4 SeekErrors
0x280 0x4 IoctlErrors
0x284 0x4 IoctlvErrors
0x288 0x4 OpenErrors
0x28C 0x4 CloseErrors
0x290 0x4
0x294 0x4 ActiveRequestsWaterline
0x298 0x4 ActiveRepliesWaterline
0x29C 0x4 PendingRequests
0x2A0 0x4 RepliedRequests

IOSProcessId

Value Description
0 IOS-KERNEL
1 IOS-MCP
2 IOS-BSP
3 IOS-CRYPTO
4 IOS-USB
5 IOS-FS
6 IOS-PAD
7 IOS-NET
8 IOS-ACP
9 IOS-NSEC
10 IOS-AUXIL
11 IOS-NIM-BOSS
12 IOS-FPD
13 IOS-TEST
14 COS-KERNEL
15 COS-ROOT
16 COS-02
17 COS-03
18 COS-OVERLAY
19 COS-HBM
20 COS-ERROR
21 COS-MASTER

IOSNodeId

Value Description
0 IOS_NODE_INTERNAL
1 IOS_NODE_EXTERNAL0
2 IOS_NODE_EXTERNAL1
3 IOS_NODE_EXTERNAL2

IOSCmdId

Value Description
0 IOS_COMMAND_INVALID
1 IOS_OPEN
2 IOS_CLOSE
3 IOS_READ
4 IOS_WRITE
5 IOS_SEEK
6 IOS_IOCTL
7 IOS_IOCTLV
8 IOS_REPLY
9 IOS_IPC_MSG0
10 IOS_IPC_MSG1
11 IOS_IPC_MSG2
12 IOS_SUSPEND
13 IOS_RESUME
14 IOS_SVCMSG

IOSSecurityLevel

Value Description
0 None
10 Test
20 Dev
30 Prod

IOSError

Value Description
0 IOS_ERROR_OK
-1 IOS_ERROR_ACCESS
-2 IOS_ERROR_EXISTS
-3 IOS_ERROR_INTR
-4 IOS_ERROR_INVALID
-5 IOS_ERROR_MAX
-6 IOS_ERROR_NOEXISTS
-7 IOS_ERROR_QEMPTY
-8 IOS_ERROR_QFULL
-9 IOS_ERROR_UNKNOWN
-10 IOS_ERROR_NOTREADY
-11 IOS_ERROR_ECC
-12 IOS_ERROR_ECC_CRIT
-13 IOS_ERROR_BADBLOCK
-14 IOS_ERROR_INVALID_OBJTYPE
-15 IOS_ERROR_INVALID_RNG
-16 IOS_ERROR_INVALID_FLAG
-17 IOS_ERROR_INVALID_FORMAT
-18 IOS_ERROR_INVALID_VERSION
-19 IOS_ERROR_INVALID_SIGNER
-20 IOS_ERROR_FAIL_CHECKVALUE
-21 IOS_ERROR_FAIL_INTERNAL
-22 IOS_ERROR_FAIL_ALLOC
-23 IOS_ERROR_INVALID_SIZE
-24 IOS_ERROR_NO_LINK
-25 IOS_ERROR_AN_FAILED
-26 IOS_ERROR_MAX_SEM_COUNT
-27 IOS_ERROR_SEM_UNAVAILABLE
-28 IOS_ERROR_INVALID_HANDLE
-29 IOS_ERROR_INVALID_ARG
-30 IOS_ERROR_NO_RESOURCE
-31 IOS_ERROR_BUSY
-32 IOS_ERROR_TIMEOUT
-33 IOS_ERROR_ALIGNMENT
-34 IOS_ERROR_BSP
-35 IOS_ERROR_DATA_PENDING
-36 IOS_ERROR_EXPIRED
-37 IOS_ERROR_NO_R_ACCESS
-38 IOS_ERROR_NO_W_ACCESS
-39 IOS_ERROR_NO_RW_ACCESS
-40 IOS_ERROR_CLIENT_TXN_LIMIT
-41 IOS_ERROR_STALE_HANDLE
-42 IOS_ERROR_UNKNOWN_VALUE

MEM_WB_CLIENTS

Value Description
0 IOS_WB_IOD
1 IOS_WB_AIM
2 IOS_WB_FLA
3 IOS_WB_AES
4 IOS_WB_SHA
5 IOS_WB_EHCI
6 IOS_WB_OHCI0
7 IOS_WB_OHCI1
8 IOS_WB_SD0
9 IOS_WB_SD1
10 IOS_WB_SD2
11 IOS_WB_SD3
12 IOS_WB_EHC1
13 IOS_WB_OHCI10
14 IOS_WB_EHC2
15 IOS_WB_OHCI20
16 IOS_WB_SATA
17 IOS_WB_AESS
18 IOS_WB_SHAS
19 IOS_WB_DMAA
20 IOS_WB_DMAB
21 IOS_WB_DMAC
22 IOS_WB_ALL

AHM_RB_CLIENTS

Value Description
0 IOS_RB_IOD
1 IOS_RB_IOI
2 IOS_RB_AIM
3 IOS_RB_FLA
4 IOS_RB_AES
5 IOS_RB_SHA
6 IOS_RB_EHCI
7 IOS_RB_OHCI0
8 IOS_RB_OHCI1
9 IOS_RB_SD0
10 IOS_RB_SD1
11 IOS_RB_SD2
12 IOS_RB_SD3
13 IOS_RB_EHC1
14 IOS_RB_OHCI10
15 IOS_RB_EHC2
16 IOS_RB_OHCI20
17 IOS_RB_SATA
18 IOS_RB_AESS
19 IOS_RB_SHAS