1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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();
}
|