In memory of Ben “bushing” Byer, who passed away on Monday, February 8th, 2016.

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.

Kernel

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.

SysCalls

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.

#NamerootSysAppLdr
0x0ConsoleWriteXXXX (sp)
0x100AppPanicXXXX
0x200EffectiveToPhysicalXXX
0x300PhysicalToEffectiveCachedXXX
0x400PhysicalToEffectiveUncachedXXX
0x500ValidateAddressSpaceRangeXXXX
0x600UpdateCoretimeXXX
0x700-----
0x800SetUserModeExHandlerXXX
0x900-----
0xA00-----
0xB00AllocateTimerXXX
0xC00FreeTimerXXX
0xD00PrimeTimerXXX
0xE00StopTimerXXX
0xF00DynLoad_DumpModuleListXXX
0x1000SetInterruptHandlerXXX
0x1100GetInterruptHandlerXXX
0x1200DisableInterruptXXX
0x1300EnableInterruptXXX
0x1400ClearAndEnableInterruptXXX
0x1500GetInterruptStatusXXX
0x1600ClearInterruptStatusXXX
0x1700FindClosestSymbolXXXX (sp)
0x1800Test_Assist
0x1900ExitXXX
0x1A00GetInfoXXX
0x1B00SetInfoXXX
0x1C00ReleaseCoreXXX
0x1D00SendICIXXX
0x1E00IPCKDriver_{Loader|User}OpenXXXX (sp)
0x1F00IPCKDriver_{Loader|User}CloseXXXX (sp)
0x2000IPCKDriver_SubmitRequestXXXX (sp)
0x2100-----
0x2200GetEnvironmentVariableXXX
0x2300-----
0x2400-----
0x2500-----
0x2600-----
0x2700Proc_GetNotifyTargetXXX
0x2800Proc_ReleaseForegroundXXX
0x2900Proc_GetForegroundBucketXXX
0x2A00Proc_RequestSwitchXXX
0x2B00LaunchTitleArgvStrXXX
0x2C00Proc_YieldCoreXXX
0x2D00-----
0x2E00Proc_GetSystemMessageXXX
0x2F00Proc_GetCallArgsXXX
0x3000GetAbsoluteSystemTimeInternalXXX
0x3100SetAbsoluteSystemTimeInternalXXX
0x3200Drivers_GetInstanceXXX
0x3300Drivers_PurgeMasterXXX
0x3400-----
0x3500-----
0x3600-----
0x3700-----
0x3800AllocVirtAddrXXX
0x3900FreeVirtAddrXXX
0x3A00GetMapVirtAddrRangeXXX
0x3B00GetDataPhysAddrRangeXXX
0x3C00GetAvailPhysAddrRangeXXX
0x3D00MapMemoryXXX
0x3E00UnmapMemoryXXX
0x3F00LogBufferXXXX
0x4000LogArgsXXXX
0x4100LogFuncXXXX
0x4200LogReportKernelXXXX
0x4300LogRetrieveXXXX
0x4400LoadUserContextXXX
0x4500FlushUserContextXXX
0x4600FlushUserFPUContextXXX
0x4700Drivers_CopyFromSaveAreaXXX
0x4800Drivers_CopyToSaveAreaXXX
0x4900Proc_ReadyToReleaseXXX
0x4A00FlushInterruptsXXX
0x4B00SetDABRXXX
0x4C00SetIABRXXX
0x4D00Proc_GetProcessInfoXXX
0x4E00GetCodegenVirtAddrRangeXXX
0x4F00DynLoad_RPLLoaderEntryXXX
0x5000RPLLoaderResumeContextX
0x5100-----
0x5200WaitIopCompleteX
0x5300FlushCodeX
0x5400FlushDataX
0x5500UpdateHeartbeatX
0x5600LogEntryX
0x5700FastClearMemoryX
0x5800GetBusClockSpeedX
0x5900Shared_GetAreaXXX
0x5A00Proc_SendPolicyXXX
0x5B00GetProcessIndexX
0x5C00IPCKDriver_PollLoaderCompletionX
0x5D00BlockLogSaveHiLoXXX
0x5E00FinishInitAndPreloadX
0x5F00ContinueStartProcessX
0x6000OpenMCPX
0x6100Proc_QuerySwitchReadyXXX
0x6200LaunchXXX
0x6300CallXXX
0x6400SetTimeInternalX
0x6500XXX
0x6600ProfileEntryX
0x6700Proc_RequestExitXXX
0x6800Proc_CoreInitDoneXXX
0x6900Proc_GetSwitchTargetXXX
0x6A00Proc_AcquireDoneXXX
0x6B00Proc_GetBuiltSDKVersionXXX
0x6C00Proc_SystemFatalXXX
0x6D00-----
0x6E00SwitchSecCodeGenModeXXX
0x6F00IopShell_RegisterCallbackXXX
0x7000Proc_GetTitleVersionXXX
0x7100Proc_IsTestKernelXXX
0x7200ForceFullRelaunchXXX
0x7300Proc_RecycleX
0x7400GetFlagsXXXX
0x7500QueryVirtAddrXXX
0x7600GetCodegenInfoXXX
0x7700GetSecCodeGenModeXXX
0x7800CodegenCopyXXX
0x7900Proc_LoadSharedX
0x7A00SetExceptionCallbackXXX
0x7B00IopShell_InjectCommandXXX
0x7C00Proc_KillXXX
0x7D00EnableOverlayArenaXXX
0x7E00DisableOverlayArenaXXX
0x7F00GetSystemModeXXX
0x8000SystemMode_RegisterCallbackXXX
0x8100ZeroProcessMemoryX
0x8200HandlePowerEventsX
0x8300ConsoleTimestampXXXX
0x8400ValidateOverlayRangeX
0x8500-0xFF00BadSysCall (jump to null on purpose)XXXX

