《ucore lab1 练习4》实验报告

[练习4]分析bootloader加载ELF格式的OS的过程

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

  • 1.bootloader如何读取硬盘扇区的?
  • 2.bootloader是如何加载ELF格式的OS?

首先要介绍一下 对于bootloader访问硬盘时都是LBA模式的PIO方式,也就是说所有的I/O操作都是通过CPU访问硬盘的I/O地址寄存器完成。操作系统位于第一个硬盘上,而访问第一个硬盘的扇区可以设置I/O端口0x1f0~0x1f7来改变地址寄存器实现。下述表格所显示的即为0x1f0~0x1f7所对应的功能:

I/o地址 功能
0x1f0 读数据,当0x1f7不为忙状态时,可以读
0x1f1 可获得详细的错误信息
0x1f2 与读写的扇区数量,每次读写前,都需要表明要读写几个扇区
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端口读数据

问题1:bootloader如何读取硬盘扇区

分析原理

阅读材料其实已经给出了读一个扇区的大致流程:

  • 1.等待磁盘准备好
  • 2.发出读取扇区的命令
  • 3.等待磁盘准备好
  • 4.把磁盘扇区数据读到指定内存

实际操作中,需要知道怎样与硬盘交互。阅读材料中同样给出了答案:所有的IO操作是通过CPU访问硬盘的IO地址寄存器完成。硬盘共有8个IO地址寄存器,其中第1个存储数据,第8个存储状态和命令,第3个存储要读写的扇区数,第4~7个存储要读写的起始扇区的编号(共28位)。了解这些信息,就不难编程实现啦。

分析代码

bootloader读取扇区的功能是在boot/bootmain.c的readsect函数中实现的,先贴代码:

static void
waitdisk(void) {
    //如果0x1F7的最高2位是01,跳出循环
    while ((inb(0x1F7) & 0xC0) != 0x40)
        /* do nothing */;
}
/* 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);        //读取一个扇区
    outb(0x1F3, secno & 0xFF);  //要读取的扇区编号
    outb(0x1F4, (secno >> 8)&0xFF);//用来存放读写柱面的低8位字节 
    outb(0x1F5, (secno >> 16)&0xFF);
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值