分享
 
 
 

FreeBSD 5.2.1 boot0(启动扇区代码分析)

王朝system·作者佚名  2006-11-23
窄屏简体版  字體: |||超大  

FreeBSD完整的内核代码在FreeBSD的“/sys”目录下。其中,FreeBSD 的 Boot Manager代码是 sys\boot\i386\boot0\boot0.s,它是FreeBSD自带的Boot Manager,其功能虽然不如Linux的lilo和Grub功能强大,但它只需按一个键就可以引导,界面直观。小小的512字节,可以给你一个简单明了的启动选择界面,还能记住你上次的选择。 以下,就对此代码进行详细分析。

当我们打开计算机电源时,计算机叽叽嘎嘎进行设备和内存检测过后就读取硬盘或者软盘的引导扇区,这个扇区只有512字节,显然这512字节不能够有多大作用,这512字节的代码被BIOS放在地址从0x0000:0x7c00开始处。然后直接跳转到0x0000:0x7c00处去执行。以上工作是BIOS干的,你什么也不用作 。操作系统需要通过这个引导扇区代码再装载操作系统的其他部分。

在还没有跳转到这段代码之前,也就是BIOS把磁盘的引导扇区读入到内存之后,其DL和ES、SI寄存器的内容如下:

DL:表示启动设备,例如,如果计算机是从软盘启动的则DL=0,若是从IDE的C、D盘(严格来说是物理磁盘一和物理磁盘二,而不是逻辑磁盘分区)启动的则DL分别为0x80和0x81。如果是从硬盘启动的话,ES:SI是指向BIOS中的硬盘分区表存放的地址。

好了,我们现在已经知道,计算机的BIOS已经把引导扇区的512字节的内容读入到了0:0x7c00处,然后就跳转到0:0x7C00处去执行,也就是执行引导扇区代码,引导扇区代码boot0执行代码dump如下(它很有用,以后我们还不时回头来看):

0000: FC 31 C0 8E C0 8E D8 8E-D0 BC 00 7C 89 E6 BF 00 .1.........|....

0010: 06 B9 00 01 F3 A5 89 FD-B1 08 F3 AB FE 45 F2 E9 .............E..

0020: 00 8A F6 46 BB 20 75 04-84 D2 78 03 8A 56 BA 88 ...F. u...x..V..

0030: 56 00 E8 FC 00 52 BB C2-07 31 D2 88 6F FC 0F A3 V....R...1..o...

0040: 56 BB 73 1B 8A 07 BF 83-07 B1 03 F2 AE 74 10 B1 V.s..........t..

0050: 0B F2 AE 75 03 83 C7 0B-8A 0D 01 CF E8 C3 00 42 ...u...........B

0060: 80 C3 10 73 D6 58 2C 7F-3A 06 75 04 72 05 48 74 ...s.X,.:.u.r.Ht

0070: 0D 30 C0 04 B0 88 46 B8-BF B2 07 E8 A4 00 BE 77 .0....F........w

0080: 07 E8 B0 00 8A 56 B9 4E-E8 8C 00 30 E4 CD 1A 89 .....V.N...0....

0090: D7 03 7E BC B4 01 CD 16-75 12 30 E4 CD 1A 39 FA ..~.....u.0...9.

00A0: 72 F2 8A 46 B9 EB 1B B0-07 E8 94 00 30 E4 CD 16 r..F........0...

00B0: 88 E0 3C 1C 74 EC 2C 3B-3C 04 76 06 2C C7 3C 04 ..<.t.,;<.v.,.<.

00C0: 77 E5 98 0F A3 46 0C 73-DE 88 46 B9 BE 00 08 8A w....F.s..F.....

00D0: 14 89 F3 3C 04 9C 74 0A-C0 E0 04 05 BE 07 93 C6 ...<..t.........

00E0: 07 80 53 F6 46 BB 40 75-08 BB 00 06 B4 03 E8 59 ..S.F.@u.......Y

00F0: 00 5E 9D 75 06 8A 56 B8-80 EA 30 BB 00 7C B4 02 .^.u..V...0..|..

0100: E8 47 00 72 A2 81 BF FE-01 55 AA 75 9A 56 BE 81 .G.r.....U.u.V..

0110: 07 E8 1A 00 5E FF E3 B0-46 E8 24 00 B0 31 00 D0 ....^...F.$..1..

0120: EB 17 0F AB 56 0C BE 74-07 E8 EB FF 89 FE E8 03 ....V..t........

0130: 00 BE 81 07 AC A8 80 75-05 E8 04 00 EB F6 24 7F .......u......$.

