IOS

From WiiUBrew
(Redirected from IOSU syscalls)
Jump to navigation Jump to search

IOS (unofficially known as IOSU for distinguishing between the Wii and Wii U variants) 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, 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 an Ancast image which, when decrypted, contains three regions: a header, an ELF loader and the actual operating system image as an ELF binary.

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

Loader

Each time the IOSU starts, the ELF loader is the first portion of code that runs in order to make preparations for the actual IOSU binary. During the console's initial boot, boot1 is responsible for fetching the "fw.img" file from NAND, verifying, decrypting and launching it (cold boot). However, IOS-MCP also has to do this when handling a system restart (warm boot) for which it follows a similar path but, ultimately, uses the LaunchOS system call in order to disable memory protections and jump to the IOSU's ELF loader code.

The loader does the following:

  • Clears it's own stack;
  • Sets 0x20 in HW_SRNPROT register, if not set already;
  • Fetches e_phnum from the IOSU's ELF header;
  • Loops through the IOSU's ELF program header structs;
  • For each program marked with PT_LOAD, copies it's code into the target physical memory;
  • Wipes the IOSU's ELF binary from MEM1;
  • Wipes itself from MEM1 (excluding the then running subroutine);
  • Jumps to 0xFFFF0000 (IOSU kernel boot).

Kernel

After being parsed by it's own ELF loader, the IOSU's kernel is launched from the Wii U's SRAM (0xFFFF0000). IOSU's kernel follows a standard ARM microkernel architecture:

// IOSU kernel entry-point
// ARM vector table (firmware 5.5.1)
start()  // 0xFFFF0000
{
  // Reset handler
  pc <- sub_FFFF0060
	
  // Undefined handler
  pc <- loc_812DD6C
	
  // SWI handler
  pc <- sub_812DD20
	
  // Prefetch handler
  pc <- sub_812E74C
	
  // Abort handler
  pc <- sub_812E720
	
  // NULL
  pc <- loc_FFFF0040
	
  // IRQ handler
  pc <- loc_FFFF0044
	
  // FIQ handler
  pc <- loc_FFFF0048
}

Execution follows into the reset handler:

// Reset handler (firmware 5.5.1)
sub_FFFF0060()
{
  r0 <- 0
	
  // Invalidate ICache
  MCR p15, 0, R0,c7,c5, 0
	
  // Invalidate DCache
  MCR p15, 0, R0,c7,c6, 0
	
  // Read control register
  MRC p15, 0, R0,c1,c0, 0
	
  // Set replacement strategy to Round-Robin
  r0 <- r0 | 0x1000
	
  // Enable alignment fault checking
  r0 <- r0 | 0x2
	
  // Write control register
  MCR p15, 0, R0,c1,c0, 0
	
  // Clear the IOS-KERNEL stack
  memset_range(stack_start, stack_end, 0, 0x04);
	
  // Disable boot0 mapping
  r0 <- 0x0D80018C   // HW_SPARE1
  r1 <- 0x00(HW_SPARE1)
  r1 <- r1 | 0x1000
  0x00(HW_SPARE1) <- r1
	
  // MSR CPSR_c, #0xD3 -> Enter supervisor mode, FIQ/IRQ disabled
  // SP == 0xFFFF0904
  init_svc_stack(0xFFFF0904);
	
  // MSR CPSR_c, #0xD2 -> Enter IRQ mode, FIQ/IRQ disabled
  // SP == 0xFFFF1104
  init_irq_stack(0xFFFF1104);
	
  // MSR CPSR_c, #0xD1 -> Enter FIQ mode, FIQ/IRQ disabled
  // SP == 0xFFFF1504
  init_fiq_stack(0xFFFF1504);
	
  // MSR CPSR_c, #0xD7 -> Enter abort mode, FIQ/IRQ disabled
  // SP == 0xFFFF0D04
  init_abort_stack(0xFFFF0D04);
	
  // MSR CPSR_c, #0xDB -> Enter undefined mode, FIQ/IRQ disabled
  // SP == 0xFFFF1904
  init_undefined_stack(0xFFFF1904);
	
  // MSR CPSR_c, #0xDF -> Enter system mode, FIQ/IRQ disabled
  // SP == 0xFFFF1904
  init_user_stack(0xFFFF1904);
	
  // Jump to MEM0 check
  lr <- pc
  pc <- sub_FFFFDA38

  while(1);
}

MEM0's integrity is checked before going any further:

// Check MEM0 for IOS-KERNEL (firmware 5.5.1)
sub_FFFFDA38()
{
  r1 <- 0x08143008  // IOSU kernel data region
  r3 <- 0xA5A51212
	
  r2 <- 0x00(0x08143008)
	
  // Deadlock
  if (0x00(0x08143008) != 0xA5A51212)
  {
     r3 <- 0xDEAD1111
     sp <- 0xDEAD1111
     while(1);
  }

  r12 <- 0xFFFF0500	// IOSU boot heap region
  r2 <- 0x00(0xFFFF0500)
	
  // Deadlock
  if (0x00(0xFFFF0500) != 0xA5A51212)
  {
     r3 <- 0xDEAD1111
     sp <- 0xDEAD1111
     while(1);
  }
	
  // Set init magic
  r2 <- 0x5A5AEDED
  0x00(0xFFFF0500) <- 0x5A5AEDED
  0x00(0x08143008) <- 0x5A5AEDED
	
  // Flush AHB for Starbuck
  ahbMemFlush(0);
  ahb_flush_to(1);
	
  // Load IOS_KERNEL
  r2 <- sub_8121B18
  sub_8121B18();
	
  // Deadlock
  r3 <- 0xDEAD2222
  sp <- 0xDEAD2222
  while(1);	
}

