babyos2(2)—— load elf format kernel

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

#define ELF_MAGIC 0x464c457FU   // "\x7FELF"

// File header
typedef 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 header
typedef 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.o

loader: 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格式的内核被解析并加载到指定的位置,然后跳转过去开始执行内核代码。

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值