Cafe OS

From WiiUBrew
Jump to navigation Jump to search

Cafe OS is the operating system running on the PowerPC in Wii U mode. It consists of the Cafe OS kernel, the executable loader, and system libraries. Unlike on the Wii, where each game provided its own copy of Revolution OS with no isolation between libraries, Wii U applications run under the supervision of a common PowerPC kernel, isolating them from each other. All applications are modified ELFs, as are the libraries themselves, and applications dynamically link with them to gain access to OS services. Cafe OS also contains a few system processes, like the home menu and error handler.


The kernel runs in supervisor mode on the PowerPC, and performs the basic tasks of a microkernel. It is responsible for process isolation, memory management, and interrupt dispatching, as well as communication with IOSU. Cafe OS applications run as user mode processes, with separate address spaces and W^X memory protection.


Cafe OS syscalls are issued by doing the following:

li r0, 0x0100 # load syscall value->r0
sc            # syscall instruction
blr           # return control to program

When you send a call to the kernel, it goes to 0xFFF00C00, which then jumps to 0xFFF021A0 + (fastcall << 5).

Normal syscalls are divisible by 0x100, so all of them will jump to 0xFFF0021A0 itself, which is a jump to the table dispatcher.

The dispatcher uses a RAMPID and the syscall dispatch tables at 0xFFEAAA40 (user table in 5.5.1) and 0xFFE84850 (loader table in 5.5.1) to get the secondary table each RAMPID is able to access.

RAMPIDs 0 (Kernel), 2, and 3 all use an empty table, while RAMPID 1 (root.rpx) has its own table with a few unique calls. RAMPIDs 4 (background app), 5 (home menu), and 6 (error display) share the same table and RAMPID 7 (foreground app) has it's own.

Below is a list of what all of them, as well as the loader which has its own bare-bones table, have access to call. (sp) indicates that the loader uses a separate function for that syscall. Additionally, the loader uses the same function for IPCKDriver_Open/Close.

