Chinaunix首页 | 论坛 | 博客
  • 博客访问: 267947
  • 博文数量: 45
  • 博客积分: 1618
  • 博客等级: 上尉
  • 技术积分: 530
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-11 10:13
文章分类

全部博文(45)

文章存档

2012年(1)

2011年(25)

2010年(19)

我的朋友

分类:

2010-10-24 18:40:04

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) |
给主人留下些什么吧!~~

mpandar2011-10-17 15:01:49

zaole: #define ELFHDR ((struct Elf *) 0x10000),帅哥,能解释那个地址0x1000的含义吗???.....
很久以前弄的了,现在也不太确定,这个地址适合内存布局有关系的,一般情况下内核存放的地址就为0x10000,你可以详细看一下内存布局相关的文章,我当时找到过一篇,但是现在忘记名字叫什么了

zaole2011-09-21 23:58:26

#define ELFHDR ((struct Elf *) 0x10000),帅哥,能解释那个地址0x1000的含义吗???