babyos2(2)—— load elf format kernel

来源:互联网 发布:网络报警主机 编辑:程序博客网 时间:2024/06/05 20:23

为了能用qemu进行C代码级别的调试,babyos2不同于babyos,babyos采用的是纯二进制格式,babyos2的kernel是elf格式。

#define ELF_MAGIC 0x464c457FU   // "\x7FELF"// File headertypedef struct elf_hdr_s {    uint32 magic;  // must equal ELF_MAGIC    uint8  elf[12];    uint16 type;    uint16 machine;    uint32 version;    uint32 entry;    uint32 phoff;    uint32 shoff;    uint32 flags;    uint16 ehsize;    uint16 phentsize;    uint16 phnum;    uint16 shentsize;    uint16 shnum;    uint16 shstrndx;} elf_hdr_t;// Program section headertypedef struct prog_hdr_s {    uint32 type;    uint32 off;    uint32 vaddr;    uint32 paddr;    uint32 filesz;    uint32 memsz;    uint32 flags;    uint32 align;} prog_hdr_t;

主要参考了xv6相关的代码,但不同于xv6,xv6是根据elf格式一步一步地通过读扇区加载elf格式内核,babyos2是boot中将内核所有数据加载到一个临时位置,然后从内核加载elf格式到elf中各个section指定的加载位置。

extern "C" void loadmain(void){    elf_hdr_t *elf = (elf_hdr_t *) (ELF_BASE_ADDR);    uint8 *base = (uint8 *) elf;    // check if it's a valid elf file    if (elf->magic != ELF_MAGIC) {        return;    }    // load program segments    prog_hdr_t *ph = (prog_hdr_t *)(base + elf->phoff);    prog_hdr_t *end_ph = ph + elf->phnum;    for (; ph < end_ph; ph++) {        uint8 *pa = (uint8 *)ph->paddr;        //memcpy(pa, base + ph->off, ph->filesz);        movsb(pa, base + ph->off, ph->filesz);        if (ph->memsz > ph->filesz) {            stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);        }    }    // find entry from elf, and call    void (*entry)(void) = (void(*)(void))(elf->entry);    entry();}

首先检测magic,是不是一个正确的elf格式文件,
然后依次读取各个program segment,并拷贝到prog_hdr指定的加载位置,因为这时未开启分页,所以加载地址是根据内核代码段的基地址+偏移,babyos2采用flat内存模式,各个段基地址都是0,所以这里逻辑地址=物理地址。
加载完成后,跳转到elf->entry去执行。

Makefile:

boot: boot.S    ${CPP} ${CFLAGS} -c boot.S    ${LD} ${LDFLAGS} --oformat binary -N -Ttext 0x7c00 -o boot boot.oloader: load.S loadmain.cc    ${CPP} ${CFLAGS} -c load.S    ${CPP} ${CFLAGS} -O -c loadmain.cc    ${LD} --oformat binary -N -Ttext 0x0000 -o loader load.o loadmain.o

到此为止,boot loader的使命完成,elf格式的内核被解析并加载到指定的位置,然后跳转过去开始执行内核代码。

内核代码的加载位置及功能,后续再描述。

原创粉丝点击