IOS/Kernel: Difference between revisions

From WiiBrew
< IOS
Jump to navigation Jump to search
Hallowizer (talk | contribs)
Threads: this part of the kernel seems to be based on the DS
Hallowizer (talk | contribs)
Message queues: added an event handlers subsection
Line 60: Line 60:
u32 messageCapacity; // 0x14
u32 messageCapacity; // 0x14
void *ptr; // 0x18
void *ptr; // 0x18
}
</pre>
=== Event handlers ===
The IRQ vector is responsible for sending event handler messages. This is done directly (not with <code>IOS_SendMessage</code>).
<pre>
struct IOS_EventHandler {
IOS_MessageQueue *mq;
u32 msg;
u32 pid;
u32 unknown;
}
}
</pre>
</pre>

Revision as of 03:42, 10 July 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

The thread system appears to be based on the DS thread system, but with round-robin scheduling due to the size of IOS. IOS uses the IOS_Thread 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
	struct IOS_ThreadQueue joinQueue; // 0x60
	struct IOS_ThreadQueue *queue; // 0x64
	struct IOS_Context immediateCtx; // 0x68
	void *defaultStackLocation ; // 0xAC
}

struct IOS_ThreadQueue {
	struct IOS_Thread *head;
}

Thread queues in IOS are circular; the scheduler simply rotates the active queue when rescheduling. Each thread is inserted before the first thread with a lower priority, which works for IOS_CreateThread due to it only allowing a lower priority than the current thread, but IOS_SetThreadPriority allows the priority to be increased (but not past the initial priority), causing threads to be shuffled.

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 waitForSend; // 0x0
	IOS_ThreadQueue waitForReceive; // 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
}

Event handlers

The IRQ vector is responsible for sending event handler messages. This is done directly (not with IOS_SendMessage).

struct IOS_EventHandler {
	IOS_MessageQueue *mq;
	u32 msg;
	u32 pid;
	u32 unknown;
}

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;
	bool allowPpcAccess; // only exists in IOS28 and above
}

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;
}