0140: 53 BB 07 00 B4 0E CD 10-5B C3 8A 74 01 8B 4C 02 S.......[..t..L.

0150: B0 01 56 89 E7 F6 46 BB-80 74 13 66 6A 00 66 FF ..V...F..t.fj.f.

0160: 74 08 06 53 6A 01 6A 10-89 E6 48 80 CC 40 CD 13 t..Sj.j...H..@..

0170: 89 FC 5E C3 20 20 A0 0A-44 65 66 61 75 6C 74 3A ..^. ..Default:

0180: A0 0D 8A 00 05 0F 01 04-06 0B 0C 0E 83 9F A5 A6 ................

0190: A9 0C 0D 0C 0B 0A 09 08-0A 12 0D 10 0F 3F BF 44 .............?.D

01A0: 4F D3 4C 69 6E 75 F8 46-72 65 65 42 53 C4 90 90 O.Linu.FreeBS...

01B0: 66 BB 44 72 69 76 65 20-00 00 80 0F B6 00 00 00 f.Drive ........

01C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

01D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

01E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

01F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U.

图(一)(注:上图中的4x16个字节是保留的4个分区信息,具体解释见下面图(三))

下面,我们对FreeBSD启动扇区代码boot0.s进行逐步分析。boot0.s代码如下:

#

# Copyright (c) 1998 Robert Nordier

# All rights reserved.

#

# Redistribution and use in source and binary forms are freely

# permitted provided that the above copyright notice and this

# paragraph and the following disclaimer are duplicated in all

# such forms.

#

# This software is provided "AS IS" and without any express or

# implied warranties, including, without limitation, the implied

# warranties of merchantability and fitness for a particular

# purpose.

#

以上的Coyright就不用翻译了。

# $FreeBSD: src/sys/boot/i386/boot0/boot0.s,v 1.27 2003/11/20 20:28:18 jhb Exp $

以上供版本管理软件使用

# A 512-byte boot manager.

.set NHRDRV,0x475 # Number of hard drives

.set ORIGIN,0x600 # Execution address

.set FAKE,0x800 # Partition entry

.set LOAD,0x7c00 # Load address

.set PRT_OFF,0x1be # Partition table

.set TBL0SZ,0x3 # Table 0 size

.set TBL1SZ,0xb # Table 1 size

.set MAGIC,0xaa55 # Magic: bootable

.set B0MAGIC,0xbb66 # Identification

.set KEY_ENTER,0x1c # Enter key scan code

.set KEY_F1,0x3b # F1 key scan code

.set KEY_1,0x02 # #1 key scan code

#

# Addresses in the sector of embedded data values.

# Accessed with negative offsets from the end of the relocated sector (%ebp).

#

.set _NXTDRV,-0x48 # Next drive

.set _OPT,-0x47 # Default option

.set _SETDRV,-0x46 # Drive to force

.set _FLAGS,-0x45 # Flags

.set _TICKS,-0x44 # Timeout ticks

.set _FAKE,0x0 # Fake partition entry

.set _MNUOPT,0xc # Menu options

以上是定义相关的参数值,例如“.set NHRDRV,0x475”类似于C语言中的“#define NHRDRV 0x475”

.globl start # Entry point

.code16 # This runs in real mode

#

# Initialise segments and registers to known values.

# segments start at 0.

# The stack is immediately below the address we were loaded to.

#

start:

cld # String ops inc

xorw %ax,%ax # Zero

movw %ax,%es # Address

movw %ax,%ds # data

movw %ax,%ss # Set up

movw $LOAD,%sp # stack

以上代码:

1)首先使用“cld”指令清除方向标志,使得以下的进行“rep”操作时SI和DI的值递增。

2)使ax清零,并使除代码段cs外的另外两个数据段寄存器es、ds和堆栈段ss清零。当然,此时cs

由于reset或初始上电已经为零了。

3)BIOS已经把引导扇区的512字节的内容读入到了0:0x7c00处,movw $LOAD,%sp 使得堆栈指针指向扇区

代码(或曰本段代码 0:0x7c00)的顶部。虽然堆栈向下生长可能会影响代码的内容,但下面我

们马上就把位于0:7c00处代码移到其他地方去执行。

#

# Copy this code to the address it was linked for

#

movw %sp,%si # Source

movw $start,%di # Destination

movw $0x100,%cx # Word count

rep # Relocate

movsw # code

把位于0:7c00处的代码搬移到0:0x600处。注意,此时由于代码连接的重定向,$start=0x600。

#

# Set address for variable space beyond code, and clear it.

# Notice that this is also used to point to the values embedded in the block,

# by using negative offsets.

movw %di,%bp # Address variables

movb $0x8,%cl # Words to clear

rep # Zero

stosw # them

通过以上一段代码的执行,本代码已被搬移到0:0x600处,此时si=di=0x600+0x100, 以上代码

把di的值保存到bp,bp此时指向本程序搬移后的未用的空间的首部,且把此bp所指的16字节空间

清零。以上过程如下图所示:

┏>0:0x600 ┏━━━━━┓

┃ ┃ ┃

┃ ┃ 搬 ┃

