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