# Name root Sys App Ldr
0x0 ConsoleWrite X X X X (sp)
0x100 AppPanic X X X X
0x200 EffectiveToPhysical X X X
0x300 PhysicalToEffectiveCached X X X
0x400 PhysicalToEffectiveUncached X X X
0x500 ValidateAddressSpaceRange X X X X
0x600 UpdateCoretime X X X
0x700 - - - - -
0x800 SetUserModeExHandler X X X
0x900 - - - - -
0xA00 - - - - -
0xB00 AllocateTimer X X X
0xC00 FreeTimer X X X
0xD00 PrimeTimer X X X
0xE00 StopTimer X X X
0xF00 DynLoad_DumpModuleList X X X
0x1000 SetInterruptHandler X X X
0x1100 GetInterruptHandler X X X
0x1200 DisableInterrupt X X X
0x1300 EnableInterrupt X X X
0x1400 ClearAndEnableInterrupt X X X
0x1500 GetInterruptStatus X X X
0x1600 ClearInterruptStatus X X X
0x1700 FindClosestSymbol X X X X (sp)
0x1800 Test_Assist
0x1900 Exit X X X
0x1A00 GetInfo X X X
0x1B00 SetInfo X X X
0x1C00 ReleaseCore X X X
0x1D00 SendICI X X X
0x1E00 IPCKDriver_{Loader|User}Open X X X X (sp)
0x1F00 IPCKDriver_{Loader|User}Close X X X X (sp)
0x2000 IPCKDriver_SubmitRequest X X X X (sp)
0x2100 - - - - -
0x2200 GetEnvironmentVariable X X X
0x2300 - - - - -
0x2400 - - - - -
0x2500 - - - - -
0x2600 - - - - -
0x2700 Proc_GetNotifyTarget X X X
0x2800 Proc_ReleaseForeground X X X
0x2900 Proc_GetForegroundBucket X X X
0x2A00 Proc_RequestSwitch X X X
0x2B00 LaunchTitleArgvStr X X X
0x2C00 Proc_YieldCore X X X
0x2D00 - - - - -
0x2E00 Proc_GetSystemMessage X X X
0x2F00 Proc_GetCallArgs X X X
0x3000 GetAbsoluteSystemTimeInternal X X X
0x3100 SetAbsoluteSystemTimeInternal X X X
0x3200 Drivers_GetInstance X X X
0x3300 Drivers_PurgeMaster X X X
0x3400 - - - - -
0x3500 - - - - -
0x3600 - - - - -
0x3700 - - - - -
0x3800 AllocVirtAddr X X X
0x3900 FreeVirtAddr X X X
0x3A00 GetMapVirtAddrRange X X X
0x3B00 GetDataPhysAddrRange X X X
0x3C00 GetAvailPhysAddrRange X X X
0x3D00 MapMemory X X X
0x3E00 UnmapMemory X X X
0x3F00 LogBuffer X X X X
0x4000 LogArgs X X X X
0x4100 LogFunc X X X X
0x4200 LogReportKernel X X X X
0x4300 LogRetrieve X X X X
0x4400 LoadUserContext X X X
0x4500 FlushUserContext X X X
0x4600 FlushUserFPUContext X X X
0x4700 Drivers_CopyFromSaveArea X X X
0x4800 Drivers_CopyToSaveArea X X X
0x4900 Proc_ReadyToRelease X X X
0x4A00 FlushInterrupts X X X
0x4B00 SetDABR X X X
0x4C00 SetIABR X X X
0x4D00 Proc_GetProcessInfo X X X
0x4E00 GetCodegenVirtAddrRange X X X
0x4F00 DynLoad_RPLLoaderEntry X X X
0x5000 RPLLoaderResumeContext X
0x5100 - - - - -
0x5200 WaitIopComplete X
0x5300 FlushCode X
0x5400 FlushData X
0x5500 UpdateHeartbeat X
0x5600 LogEntry X
0x5700 FastClearMemory X
0x5800 GetBusClockSpeed X
0x5900 Shared_GetArea X X X
0x5A00 Proc_SendPolicy X X X
0x5B00 GetProcessIndex X
0x5C00 IPCKDriver_PollLoaderCompletion X
0x5D00 BlockLogSaveHiLo X X X
0x5E00 FinishInitAndPreload X
0x5F00 ContinueStartProcess X
0x6000 OpenMCP X
0x6100 Proc_QuerySwitchReady X X X
0x6200 Launch X X X
0x6300 Call X X X
0x6400 SetTimeInternal X
0x6500 X X X
0x6600 ProfileEntry X
0x6700 Proc_RequestExit X X X
0x6800 Proc_CoreInitDone X X X
0x6900 Proc_GetSwitchTarget X X X
0x6A00 Proc_AcquireDone X X X
0x6B00 Proc_GetBuiltSDKVersion X X X
0x6C00 Proc_SystemFatal X X X
0x6D00 - - - - -
0x6E00 SwitchSecCodeGenMode X X X
0x6F00 IopShell_RegisterCallback X X X
0x7000 Proc_GetTitleVersion X X X
0x7100 Proc_IsTestKernel X X X
0x7200 ForceFullRelaunch X X X
0x7300 Proc_Recycle X
0x7400 GetFlags X X X X
0x7500 QueryVirtAddr X X X
0x7600 GetCodegenInfo X X X
0x7700 GetSecCodeGenMode X X X
0x7800 CodegenCopy X X X
0x7900 Proc_LoadShared X
0x7A00 SetExceptionCallback X X X
0x7B00 IopShell_InjectCommand X X X
0x7C00 Proc_Kill X X X
0x7D00 EnableOverlayArena X X X
0x7E00 DisableOverlayArena X X X
0x7F00 GetSystemMode X X X
0x8000 SystemMode_RegisterCallback X X X
0x8100 ZeroProcessMemory X
0x8200 HandlePowerEvents X
0x8300 ConsoleTimestamp X X X X
0x8400 ValidateOverlayRange X
0x8500-0xFF00 BadSysCall (jump to null on purpose) X X X X


