ES

From WiiBrew
Jump to navigation Jump to search

ES is an IOS module responsible for title management and launching.

Devices

Startup

After initializing the /dev/es device, ES calls the get_kernel_flavor syscall; if the flavor is below 3 (only happens for boot2 which uses 0), it checks for /sys/boot.sys on the NAND and finishes the Boot2 update it is present. After this, it calls the GetBusSpeed syscall to determine whether to load MIOS or the System Menu.

When the kernel flavor is greater than or equal to 3, ES checks for /sys/launch.sys and calls ES_LaunchTitle with the info in that file. If that file is absent, newer versions of ES check for /sys/disc.sys and set the access rights accordingly.

Title launching

Titles are launched with ES_LaunchTitle, which uses a context to track launching:

struct ESLaunchContext {
	struct TIK *ticket;
	struct TMD *tmd;
	u32 status; // 0 = unable to launch, 1 = launching/launched
}

ES_LaunchTitle calls a function to initialize this struct. The function reads the system version from the TMD, and creates /sys/launch.sys with the given title ID and ticket view and recursively calls ES_LaunchTitle if the title is either 1-2 (System Menu) or anything that is not a system title, assuming /sys/launch.sys did not already exist; if /sys/launch.sys exists, the function replaces /sys/launch.sys with /sys/space.sys. If the title to be launched is an IOS, the system version is compared against the boot2 version; this could be used to require a minimum boot2 version, although Nintendo has never actually done this.

After this, ES_LaunchTitle builds the path to the main binary from the TMD content, and passes it to either ppc_boot or ios_boot (for everything between 1-3 and 1-257), and updates /sys/cc.sys if necessary.

Title import context

struct ESImportContext __attribute__((aligned(0x40))) {
	/* 0x00 */  struct TMD *tmd;
	/* 0x04 */  u32 tmdSize;
	/* 0x08 */  s32 keyhandle;
	/* 0x0C */  s32 contentFD;
	/* 0x10 */  u32 contentIndex;
	/* 0x14 */  u64 contentProgress;
	/* 0x1C */  u32 contentID;
	/* 0x20 */  IOSCHashContext ctx; // 0x60 bytes but only uses 0x1C. annoying
	/* 0x80 */  u32 contentHashDigest[5];
	/* 0xA0 */  u32 contentIV[4] __attribute__((aligned(0x20)));
	/* 0xC0 */  u8  contentBuffer[0x40] __attribute__((aligned(0x40)));
	/* 0x100 */ u32 contentBufferLen;
	/* 0x104 */ s32 ret;
	/* 0x108 */ int active;
};

ES context

struct ESContext __attribute__((aligned(0x40))) {
	/* I'm impressed at how inefficiently laid out this structure is. */
	/* 0x000 */ u16 gid;
	/* 0x004 */ u32 uid;
	/* 0x040 */ struct ESImportContext import_ctx;
	/* 0x14C */ u8 pad[0x3C]; // ?
	/* 0x180 */ s32 active;
	/* 0x184 */ u8 pad2[0x3C]; // > memset(&ES_ContextArray[i], 0, 0x1c0);
};