From a4617c29c06cdbdbb8a02af77a3d96e0f2a1b7c5 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 14 Sep 2024 16:33:54 +0800 Subject: [PATCH] Add m1n1 boot support Entry ABI: x0 = Kernel Boot args CurrentEL = Highest EL Entry point is 0x800 into the image. Link: https://github.com/asdfugil/m1n1-idevice --- src/kernel/entry.c | 32 ++++++++++++++++++++++---------- src/kernel/main_task.c | 2 ++ src/kernel/pongo.h | 2 +- src/shell/main.c | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/kernel/entry.c b/src/kernel/entry.c index 97dff272..e0c90915 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -245,6 +245,7 @@ __attribute__((noinline)) void pongo_entry_cached() { default: // >4 case BOOT_FLAG_RAW: // 4 + case BOOT_FLAG_M1N1: // 3 break; case BOOT_FLAG_HOOK: // 2 @@ -291,7 +292,7 @@ __attribute__((noinline)) void pongo_entry_cached() */ extern void set_exception_stack_core0(); extern void lowlevel_set_identity(void); -extern _Noreturn void jump_to_image_extended(uint64_t image, uint64_t args, uint64_t tramp, uint64_t original_image); +extern _Noreturn void jump_to_image_extended(uint64_t image, uint64_t args, void* tramp, uint64_t original_image); extern uint64_t gPongoSlide; _Noreturn void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)(void *boot_args, void *boot_entry_point, void *trampoline)) @@ -308,22 +309,33 @@ _Noreturn void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_e set_exception_stack_core0(); gFramebuffer = (uint32_t*)gBootArgs->Video.v_baseAddr; lowlevel_cleanup(); - if(gBootFlag == BOOT_FLAG_RAW) - { + + uint64_t pfr0 = 0; + + if (gBootFlag > BOOT_FLAG_HOOK) { // We're in EL1 here, but we might need to go back to EL3 - uint64_t pfr0; __asm__ volatile("mrs %0, id_aa64pfr0_el1" : "=r"(pfr0)); if((pfr0 & 0xf000) != 0) { __asm__ volatile("smc 0"); // elevate to EL3 } - // XXX: We should really replace loader_xfer_recv_data with something dedicated here. - jump_to_image_extended(((uint64_t)loader_xfer_recv_data) - kCacheableView + 0x800000000, (uint64_t)gBootArgs, 0, (uint64_t)gEntryPoint); } - else - { - xnu_boot(); - exit_to_el1_image(gBootArgs, gEntryPoint, (void*)((gTopOfKernelData + 0x3fffULL) & ~0x3fffULL)); + + void* boot_tramp = (void*)((gTopOfKernelData + 0x3fffULL) & ~0x3fffULL); + uint64_t entryOff = 0x800; + + switch (gBootFlag) { + case BOOT_FLAG_RAW: + boot_tramp = 0; + entryOff = 0; + case BOOT_FLAG_M1N1: + // XXX: We should really replace loader_xfer_recv_data with something dedicated here. + jump_to_image_extended(((uint64_t)loader_xfer_recv_data) - kCacheableView + 0x800000000 + entryOff, (uint64_t)gBootArgs, boot_tramp, (uint64_t)gEntryPoint); + break; + default: + xnu_boot(); + exit_to_el1_image(gBootArgs, gEntryPoint, boot_tramp); + break; } screen_puts("didn't boot?!"); while(1) diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 4787ae12..1c438449 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -38,6 +38,7 @@ void shell_main(); */ uint64_t gBootTimeTicks; +char gFWVersion[256]; void pongo_main_task() { gBootTimeTicks = get_ticks(); @@ -87,6 +88,7 @@ void pongo_main_task() { char *fwversion = dt_get_prop("/chosen", "firmware-version", NULL); iprintf("Booted by: %s\n", fwversion); + strlcpy(gFWVersion, fwversion, 256); strcpy(fwversion, "pongoOS-" PONGO_VERSION); #ifdef __clang__ iprintf("Built with: Clang %s\n", __clang_version__); diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 2089377e..d0d61508 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -110,7 +110,7 @@ extern volatile char gBootFlag; #define BOOT_FLAG_DEFAULT 0 #define BOOT_FLAG_HARD 1 #define BOOT_FLAG_HOOK 2 -// 3: Reserved +#define BOOT_FLAG_M1N1 3 #define BOOT_FLAG_RAW 4 typedef uint64_t lock; diff --git a/src/shell/main.c b/src/shell/main.c index 7c897a16..5bea0409 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -46,6 +46,21 @@ void pongo_boot_raw() { task_yield(); } +extern char gFWVersion[256]; +void pongo_boot_m1n1() { + if (!loader_xfer_recv_count) { + iprintf("please upload a raw m1n1.bin before issuing this command\n"); + return; + } + + loader_xfer_recv_count = 0; + char *fwversion = dt_get_prop("/chosen", "firmware-version", NULL); + strlcpy(fwversion, gFWVersion, 256); + + gBootFlag = BOOT_FLAG_M1N1; + task_yield(); +} + void* ramdisk_buf; uint32_t ramdisk_size; @@ -251,6 +266,7 @@ void shell_main() { command_register("ps", "lists current tasks and irq handlers", task_list); command_register("ramdisk", "loads a ramdisk for xnu", ramdisk_cmd); command_register("bootr", "boot raw image", pongo_boot_raw); + command_register("bootm", "boots m1n1", pongo_boot_m1n1); command_register("spin", "spins 1 second", pongo_spin); command_register("md8", "memory dump", md8_cmd); command_register("peek", "32bit mem read", peek_cmd);