/* * EFI-загрузчик amd64-ядра (Plan9 a.out) для UEFI. Сам — PE32+ (bootx64.efi). * Печатает статус через UEFI ConOut, разбирает встроенное ядро (a.out, S_MAGIC), * копирует сегменты по адресу линковки и прыгает в него (long mode). Ядро пишет 0xB8000. */ #include #include "efi.h" #include "kernel_blob.h" EFI_HANDLE IH; EFI_SYSTEM_TABLE *ST; extern uintptr eficall(void *fn, ...); typedef unsigned int u32; typedef unsigned char u8; static void eputs(char *s) /* ASCII -> UTF-16 -> ConOut */ { CHAR16 w[2]; w[1] = 0; for(; *s; s++){ if(*s == '\n'){ w[0] = '\r'; eficall(ST->ConOut->OutputString, ST->ConOut, w); } w[0] = (uchar)*s; eficall(ST->ConOut->OutputString, ST->ConOut, w); } } static u32 be32(u8 *p) /* заголовок Plan9 a.out — big-endian */ { return ((u32)p[0]<<24) | ((u32)p[1]<<16) | ((u32)p[2]<<8) | (u32)p[3]; } void efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) { u8 *k, *src, *dst; u32 magic, text, data, bss, entry, i; void (*kentry)(void); IH = ih; ST = st; eputs("\nPlan9 EFI loader (amd64)\n"); eputs("parsing embedded a.out kernel...\n"); k = kernel_blob; magic = be32(k + 0); /* S_MAGIC(amd64) = 0x8A97 */ if(magic != 0x8A97){ eputs("bad magic, halt\n"); for(;;); } text = be32(k + 4); data = be32(k + 8); bss = be32(k + 12); entry = be32(k + 36); /* 64-бит entry (мл. слово) на off 32; = 0x100000 */ src = k + 40; /* сегменты идут за 40-байтным заголовком */ dst = (u8*)(uintptr)entry; /* грузим по адресу линковки (-T) */ for(i = 0; i < text + data; i++) dst[i] = src[i]; for(i = 0; i < bss; i++) dst[text + data + i] = 0; eputs("kernel loaded @0x100000, jumping...\n"); kentry = (void(*)(void))(uintptr)entry; kentry(); /* -> ядро пишет 0xB8000, назад не вернётся */ for(;;); }