commit 07a6397e8cac8687fd9926355e880455e382338d
parent f446c577058046234a369720c109eba6493fb26e
Author: Brian Swetland <swetland@frotz.net>
Date: Thu, 2 Jan 2014 17:38:57 -0800
bootblock: use multiboot header for loading instead of ELF header
This lets us boot both the 32bit and 64bit variants of Xv6
with the same boot sector.
Diffstat:
M | kernel/bootmain.c | | | 66 | ++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 file changed, 44 insertions(+), 22 deletions(-)
diff --git a/kernel/bootmain.c b/kernel/bootmain.c
@@ -2,48 +2,70 @@
//
// Part of the boot sector, along with bootasm.S, which calls bootmain().
// bootasm.S has put the processor into protected 32-bit mode.
-// bootmain() loads an ELF kernel image from the disk starting at
+// bootmain() loads a multiboot kernel image from the disk starting at
// sector 1 and then jumps to the kernel entry routine.
#include "types.h"
-#include "elf.h"
#include "x86.h"
#include "memlayout.h"
#define SECTSIZE 512
+struct mbheader {
+ uint32 magic;
+ uint32 flags;
+ uint32 checksum;
+ uint32 header_addr;
+ uint32 load_addr;
+ uint32 load_end_addr;
+ uint32 bss_end_addr;
+ uint32 entry_addr;
+};
+
void readseg(uchar*, uint, uint);
void
bootmain(void)
{
- struct elfhdr *elf;
- struct proghdr *ph, *eph;
+ struct mbheader *hdr;
void (*entry)(void);
- uchar* pa;
+ uint32 *x;
+ uint n;
+
+ x = (uint32*) 0x10000; // scratch space
+
+ // multiboot header must be in the first 8192 bytes
+ readseg((uchar*)x, 8192, 0);
+
+ for (n = 0; n < 8192/4; n++)
+ if (x[n] == 0x1BADB002)
+ if ((x[n] + x[n+1] + x[n+2]) == 0)
+ goto found_it;
+
+ // failure
+ return;
- elf = (struct elfhdr*)0x10000; // scratch space
+found_it:
+ hdr = (struct mbheader *) (x + n);
- // Read 1st page off disk
- readseg((uchar*)elf, 4096, 0);
+ if (!(hdr->flags & 0x10000))
+ return; // does not have load_* fields, cannot proceed
+ if (hdr->load_addr > hdr->header_addr)
+ return; // invalid;
+ if (hdr->load_end_addr < hdr->load_addr)
+ return; // no idea how much to load
- // Is this an ELF executable?
- if(elf->magic != ELF_MAGIC)
- return; // let bootasm.S handle error
+ readseg((uchar*) hdr->load_addr,
+ (hdr->load_end_addr - hdr->load_addr),
+ (n * 4) - (hdr->header_addr - hdr->load_addr));
- // Load each program segment (ignores ph flags).
- ph = (struct proghdr*)((uchar*)elf + elf->phoff);
- eph = ph + elf->phnum;
- for(; ph < eph; ph++){
- pa = (uchar*)ph->paddr;
- readseg(pa, ph->filesz, ph->off);
- if(ph->memsz > ph->filesz)
- stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);
- }
+ if (hdr->bss_end_addr > hdr->load_end_addr)
+ stosb((void*) hdr->load_end_addr, 0,
+ hdr->bss_end_addr - hdr->load_end_addr);
- // Call the entry point from the ELF header.
+ // Call the entry point from the multiboot header.
// Does not return!
- entry = (void(*)(void))(elf->entry);
+ entry = (void(*)(void))(hdr->entry_addr);
entry();
}