┃ ┃ 移 ┃

┃ ┃ 之 ┃

┃ ┃ 后 ┃

┃ ┃ 的 ┃

┃ ┃ 代 ┃

┃ ┃ 码 ┃

┃ ┃ ┃

┃ 0:0x7ff ┣━━━━━┫

┃ ┃ 0 ┃<-bp指向这里(0:0x800), 以此开始的16字节被清零。

┃ ┣━━━━━┫以下所称的fake partition entry就是指这里。

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┣━━━━━┫

┃ ┃ 0 ┃

┃ ┗━━━━━┛

0:0x7c00 ┏━━━━━┓ ┛

┃ ┃

┃ 搬 ┃

┃ 移 ┃

┃ 之 ┃

┃ 前 ┃

┃ 的 ┃

┃ 代 ┃

┃ 码 ┃

┃ ┃

0:0x7dff ┗━━━━━┛

图(二)

#

# Relocate to the new copy of the code.

#

incb -0xe(%di) # Sector number

jmp main-LOAD+ORIGIN # To relocated code

把以上清零的16字节的第二个字节置为1,表示我们已经读取了一个分区。然后跳转到搬

移之后的新代码的main处执行。

#

# Check what flags were loaded with us, specifically, Use a predefined Drive.

# If what the bios gives us is bad, use the '0' in the block instead, as well.

#

main:

testb $0x20,_FLAGS(%bp) # Set number drive?

jnz main.1 # Yes

testb %dl,%dl # Drive number valid?

js main.2 # Possibly (0x80 set)

main.1:

movb _SETDRV(%bp),%dl # Drive number to use

上面说过,BIOS把磁盘的引导扇区读入到内存之后,其dl的内容表示启动设备,但我们 安装好FreeBSD

之后,我们可以改变此引导扇区的内容,其中的一个改变就是可以使我们可以“手动指定”我们实际安

装FreeBSD的分区,如果我们希望指定FreeBSD所在的boot分区,那么我们在bp-0x45处的位置

(即_FLAGS(%bp)处)的bit 0x20置1,那么上面的“movb _SETDRV(%bp),%dl”一句中movb

_SETDRV(%bp),%dl(即bp-0x46)即指向我们“手动指定”FreeBSD所在分区 代码,例如,IDE的C、D

盘(严格来说是第一个物理磁 盘的第一个和第二个分区)的代码分别为 0x80和0x81。如果没有“手动指

定”启动分区,那么,我们 缺省使用机器当前启动的分区,上面说过,机器当前启动的分区代码放在dl中。

因为FreeBSD Boot Manager 不可能安装到软盘(如果从软盘启动则dl为0),所以,使用testb %dl,%dl

来判断驱动器代码是否合法(volid)。

有关_FLAGS(%bp)中其他bit位表示的意义,在随后的代码分析中慢慢给你道来。

#

# Whatever we decided to use, now store it into the fake

# partition entry that lives in the data space above us.

#

main.2:

movb %dl,_FAKE(%bp) # Save drive number

callw putn # To new line

pushw %dx # Save drive number

以上第一句把FreeBSD启动分区的代码保存到_FAKE(%bp)(bp-0)处,也就是说,上图(二)的bp

处保存的是FreeBSD启动分区的代码(_FAKE=0)。

“callw putn”一句在屏幕上打印“回车”和“换行”,“pushw %dx”一句把启动分区

的值压入堆栈。

#

# Start out with a pointer to the 4th byte of the first table entry

# so that after 4 iterations it's beyond the end of the sector.

# and beyond a 256 byte boundary and has overflowed 8 bits (see next comment).

# (remember that the table starts 2 bytes earlier than you would expect

# as the bootable flag is after it in the block)

#

movw $(partbl+0x4),%bx # Partition table (+4)

xorw %dx,%dx # Item number

以上代码首先把%bx指向分区表partbl的的第四个字节,这里存放的是分区类型,如82表示

Linux Native分区83表示Linux Swap 分区,有关分区表的细节请详见本文的尾部。然后dx清零 ,

此后,dx将作为遍历磁盘分区的列举代号使用。 启动分区代码dl的原来的值在上面已经压入

了堆栈保存。

#

# Loop around on the partition table, printing values until we

# pass a 256 byte boundary. The end of loop test is at main.5.

#

main.3:

movb %ch,-0x4(%bx) # Zero active flag (ch == 0)

btw %dx,_FLAGS(%bp) # Entry enabled?

jnc main.5 # No

上面首先使得第一个分区的活动标志为0,标志它不为活动标志,因为ch的值为0。至

于第二句“btw %dx,_FLAGS(%bp)”中的_FLAGS(%bp)是上面我们说到的“手动指定我们

实际安装FreeBSD的分区代码”。其中的bit 0x20我们在上面已经提到过。_FLAGS(

[1] [2] [3] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有