Fastcalls, on the other hand, are system calls that aren't routed through the dispatcher and can be accessed by any RAMPID. Attempting to access an unimplemented fastcall will redirect the code flow to syscall 0x0100 (AppPanic).

Below is a list of all the currently supported fastcalls.

# Name
0x0 SysCall (default branch to syscall dispatcher)
0x1 MemoryBarrier
0x2 EnableInterrupts (deprecated, jumps to error)
0x3 DisableInterrupts (deprecated, jumps to error)
0x4 IsInterruptEnabled (deprecated, jumps to error)
0x5 RestoreInterrupts (deprecated, jumps to error)
0x6 LoadContext
0x7 GetMSR
0x8 SetCurrentContext
0x9 GetCurrentFPUContext
0xA SetCurrentFPUContext
0xB CompareAndSwapCurrentFPUContext
0xC WriteGatherInit
0xD SetPerformanceMonitor
0xE SetUserDMA
0xF ReturnFromInterrupt
0x10 FlushFPUContext
0x11 ReadRegister32Ex
0x12 WriteRegister32Ex
0x15 WriteGatherInitWritePtr
0x17 WriteGatherReadWritePtr
0x18 EnableFPU
0x19 GetSecurityLevel
0x1A-0x1F BadFastCall (jump to error on purpose)


Takes two u32s WhitelistIndex and RegisterIndex. Returns an u32 RegisterValue.

Reads a hardware register from the following whitelist:

0                // Invalid
0xFD020068       // 2 registers at 0x0D000068 (HW_I2CIOPINTEN to HW_I2CIOPINTSTS)
0xFD0100C0       // 1 registers at 0x0D0000C0 (HW_GPIOPPCOUT)
0xFD04021C       // 4 registers at 0x0D00021C
0xFD040250       // 4 registers at 0x0D000250 (HW_I2CMCTRL to HW_I2CMDATARD)
0xFD060520       // 6 registers at 0x0D000520 (LT_GPIOPPCOUT to LT_GPIOPPCINTEN)
0xFD106400       // 16 registers at 0x0D006400
0xFD046C00       // 4 registers at 0x0D006C00
0xFD046E00       // 4 registers at 0x0D006E00
0xFD0F6800       // 15 registers at 0x0D006800 (EXI0_CSR to EXI2_DATA)
0                // Invalid
0                // Invalid
0                // Invalid
0                // Invalid
0                // Invalid
0                // Invalid


Takes three u32s WhitelistIndex, RegisterIndex and RegisterValue. No output.

Same as ReadRegister32Ex, but for writing to a whitelisted hardware register instead.


This is a structure mapped to address 0x1FFF000 in MEM1 for communicating with the MCP process.

