xv6的bootloader之bootmain.c

原创 2011年01月24日 14:52:00

xv6 系统中的bootloader 程序的组成之一是bootmain.c部分的功能:

加载硬盘的kernel部分到内存中;

#include"type.h"

#incude"xv6.h"

#include"elf.h"

#define SECTSIZE 512

void readseg(uint ,uint,uint);

 

 void bootmain(void)

{

struct elfhdr *elf, proghdr *ph,*eph;

int elf ,i;

void (*entry)(void);

//Back in boot sector ,   what should  be an ELF binary header has been loaded into memory at address 0x10000.

elf=(struct elfhdr*)0x10000;

The next step is to check the first 4 bytes of header ,the so-called magic number ,are the bytes 0x7F,'E','L',"F",or

ELF_MAGIC.

if(elf->magic!=ELF_MAGIC)

goto bad;

//ALL ELF binary headers are required to begin with this magic number as identication;if the ELF header has 

right magic number ,the boot sector assume that the binary is well-formed;There are many other sanity check that

a proper ELF loader would do;as we will see in Chapter 9;

readseg((uint)elf,SECTSIZE*8,0);

ph=(struct proghdr*)((uchar *)elf +elf->phoff);

 

eph=ph+elf->phnum;

for(;ph<eph;ph++)

{

readseg(struct *ph&0xFFFFFF ,ph->memsz,ph->offset);

entry =(void (*)(void))(elf->entry&0xffffff);

entry();

bad:
  crt[pos++] = ('E'&0xff) | 0x0700;  // black on white
  outw(0x8A00, 0x8A00);
  outw(0x8A00, 0x8E00);

 for(;;)

;

 

}

//

void waitdisk(void)

{

while((inb(0x1f7)&0xc0)!=0x40)

;

}

//Readsect read a single disk sector .it is our first example of a device  drive  ,albeit a tiny one ,Readsect  begins by calling

waitdisk to wait until the disk signals that it is ready to accept a command .the disk does so by setting the top two bits

of its status byte (connected to input port 0x1f7 )to 01 .waitdisk reads the status byte until the bits are set that way .

chapter 6 will examine more effiient ways to wait for hardware status changes ,but busy waiting like this is fine for the

boot sector;

  once the disk is ready ,readsect issues a read command .it first write command argument -sector count and the sector

number(offset) to the disk register on output ports 0x1f2-0x1f6 .The bits 0xe0 in the write to port 0x1f6 signals to the disk

that 0x1f3~0x1f6  contain a sector number  (so-called linear block address )in contrast to a more complicated cylinder/head/

sector address  used in early PC disk .After writing the arguments ,readsect writes to the command register to trigger the read .The command 0x20 is "read sectors ",Now the disk will read data stored in the specified sectors and make it available

in 32-bit pieces on input port 0x1f0 ; waidisk()waits until the disk  signals that the data is ready ,and then the call to insl

read the 128 (SECTSIZE/4)32-bit pieces into memory starting at dst ;

inb outb and insl are not ordinary c functions .They are inlined functions whose bodies are assembly language fragments

when gcc sees the call to inb ,the inlined assembly causes it to emit a single  inb instruction .This style allows the use of

low-level instructions like inb and outb while still writing the control  logic in C instead of assembly.

     The implementation of insl (0412) is worth looking at more closely. Rep ins l is actually a tight loop masquerading as a single instruction. The rep prefix executes the  following instruction %ecx times, decrementing %ecx after each iteration. The inslinstruction reads a 32-bit value from port %dx into memory at address %edi and then increments %edi by 4. Thus rep insl copies 4×%ecx bytes, in 32-bit chunks, from port %dx into memory starting at address %edi. The register annotation s tell GCC to prepare for the assembly sequence by storing dst in %edi, cnt in %ecx, and port in%dx. Thus the insl function copies 4×cnt bytes from the 32-bit port port into memory starting at dst . The cld instruction clears the processor’s direction flag, so that the insl instruction increments %ed i; when the flag is set , insl decrements %edi instead.
The x86 calling convention does not define the state of the direction flag on entry to a function, so each use of an instruction like insl must initialize it to the desired value

 //这是LBA方式pio(Program IO即所有的IO操作是通过cpu访问硬盘的io地址寄存器)读写硬盘;

一般主板上的有2个IDE通道,每个通道可以接2个ide硬盘;如访问第一个硬盘的扇区可以设置它的io地址寄存器0x1f0~0x1f7实现!

void readsect(void *dst,uint offset)

{

waitdisk();

 

outb(0x1f2,1);代表扇区数

outb(0x1f3,offset);//LBA参数的0~7位,扇区号

outb(0x1f4,offset>>8); //LBA参数的8~15,柱面的低8位

outb(0x1f5,offset>>16);//LBA参数的16~23,柱面的高8位

outb(0x1f6,offset>>24|0xE0);//HD_CURRENT 驱动器/磁头寄存器 -- 驱动器号/磁头号(101dhhhh, d=驱动器号,h=磁头号)

outb(0x1f7,0x20);/cmd读扇区命令

//读数据

waitdisk();

insl(0x1f0,dst,SECTSIZE/4);

//Readseg read at least count bytess from disk offfset into memory at va;  The x86 IDE disk interface operates in terms of 512-byte chunks called sectors ,so readseg may read not only  the desired section of memory but also some bytes befores

and afterward ,depend on alignment;For the second program segment in the example above ,the boot sector will call readseg

0x1073e0,0x73e0,ox79e) Due to sector granularity ,this call is equivalent to readseg (uchar*)0x107200,0x7200,0xa00

:it read 0x1e0 bytes before the disired memory region and 0x82 bytes afterward ; in practice,this sloppy behavior turns out not to be a problem ;Readseg begins by computing the ending virtual address ,the first memory address above va that doesnot need to be loaded from disk ,and rounding va down to a sector-aligned  disk offset; Then it convert the offset from

a byte offset to a sector offset ; it add 1because the kernel start at disk sector 1(disk sector 0 is the bootsector ).finally ,it call

readsec t to read  each sector into memory.

void readseg(uint va,uint count,uint offset)

{

uint eva;

eva=va +count;

va&=~(SECTSIZE-1);

offset=(offset/SECTSIZE)+1;

for(;va<eva;va+=SECTSIZE,offset++)

//Readsect reads a single disk sector .It is our first example of a device driver,albeit a tiny one,Readsect begin by calling wait

 disk to wait until the disk signals that it is ready to accept a command .The disk does so by setting the top two bits of its status byte (connected to input port 0x1f7 )to 01 .Waitdisk() reads the status  byte until the bits are set that way .Chapter6

will examine more efficient ways to wait for hardware status changes,but busy waiting like this is fine for the boot sector

   once the disk is ready ,readsect issues a read command.it first writes command arguments -the sector count and the sector number (offset) -to the disk register on output port 0x1f2~0x1f6

readsect((char*) va,offset);

}

 

void readseg(uint va,)

 

 

http://blog.csdn.net/justin_shi/archive/2010/08/10/5802578.aspx

http://topic.csdn.net/u/20080611/10/da3c08d4-80db-4fae-98e4-1fe9c970cf6e.html

相关文章推荐

Xv6下载 编译 运行

大环境: Ubuntu 下载:                   从https://github.com/panks/Xv6上下载的源代码可以直接编译通过,而且在qemu上能顺利运行!我从其他的源代...

xv6的lab1中的proj1的bootmain.c

//boot loader //Part of the boot sector ,along with bootasm.S which calls bootmain(),//bootasm.S has...

xv6源码分析(一):BootLoader

BootLoader是操作系统启动时的重要一环,负责从实模式切换到保护模式并且将存在存储设备的操作系统二进制文件读入内存,最后将控制权交给操作系统。 一、计算机启动时的硬件动作 PC机上电时运行的...

xv6的main.c

//Bootloader////Part of the boot sector ,along with  bootasm.s which calls bootmain()//bootasm.S has...

STM32f103C8T6 bootloader设计

STM32 bootloader设计          使用的是STM32f103C8T6:64Kflash,在应用程序中通过CAN把接受到的bin写到外置 flash的指定地址处。在bootload...

基于mini2440 的 bootloader 设计 ---- 6、C程序运行环境搭建

开发环境:                电脑系统:RedHat Enterprise Linux6   kernel version : linux-2.6.32                ...

xv6之添加alarm CPU中断检测

第三次修改了。再次记录下。 作业要求: In-class: xv6 CPU alarm We encourage you to collaborate with others on these...

xv6 一个简单的,类unix适于教学的操作系统

Contents 0  操作系统接口 1 第一个进程 2 页表 3 陷阱(traps), 中断,以及驱动 4 锁 5 调试 (scheduling) 6 文件系统 A PC 硬件 B boot loa...

xv6源码分析(七):文件系统

xv6文件系统采用了分层的实现,下面的每一层都向上提供接口供上层调用,这里并不阐述xv6文件系统的系统细节,仅仅针对每一层需要注意的问题和各种接口的联系做解释,具体的文件系统细节可参考xv6中文文档。...

XV6操作系统的安装与使用

1.1  XV6操作系统的安装与使用     麻省理工大学的网站上 http://pdos.csail.mit.edu/6.828/2011/xv6.html,已经对XV6的来龙去脉及如何下载做了较详...
  • SheIsC
  • SheIsC
  • 2015年06月27日 22:07
  • 2297
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:xv6的bootloader之bootmain.c
举报原因:
原因补充:

(最多只允许输入30个字)