MIT 6.828 main.c文件分析
2014-04-04 18:23
1231 查看
#include <inc/x86.h> #include <inc/elf.h> /*这是一个简单粗略的boot loader,它唯一的工作就是 从硬盘的第一个扇区启动格式为ELF的内核镜像 硬盘布局 这个程序(包括boot.S和main.c)组成了bootloader, 它应该存储在硬盘的第一个扇区 第二个扇区存储着内核映像 内核映像必须为ELF格式的 启动步骤 当CPU启动时,它加载BIOS到内存中并且执行BIOS BIOS程序初始化设备,设置中断例程,并且将启动装置(例如硬盘) 中的第一个扇区的内容加载到内存,并且跳转到那里 假设这个bootloader存储在硬盘的第一个扇区,这个代码从BIOS接收了CPU控制权 控制从boot.S文件开始--这个文件设置了保护模式和一个栈,这样 C代码就可以运行了,然后再调用bootmain() 这个文件中的bootmain函数接过控制权之后,读取内核文件并且跳转到内核*/ //扇区的大小为512 #define SECTSIZE 512 //将内核加载到内存的起始地址 #define ELFHDR ((struct Elf *) 0x10000) // scratch space //该函数的作用是读取一个节的内容,也就是读取一个扇区的内容 void readsect(void*, uint32_t); //函数的作用是读取一个程序段 void readseg(uint32_t, uint32_t, uint32_t); void bootmain(void) { //定义了两个程序头表项指针 struct Proghdr *ph, *eph; //将硬盘上从第一个扇区开始的4096个字节读到内存中地址为0x10000处 readseg((uint32_t) ELFHDR, SECTSIZE*8, 0); //检查这是否是一个合法的ELF文件 if (ELFHDR->e_magic != ELF_MAGIC) goto bad; //找到第一程序头表项的起始地址 ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff); //程序头表的结束位置 eph = ph + ELFHDR->e_phnum; //将内核加载进入内存 for (; ph < eph; ph++) //p_pa就是该程序段应该加载到内存中的位置 //读取一个程序段的数据到内存中 readseg(ph->p_pa, ph->p_memsz, ph->p_offset); //开始执行内核 ((void (*)(void)) (ELFHDR->e_entry))(); bad: outw(0x8A00, 0x8A00); outw(0x8A00, 0x8E00); while (1) /* do nothing */; } //这个函数的作用是从ELF文件偏移为offset处,读取count个字节到内存地址为pa处 void readseg(uint32_t pa, uint32_t count, uint32_t offset) { //段的结束地址 uint32_t end_pa; //计算段的结束地址 end_pa = pa + count; //将pa设置为512字节对齐的地方 pa &= ~(SECTSIZE - 1); //将相对于ELF文件头的偏移量转换为扇区,ELF格式的内核文件存放在第一个扇区中 offset = (offset / SECTSIZE) + 1; //开始读取该程序段的内容 while (pa < end_pa) { //每次读取程序的一个节,即一个扇区 //也就是将offset扇区中的内容,读到物理地址为pa的地方 readsect((uint8_t*) pa, offset); //将pa的值增加512字节 pa += SECTSIZE; //读取下一个扇区 offset++; } } void waitdisk(void) { // wait for disk reaady while ((inb(0x1F7) & 0xC0) != 0x40) /* do nothing */; } void readsect(void *dst, uint32_t offset) { // wait for disk to be ready waitdisk(); outb(0x1F2, 1); // count = 1 outb(0x1F3, offset); outb(0x1F4, offset >> 8); outb(0x1F5, offset >> 16); outb(0x1F6, (offset >> 24) | 0xE0); outb(0x1F7, 0x20); // cmd 0x20 - read sectors // wait for disk to be ready waitdisk(); // read a sector insl(0x1F0, dst, SECTSIZE/4); }
相关文章推荐
- MIT6.828 boot.S文件分析
- Yii框架配置文件main.php分析
- Yii框架配置文件main.php分析
- Tor源码文件分析 -- Main
- MIT 6.828 学习笔记2 阅读main.c
- iOS系统Crash文件分析方法
- php笔记之:有规律大文件的读取与写入的分析
- JS 文件传参及处理技巧分析(转)
- iphone/ipad crash文件分析方法
- mpegts.c文件分析
- C# 窗口项目中文件架构分析(一)
- 客户端自动升级、文件更新功能分析一
- python读写ini配置文件方法实例分析
- 学习Android从0开始之基础篇(2)-AndroidMainfest.xml文件详解
- 用JSP分析multipart/form-data基于表单的文件上传
- 【转】PNG文件结构分析(下:在手机上生成PNG文件)
- (转载) Linux下 /proc/maps 文件分析
- Nginx(3)-nginx配置文件详解-nginx主配置段分析
- C++类模板 .h和.cpp文件要写在一起||要在主函数main中用#include "Test.h" Test是模板类名
- 区块链教程open-ethereum-pool矿池源码分析main入口