Offset Size Description
0x0 0x4 Magic (0x5726)
0x4 0x4 Size (0x40C)
0x8 0x4 Flags
0xC 0x4 ConsoleType
0x10 0x4 Iop2x
0x14 0x4 Bperf
0x18 0x4 PpcSystemClockFrequency
0x1C 0x4 PpcCore0L2Size
0x20 0x4 PpcCore0L2LineSize
0x24 0x4 PpcCore0L2SectorSize
0x28 0x4 PpcCore0L2FetchSize
0x2C 0x4 PpcCore0L2SetAssociativity
0x30 0x4 PpcCore1L2Size
0x34 0x4 PpcCore1L2LineSize
0x38 0x4 PpcCore1L2SectorSize
0x3C 0x4 PpcCore1L2FetchSize
0x40 0x4 PpcCore1L2SetAssociativity
0x44 0x4 PpcCore2L2Size
0x48 0x4 PpcCore2L2LineSize
0x4C 0x4 PpcCore2L2SectorSize
0x50 0x4 PpcCore2L2FetchSize
0x54 0x4 PpcCore2L2SetAssociativity
0x58 0x64 Reserved
0xBC 0x4 PpcCorePropertiesCount
0xC0 0x4 PpcCorePropertiesFlags
0xC4 0x4 PpcMem0Id
0xC8 0x4 PpcMem0BaseAddress
0xCC 0x4 PpcMem0Size
0xD0 0x4 PpcMem1Id
0xD4 0x4 PpcMem1BaseAddress
0xD8 0x4 PpcMem1Size
0xDC 0x4 PpcMem2Id
0xE0 0x4 PpcMem2BaseAddress
0xE4 0x4 PpcMem2Size
0xE8 0x3C Reserved
0x124 0x4 PpcMemRegionCount
0x128 0x4 PpcMemRegionFlags
0x12C 0x244 Reserved
0x370 0x4 HardwareVersion
0x374 0x40 Reserved
0x3B4 0x4 SmdBaseAddress
0x3B8 0x48 Reserved
0x400 0x4 LastPMState
0x404 0x4 CurrentPMState
0x408 0x4 BootPMFlags


Bits Description
26 IsEnterBgNormalMode
27 IsDevMode
28 IsFastRelaunch
29 IsColdBoot
30 IsSynchronousPrintingEnabled


Offset Size Description
0x0 0x8 Tag
0x8 0x80 Gpr
0x88 0x4 Cr
0x8C 0x4 Lr
0x90 0x4 Ctr
0x94 0x4 Xer
0x98 0x4 Srr0
0x9C 0x4 Srr1
0xA0 0x4 Dsisr
0xA4 0x4 Dar
0xA8 0x4 CrashType
0xAC 0x4 Reserved
0xB0 0x4 FpscrHigh
0xB4 0x4 FpscrLow
0xB8 0x100 Fpr
0x1B8 0x2 SpinLockCount
0x1BA 0x2 ContextState
0x1BC 0x20 Ugqr
0x1DC 0x4 Pir
0x1E0 0x100 Psf
0x2E0 0x18 Coretime
0x2F8 0x8 Starttime
0x300 0x4 Error
0x304 0x4 Attributes
0x308 0x4 Pmc1
0x30C 0x4 Pmc2
0x310 0x4 Pmc3
0x314 0x4 Pmc4
0x318 0x4 Mmcr0
0x31C 0x4 Mmcr1


Offset Size Description
0x0 0x40
0x40 0x4 BootStage
0x44 0x4 CoreInitFunc
0x48 0x4 CoreState
0x4C 0x4
0x50 0x4
0x54 0x4 IsKernelPanic
0x58 0x4 InterruptedContext
0x5C 0x4 CurrentFpuContext
0x60 0x4 CurrentCoreControl
0x64 0x4 SysCallTableAddress
0x68 0x4 FastCallBaseAddress
0x6C 0x4 NonRecoverableExceptionHandlerTableAddress
0x70 0x4 RecoverableExceptionHandlerTableAddress
0x74 0x2
0x76 0x2
0x78 0x4 LoadPerfMonContext
0x7C 0x4 CurrentSysCallAddress
0x80 0x4 CurrentSysCallCallback
0x84 0x4 NonRecoverableExceptionContextAddress
0x88 0x4 RecoverableExceptionContextAddress
0x8C 0x4 NormalSysCalls
0x90 0x4 FpuExceptions
0x94 0x4 DsiExceptions
0x98 0x4 IciExceptions
0x9C 0x4
0xA0 0x4 Ps0
0xA4 0x4 Ps1
0xA8 0x8 ProcessWork
0xB0 0x4
0xB4 0x4 RamPid
0xB8 0x4 Upid
0xBC 0x4 Mem1Address
0xC0 0x4 InterceptedLoadContext
0xC4 0x4 SintEnableAfterKernelExit
0xC8 0x4 AddrConfig
0xCC 0x20 SysCallCallbackGpr
0xEC 0x4 EaDataBegin
0xF0 0x4 EaDataEnd
0xF4 0x18
0x10C 0x4 WriteGatherDataOffset
0x110 0x30 ExceptionInfo
0x140 0x4 OverwriteGprOnExceptionExit
0x144 0x28 ExceptionExitGpr
0x16C 0x28 PostException
0x194 0x4
0x198 0x128 RecoverableExceptionContext
0x2C0 0x14
0x2D8 0x128 NonRecoverableExceptionContext


