ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

main.C

2021-11-09 12:02:55  阅读:163  来源: 互联网

标签:void 扇区 pa offset ph main uint32


  1 #include <inc/x86.h>
  2 #include <inc/elf.h>
  3 
  4 /**********************************************************************
  5  * 这是一个非常简单的引导加载程序,它的唯一任务是从第一个IDE硬盘引导ELF内核映像。
  6  *
  7  * 磁盘布局
  8  *  * 引导加载程序由boot.S和main.C组成,这两个文件应该储存在磁盘的第一个扇区。
  9  *
 10  *  * 第二个扇区是内核映像(kernel image)。
 11  *
 12  *  * kernel image 必须是ELF格式。
 13  *
 14  * 启动步骤
 15  *  * 计算机启动时,CPU将BIOS加载到内存中并执行它。
 16  *
 17  *  * BIOS初始化设备,初始化中断,将启动设备(磁盘或者CD)的第一个扇区(包含boot.S和main.C)读取进内存,
 18  *    并跳转执行。
 19  *
 20  *  * 首先执行的是boot.S,boot.S启动了保护模式,并且设置了一个堆栈(使得C代码可以运行),
 21  *    然后调用了本文件也就是main.C中的bootmain函数。
 22  *
 23  *  *之后由本文件的bootmain()接管,主要功能是读入内核并跳转到它。
 24  *
 25  **********************************************************************/
 26 
 27 //扇区的大小为512
 28 #define SECTSIZE    512
 29 //将内核加载到内存的起始地址
 30 #define ELFHDR        ((struct Elf *) 0x10000) // scratch space
 31 
 32 //该函数的作用是读取一个节的内容,也就是读取一个扇区的内容
 33 void readsect(void*, uint32_t);
 34 //函数的作用是读取一个程序段
 35 void readseg(uint32_t, uint32_t, uint32_t);
 36 
 37 void
 38 bootmain(void)
 39 {
 40     //定义了两个程序头表项指针
 41     struct Proghdr *ph, *eph;
 42 
 43     //将硬盘上从第一个扇区开始的4096个字节读到内存中地址为0x10000处
 44     readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);
 45 
 46     //检查这是否是一个合法的ELF文件
 47     if (ELFHDR->e_magic != ELF_MAGIC)
 48         goto bad;
 49 
 50     //找到第一程序头表项的起始地址
 51     ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff);
 52     //程序头表的结束位置
 53     eph = ph + ELFHDR->e_phnum;
 54 
 55     //将内核加载进入内存
 56     for (; ph < eph; ph++)
 57         //p_pa就是该程序段应该加载到内存中的位置
 58         //读取一个程序段的数据到内存中
 59         readseg(ph->p_pa, ph->p_memsz, ph->p_offset);
 60 
 61     //开始执行内核
 62     ((void (*)(void)) (ELFHDR->e_entry))();
 63 
 64 bad:
 65     outw(0x8A00, 0x8A00);
 66     outw(0x8A00, 0x8E00);
 67     while (1)
 68         /* do nothing */;
 69 }
 70 
 71 //这个函数的作用是从ELF文件偏移为offset处,读取count个字节到内存地址为pa处
 72 void
 73 readseg(uint32_t pa, uint32_t count, uint32_t offset)
 74 {
 75     //段的结束地址
 76     uint32_t end_pa;
 77 
 78     //计算段的结束地址
 79     end_pa = pa + count;
 80 
 81     //将pa设置为512字节对齐的地方
 82     pa &= ~(SECTSIZE - 1);
 83 
 84     //将相对于ELF文件头的偏移量转换为扇区,ELF格式的内核文件存放在第一个扇区中
 85     offset = (offset / SECTSIZE) + 1;
 86 
 87     //开始读取该程序段的内容
 88     while (pa < end_pa) {
 89         //每次读取程序的一个节,即一个扇区
 90         //也就是将offset扇区中的内容,读到物理地址为pa的地方
 91         readsect((uint8_t*) pa, offset);
 92         //将pa的值增加512字节
 93         pa += SECTSIZE;
 94         //读取下一个扇区
 95         offset++;
 96     }
 97 }
 98 
 99 void
100 waitdisk(void)
101 {
102     // wait for disk reaady
103     while ((inb(0x1F7) & 0xC0) != 0x40)
104         /* do nothing */;
105 }
106 
107 void
108 readsect(void *dst, uint32_t offset)
109 {
110     // wait for disk to be ready
111     waitdisk();
112 
113     outb(0x1F2, 1);        // count = 1
114     outb(0x1F3, offset);
115     outb(0x1F4, offset >> 8);
116     outb(0x1F5, offset >> 16);
117     outb(0x1F6, (offset >> 24) | 0xE0);
118     outb(0x1F7, 0x20);    // cmd 0x20 - read sectors
119 
120     // wait for disk to be ready
121     waitdisk();
122 
123     // read a sector
124     insl(0x1F0, dst, SECTSIZE/4);
125 }

 

标签:void,扇区,pa,offset,ph,main,uint32
来源: https://www.cnblogs.com/pilBolog/p/15528149.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有