diff options
| author | claude <[email protected]> | 2026-07-12 10:27:24 +0000 |
|---|---|---|
| committer | claude <[email protected]> | 2026-07-12 10:27:24 +0000 |
| commit | 3caf5e9682807b9579938431cca4446d7efcf615 (patch) | |
| tree | 119845f998ad6dbf36cc486bad7f2bb646660c7b /efi-kernel/efi_load.c | |
| parent | c480e76433f9bb8ce8ce9d5802cdada8883db184 (diff) | |
| download | plan9-kencc-linux-3caf5e9682807b9579938431cca4446d7efcf615.tar.gz plan9-kencc-linux-3caf5e9682807b9579938431cca4446d7efcf615.zip | |
По уточнению @lzcnt (нужен EFI-загрузчик, не a.out-парсер, и amd64-ядро):
- kernel.c + kern64.s -> 6c/6a/6l -> amd64 Plan9 a.out (S_MAGIC 0x8A97, entry 0x100000),
kmain пишет строку в VGA 0xB8000.
- efi_load.c -> PE32+ bootx64.efi (через pe64.s из 9legacy + dd skip=40): под UEFI
печатает через ConOut, разбирает встроенный a.out (big-endian 40-байтный заголовок),
копирует сегменты по entry, прыгает в ядро (long mode).
- Проверено: валидный PE32+ x64 EFI_APPLICATION, ядро встроено и парсится, ESP собран.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Diffstat (limited to 'efi-kernel/efi_load.c')
| -rw-r--r-- | efi-kernel/efi_load.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/efi-kernel/efi_load.c b/efi-kernel/efi_load.c new file mode 100644 index 0000000..24539ae --- /dev/null +++ b/efi-kernel/efi_load.c @@ -0,0 +1,65 @@ +/* + * EFI-загрузчик amd64-ядра (Plan9 a.out) для UEFI. Сам — PE32+ (bootx64.efi). + * Печатает статус через UEFI ConOut, разбирает встроенное ядро (a.out, S_MAGIC), + * копирует сегменты по адресу линковки и прыгает в него (long mode). Ядро пишет 0xB8000. + */ +#include <u.h> +#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(;;); +} |
