ucore lab1 bootloader学习笔记
---恢复内容开始---
开机流程回忆
以Intel 80386为例,计算机加电后,CPU从物理地址0xFFFFFFF0(由初始化的CS:EIP确定,此时CS和IP的值分别是0xF000和0xFFF0))开始执行。在0xFFFFFFF0这里只是存放了一条跳转指令,通过跳转指令跳到BIOS例行程序起始点。BIOS做完计算机硬件自检和初始化后,会选择一个启动设备(例如软盘、硬盘、光盘等),并且读取该设备的第一扇区(即主引导扇区或启动扇区)到内存一个特定的地址0x7c00处,然后CPU控制权会转移到那个地址继续执行。至此BIOS的初始化工作做完了,进一步的工作交给了ucore的bootloader。
简单来说,就是
加电-->CPU执行内存地址为0xFFFFFFF0的指令(一条跳转指令)--->跳到BIOS程序起始点,执行BIOS程序(功能:计算机硬件自检和初始化),自检等完成后--->选择一启动设备,并读取第一扇区(主引导扇区)到内存的0x7c00处--->BIOS所有工作完成后, CPU执行内存的0x7c00中的程序,即bootloader。
bootloader启动过程
BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中的位置执行bootloader。bootloader完成的工作包括:
- 打开A20地址线,设置CR0,切换到保护模式,启用分段机制
- 读磁盘中ELF执行文件格式的ucore操作系统到内存
- 显示字符串信息
- 把控制权交给ucore操作系统
对应其工作的实现文件在lab1中的boot目录下的三个文件asm.h、bootasm.S和bootmain.c。
代码简单分析
bootasm.S
.code16 # Assemble for -bit mode cli # Disable interrupts cld # String operations increment # Set up the important data segment registers (DS, ES, SS). xorw %ax, %ax # Segment number zero movw %ax, %ds # -> Data Segment movw %ax, %es # -> Extra Segment movw %ax, %ss # -> Stack Segment
注释:.code16表示为16位的实模式,cli表示屏蔽系统中断 6-9为清空ds , es , ss 等段寄存器内容。
# Enable A20: # For backwards compatibility with the earliest PCs, physical # address line is tied low, so that addresses higher than # 1MB wrap around to zero by default. This code undoes this. seta20.: inb $0x64, %al # input buffer empty). testb $0x2, %al movb $0xd1, %al # 0xd1 -> port 0x64 outb %al, $0x64 # 0xd1 's P2 port seta20.2: inb $0x64, %al # Wait for not busy(8042 input buffer empty). testb $0x2, %al jnz seta20.2 movb $0xdf, %al # 0xdf -> port 0x60 bit) to
注释: 参考“百度文库 激活A20地址线详解”
# Switch from real to protected mode, using a bootstrap GDT # and segment translation that makes virtual addresses # identical to physical addresses, so that the # effective memory map does not change during the switch. lgdt gdtdesc movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0
注释:通过将CR0寄存器第一位置1,开启保护模式。
# Set up the stack pointer --start(0x7c00) movl $0x0, %ebp movl $start, %esp call bootmain
注释:跳转到bootmain.c
bootmain.c
bootloader让CPU进入保护模式后,下一步的工作就是从硬盘上加载并运行OS。考虑到实现的简单性,bootloader的访问硬盘都是LBA模式的PIO(Program IO)方式,即所有的IO操作是通过CPU访问硬盘的IO地址寄存器完成。
一般主板有2个IDE通道,每个通道可以接2个IDE硬盘。访问第一个硬盘的扇区可设置IO地址寄存器0x1f0-0x1f7实现的,具体参数见下表。一般第一个IDE通道通过访问IO地址0x1f0-0x1f7来实现,第二个IDE通道通过访问0x170-0x17f实现。每个通道的主从盘的选择通过第6个IO偏移地址寄存器来设置。
表一 磁盘IO地址和对应功能
第6位:为1=LBA模式;0 = CHS模式 第7位和第5位必须为1
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端口读数据 |
当前 硬盘数据是储存到硬盘扇区中,一个扇区大小为512字节。读一个扇区的流程(可参看boot/bootmain.c中的readsect函数实现)大致如下:
- 等待磁盘准备好
- 发出读取扇区的命令
- 等待磁盘准备好
- 把磁盘扇区数据读到指定内存
/* waitdisk - wait for disk ready */ static void waitdisk(void) { 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(); // count = 1 outb(0x1F3, secno & 0xFF); outb() & 0xFF); outb() & 0xFF); outb() & 0xF) | 0xE0); outb(0x1F7, 0x20); // cmd 0x20 - read sectors // wait for disk to be ready waitdisk(); // read a sector insl(); }
---恢复内容结束---
ucore lab1 bootloader学习笔记的更多相关文章
- DSP - Bootloader学习笔记2
DSP - Bootloader学习笔记2 彭会锋 1 本文主要以F2812为例进行说明的: F28027内部资源 F28027内存映射
- DSP bootloader学习笔记1
DSP bootloader学习笔记1 彭会锋 参考: TMS320F28xx DSP中内部Flash的应用研究 http://wenku.baidu.com/view/83e9837931b765c ...
- ucore lab8 文件系统 学习笔记
最后一战果然过瘾.代码量够多,新机制够复杂度,都管饱.做这一课就像从高山上往下走,坡急且路险,还不知自己的方位,琢磨不透系统的架构.待到下了山,回头一看豁然开朗,原来方才自己所下的山是这般模样.在这里 ...
- ucore操作系统学习笔记(一) ucore lab1系统启动流程分析
一.ucore操作系统介绍 操作系统作为一个基础系统软件,对下控制硬件(cpu.内存.磁盘网卡等外设),屏蔽了底层复杂多样的硬件差异:对上则提供封装良好的应用程序接口,简化应用程序开发者的使用难度.站 ...
- ucore操作系统学习笔记(二) ucore lab2物理内存管理分析
一.lab2物理内存管理介绍 操作系统的一个主要职责是管理硬件资源,并向应用程序提供具有良好抽象的接口来使用这些资源. 而内存作为重要的计算机硬件资源,也必然需要被操作系统统一的管理.最初没有操作系统 ...
- Linux 学习笔记
Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...
- GRUB学习笔记(转自http://www.cnblogs.com/evilzy/archive/2008/03/30/1130173.html)
grub学习笔记1 首先要了解的几个概念 1.1 启动管理器 启动管理器是存储在磁盘开始扇区中的一段程序,例如,硬盘的MBR(Master Boot Record),在系统完成启动测试后,如果系统是从 ...
- jz2440-linux3.4.2-kernel移植【学习笔记】【原创】
平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山二期视频学习笔记 交叉编译工具:arm-linux-gcc (GCC)4.3.2 linux:linu3.4.2 PC环境:ubu ...
- Linux学习笔记——基于鸟哥的Linux私房菜
Linux学习笔记--基于鸟哥的Linux私房菜 ***** ARM与嵌入式linux的入门建议 (1) 学习基本的裸机编程:ARM7或ARM9,理解硬件架构和控制原理 (这一步是绝对的根基) (2) ...
随机推荐
- ERP中文档权限设置:只能浏览不能下载?如何实现
文档中心的文件夹授权只能是对岗位或者用户授权(这个跟我们的[[url=]用户及权限[/url]]下面的授权方式还不太一样)比如:要将文档中心的文件夹[公司文档]授权给用户A和用户B 授权逻辑: 软件界 ...
- 开源API测试工具 Hitchhiker v0.5更新 - 完善细节
Hitchhiker 是一款开源的支持多人协作的 Restful Api 测试工具,支持Schedule, 数据对比,压力测试,支持上传脚本定制请求,可以轻松部署到本地,和你的team成员一起管理Ap ...
- vue.js的学习中的简单案例
今天学习了近年来挺火的一门JS技术,叫vue.js下面是它的一个简单案例: <html> <head> <title>$Title$</title> / ...
- JS构造函数模式
构造函数是可以创建特定类型对象的函数,可以接受参数定义函数成员.如果之前做过java比较好理解,举个例子: function exampleFunction(arg1, arg2, arg3){ th ...
- MFC中小笔记(二)
6.有三个API函数可以运行可执行文件WinExec.ShellExecute和CreateProcess. 关于这三者的概述总结,有好几篇,自己选择. 1.CreateProcess因为使用复杂, ...
- .bash_profile 加载
1.Debian默认的shell是Bash, 1.1 命令行 和 ssh 登录 ,首先读入 /etc/profile,这是对所有用户都有效的配置:然后依次寻找下面三个文件,这是针对当前用户的配置. ~ ...
- TCP/IP协议栈 --- IP路由
IP路由:当一个IP包在主机发送出去或者在网络当中时,是怎么选择路径到达目的主机的呢? 一般情况下, 如果说源主机和目的主机在同一个网络中的话,那个数据报可以直接到达目的主机而不经过路由器,下面可以试 ...
- log4net使用注意事项
1配置Log4net Log4net的配置文件有几种使用方式,这里将配置log4net的部分独立出来,即关于log4net的配置独立成文件log4net.config. 1)写入Mysql log4n ...
- Libevent 事件循环(2)---事件被加入激活队列
由Libevent 事件循环(1) 在上文中我们提到了libevent 事件循环event_dispatch 的大致过程,以epoll为例,我们看一下事件被如何加入激活队列. //在epoll_dis ...
- SEO中TDK写法的意思以及注意事项
在SEO中,所谓的TDK其实就是title.description.keywords这三个标签,这三个标签在网站的优化过程中,至关重要所以今天童童来和大家分享下,如何去写好TDK标签! 1.title ...