mit的操作系统由汇编语言完成初始化后,即有c语言进行载入内核,下面是过程:
1、bochs将Bootloader写到自己硬盘的第一个扇区,Bootloader将内核共514*8个字节读取到紧挨着自己的第二个扇区,首先是读取八个扇区内容到硬盘
readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);
|
这个函数专门用来读写硬盘,第一个参数是目的地址
#define ELFHDR ((struct Elf *) 0x10000)
|
第二个是读取的大小,第三个参数时内核的偏移量,很显然在这是0
PS:关于如何读取硬盘数据
void waitdisk(void)
{
// wait for disk reaady
while ((inb(0x1F7) & 0xC0) != 0x40) // in 0x1F7 0xC0 1f7端口检测硬盘状态,第七位
/* do nothing */;
}
void readsect(void *dst, uint32_t offset)
{
// wait for disk to be ready
waitdisk();
outb(0x1F2, 1); // count = 1 要读取的扇区数目,此处我们就读取一个
outb(0x1F3, offset); // 要读取的扇区编号,由上面可知从1开始,0存放的Bootloader
outb(0x1F4, offset >> 8);// 用来存放读写柱面的低 8位字节
outb(0x1F5, offset >> 16);// 用来存放读写柱面的高 2位字节(其高6位恒为0)
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); //获取数据
}
|
Channel(通道) | IRQ Used | I/O Addresses Used | Popularity and Support |
Primary | 14 | 1F0-1F7h and 3F6-3F7h | Used by all PCs using IDE/ATA |
Secondary | 15 (10) | 170-177h and 376-377h | Present on all modern PCs; usually used for an ATAPI optical drive |
Tertiary | 11 (12) | 1E8-1EFh and 3EE-3EFh | Used uncommonly, can have software support problems |
Quaternary | 10 or 11 | 168-16Fh and 36E-36Fh | Very rarely used, can have software support problems |
主板上共有两个IDE接口,每个接口上又分主、从,所以可以接4个IDE设备,这4个端口号各不同,本程序用端口1F0-1F7是主板上的第一个IDE接口上的主接口,最常用的就是这个了。
如上面图标所示,前两种通道是常用的,而上面函数说是用的接口就是
Primary通道,其端口映射的I/O地址是1F0-1F7h和376-377h,上面做了简单的解释,但是难度对我有点大,不在细究,就直接用readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);好了
2、操作系统内核被读入内存后,检测一下ELF格式是否正确,然后在根据EFL头去读取内核剩余部分,并在最后跳入ELFHDR->e_entry处开始执行,此处的地址为0x10000c,我们可以在bochs里面设置该处断点,进行调试
3、进入内核后首先是热启动
movw $0x1234,0x472 # warm boot
|
4、随后是载入新的全局描述符表(再分析),并进行一些寄存器初始化,即跳入i386_init()函数执行
阅读(1945) | 评论(2) | 转发(0) |