Offset Size Description
0x0 0x8 Tbr64
0x8 0x80 Gpr
0x88 0x4 Cr
0x8C 0x4 Lr
0x90 0x4 Ctr
0x94 0x4 Xer
0x98 0x4 Srr0
0x9C 0x4 Srr1
0xA0 0x88


Offset Size Description
0x0 0x4
0x4 0x4
0x8 0x4 UserStackPtr
0xC 0x4 ExHandler
0x10 0x4 Msr
0x14 0x4 Sprg0
0x18 0x4 Dsisr
0x1C 0x4 Dar
0x20 0x4
0x24 0x4
0x28 0x4
0x2C 0x4 CallbackContext


Offset Size Description
0x0 0x4 OldUpid
0x4 0x4 TargetUpid
0x8 0x4 Exit
0xC 0x4 Callback
0x10 0x4 CurrentExceptionContext
0x14 0x4 InterruptedContext
0x18 0x4
0x1C 0x4
0x20 0x4
0x24 0x4


Offset Size Description
0x0 0x4 InterruptedContext
0x4 0x4 CurrentFpuContext
0x8 0x4
0xC 0x4 FastCallBaseAddress
0x10 0x4 SintEnableAfterKernelExit
0x14 0x4
0x18 0x4
0x1C 0x4 Dabr
0x20 0x4 Iabr
0x24 0x4 EaDataBegin
0x24 0x4 EaDataEnd
0x28 0x1C
0x48 0x4 AddrConfig
0x4C 0x3C PerCore


This is a structure mapped to address 0xFFFFFFC0.

Offset Size Description
0x0 0x18
0x18 0x4 UserHeartBeat
0x1C 0x4
0x20 0x4 CurrentThread
0x24 0x4 SoftIntEnabled
0x28 0x4 SoftIntPending
0x2C 0x4 CurrentContext
0x30 0x4
0x34 0x4
0x38 0x4 ThreadQueue


A process in Cafe OS represents a single running application, with its own code, memory, and permissions. Cafe OS only executes the code of a single process at a time, but it can hold the data of multiple processes in memory simultaneously, and switch between them. Rather than allowing arbitrary process creation, there is RAM reserved for a single foreground app, a single background app, and various other special processes. Each running process is assigned a unique identifier called a RAMPID:

RAMPID Description IOS Name
1 root.rpx COS-ROOT
2 ??? COS-02
3 ??? COS-03
4 Background app COS-OVERLAY
5 Home Menu COS-HBM
6 Error display COS-ERROR
7 Foreground app COS-MASTER

In addition to RAMPID, Cafe OS processes have another type of process ID called a fixed process ID (PFID). Rather than representing which part of memory a process occupies, PFID actually specifies which specific app/task is running (browser, game, eShop, etc.). Cafe OS maps PFIDs to the RAMPID that they occupy when running (for example, a game is RAMPID 7 due to running in the foreground):

PFID Description RAMPID
0 Cafe OS kernel 0
1 root.rpx 1
2 Wii U Menu 7
3 TVii ???
4 E-Manual ???
5 Home Menu 5
6 Error Display 6
7 "MiniMiiverse" ???
8 Internet Browser 4
9 Miiverse ???
10 eShop ???
11 COS-FLV ???
12 Download Manager ???
13 COS-RSVD-13 ???
14 COS-RSVD-14 ???
15 Game 7


Main article: Loader