FastCalls

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
0x0SysCall (default branch to syscall dispatcher)
0x1MemoryBarrier
0x2EnableInterrupts (deprecated, jumps to error)
0x3DisableInterrupts (deprecated, jumps to error)
0x4IsInterruptEnabled (deprecated, jumps to error)
0x5RestoreInterrupts (deprecated, jumps to error)
0x6LoadContext
0x7GetMSR
0x8SetCurrentContext
0x9GetCurrentFPUContext
0xASetCurrentFPUContext
0xBCompareAndSwapCurrentFPUContext
0xCWriteGatherInit
0xDSetPerformanceMonitor
0xESetUserDMA
0xFReturnFromInterrupt
0x10FlushFPUContext
0x11ReadRegister32Ex
0x12WriteRegister32Ex
0x13
0x14
0x15WriteGatherInitWritePtr
0x16
0x17WriteGatherReadWritePtr
0x18EnableFPU
0x19GetSecurityLevel
0x1A-0x1FBadFastCall (jump to error on purpose)

ReadRegister32Ex

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

WriteRegister32Ex

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

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

OSPlatformInfo

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

OffsetSizeDescription
0x00x4Magic (0x5726)
0x40x4Size (0x40C)
0x80x4Flags
0xC0x4ConsoleType
0x100x4Iop2x
0x140x4Bperf
0x180x4PpcSystemClockFrequency
0x1C0x4PpcCore0L2Size
0x200x4PpcCore0L2LineSize
0x240x4PpcCore0L2SectorSize
0x280x4PpcCore0L2FetchSize
0x2C0x4PpcCore0L2SetAssociativity
0x300x4PpcCore1L2Size
0x340x4PpcCore1L2LineSize
0x380x4PpcCore1L2SectorSize
0x3C0x4PpcCore1L2FetchSize
0x400x4PpcCore1L2SetAssociativity
0x440x4PpcCore2L2Size
0x480x4PpcCore2L2LineSize
0x4C0x4PpcCore2L2SectorSize
0x500x4PpcCore2L2FetchSize
0x540x4PpcCore2L2SetAssociativity
0x580x64Reserved
0xBC0x4PpcCorePropertiesCount
0xC00x4PpcCorePropertiesFlags
0xC40x4PpcMem0Id
0xC80x4PpcMem0BaseAddress
0xCC0x4PpcMem0Size
0xD00x4PpcMem1Id
0xD40x4PpcMem1BaseAddress
0xD80x4PpcMem1Size
0xDC0x4PpcMem2Id
0xE00x4PpcMem2BaseAddress
0xE40x4PpcMem2Size
0xE80x3CReserved
0x1240x4PpcMemRegionCount
0x1280x4PpcMemRegionFlags
0x12C0x244Reserved
0x3700x4HardwareVersion
0x3740x40Reserved
0x3B40x4SmdBaseAddress
0x3B80x48Reserved
0x4000x4LastPMState
0x4040x4CurrentPMState
0x4080x4BootPMFlags

