root/bootmain.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. bootmain
  2. waitdisk
  3. readsect
  4. readseg

   1 // Boot loader.
   2 //
   3 // Part of the boot block, 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 #include "memlayout.h"
  12 
  13 #define SECTSIZE  512
  14 
  15 void readseg(uchar*, uint, uint);
  16 
  17 void
  18 bootmain(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  19 {
  20   struct elfhdr *elf;
  21   struct proghdr *ph, *eph;
  22   void (*entry)(void);
  23   uchar* pa;
  24 
  25   elf = (struct elfhdr*)0x10000;  // scratch space
  26 
  27   // Read 1st page off disk
  28   readseg((uchar*)elf, 4096, 0);
  29 
  30   // Is this an ELF executable?
  31   if(elf->magic != ELF_MAGIC)
  32     return;  // let bootasm.S handle error
  33 
  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);
  42   }
  43 
  44   // Call the entry point from the ELF header.
  45   // Does not return!
  46   entry = (void(*)(void))(elf->entry);
  47   entry();
  48 }
  49 
  50 void
  51 waitdisk(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  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)
     /* [previous][next][first][last][top][bottom][index][help]  */
  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 physical address 'pa'.
  77 // Might copy more than asked.
  78 void
  79 readseg(uchar* pa, uint count, uint offset)
     /* [previous][next][first][last][top][bottom][index][help]  */
  80 {
  81   uchar* epa;
  82 
  83   epa = pa + count;
  84 
  85   // Round down to sector boundary.
  86   pa -= offset % SECTSIZE;
  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(; pa < epa; pa += SECTSIZE, offset++)
  95     readsect(pa, offset);
  96 }

/* [previous][next][first][last][top][bottom][index][help]  */