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) ...
随机推荐
- csv格式订单下载,完成后伴随邮件通知下载
前言 功能开发中会遇到大量订单下载,而服务器的请求响应时间又配置的很短,导致下载时候请求超时. 这篇文章主要思路:异步查询数据,生成csv文件,放入email中并发送给用户.(异步部分本文不做介绍,配 ...
- Less 的使用方法
Less 的使用方法 Less 可以直接在浏览器端运行(支持IE6+.Webkit.Firefox),也可以借助Node.js或者Rhino在服务端运行. Less是一种动态语言,无论是在浏览器端,还 ...
- Error when sending message to topic test with key: null, value: 2 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
windows下使用kafka遇到这个问题: Error when sending message to topic test with key: null, value: 2 bytes with ...
- iscroll遇到的两个坑
最近移动端闪付遇到的两个坑做下总结: 1.使用iscroll后,滑动并没有生效 解决方案: 首先要查看:结构是否正确: <div id="wrapper"> //w ...
- Sonar常见问题分析
1.Equality tests should not be made with floating point value 代码举例: if (result == num) //result和num均 ...
- PHP基础知识点
//语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. /* [命名规则] */常量名 类常量建议全大写,单词间用下划线分隔 // MIN_WIDTH变量名建议用 ...
- PostgreSQL索引描述
索引方式:唯一索引,主键索引,多属性索引,部分索引,表达式索引. 索引类型:B-Tree,Hash,GiST,GIN以及表达式索引 PostgreSQL所有索引都是“从属索引”,也就是说,索引在物理上 ...
- 过渡与动画 - steps调速函数&CSS值与单位之ch
写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...
- 利用KindEditor实现公司通讯录的维护
引言: 本人所属施工单位,在建项目较多,通讯录是以项目为单位挂接在公司内部网站通讯录板块,以静态页面展示.一直以来都是项目部办公室通过电话.邮件等方式通知总部信息部门变更通讯录,日常维护的工作量较大. ...
- Django中多表查询思路
需求: 1.有一张文章表和一张评论表 2.两张表的关系是一对多 3.规则:若是有新评论,则将对应的文章置顶,若是有新文章则将新文章置顶. 思路: 在文章表中增加一个最后评论时间的字段.然后采用分组排序 ...