Flags

BitsDescription
0-25
26IsEnterBgNormalMode
27IsDevMode
28IsFastRelaunch
29IsColdBoot
30IsSynchronousPrintingEnabled
31

OSContext

OffsetSizeDescription
0x00x8Tag
0x80x80Gpr
0x880x4Cr
0x8C0x4Lr
0x900x4Ctr
0x940x4Xer
0x980x4Srr0
0x9C0x4Srr1
0xA00x4Dsisr
0xA40x4Dar
0xA80x4CrashType
0xAC0x4Reserved
0xB00x4FpscrHigh
0xB40x4FpscrLow
0xB80x100Fpr
0x1B80x2SpinLockCount
0x1BA0x2ContextState
0x1BC0x20Ugqr
0x1DC0x4Pir
0x1E00x100Psf
0x2E00x18Coretime
0x2F80x8Starttime
0x3000x4Error
0x3040x4Attributes
0x3080x4Pmc1
0x30C0x4Pmc2
0x3100x4Pmc3
0x3140x4Pmc4
0x3180x4Mmcr0
0x31C0x4Mmcr1

CoreControl

OffsetSizeDescription
0x00x40
0x400x4BootStage
0x440x4CoreInitFunc
0x480x4CoreState
0x4C0x4
0x500x4
0x540x4IsKernelPanic
0x580x4InterruptedContext
0x5C0x4CurrentFpuContext
0x600x4CurrentCoreControl
0x640x4SysCallTableAddress
0x680x4FastCallBaseAddress
0x6C0x4NonRecoverableExceptionHandlerTableAddress
0x700x4RecoverableExceptionHandlerTableAddress
0x740x2
0x760x2
0x780x4LoadPerfMonContext
0x7C0x4CurrentSysCallAddress
0x800x4CurrentSysCallCallback
0x840x4NonRecoverableExceptionContextAddress
0x880x4RecoverableExceptionContextAddress
0x8C0x4NormalSysCalls
0x900x4FpuExceptions
0x940x4DsiExceptions
0x980x4IciExceptions
0x9C0x4
0xA00x4Ps0
0xA40x4Ps1
0xA80x8ProcessWork
0xB00x4
0xB40x4RamPid
0xB80x4Upid
0xBC0x4Mem1Address
0xC00x4InterceptedLoadContext
0xC40x4SintEnableAfterKernelExit
0xC80x4AddrConfig
0xCC0x20SysCallCallbackGpr
0xEC0x4EaDataBegin
0xF00x4EaDataEnd
0xF40x18
0x10C0x4WriteGatherDataOffset
0x1100x30ExceptionInfo
0x1400x4OverwriteGprOnExceptionExit
0x1440x28ExceptionExitGpr
0x16C0x28PostException
0x1940x4
0x1980x128RecoverableExceptionContext
0x2C00x14
0x2D80x128NonRecoverableExceptionContext

ExceptionContext

OffsetSizeDescription
0x00x8Tbr64
0x80x80Gpr
0x880x4Cr
0x8C0x4Lr
0x900x4Ctr
0x940x4Xer
0x980x4Srr0
0x9C0x4Srr1
0xA00x88

ExceptionInfo

OffsetSizeDescription
0x00x4
0x40x4
0x80x4UserStackPtr
0xC0x4ExHandler
0x100x4Msr
0x140x4Sprg0
0x180x4Dsisr
0x1C0x4Dar
0x200x4
0x240x4
0x280x4
0x2C0x4CallbackContext

PostException

OffsetSizeDescription
0x00x4OldUpid
0x40x4TargetUpid
0x80x4Exit
0xC0x4Callback
0x100x4CurrentExceptionContext
0x140x4InterruptedContext
0x180x4
0x1C0x4
0x200x4
0x240x4

NewExecCtx