The loader is responsible for loading RPL formatted libraries and executables into memory. It is a standard ELF executable named loader.elf. It includes a statically linked copy of zlib, probably for decompressing sections of RPL files.


Cafe OS applications dynamically link with system libraries to get access to OS services. These OS services include memory management, graphics, audio, and controller input. All libraries are RPL files, a modification of the standard ELF format with compressed sections and more Windows-like dynamic linking. The main system libraries are listed below, with some having their own pages of documentation:

Virtual Memory Map

Virtual address start Virtual address size Physical address start Flags Description
0x1000000 0x800000 0x32000000 0x2CE08002 Loader and system libraries
0x1800000 0x20000 0 0x28101200 This is the codegen/JIT memory area, only available under processes which have it enabled under cos.xml (the size comes from cos.xml too)
0x2000000 (variable) 0xE000000 (variable) 0x72000000 or 0xB2000000 (variable) 0x2CF09400 App executable and libraries (start varies, but end is always 0x10000000)
0x10000000 0x52000000 or 0x92000000 (variable) 0x20000000 (variable) 0x28305800 Application/library data area (may be smaller)
0xA0000000 0x40000000 0 0x2000 Overlay of application memory (used by loader?)
0xE0000000 0x4000000 0x14000000 0x28204004 Some sort of hardware communication area
0xE8000000 0x2000000 0xD0000000 0x78200004
0xEFE00000 0x80000 0x1B900000 0x28109010 Loader data area (only mapped when running loader)
0xF4000000 0x2000000 0 0x28204004 MEM1
0xF6000000 0x800000 0x1B000000 0x3CA08002 Loader chunk buffer
0xF8000000 0x3000000 0x18000000 0x2CA08002 Read-only shared data (system fonts mostly)
0xFB000000 0x800000 0x1C800000 0x28200002
0xFC000000 0xC0000 0xC000000 0x70100022 Processor Interface
0xFC0C0000 0x120000 0xC0C0000 0x70100022
0xFC1E0000 0x20000 0xC1E0000 0x78100024 VI
0xFC200000 0x80000 0xC200000 0x78100024 GFXSP
0xFC280000 0x20000 0xC280000 0x78100024 DSP
0xFC2A0000 0x20000 0xC2A0000 0x78100023 Write Gather Pipe
0xFC300000 0x20000 0xC300000 0x78100024
0xFC320000 0xE0000 0xC320000 0x70100022 Espresso eFuses
0xFD000000 0x400000 0xD000000 0x70100022 Latte Registers
0xFE000000 0x800000 0x1C000000 0x20200002
0xFF200000 0x80000 0x1B800000 0x20100040 Kernel heap
0xFF280000 0x80000 0x1B880000 0x20100040
0xFFC00000 0x20000 0xFFC00000 0x8100004 Codegen area used with OSCodegenCopy
0xFFC40000 0x20000 0xFFC40000 0x8100004 Codegen area used with OSCodegenCopy
0xFFC80000 0x20000 0xFFC80000 0x810000C Codegen area used with OSCodegenCopy
0xFFCE0000 0x20000 0 0x50100004
0xFFE00000 0x20000 0xFFE00000 0x20100040 Kernel ancast image
0xFFE40000 0x20000 0xFFE40000 0x20100040
0xFFE80000 0x60000 0xFFE80000 0x20100040
0xFFEE0000 0x20000 0xFFEE0000 0x20100040
0xFFF00000 0x20000 0xFFF00000 0x20100040
0xFFF60000 0x20000 0xFFE20000 0x20100080
0xFFF80000 0x20000 0xFFE60000 0x2C100040
0xFFFA0000 0x20000 0xFFE60000 0x20100080
0xFFFC0000 0x20000 0x1BFE0000 0x24100002
0xFFFE0000 0x20000 0x1BF80000 0x28100102 Per-thread data (e.g. pointer to thread descriptor and thread queue) at 0xFFFFFFE0 - 0xFFFFFFFC.