diff options
Diffstat (limited to 'kernel/loader.c')
| -rw-r--r-- | kernel/loader.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/kernel/loader.c b/kernel/loader.c new file mode 100644 index 0000000..0246628 --- /dev/null +++ b/kernel/loader.c @@ -0,0 +1,63 @@ +/* + * Загрузчик ядра в формате 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(); +} |
