minix引导程序剖析之masterboot

大体的引导过程可以看我前面写的博客:

http://simohayha.iteye.com/blog/269093


masterboot的主要功能是从硬盘的一个已激活分区装载引导分区的第1个扇区的引导信息,并将控制权交给此引导程序。

引导过程中,未分区磁盘和已分区磁盘的布局是不同的,已分区磁盘的话,第一个扇区是主引导记录和分区表,而masterboot就存放在这里,将由它来查找激活分区的引导块(也就是在激活分区的第一个扇区里面),也就是下一次我们要分析的bootblock程序。而未分区磁盘的话第一个扇区直接存储的就是引导块。然后由引导块去加载引导程序也就是boot monitor 。

这里它会一个硬盘一个硬盘的去查找,如果都不符合条件那么就提示出错。

我们来看masterboot.s的源码:

! To make things a little clearer, the boot path might be:
!	/dev/fd0	- Floppy disk containing data, tries fd1 then d0
!	[/dev/fd1]	- Drive empty
!	/dev/c0d0	- Master boot block, selects active partition 2
!	/dev/c0d0p2	- Submaster, selects active subpartition 0
!	/dev/c0d0p2s0	- Minix bootblock, reads Boot Monitor /boot
!	Minix		- Started by /boot from a kernel image in /minix

	LOADOFF	   =	0x7C00	! 0x0000:LOADOFF is where this code is loaded
	BUFFER	   =	0x0600	! First free memory
	PART_TABLE =	   446	! Location of partition table within this code
	PENTRYSIZE =	    16	! Size of one partition table entry
	MAGIC	   =	   510	! Location of the AA55 magic number

	! <ibm/partition>.h:
	bootind	   =	     0
	sysind	   =	     4
	lowsec	   =	     8


这段代码中,定义了一些数据段,比如代码的加载地址LOADOFF(也就是这段代码被固件加载到的内存位置),以及BUFFER(也就是要把当前的代码拷贝到这个地址,然后再load).以及分区表的大小以及位置,魔术数。。

下面的代码主要是拷贝代码从LOADOFF到buffer,以及一些初始化


这个图就是开始的内存模型。

master:
	xor	ax, ax          !寄存器ax清零
	mov	ds, ax          
	mov	es, ax
	cli                      !关闭中断
	mov	ss, ax			! ds = es = ss = Vector segment
	mov	sp, #LOADOFF            !设置栈指针为LOADOFF
	sti                       !打开中断
 
! Copy this code to safety, then jump to it.
	mov	si, sp			! si 保存代码的开始地址
	push	si			!  si进站,当下面的ret指令的时候会直接返回到初始地址。
	mov	di, #BUFFER		! Buffer area
	mov	cx, #512/2		!  主要这里是实模式和保护模式1个字所表示的字节数是不同的。cx保存下面我们要拷贝的大小
	cld
  rep	movs                           !这句也就是拷贝从LOADOFF的数据代码到buffer所指的地址的位置.
	jmpf	BUFFER+migrate, 0



下面的代码主要是用来查找激活分区,以便加载执行,以及一些处理错误。




这个图就是分区表的内存模型。



findactive:
	testb	dl, dl              !检测dl的正负.dl里保存有当前设备的编号,0x00是第一块软盘,0x01第二块软盘,0x80,0x81,0x82,0x83...是指硬盘的编号。因此当为软盘时dl才是正数。所以这里也就是判断当前启动的设备。

	jns	nextdisk		!  如果为正数的话,也就是软盘.跳转到nextdisk
	mov	si, #BUFFER+PART_TABLE   ! 讲分区表的地址付给寄存器si.

!find用来搜索分区表,查找激活的分区,在当前设备的其他分区
find:	cmpb	sysind(si), #0		! 分区类型,如果已使用的话,就是0.
	jz	nextpart                ! 查找未使用的分区.
	testb	bootind(si), #0x80	! 检测是否是已激活的分区
	jz	nextpart		! 不是已激活的,就去下一分区查找
loadpart:
	call	load			! Load partition bootstrap
	jc	error1			! Not supposed to fail
bootstrap:
	ret				! Jump to the master bootstrap
nextpart:
	add	si, #PENTRYSIZE
	cmp	si, #BUFFER+PART_TABLE+4*PENTRYSIZE
	jb	find
! No active partition, tell 'em
	call	print
	.ascii	"No active partition\0"
	jmp	reboot
! 去下一个设备查找激活分区。
nextdisk:
	incb	dl			! Increment dl for the next drive
	testb	dl, dl
	js	nexthd			! 负数的话,就是硬盘,因此直接跳转到nexthd,然后调用load。
	int	0x11			! Get equipment configuration
	shl	ax, #1			! Highest floppy drive # in bits 6-7
	shl	ax, #1			! Now in bits 0-1 of ah
	andb	ah, #0x03		! Extract bits
	cmpb	dl, ah			! Must be dl <= ah for drive to exist
	ja	nextdisk		! Otherwise try disk 0 eventually
	call	load0			! Read the next floppy bootstrap
	jc	nextdisk		! It failed, next disk please
	ret				! Jump to the next master bootstrap
nexthd:	call	load0			! 从硬盘开始
error1:	jc	error			! No disk?
	ret



下面的这段代码从当前的激活扇区读取引导块,然后将控制权交给引导块,这里主要是一些处理磁盘的操作,很繁琐,看的头大的说。。这里要注意的就是几个读取扇区的指令,比如int 0x13.
! 
load0:
	mov	si, #BUFFER+zero-lowsec	! si = where lowsec(si) is zero
	!jmp	load

load:
	mov	di, #3		! Three retries for floppy spinup
retry:	push	dx		! Save drive code
	push	es
	push	di		! Next call destroys es and di
	movb	ah, #0x08	! Code for drive parameters
	int	0x13
	pop	di
	pop	es
	andb	cl, #0x3F	! cl = max sector number (1-origin)
	incb	dh		! dh = 1 + max head number (0-origin)
	movb	al, cl		! al = cl = sectors per track
	mulb	dh		! dh = heads, ax = heads * sectors
	mov	bx, ax		! bx = sectors per cylinder = heads * sectors
	mov	ax, lowsec+0(si)
	mov	dx, lowsec+2(si)! dx:ax = sector within drive
	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
	jae	bigdisk
	div	bx		! ax = cylinder, dx = sector within cylinder
	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
	movb	ch, dl		! ch = low 8 bits of cylinder
	divb	cl		! al = head, ah = sector (0-origin)
	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
	shr	dx, #1
	shr	dx, #1		! dl[6..7] = high cylinder
	orb	dl, ah		! dl[0..5] = sector (0-origin)
	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
	incb	cl		! cl[0..5] = sector (1-origin)
	pop	dx		! Restore drive code in dl
	movb	dh, al		! dh = al = head
	mov	bx, #LOADOFF	! es:bx = where sector is loaded
	mov	ax, #0x0201	! Code for read, just one sector
	int	0x13		!  Call the BIOS for a read
	jmp	rdeval		! Evaluate read result



更多的细节的部分还是要去看源码。。


你可能感兴趣的:(Blog)