And, finally, execution switches over to MEM0 where the IOS-KERNEL module will be running:

// Load IOS-KERNEL (firmware 5.5.1)
sub_8121B18()
{
  // Read LT_DEBUG register
  // and store it's value at 0x08150000
  sub_8120970();
	
  // Clear LT_DEBUG register
  sub_8120988();
	
  // Do a bitwise AND with the LT_DEBUG value
  r0 <- 0x80000000
  r0 <- sub_81209B8(0x80000000);
	
  // If LT_DEBUG is 0x80000000
  // the hardware is using RealView
  if (r0 != 0)
  {
    r4 <- (sp + 0x04)
    r3 <- 0
    0x00(sp) <- 0
		
    // Wait for user input
    // to start the kernel
    while (r3 != 0x01)
    {
	r0 <- "\n\n\n\n\n\n\n\n\n\n"
	debug_printf("\n\n\n\n\n\n\n\n\n\n");
			
	r0 <- "Enter '1' to proceed with kernel startup. "
	debug_printf("Enter '1' to proceed with kernel startup. ");
			
	r0 <- "%d"
        r1 <- sp
	debug_read("%d", sp);			
	
       r3 <- 0x00(sp)
    }
  }
	
  // Initialize the MMU and map memory regions
  sub_8120C58();
	
  // Reset GPIOs and IRQs
  sub_8120510();
	
  // Setup IRQ handlers
  sub_8120488();
	
  // Clear and set some kernel structures
  sub_812B308();
	
  // Setup iobuf
  sub_81235E8();
	
  // Re-map shared_user_ro
  sub_81294AC();
	
  // Clear IOS_KERNEL module's thread stack and run it
  sub_812CD08();
	
  return;
}

At this point, the IOS-KERNEL module is running on it's own thread and becomes responsible for launching and controlling all the other IOSU modules. The kernel is responsible for tasks such as as IPC handling, permissions' control, resource managers (/dev nodes) and much more.

System calls are handled through the ARM undefined handler and mapped into their respective kernel functions.

There are 2 types of syscalls:

  • Syscalls using undefined ARM instruction
  • Syscalls using ARM syscall instruction

Syscalls (via undefined instructions)

Similarly to the Wii's IOS, the IOSU uses a syscall table that is stored towards the end of the kernel area inside the main ARM binary (fw.img).

The second vector is the invalid instruction handler, which is used to implement syscalls:

fw:FFFF0000               LDR     PC, =_reset
fw:FFFF0004               LDR     PC, =starbuck_syscall_handler

The Starbuck syscall handler:

starbuck_syscall_handler
   STMFA           SP, {R0-LR}^
   MRS             R8, SPSR
   STR             R8, [SP]
   STR             LR, [SP,#0x40]
   LDR             R10, [LR,#-4]   ; R10 = E7F0XXXX  (the invalid instruction)
   BIC             R9, R10, #0xFF00
   LDR             R8, =0xE7F000F0   ; Syscall base
   CMP             R9, R8            ; Were any bits set other than the syscall number
   BNE             invalid_syscall
   MOV             R10, R10,ASR#8
   AND             R10, R10, #0xFF
   CMP             R10, #0x94        ; Max index of syscall (can possibly vary)
   BGT             return_to_caller
   MOV             R8, SP
   MOV             R11, #0x1F
   MSR             CPSR_c, R11       ; Switch to system mode and disable FIQ/IRQ
   
   LDR             R9, [R8,#0x48]    ; Added in 5.5.0: Check for invalid stack
   CMP             SP, R9
   BLCS            bad_stack
   LDR             R11, [R8,#0x4C]
   SUB             R9, R9, R11
   CMP             SP, R9
   BCC             bad_stack
   
   LDR             R8, [R8,#0x44]
   LDR             R11, =syscall_stack_arg_counts
   LDR             R11, [R11,R10,LSL#2]  ; Number of args on stack for this syscall
   ADD             SP, SP, R11,LSL#2
get_stack_arg                             
   CMP             R11, #0
   BEQ             find_syscall_and_jump
   LDR             R9, [SP,#-4]!	 ; Copy argument value
   STR             R9, [R8,#-4]!
   SUB             R11, R11, #1
   B               get_stack_arg
find_syscall_and_jump
   MOV             SP, R8
   LDR             R11, =syscall_table
   LDR             R11, [R11,R10,LSL#2]
   MOV             LR, PC
   BX              R11
return_to_caller
   MOV             R11, #0xDB   ; Switch to undefined mode and re-enable FIQ/IRQ
   MSR             CPSR_c, R11
   LDR             R11, [SP]
   MSR             SPSR_cxsf, R11
   MOV             LR, R0
   LDMED           SP, {R0-LR}^
   NOP
   MOV             R0, LR
   LDR             LR, [SP,#0x40]
   MOVS            PC, LR	      ; Return
invalid_syscall
   LDR             SP, =current_thread_ctx_addr
   LDR             SP, [SP]
   STR             LR, [SP,#0x40]
   ADD             SP, SP, #0x40
   STMFD           SP, {R0-LR}^
   SUB             R0, SP, #0x40
   MOV             LR, #6	 ; STATE_FAULTED
   STR             LR, [R0,#0x50]
   LDR             SP, =debug_args_addr
   BL              debug_print  ; Illegal Instruction:tid=%d,pid=%d,pc=0x%08x,sp=0x%08x
   B               schedule_yield
bad_stack
   BL      disable_interrupts
   LDR     R0, =current_thread_ctx_addr
   LDR     R0, [R0]
   MOV     LR, #6               ; STATE_FAULTED
   STR     LR, [R0,#0x50]
   MOV     R1, SP
   MOV     R2, R10
   LDR     SP, =debug_args_addr
   BL      debug_print_bad_stack ; Bad stack upon making system call:tid=%d,pid=%d,sp=0x%08x,sysCallNum=%d\n
   B       schedule_yield

Syscalls are invoked by way of the invalid instruction handler; syscalls take the form 0xE7F000F0 | (syscall_num << 8). (E.g. E7F000F0 is syscall 0, E7F036F0 is syscall 0x36, etc.).
The IOSU has 0x94 available syscalls with 5.3.2 (the number of installed syscalls can vary between system versions).

With 5.5.0 sp(user-mode/system-mode) is now bounds-checked right after the switch to system-mode. When out-of-bounds it will execute code similar to "invalid_syscall" described above. Hence, userland sp has to be within the current thread userland stackbottom/stacktop at the time a syscall is used, otherwise the fault code will be executed.

The following syscall numbers were last verified on 5.3.2 development OSv10 and 5.5.0 production OSv10. They may vary for newer/older versions or OSv9.

NOTE: Official syscall names begin with "IOS_", the rest are merely educated guesses.

ID (Development) ID (Production) Return Name Arguments
0x00 0x00 IOSThreadId IOS_CreateThread u32 (*entry)(void* arg), void* arg, void* stack, u32 stack_size, u32 priority, u32 attributes
0x01 0x01 IOSError JoinThread IOSThreadId id, u32 **return_value
0x02 0x02 IOSError DestroyThread IOSThreadId id, u32 *return_value
0x03 0x03 IOSThreadId GetThreadId
0x04 0x04 void * AccessIpcPool
0x05 0x05 IOSProcessId GetProcessId
0x06 0x06 IOSError GetProcessName IOSProcessId pid, char *name
0x07 0x07 IOSError IOS_StartThread IOSThreadId id
0x08 0x08 IOSError StopThread IOSThreadId id
0x09 0x09 void YieldThread
0x0A 0x0A u32 IOS_GetThreadPriority IOSThreadId id
0x0B 0x0B IOSError IOS_SetThreadPriority IOSThreadId id, u32 priority
0x0C 0x0C IOSMessageQueueId IOS_CreateMessageQueue IOSMessage *ptr, u32 count
0x0D 0x0D IOSError IOS_DestroyMessageQueue IOSMessageQueueId mqid
0x0E 0x0E IOSError IOS_SendMessage IOSMessageQueueId mqid, IOSMessage message, u32 flags
0x0F 0x0F IOSError IOS_JamMessage IOSMessageQueueId mqid, IOSMessage message, u32 flags
0x10 0x10 IOSError IOS_ReceiveMessage IOSMessageQueueId mqid, IOSMessage *message, u32 flags
0x11 0x11 IOSError IOS_HandleEvent IOSEvent event, IOSMessageQueueId mqid, IOSMessage message
0x12 0x12 IOSError UnhandleEvent IOSEvent event
0x13 0x13 IOSTimerId IOS_CreateTimer IOSTime time, IOSTime interval, IOSMessageQueueId mqid, IOSMessage message
0x14 0x14 IOSError IOS_RestartTimer IOSTimerId id, IOSTime time, IOSTime interval
0x15 0x15 IOSError IOS_StopTimer IOSTimerId id
0x16 0x16 IOSError IOS_DestroyTimer IOSTimerId id
0x17 0x17 IOSTime GetUpTimer
0x18 0x18 u32 GetTimer
0x19 0x19 IOSError IOS_GetUpTimeStruct IOSTimeStruct *out
0x1A 0x1A IOSError IOS_GetUpTime64 u64 *out
0x1B 0x1B IOSError SetRtcTimeStruct IOSTimeStruct *in
0x1C 0x1C IOSError IOS_GetAbsTimeCalendar IOSTimeCalendar *out
0x1D 0x1D IOSError IOS_GetAbsTime64 u64 *out
0x1E 0x1E IOSError IOS_GetAbsTimeStruct IOSTimeStruct *out
0x1F 0x1F IOSError EnablePanicOnException IOSProcessId pid, bool enable
0x20 0x20 IOSError IsDevelopment
0x21 0x21 IOSError IsJtagEnabled
0x22 0x22 IOSError ReadEfuse u32 word, void *out_buf, u32 size
0x23 0x23 IOSHeapId CreateHeap void *ptr, u32 size
0x24 0x24 IOSHeapId IOS_CreateLocalProcessHeap void *ptr, u32 size
0x25 0x25 IOSHeapId IOS_CreateCrossProcessHeap int size
0x26 0x26 IOSError DestroyHeap IOSHeapId id
0x27 0x27 void* IOS_Alloc IOSHeapId id, u32 size
0x28 0x28 void* AllocAligned IOSHeapId id, u32 size, u32 align
0x29 0x29 IOSError IOS_Free IOSHeapId id, void *ptr
0x2A 0x2A IOSError FreeAndClear IOSHeapId id, void *ptr
0x2B 0x2B IOSError ReAlloc IOSHeapId id, void *ptr, u32 size
0x2C 0x2C IOSError IOS_RegisterResourceManager const char* path, IOSMessageQueueId mqid
0x2D 0x2D IOSError AssociateResourceManager const char* path, u32 id
0x2E 0x2E IOSError SetResourceManagerMaxIoVectors const char* path, u32 max_vectors
0x2F 0x2F IOSError SetResourceClientCapabilities IOSProcessId pid, u32 feature_id, u32 *caps
0x30 0x30 IOSError ClearResourceClientCapabilities IOSProcessId pid
0x31 0x31 IOSError GetResourceClientCapabilities IOSProcessId pid, u32 feature_id, u32 *caps
0x32 0x32 IOSError GetResourceManagers u32 feature_id, u32 max_count, IOSResourceManager *out
0x33 0x33 IOSFd IOS_Open const char* path, u32 flags
0x34 0x34 IOSError IOS_Close IOSFd fd
0x35 0x35 s32 IOS_Read IOSFd fd, void *buf, u32 len
0x36 0x36 s32 IOS_Write IOSFd fd, void *buf, u32 len
0x37 0x37 s32 IOS_Seek IOSFd fd, s32 offset, u32 origin
0x38 0x38 IOSError IOS_Ioctl IOSFd fd, s32 cmd, void *input, u32 input_size, void *output, u32 output_size
0x39 0x39 IOSError IOS_Ioctlv IOSFd fd, s32 cmd, u32 read_count, u32 write_count, IOSIoVector *vector
0x3A 0x3A IOSFd IOS_OpenAsync const char* path, u32 flags, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x3B 0x3B IOSError IOS_CloseAsync IOSFd fd, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x3C 0x3C s32 IOS_ReadAsync IOSFd fd, void *buf, u32 len, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x3D 0x3D s32 IOS_WriteAsync IOSFd fd, void *buf, u32 len, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x3E 0x3E s32 IOS_SeekAsync IOSFd fd, s32 offset, u32 origin, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x3F 0x3F IOSError IOS_IoctlAsync IOSFd fd, s32 cmd, void *input, u32 input_size, void *output, u32 output_size, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x40 0x40 IOSError IOS_IoctlvAsync IOSFd fd, s32 cmd, u32 read_count, u32 write_count, IOSIoVector *vector, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x41 0x41 IOSError OpenAsyncAs const char* path, u32 flags, IOSMessageQueueId mqid, IOSResourceRequest *reply, IOSProcessId pid, IOSNodeId node_id
0x42 0x42 IOSError WriteAsyncAs IOSFd fd, void *buf, u32 len, IOSMessageQueueId mqid, IOSResourceRequest *reply, IOSProcessId pid, IOSNodeId node_id
0x43 0x43 IOSError Resume IOSFd fd, SystemMode mode, PowerFlags flags
0x44 0x44 IOSError Suspend IOSFd fd, SystemMode mode, PowerFlags flags
0x45 0x45 IOSError SvcMsg IOSFd fd, u32 unk0, u32 unk1, u32 unk2, u32 unk3
0x46 0x46 IOSError ResumeAsync IOSFd fd, SystemMode mode, PowerFlags flags, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x47 0x47 IOSError SuspendAsync IOSFd fd, SystemMode mode, PowerFlags flags, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x48 0x48 IOSError SvcMsgAsync IOSFd fd, u32 unk0, u32 unk1, u32 unk2, u32 unk3, IOSMessageQueueId mqid, IOSResourceRequest *reply
0x49 0x49 IOSError IOS_ResourceReply IOSResourceTransaction *txn, IOSFd fd
0x4A 0x4A IOSError SetUidGid IOSProcessId pid, u32 uid_high, u32 uid_low, u32 gid
0x4B 0x4B IOSError GetUidGid IOSProcessId pid, u32 *uid, u32 *gid
0x4C 0x4C IOSError FlushMem MEM_WB_CLIENTS client
0x4D 0x4D IOSError ForceFlushMem MEM_WB_CLIENTS client
0x4E 0x4E IOSError IsMemDataPending int client
0x4F 0x4F IOSError InvalidateRdb AHM_RB_CLIENTS client
0x50 0x50 IOSError IOS_ClearAndEnable u32 id
0x51 IOSError AccessIobPool u32 pool
0x52 IOSIobuf * AllocIob u32 pool, u32 size
0x53 IOSError FreeIob IOSIobuf *iob
0x54 void DebugDumpIobFreeHdrsList
0x55 void DebugDumpIobFreeBufsList
0x56 u8 * PutIob IOSIobuf *iob, u16 len
0x57 u8 * IOS_PushIob IOSIobuf *iob, u16 len
0x58 u8 * IOS_PullIob IOSIobuf *iob, u16 len
0x59 IOSError IsValidIob IOSIobuf *iob
0x5A IOSIobuf * CloneIob IOSIobuf *iob
0x5B 0x51 void IOS_InvalidateDCache void *ptr, u32 len
0x5C 0x52 void IOS_FlushDCache void *ptr, u32 len
0x5D 0x53 IOSError LaunchOS BootOSImageHeader *os_image
0x5E 0x54 void GetOSVersion u32 *major, u16 *minor
0x5F 0x55 void GetBootVersion u32 *major, u16 *minor
0x60 0x56 void * VirtualToPhysical void *address
0x61 0x57 IOSSemaphoreId IOS_CreateSemaphore u32 max_count, u32 initial_count
0x62 0x58 IOSError IOS_WaitSemaphore IOSSemaphoreId id, bool try_wait
0x63 0x59 IOSError IOS_SignalSemaphore IOSSemaphoreId id
0x64 0x5A IOSError IOS_DestroySemaphore IOSSemaphoreId id
0x65 0x5B IOSError InitializeIpc
0x66 0x5C IOSError SetBspReady
0x67 0x5D IOSError CheckIopBuffer void *address, u32 size, u32 rw_flags
0x68 0x5E IOSError CheckPpcBuffer void *address, u32 size
0x69 0x5F void InitializePpc
0x6A 0x60 u32 GetIopCpuUtilization
0x6B 0x61 IOSError GetThreadStackInfo IOSThreadId id, IOSThreadStackInfo *out
0x6C 0x62 IOSError IOS_ThreadProfileCommand IOSThreadProfileCommand cmd, void *data
0x6D 0x63 IOSError IOS_GetThreadUtilization IOSThreadUtilization *out
0x6E 0x64 IOSError GetThreadProfile IOSThreadId id, IOSThreadProfile *out
0x6F 0x65 IOSError GetThreadProfiles u32 max_count, IOSThreadProfile *out
0x70 IOSError GetIobContext u32 id, IOSIobContext *out
0x71 u32 IOS_GetIobPoolsUtilization u32 max_count, IOSIobPoolsUtilization *out
0x72 0x66 IOSError IOS_GetMessageUtilization IOSMessageUtilization *out
0x73 0x67 IOSError GetResourceAggregateUtilization IOSResourceAggregateUtilization* out, bool clear
0x74 0x68 IOSError GetResourcePerProcessUtilization IOSResourcePerProcessUtilization* out, IOSProcessId pid, bool clear
0x75 0x69 IOSError IOS_GetTimerUtilization IOSTimerUtilization *out
0x76 0x6A IOSError IOS_GetSemaphoreUtilization IOSSemaphoreUtilization *out
0x77 0x6B IOSError GetHeapProfile IOSHeapId id, IOSHeapProfile *profile
0x78 0x6C IOSError EnableIop2xClockMultiplier bool enable
0x79 0x6D IOSError SetPpcPlatformInfo OSPlatformInfo *info
0x7A 0x6E void LoadSystemConfiguration
0x7B 0x6F void ClearSystemConfiguration
0x7C 0x70 void SetSystemConfiguration u32 syscfg
0x7D 0x71 u32 IsSystemConfigurationEnabled u32 flag
0x7E 0x72 void Standby bool unk
0x7F 0x73 void IOS_Panic char *panic_desc, u32 panic_desc_size
0x80 0x74 void Shutdown
0x81 0x75 void EnableResetOnPanic u32 mode
0x82 0x76 IOSError SetSyslogBuffer void *log_buf
0x83 0x77 IOSError LoadPpcKernel u32 address, u32 size
0x84 0x78 IOSError LoadPpcApplication u32 mem_id, u32 addr1, u32 size1, u32 addr2, u32 size2
0x85 0x79 IOSError SetSecurityLevel IOSSecurityLevel level
0x86 0x7A IOSSecurityLevel GetSecurityLevel
0x87 0x7B IOSError GetOpenResourceHandles u32 max_count, IOSOpenResourceHandle *out, IOSProcessId pid
0x88 0x7C IOSError SetMainTitleSdkVersion u32 version
0x89 0x7D u32 GetMainTitleSdkVersion
0x8A 0x7E IOSError IsCrossProcessHeap void *ptr, u32 size
0x8B 0x7F IOSError HandleDebugInterrupt const char *dbg_sts, u32 dbg_sts_size, IOSMessageQueueId mqid, IOSMessage message
0x8C 0x80 IOSError UnhandleDebugInterrupt IOSMessageQueueId mqid, bool panic
0x8D 0x81 IOSError
0x8E 0x82 IOSError GetViolatingResourceManagers u32 max_count, IOSResourceManager *out
0x8F 0x83 u32 MakeResourceClientHandlesStale char *path
0x90 0x84 IOSError EnableResourceSecurity bool enable
0x91 0x85 IOSError GetPendingResourceRequests u32 max_count, IOSPendingResourceRequest *out, IOSProcessId pid
0x92 0x86 IOSError InitializeIOS
0x93 0x87 void Enable4sOffTimer

GetUpTimer

Returns the number of microseconds elapsed since boot as an u32.

GetTimer

Returns the raw tick count from the HW_TIMER register.

IOS_GetUpTimeStruct

Returns the time elapsed since boot in struct format.

IOS_GetUpTimeStruct

Returns the time elapsed since boot as an u64.

SetRtcTimeStruct

Sets the time provided by the RTC in struct format.

IOS_GetAbsTimeCalendar

Returns the absolute time (up time + RTC) in calendar format.

IOS_GetAbsTime64

Returns the absolute time (up time + RTC) as an u64.

IOS_GetAbsTimeStruct

Returns the absolute time (up time + RTC) in struct format.

EnablePanicOnException

Enables/disables raising a panic when an exception occurs in the specified process. IOS-MCP can call this with any IOSProcessId while other processes must use their own IOSProcessId. Only IOS processes can be targeted and IOS-KERNEL is always forced back to the enabled state.

ReadEfuse

Read data from the eFuses. This can only be used from the IOS-CRYPTO process.

AssociateResourceManager

Associates a resource manager to the specified group ID. This ID appears to correspond to the cos.xml permissions groupid? This syscall isn't used with devices that don't require any permissions(and are PowerPC-accessible) it seems. It appears when this ID isn't listed in the cos.xml groupids at all, the device is ARM-only.

LaunchOS

Disables memory protection, cleans up executable memory areas and jumps to the specified OS image. This can only be called by MCP and will infinite loop on return.

CheckIopBuffer

Checks an IOSU address range for read/write permissions.

CheckPpcBuffer

Checks if a PPC address range is registered in the IOSU's address table.

InitializePpc

Fills range 0x00000000 to 0x00002000 in MEM1 with empty PPC branches.

LoadSystemConfiguration

Stores the value from LT_SYSCFG1 register in the IOSU heap.

ClearSystemConfiguration

Clears the LT_SYSCFG1 register.

SetSystemConfiguration

Sets the value of the LT_SYSCFG1 register.

IsSystemConfigurationEnabled

Checks if the supplied flag is enabled in the LT_SYSCFG1 register copy on the IOSU heap.

SetResetOnPanic

Changes the system behavior on panic.

LoadPpcKernel

Maps the PPC kernel image memory: address == 0x08000000 size == 0x00120000

LoadPpcApplication

Maps the PPC user application memory: mem_id == 0x02 addr1 == 0x00 size1 == 0x00 addr2 == 0x28000000 size2 == 0xA8000000

InitializeIOS

Maps the IOS kernel image memory.

Enable4sOffTimer

Programs the RTC off timer with RTC_COUNTER + 4 seconds and enables it.

Syscalls (via syscall instruction)

These types of syscalls are created with the thumb syscall instruction. When the u16 from retaddr-0x2 matches 0xdfab(intended as thumb "svc 0xab" but ARM "svc 0xdfab" would pass too), it will just return from the exception-handler, otherwise it will do the same thing described here for exceptions. These syscalls are RealView semihosting operations that allow communication with a debugger.
Currently only syscall 0x04 is still used in production versions of IOSU. Syscall 0x06 is only used for a scanf call in some kind of debug configuration, with the following prompt: "Enter '1' to proceed with kernel startup."

MOVS r0, #syscall_number
SVC 0xAB

Register r0 takes the syscall number.
Register r1 takes the first parameter.

ID Return Name Arguments
0x01 __sys_open
0x02 __sys_close
0x03 __sys_writec
0x04 __sys_write0
0x05 __sys_write
0x06 __sys_read
0x07 __sys_readc
0x08 __sys_iserror
0x09 __sys_istty
0x0A __sys_seek
0x0C __sys_flen
0x0D __sys_tmpnam
0x0E __sys_remove
0x0F __sys_rename
0x10 __sys_clocK
0x11 __sys_time
0x12 __sys_system
0x13 __sys_errno
0x15 __sys_get_cmdline
0x16 __sys_heapinfo
0x30 __sys_elapsed
0x31 __sys_tickfreq

__sys_write0

Prints a null-terminated debug message.

__sys_read

Reads input from debugger stdin.

IOSMemoryRegion

Offset Size Description
0x0 0x4 Paddr
0x4 0x4 Vaddr
0x8 0x4 Size
0xC 0x4 Domain
0x10 0x4 Ap
0x14 0x4 Cached

IOSContext

Offset Size Description
0x0 0x4 Cpsr
0x4 0x4 R0
0x8 0x4 R1
0xC 0x4 R2
0x10 0x4 R3
0x14 0x4 R4
0x18 0x4 R5
0x1C 0x4 R6
0x20 0x4 R7
0x24 0x4 R8
0x28 0x4 R9
0x2C 0x4 R10
0x30 0x4 R11
0x34 0x4 R12
0x38 0x4 R13
0x3C 0x4 Lr

IOSThread

The IOSU is able to create and handle up to 0xB4 threads. Each thread has a corresponding internal structure stored in kernel SRAM (0xFFFF4D78 in firmware 5.5.1).

Offset Size Description
0x0 0x40 Context
0x40 0x4 Pc
0x44 0x4 Next
0x48 0x4 InitPriority
0x4C 0x4 Priority
0x50 0x4 State
0x54 0x4 Pid
0x58 0x4 Tid
0x5C 0x4 Attributes
0x60 0x4 ExitValue
0x64 0x4 JoinQueue
0x68 0x4 Queue
0x6C 0x38
0xA4 0x4 Sp
0xA8 0x8
0xB0 0x4 SysStackBase
0xB4 0x4 UsrStackBase
0xB8 0x4 UsrStackSize
0xBC 0x4 IpcBufferPool
0xC0 0x4 ScheduledCount
0xC4 0x4 ScheduledTime

State

Value Description
0 Available
1 Ready
2 Running
3 Stopped
4 Waiting
5 Dead
6 Faulted
7 Unknown

IOSThreadStackInfo

Offset Size Description
0x0 0x4 SysStackBase
0x4 0x4 SysStackSize
0x8 0x4 SysStackUsedSize
0xC 0x4 UsrStackBase
0x10 0x4 UsrStackSize
0x14 0x4 UsrStackUsedSize

IOSThreadUtilization

Offset Size Description
0x0 0x4 MaxThreads
0x4 0x4 AllocatedThreads
0x8 0x4 MaxAllocatedThreads
0xC 0x4 FaultedThreads

IOSThreadProfile

Offset Size Description
0x0 0x4 Tid
0x4 0x4 Pid
0x8 0x4 Priority
0xC 0x4 State
0x10 0x4 ScheduledCount
0x14 0x4 TotalScheduledCount
0x18 0x4 ScheduledTime
0x1C 0x4 TotalScheduledTime
0x20 0x4
0x24 0x4 Sp
0x28 0x4

IOSThreadTrace

Offset Size Description
0x0 0x4 Total
0x4 0x4 Idx
0x8 0x4 TimerVal
0xC 0x4 TimerBase
0x10 0x8 UpTime
0x18 0x4 Flags
0x1C 0x1 * 180 Pids

IOSThreadProfileCommand

Value Description
100
101 ProfileEndEx
102
103 ProfileStart
104
105 SamplingProfileResume
106 SamplingProfileEnd
107 SamplingProfileStart
108
109 SamplingProfileMark
110
111

IOSMessage

This is a s32.

IOSMessageQueueId

This is an u32.

IOSMessageQueue

Offset Size Description
0x0 0x4 EmptyQueue
0x4 0x4 FullQueue
0x8 0x4 Count
0xC 0x4 Rptr
0x10 0x4 Size
0x14 0x4 Buffer
0x18 0x4 Id
0x1C 0x1 Owner
0x1D 0x1 HasEvent
0x1E 0x2

IOSMessageUtilization

Offset Size Description
0x0 0x4 MaxCount
0x4 0x4 AllocatedCount
0x8 0x4 MaxAllocatedCount
0xC 0x2 * 14 PerPidUtilization

IOSEvent

This is an u32.

IOSEventState

Offset Size Description
0x0 0x4 MessageQueue
0x4 0x4 Message
0x8 0x4 Owner
0xC 0x4

IOSFd

This is an u32.

IOSResource

Offset Size Description
0x0 0x20 Path
0x20 0x4 MqId
0x24 0x4 RegisteredResourcesManager
0x28 0x4 FeatureId
0x2C 0x2 PathLen
0x2E 0x2
0x30 0x2
0x32 0x2 ActiveTxnCount
0x34 0x2 OpenHandles
0x36 0x2
0x38 0x2
0x3A 0x2 BusyCloseViolations
0x3C 0x2 MaxIoVectors
0x3E 0x2

IOSResourceHandle

Offset Size Description
0x0 0x4 ServerHandle
0x4 0x4 ClientFd
0x8 0x4 Resource
0xC 0x1 State
0xD 0x3 Reserved

IOSResourceCapability

Offset Size Description
0x0 0x4 FeatureId
0x4 0x4 Mask0
0x8 0x4 Mask1

IOSResourceRequest

Offset Size Description
0x0 0x4 Cmd
0x4 0x4 ClientHandle
0x8 0x4 ServerHandle
0xC 0x4 Flags
0x10 0x4 ClientNodeId
0x14 0x4 ClientPid
0x18 0x4 ClientUniqueIdHigh
0x1C 0x4 ClientUniqueIdLow
0x20 0x4 ClientGroupId
0x24 0x14 Args

IOSResourceTransaction

Offset Size Description
0x0 0x38 Req
0x38 0x4 Mq
0x3C 0x4 MqId
0x40 0x4 Reply
0x44 0x4 RegisteredResourcesManager
0x48 0x4 Resource
0x4C 0x4 ClientFd
0x50 0x4
0x54 0x4 Path
0x58 0x5C

IOSRegisteredResourcesManager

Offset Size Description
0x0 0x4 UniqueIdHigh
0x4 0x4 UniqueIdLow
0x8 0x4 GroupId
0xC 0x4 Owner
0x10 0x4 OpenHandles
0x14 0x4 OpenHandlesWaterline
0x18 0x4 MaxOpenHandles
0x1C 0x10 * 96 Handles
0x61C 0x4 ActiveTxns
0x620 0x4 ActiveTxnWaterline
0x624 0x4 TotalTxnAllocFailures
0x628 0x4 MaxActiveTxns
0x62C 0xC * 20 Capabilities
0x71C 0x4 RegisteredResources
0x720 0x4 MaxRegisteredResources
0x724 0x4 InvalidResourceReplies

IOSActiveResourcesManager

Offset Size Description
0x0 0x2 ActiveResources
0x2 0x2 ActiveResourcesWaterline
0x4 0x2
0x6 0x2
0x8 0x2 CurrentResource
0xA 0x2 MaxResources
0xC 0x40 * 96 Resources

IOSResourceTransactionsManager

Offset Size Description
0x0 0x2 TotalActiveTxns
0x2 0x2 TotalActiveTxnsWaterline
0x4 0x2 TotalTxnAllocFailures
0x6 0x2 CurrentTxn
0x8 0x2
0xA 0x2 MaxTotalActiveTxns
0xC 0xB4 * 256 Txns

IOSResourceManager

Offset Size Description
0x0 0x20 Path
0x20 0x4 FeatureId
0x24 0x4 Owner
0x28 0x4 BusyCloseViolations
0x2C 0x4 ActiveTxnCount
0x30 0x4 OpenHandles

IOSResourceAggregateUtilization

Offset Size Description
0x0 0x4 ActiveResources
0x4 0x4 ActiveResourcesWaterline
0x8 0x4 MaxResources
0xC 0x4 TotalActiveTxns
0x10 0x4 TotalActiveTxnsWaterline
0x14 0x4 TotalTxnAllocFailures
0x18 0x4 MaxTotalActiveTxns

IOSResourcePerProcessUtilization

Offset Size Description
0x0 0x4 Owner
0x4 0x4 OpenHandles
0x8 0x4 OpenHandlesWaterline
0xC 0x4 MaxOpenHandles
0x10 0x4 ActiveTxns
0x14 0x4 ActiveTxnWaterline
0x18 0x4 TotalTxnAllocFailures
0x1C 0x4 MaxActiveTxns
0x20 0x4 RegisteredResources
0x24 0x4 MaxRegisteredResources
0x28 0x4 InvalidResourceReplies

IOSOpenResourceHandle

Offset Size Description
0x0 0x4 Pid
0x4 0x4 ClientFd
0x8 0x4 ServerHandle
0xC 0x20 Path

IOSPendingResourceRequest

Offset Size Description
0x0 0x4 ClientReplyAddress
0x4 0x4 Owner
0x8 0x4 Host
0xC 0x4 ClientFd
0x10 0x38 Req
0x48 0x20 Path

IOSHeap

The IOSU is able to create and handle up to 0x30 heaps. Each heap has a corresponding descriptor structure stored in the kernel's BSS section (0x08150008 in firmware 5.5.1).

Offset Size Description
0x0 0x4 Base
0x4 0x4 Owner
0x8 0x4 Size
0xC 0x4 FreeList
0x10 0x4 AllocErrors
0x14 0x4 FreeErrors
0x18 0x4 ReAllocErrors
0x1C 0x4 InvalidChunks
0x20 0x4 Flags
0x24 0x4 TotalAllocatedSize
0x28 0x4 LargestAllocatedSize
0x2C 0x4 AllocatedChunks
0x30 0x4 FreeChunks
0x34 0x4 FreeUnusedChunkErrors
0x38 0x4 AllocInvalidHeapErrors
0x3C 0x4 AllocInvalidHeapId

All accesses to heaps are verified using owner PID and active PID. Heaps are referenced using IDs that are used as indices into the heap descriptor array. There are 3 special heap IDs:

Value Description
0x0001 Shared heap
0xCAFE Local process heap for active PID
0xCAFF Cross process heap for active PID

Access to special heap IDs is redirected to the appropriate heap.

Each process can allocate a cross process heap for multiple processes to use and a local process heap for itself. These are kept tracked of using two arrays following the heap descriptor array in kernel BSS:

int32 local_process_heaps[14];
int32 cross_process_heaps[14];

They are initialized to IOS_ERROR_INVALID within the IOSU kernel and are set to the appropriate heap ID when created using IOS_CreateLocalProcessHeap or IOS_CreateCrossProcessHeap. There may only be one cross/local process heap for each PID.

Each heap descriptor contains a flag field that contains information about the heap:

0x1: Local process heap
0x2: Cross process heap

Each heap is created from memory of the shared heap. It is initialized as one big seperate memory chunk.

When memory is allocated to a heap, the linked list (terminated using nullptr's) is traversed to find a large enough chunk, chunks are split and back and forward pointers are cleared for the allocated chunk. When a chunk is allocated aligned, a chunk bigger than the needed one may be allocated. Inside this chunk, a second heap chunk is set up in a fashion that the beginning of the memory block described by this "inner" chunk is aligned according to the specified alignment. It's magic is set to 0xBABE0002 and the back pointer is set to the chunk containing it. These inner chunks can not be expanded.

IOSChunk

Offset Size Description
0x0 0x4 Status
0x4 0x4 Size
0x8 0x4 PrevFree
0xC 0x4 NextFree

Status

Value Description
0xBABE0000 Chunk is free
0xBABE0001 Chunks is used
0xBABE0002 Chunk is inner chunk and used

IOSHeapProfile

Offset Size Description
0x0 0x4 Owner
0x4 0x4 Base
0x8 0x4 Size
0xC 0x4 FreeChunks
0x10 0x4 LargestChunkSize
0x14 0x4 SmallestChunkSize
0x18 0x4 TotalFreeSize
0x1C 0x4 AllocErrors
0x20 0x4 FreeErrors
0x24 0x4 ReAllocErrors
0x28 0x4 CorruptChunks
0x2C 0x4 InvalidChunks
0x30 0x4 Flags

IOSTimeStruct

Offset Size Description
0x0 0x4 Microsecond
0x4 0x4 Second

IOSTimeCalendar

Offset Size Description
0x0 0x4 Year
0x4 0x4 Month
0x8 0x4 Day
0xC 0x4 Hour
0x10 0x4 Minute
0x14 0x4 Second
0x18 0x4 Microsecond

IOSTimerUtilization

Offset Size Description
0x0 0x4 MaxCount
0x4 0x4 AllocatedCount
0x8 0x4 MaxAllocatedCount
0xC 0x2 * 14 PerPidUtilization

IOSSemaphoreUtilization

Offset Size Description
0x0 0x4 MaxCount
0x4 0x4 AllocatedCount
0x8 0x4 MaxAllocatedCount
0xC 0x2 * 14 PerPidUtilization

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

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

Modules

Similarly to the Wii, IOS modules roughly 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, as of 5.5.0 this is: "OpenSSL 1.0.0f 4 Jan 2012".

IOS-NIM-BOSS

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

  • /dev/nim - Nintendo installation manager? (installs updates)
  • /dev/boss - BOSS service

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).

Virtual Memory Map

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 (5.5.1 production)
0x10800000 - 0x11EE0000 0x10800000 - 0x11EE0000 0x16E0000 IOS-FS (5.3.2 development)
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).