added base src
[xv6-db.git] / bootmain.c
blob7cd469fee68049d6618424c96eaa80bc403729ea
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.
8 #include "types.h"
9 #include "elf.h"
10 #include "x86.h"
12 #define SECTSIZE 512
14 void readseg(uchar*, uint, uint);
16 void
17 bootmain(void)
19 struct elfhdr *elf;
20 struct proghdr *ph, *eph;
21 void (*entry)(void);
22 uchar* va;
24 elf = (struct elfhdr*)0x10000; // scratch space
26 // Read 1st page off disk
27 readseg((uchar*)elf, 4096, 0);
29 // Is this an ELF executable?
30 if(elf->magic != ELF_MAGIC)
31 return; // let bootasm.S handle error
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 va = (uchar*)ph->va;
38 readseg(va, ph->filesz, ph->offset);
39 if(ph->memsz > ph->filesz)
40 stosb(va + ph->filesz, 0, ph->memsz - ph->filesz);
43 // Call the entry point from the ELF header.
44 // Does not return!
45 entry = (void(*)(void))(elf->entry);
46 entry();
49 void
50 waitdisk(void)
52 // Wait for disk ready.
53 while((inb(0x1F7) & 0xC0) != 0x40)
57 // Read a single sector at offset into dst.
58 void
59 readsect(void *dst, uint offset)
61 // Issue command.
62 waitdisk();
63 outb(0x1F2, 1); // count = 1
64 outb(0x1F3, offset);
65 outb(0x1F4, offset >> 8);
66 outb(0x1F5, offset >> 16);
67 outb(0x1F6, (offset >> 24) | 0xE0);
68 outb(0x1F7, 0x20); // cmd 0x20 - read sectors
70 // Read data.
71 waitdisk();
72 insl(0x1F0, dst, SECTSIZE/4);
75 // Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
76 // Might copy more than asked.
77 void
78 readseg(uchar* va, uint count, uint offset)
80 uchar* eva;
82 eva = va + count;
84 // Round down to sector boundary.
85 va -= offset % SECTSIZE;
87 // Translate from bytes to sectors; kernel starts at sector 1.
88 offset = (offset / SECTSIZE) + 1;
90 // If this is too slow, we could read lots of sectors at a time.
91 // We'd write more to memory than asked, but it doesn't matter --
92 // we load in increasing order.
93 for(; va < eva; va += SECTSIZE, offset++)
94 readsect(va, offset);