5 /**********************************************************************
6 * This a dirt simple boot loader, whose sole job is to boot
7 * an elf kernel image from the first IDE hard disk.
10 * * This program(boot.S and main.c) is the bootloader. It should
11 * be stored in the first sector of the disk.
13 * * The 2nd sector onward holds the kernel image.
15 * * The kernel image must be in ELF format.
18 * * when the CPU boots it loads the BIOS into memory and executes it
20 * * the BIOS intializes devices, sets of the interrupt routines, and
21 * reads the first sector of the boot device(e.g., hard-drive)
22 * into memory and jumps to it.
24 * * Assuming this boot loader is stored in the first sector of the
25 * hard-drive, this code takes over...
27 * * control starts in bootloader.S -- which sets up protected mode,
28 * and a stack so C code then run, then calls cmain()
30 * * cmain() in this file takes over, reads in the kernel and jumps to it.
31 **********************************************************************/
33 #define SECTOR_SIZE 512
35 static u_char
*sect
= (u_char
*)0x10000; // scratch space
37 void readsect(u_char
*, u_int
, u_int
);
38 void readseg(u_int
, u_int
, u_int
);
47 // read 1st page off disk
50 if(*(u_int
*)sect
!= 0x464C457F) // \x7F ELF in little endian
53 // look at ELF header - ignores ph flags
54 elf
= (struct Elf
*)sect
;
56 ph
= (struct Proghdr
*)(sect
+elf
->e_phoff
);
57 for(i
=0; i
<elf
->e_phnum
; i
++, ph
++)
58 readseg(ph
->p_va
, ph
->p_memsz
, ph
->p_offset
);
61 ((void(*)(void))entry
)();
71 // read count bytes at offset from kernel into addr dst
72 // might copy more than asked
74 readseg(u_int va
, u_int count
, u_int offset
)
80 // round down to sector boundary; offset will round later
85 // translate from bytes to sectors
87 count
= (count
+511)/512;
89 // kernel starts at sector 1
92 // if this is too slow, we could read lots of sectors at a time.
93 // we'd write more to memory than asked, but it doesn't matter --
94 // we load in increasing order.
95 for(i
=0; i
<count
; i
++){
96 readsect((u_char
*)va
, 1, offset
+i
);
104 while(inb(0x1F7) & 0x80); // wait for disk not busy
108 readsect(u_char
*dst
, u_int count
, u_int offset
)
114 outb(0x1F4, offset
>>8);
115 outb(0x1F5, offset
>>16);
116 outb(0x1F6, (offset
>>24)|0xE0);
117 outb(0x1F7, 0x20); // cmd 0x20 - read sectors
121 insl(0x1F0, dst
, count
*512/4);