IOS/Kernel: Difference between revisions

From WiiBrew
< IOS
Jump to navigation Jump to search
Hallowizer (talk | contribs)
Message queues: identified the unknown field
Hallowizer (talk | contribs)
Message queues: added names for the thread queues
Line 49: Line 49:
<pre>
<pre>
struct IOS_MessageQueue {
struct IOS_MessageQueue {
IOS_ThreadQueue threadQueue; // 0x0
IOS_ThreadQueue waitSendThreadQueue; // 0x0
IOS_ThreadQueue threadQueue2; // 0x4 - unknown purpose
IOS_ThreadQueue waitReceiveThreadQueue; // 0x4
u32 processId; // 0x8
u32 processId; // 0x8
u32 messagesEnqueued; // 0xC
u32 messagesEnqueued; // 0xC

Revision as of 01:27, 6 June 2022

The IOS kernel is responsible for dispatching interrupts to processes, handling syscalls, and running the IOSP threads. It is independent of the Wii's specific architecture, as Wii-specific functions such as high-level title launching are provided by ES.

Threads

IOS uses this struct to keep track of a thread.

struct IOS_Context {
	u32 psr; // 0x0
	u32 r0; // 0x4
	u32 r1; // 0x8
	u32 r2; // 0xC
	u32 r3; // 0x10
	u32 r4; // 0x14
	u32 r5; // 0x18
	u32 r6; // 0x1C
	u32 r7; // 0x20
	u32 r8; // 0x24
	u32 r9; // 0x28
	u32 r10; // 0x2C
	u32 r11; // 0x30
	u32 r12; // 0x34
	void *sp; // 0x38
	void *lr; // 0x3C
	void *pc; // 0x40
}

struct IOS_Thread {
	struct IOS_Context persistentCtx; // 0x0
	struct IOS_Thread *next; // 0x44
	s32 initialPriority; // 0x48
	s32 priority; // 0x4C
	u32 state; // 0x50 - 0 for a destroyed/uncreated thread, 1 for a thread that is queued to start, 2 for an active thread, 3 for a thread that has not been started, 4 for a blocked thread
	u32 processId; // 0x54
	bool detached; // 0x58
	u32 result; // 0x5C
	IOS_ThreadQueue joinQueue; // 0x60
	IOS_ThreadQueue *queue; // 0x64
	struct IOS_Context immediateCtx; // 0x68
	void *syscallStack; // 0xAC
}

Note that IOS_ThreadQueue is just a pointer to an IOS_Thread.

Unlike in Revolution OS, where the initial thread is created over the current code with __OSThreadInit, the first IOS thread (IOSP) is created by the reset vector, launching new code with the standard IOS_CreateThread function.

Message queues

Message queue IDs are allocated globally. A total of 255 message queues can be created.

struct IOS_MessageQueue {
	IOS_ThreadQueue waitSendThreadQueue; // 0x0
	IOS_ThreadQueue waitReceiveThreadQueue; // 0x4
	u32 processId; // 0x8
	u32 messagesEnqueued; // 0xC
	u32 rotation; // 0x10 - first message is at index rotation, last message is at index rotation-1
	u32 messageCapacity; // 0x14
	void *ptr; // 0x18
}

Memory allocation

Memory allocation is similar to in the IPC library, although the IOS kernel supports 16 heaps instead of 8.

struct HeapBlockHeader {
	u16 magic; // 0xbabe
	u16 status; // 0 = free, 1 = allocated, 2 = aligned alias for header
	u32 size;
	struct HeapBlockHeader *prev; // depends on status; status 0 has the previous free block, status 1 has NULL, status 2 has the main block
	struct HeapBlockHeader *next; // NULL for anything besides status 0
}

struct Heap {
	void *base;
	u32 owner; // pid of owning process
	u32 size;
	struct HeapBlockHeader *freeList;
}

When writing an aligned copy of a block, IOS does not check if it overlaps the existing copy; this could potentially be exploited.

IPC

Resource managers are the backends to the devices that can be opened with IOS_Open. The file descriptors returned by IOS_Open are mapped to internal file descriptors generated by the resource manager.

struct IOS_ResourceManager {
	char path[0x40];
	u32 pathLen;
	struct IOS_MessageQueue *messageQueue;
	u32 processId;
}

struct IOS_FileDescriptor {
	u32 internalFd;
	struct IOS_ResourceManager *resourceManager;
}

struct RequestWrapper {
	struct IOSRequest request;
	struct IOS_MessageQueue callbackQueue;
	struct IOSRequest *replyBuf;
	u32 owningThread; // shared pool only
	bool allocated; // shared pool only
	u32 resourceManagerPid;
}