Ucore------Lab1_Practice4

分析 bootloader 加载 ELF 格式的 OS 的过程。

通过阅读 bootmain.c,了解 bootloader 如何加载 ELF 文件。通过分析源代码和通过 qemu 来运行并调试 bootloader&OS

  • bootloader 如何读取硬盘扇区的?
    所有的IO操作是通过CPU访问硬盘的IO地址寄存器完成的。
IO地址功能
0x1f0读数据,当0x1f7不为忙状态时,可以读。
0x1f2要读写的扇区数,每次读写前,你需要表明你要读写几个扇区。最小是1个扇区
0x1f3如果是LBA模式,就是LBA参数的0-7位
0x1f4如果是LBA模式,就是LBA参数的8-15位
0x1f5如果是LBA模式,就是LBA参数的16-23位
0x1f6第0~3位:如果是LBA模式就是24-27位 第4位:为0主盘;为1从盘
0x1f7状态和命令寄存器。操作时先给命令,再读取,如果不是忙状态就从0x1f0端口读数据
读一个扇区的流程(boot/bootmain.c readsect函数):
  1. 等待磁盘准备好
  2. 发出读取扇区命令
  3. 等待磁盘准备好
  4. 把磁盘扇区数据读到指定内存
  • bootloader 是如何加载 ELF 格式的 OS?
    ELF文件格式是Linux系统下的一种常用目标文件格式,有三种主要类型:
    + 用于执行的可执行文件(executable file),用于提供程序的进程映像,加载的内存执行。 这也是本实验的 OS 文件类型。
    + 用于连接的可重定位文件(relocatable file),可与其它目标文件一起创建可执行文件和共享目标文件。
    + 共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件,动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。
/* readsect - read a single sector at @secno into @dst */
static void
readsect(void *dst, uint32_t secno) {
    // wait for disk to be ready
    waitdisk();

    outb(0x1F2, 1);                         // count = 1
    outb(0x1F3, secno & 0xFF);
    outb(0x1F4, (secno >> 8) & 0xFF);
    outb(0x1F5, (secno >> 16) & 0xFF);
    outb(0x1F6, ((secno >> 24) & 0xF) | 0xE0);
    outb(0x1F7, 0x20);                      // cmd 0x20 - read sectors

    // wait for disk to be ready
    waitdisk();

    // read a sector
    insl(0x1F0, dst, SECTSIZE / 4);
}

在bootmain中判断读入的扇区的数据是否位ELF文件。读取ELF的header-》判断一个成员变量是都等于一个特定的值,是的话就是一个合法的ELF文件
最后一条决定调到什么地方去,将控制权交给ucore

在这里插入图片描述
在这里插入图片描述

通过 qemu 来运行并调试 bootloader&OS:
先将程序跑起来调用GDB和Qemu
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值