OffsetSizeDescription
0x00x4InterruptedContext
0x40x4CurrentFpuContext
0x80x4
0xC0x4FastCallBaseAddress
0x100x4SintEnableAfterKernelExit
0x140x4
0x180x4
0x1C0x4Dabr
0x200x4Iabr
0x240x4EaDataBegin
0x240x4EaDataEnd
0x280x1C
0x480x4AddrConfig
0x4C0x3CPerCore

PerCore

This is a structure mapped to address 0xFFFFFFC0.

OffsetSizeDescription
0x00x18
0x180x4UserHeartBeat
0x1C0x4
0x200x4CurrentThread
0x240x4SoftIntEnabled
0x280x4SoftIntPending
0x2C0x4CurrentContext
0x300x4
0x340x4
0x380x4ThreadQueue

Processes

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:

RAMPIDDescriptionIOS Name
0Cafe OSCOS-KERNEL
1root.rpxCOS-ROOT
2???COS-02
3???COS-03
4Background appCOS-OVERLAY
5Home MenuCOS-HBM
6Error displayCOS-ERROR
7Foreground appCOS-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):

PFIDDescriptionRAMPID
0Cafe OS kernel0
1root.rpx1
2Wii U Menu7
3TVii???
4E-Manual???
5Home Menu5
6Error Display6
7"MiniMiiverse"???
8Internet Browser4
9Miiverse???
10eShop???
11COS-FLV???
12Download Manager???
13COS-RSVD-13???
14COS-RSVD-14???
15Game7

Loader

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.

Libraries

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 startVirtual address sizePhysical address startFlagsDescription
0x10000000x8000000x320000000x2CE08002Loader and system libraries
0x18000000x2000000x28101200This 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)0x2CF09400App executable and libraries (start varies, but end is always 0x10000000)
0x100000000x52000000 or 0x92000000 (variable)0x20000000 (variable)0x28305800Application/library data area (may be smaller)
0xA00000000x4000000000x2000Overlay of application memory (used by loader?)
0xE00000000x40000000x140000000x28204004Some sort of hardware communication area
0xE80000000x20000000xD00000000x78200004
0xEFE000000x800000x1B9000000x28109010Loader data area (only mapped when running loader)
0xF40000000x200000000x28204004MEM1
0xF60000000x8000000x1B0000000x3CA08002Loader chunk buffer
0xF80000000x30000000x180000000x2CA08002Read-only shared data (system fonts mostly)
0xFB0000000x8000000x1C8000000x28200002
0xFC0000000xC00000xC0000000x70100022Processor Interface
0xFC0C00000x1200000xC0C00000x70100022
0xFC1E00000x200000xC1E00000x78100024VI
0xFC2000000x800000xC2000000x78100024GFXSP
0xFC2800000x200000xC2800000x78100024DSP
0xFC2A00000x200000xC2A00000x78100023Write Gather Pipe
0xFC3000000x200000xC3000000x78100024
0xFC3200000xE00000xC3200000x70100022Espresso eFuses
0xFD0000000x4000000xD0000000x70100022Latte Registers
0xFE0000000x8000000x1C0000000x20200002
0xFF2000000x800000x1B8000000x20100040Kernel heap
0xFF2800000x800000x1B8800000x20100040
0xFFC000000x200000xFFC000000x8100004Codegen area used with OSCodegenCopy
0xFFC400000x200000xFFC400000x8100004Codegen area used with OSCodegenCopy
0xFFC800000x200000xFFC800000x810000CCodegen area used with OSCodegenCopy
0xFFCE00000x2000000x50100004
0xFFE000000x200000xFFE000000x20100040Kernel ancast image
0xFFE400000x200000xFFE400000x20100040
0xFFE800000x600000xFFE800000x20100040
0xFFEE00000x200000xFFEE00000x20100040
0xFFF000000x200000xFFF000000x20100040
0xFFF600000x200000xFFE200000x20100080
0xFFF800000x200000xFFE600000x2C100040
0xFFFA00000x200000xFFE600000x20100080
0xFFFC00000x200000x1BFE00000x24100002
0xFFFE00000x200000x1BF800000x28100102Per-thread data (e.g. pointer to thread descriptor and thread queue) at 0xFFFFFFE0 - 0xFFFFFFFC.