/* * Загрузчик ядра в формате Plan9 a.out (386, I_MAGIC). * Чистый C без хедеров: собирается и нашим 8c (часть a.out-тулчейна), * и хостовым gcc (тест разбора заголовка). "Выхлоп у нас в а.аут" — * поэтому разбираем именно Plan9 a.out, а не ELF. */ typedef unsigned int u32; /* 4 байта и на 386, и на x86_64 */ typedef unsigned char u8; typedef struct Exec { u32 magic, text, data, bss, syms, entry, spsz, pcsz; } Exec; #define I_MAGIC 0x1EB /* intel 386 = _MAGIC(0,11) */ #define HDRSZ 32 /* 8 x 4 байта, big-endian */ 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]; } /* разбор заголовка. 0 = ок (это наш 386 a.out), заполняет e. */ int aout_parse(u8 *img, Exec *e) { e->magic = be32(img+0); e->text = be32(img+4); e->data = be32(img+8); e->bss = be32(img+12); e->syms = be32(img+16); e->entry= be32(img+20); e->spsz = be32(img+24); e->pcsz = be32(img+28); return e->magic == I_MAGIC ? 0 : -1; } /* загрузить сегменты [text][data] по адресу линковки и обнулить bss; * вернуть адрес входа. freestanding — пишет по абсолютному адресу. */ void * aout_load(u8 *img) { Exec e; u8 *src, *dst; u32 i; if(aout_parse(img, &e) < 0) return (void*)0; src = img + HDRSZ; /* сегменты идут сразу за заголовком */ dst = (u8*)e.entry; /* грузим по entry (= -T линкера) */ for(i = 0; i < e.text + e.data; i++) dst[i] = src[i]; for(i = 0; i < e.bss; i++) dst[e.text + e.data + i] = 0; return (void*)e.entry; } /* точка входа загрузчика: грузит ядро и прыгает в него (назад не вернётся). */ void bootkernel(u8 *kern) { void (*entry)(void); entry = (void(*)(void))aout_load(kern); if(entry) entry(); }