3 // Part of the boot sector, along with bootasm.S, which calls bootmain().
4 // bootasm.S has put the processor into protected 32-bit mode.
5 // bootmain() loads an ELF kernel image from the disk starting at
6 // sector 1 and then jumps to the kernel entry routine.
11 #include "memlayout.h"
15 void readseg(uchar
*, uint
, uint
);
21 struct proghdr
*ph
, *eph
;
25 elf
= (struct elfhdr
*)0x10000; // scratch space
27 // Read 1st page off disk
28 readseg((uchar
*)elf
, 4096, 0);
30 // Is this an ELF executable?
31 if(elf
->magic
!= ELF_MAGIC
)
32 return; // let bootasm.S handle error
34 // Load each program segment (ignores ph flags).
35 ph
= (struct proghdr
*)((uchar
*)elf
+ elf
->phoff
);
36 eph
= ph
+ elf
->phnum
;
37 for(; ph
< eph
; ph
++){
38 pa
= (uchar
*)ph
->paddr
;
39 readseg(pa
, ph
->filesz
, ph
->off
);
40 if(ph
->memsz
> ph
->filesz
)
41 stosb(pa
+ ph
->filesz
, 0, ph
->memsz
- ph
->filesz
);
44 // Call the entry point from the ELF header.
46 entry
= (void(*)(void))(elf
->entry
);
53 // Wait for disk ready.
54 while((inb(0x1F7) & 0xC0) != 0x40)
58 // Read a single sector at offset into dst.
60 readsect(void *dst
, uint offset
)
64 outb(0x1F2, 1); // count = 1
66 outb(0x1F4, offset
>> 8);
67 outb(0x1F5, offset
>> 16);
68 outb(0x1F6, (offset
>> 24) | 0xE0);
69 outb(0x1F7, 0x20); // cmd 0x20 - read sectors
73 insl(0x1F0, dst
, SECTSIZE
/4);
76 // Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
77 // Might copy more than asked.
79 readseg(uchar
* pa
, uint count
, uint offset
)
85 // Round down to sector boundary.
86 pa
-= offset
% SECTSIZE
;
88 // Translate from bytes to sectors; kernel starts at sector 1.
89 offset
= (offset
/ SECTSIZE
) + 1;
91 // If this is too slow, we could read lots of sectors at a time.
92 // We'd write more to memory than asked, but it doesn't matter --
93 // we load in increasing order.
94 for(; pa
< epa
; pa
+= SECTSIZE
, offset
++)