1 // Boot loader. 2 // 3 // The BIOS loads boot sector (bootasm.S) from sector 1 of the disk 4 // into memory and executes it. The boot sector puts the processor 5 // in 32-bit mode and calls cmain below, which loads an ELF kernel 6 // image from the disk starting at sector 2 and then jumps to the 7 // kernel entry routine. 8 9 #include "types.h" 10 #include "elf.h" 11 #include "x86.h" 12 13 #define SECTSIZE 512 14 15 void readseg(uint, uint, uint); 16 17 void 18 bootmain(void) 19 { 20 struct elfhdr *elf; 21 struct proghdr *ph, *eph; 22 void (*entry)(void); 23 24 elf = (struct elfhdr*)0x10000; // scratch space 25 26 // Read 1st page off disk 27 readseg((uint)elf, SECTSIZE*8, 0); 28 29 // Is this an ELF executable? 30 if(elf->magic != ELF_MAGIC) 31 goto bad; 32 33 // Load each program segment (ignores ph flags). 34 ph = (struct proghdr*)((uchar*)elf + elf->phoff); 35 eph = ph + elf->phnum; 36 for(; ph < eph; ph++) 37 readseg(ph->va, ph->memsz, ph->offset); 38 39 // Call the entry point from the ELF header. 40 // Does not return! 41 entry = (void(*)(void))(elf->entry & 0xFFFFFF); 42 entry(); 43 44 bad: 45 outw(0x8A00, 0x8A00); 46 outw(0x8A00, 0x8E00); 47 for(;;) 48 ; 49 } 50 51 void 52 waitdisk(void) 53 { 54 // Wait for disk ready. 55 while((inb(0x1F7) & 0xC0) != 0x40) 56 ; 57 } 58 59 // Read a single sector at offset into dst. 60 void 61 readsect(void *dst, uint offset) 62 { 63 // Issue command. 64 waitdisk(); 65 outb(0x1F2, 1); // count = 1 66 outb(0x1F3, offset); 67 outb(0x1F4, offset >> 8); 68 outb(0x1F5, offset >> 16); 69 outb(0x1F6, (offset >> 24) | 0xE0); 70 outb(0x1F7, 0x20); // cmd 0x20 - read sectors 71 72 // Read data. 73 waitdisk(); 74 insl(0x1F0, dst, SECTSIZE/4); 75 } 76 77 // Read 'count' bytes at 'offset' from kernel into virtual address 'va'. 78 // Might copy more than asked. 79 void 80 readseg(uint va, uint count, uint offset) 81 { 82 uint eva; 83 84 va &= 0xFFFFFF; 85 eva = va + count; 86 87 // Round down to sector boundary. 88 va &= ~(SECTSIZE - 1); 89 90 // Translate from bytes to sectors; kernel starts at sector 1. 91 offset = (offset / SECTSIZE) + 1; 92 93 // If this is too slow, we could read lots of sectors at a time. 94 // We'd write more to memory than asked, but it doesn't matter -- 95 // we load in increasing order. 96 for(; va < eva; va += SECTSIZE, offset++) 97 readsect((uchar*)va, offset); 98 } 99