簡介

x86的開機流程為BIOS->POST->MBR->Boot sector->OS,先介紹MBR。MBR是硬碟的第一個sector,每個sctor是512 bytes。這 512 bytes由3個部分組成:

1. Boot Partition Loader (Pre-loader or Pre-boot): 共446 bytes,其功能就是將可啟動的作業系統分割區 (boot sector)載入,並將控制權交給其boot sector,多重開機選單就是在這邊做的。

2. partition table: 共64 bytes,4個partition,每個16 bytes,這也限制了一顆硬碟只能有4個partition。每個byte代表的意義見最註1。

3. 結束符號: 共2 bytes,其值為55AA,用來讓BPL驗證是否為MBR。

MBR壞掉,意謂著硬碟沒救了

 

The sectors

The Sectors  

一顆硬碟上的第一個sector是MBR,也就是所謂的stage1,其結構如前所述。接下來有62個sectors,是用來放 stage 1.5,62個的原因見下圖:

fdisk-ul

BIOS將BPL載入後,PBL先把stage 1.5載入,這樣才可以存取在filesystem上的stage2。stage1.5即存放有關filesystem的識別,只有62個sectors (31K)可用,因此通常只載入某一格式的file system。stage2是grub的核心功能所在,大小有一百多K,因此只能放在固定路徑的file system內,以便stage 1.5找的到。

grub-file

接著去partition table尋找可開機的分割區 (每個分割區的第1個byte為80),並將其boot sector載入。此時有兩種可能:

1. 直接指向: 此時boot sector為空 (值為0),直接載入kernel/ramdisk (根據menu.lst)。

menu-lst

2. chainloader: 將控制權交給該分割區的boot sector。

 

開始

知道了這些,就可以開始來玩玩看。

root:/home/latrell/temp# dd if=/dev/sdb of=sdb.mbr bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000108953 s, 4.7 MB/s

root:/home/latrell/temp# hexdump -C sdb.mbr

可看到partition table如下,表示此usb只有一個partition。

000001b0  00 02 90 c7 12 00 80 00  00 00 00 00 a8 01 00 01    |................|
000001c0   01 00 06 7b  fe f9  3e 00  00 00  92 6b 77 00
00 00  |...{..>....kw...|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00
00 00    |................|

000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    |................|
000001f0   00 00 00 00 00 00 00 00  00 00 00 00 00 00
55 aa    |..............U.|

這樣表示用usb可開機,看到MBR字樣。

再來把MBR毀了

root:/home/latrell/temp# dd if=/dev/zero of=/dev/sdb bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0149138 s, 34.3 kB/s

只剩0了
root:/home/latrell/temp# hexdump -C sdb.mbr
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200

拿來一開,果然fail。再把他裝回去

root:/home/latrell/temp# install-mbr /dev/sdb --force

就又可以了。記得要在umount的情況下弄,或是弄完要umount,不然不會生效。

 

Bootloader

MBR是要載入Bootsector,利用syslinux來做一個。syslinux需要FAT,見如下操作:

root:/home/latrell/temp# fdisk /dev/sdb

Command (m for help): p

Disk /dev/sdb: 4009 MB, 4009754624 bytes
124 heads, 62 sectors/track, 1018 cylinders
Units = cylinders of 7688 * 512 = 3936256 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1        1018     3913161    6  FAT16

Command (m for help): d
Selected partition 1

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-1018, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-1018, default 1018):
Using default value 1018

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 6
Changed system type of partition 1 to 6 (FAT16)
Command (m for help): a
Partition number (1-4): 1

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.

再來格式化:
root:/home/latrell/temp# mkfs.vfat -F 16 /dev/sdb1
mkfs.vfat 2.11 (12 Mar 2005)

安裝syslinux

root:/home/latrell/temp# syslinux -sf /dev/sdb1

這樣就可以開進syslinux,看到boot:

 

USB install Key

再來,可以來做一支usb install key,拿ubuntu當例子:

root:/home/latrell/temp# mount -oloop ubuntu-9.10-netbook-remix-i386.iso /mnt/iso/

利用rsync將整張光碟幹進去剛剛建好的partition:
root:/home/latrell/temp# rsync -av /mnt/iso/ /media/disk/

之前用cp -af一直失敗,搞了好久弄不出來,一直停在busybox的shell(initramfs),只好call 兔哥 for help。在兔哥的大力贊助下,發現是UUID比對失敗,而這個UUID是存在iso的.disc裡。換言之,是個隱藏檔,cp沒有複製過去。因此使用rsync好像比較保險! 記得不要用/mnt/iso/*,不然隱藏檔會co不過去。

再來還是syslinux版本的問題。如果是3.7版,則是要用syslinux這個名字。前版則是用isolinux。這裡是指ubuntu iso裡的syslinux/isolinux。要改的地方有兩個,一個是folder裡的isolinux.cfg改成syslinux.cfg,再來是把folder name也改成syslinux。不然會看到找不到kernel等錯誤!

接下來,用這個開機,就可以裝ubuntu了。

 

註1:

----------------------------------------------------------------------------
|位移值|大小 | 說明 |
+------+-------------------------------------------------------------------+
| 00 |Byte | BOOT ID - 若為可開機的分割區則為 80h ~ FFh, 否則為 00h。 |
| | | 80h = C, 81h = D, 82h = E ... 以此類推 |
| | | 以 fdisk 來說,若第一顆硬碟的分割區設為 Active 則 ID = 80h。 |
| | | 4 個分割表中, 只能有一個被設為可開機, 否則將會發生錯誤。 |
+------+-----+-------------------------------------------------------------+
| 01h |Byte | 此分割開始之磁頭編號 |
+------+-----+-------------------------------------------------------------+
| 02h |Byte | 此分割開始之磁區編號 (6 bits) |
| | | 最高的 2 個 bits(bit6-7), 為磁柱編號的 bit8-9 |
+------+-----+-------------------------------------------------------------+
| 03h |Byte | 此分割開始之磁柱編號 (10 bits) |
| | | bit8-9 放在位移值 02h 的 bit 6-7 |
+------+-----+-------------------------------------------------------------+
| 04h |Byte | 作業系統識別碼 |
| | | 00 None |
| | | 01 DOS FAT-12 bits |
| | | 02 XENIX root |
| | | 03 XENIX usr |
| | | 04 DOS FAT-16 bits < 32M |
| | | 05 Extended |
| | | 06 DOS FAT-16 bits > 32M |
| | | 07 HPFS/NTFS |
| | | 08 AIX |
| | | 09 AIX bootable |
| | | 0A OS/2 Boot Manager |
| | | 0B DOS FAT-32 bits (Int 13h extensions) |
| | | 0C DOS FAT Cylinder > 1024 (Int 13h extensions) |
| | | 0E DOS FAT System (Int 13h extensions) |
| | | 0F DOS BigExtended (Int 13h extensions) |
| | | 20 SPF Boot manager |
| | | 40 Venix 80286 |
| | | 41 PPC PReP Boot |
| | | 51 Novell |
| | | 52 Microport |
| | | 63 GNU HURD |
| | | 64 Novell Netware |
| | | 65 Novell Netware |
| | | 75 PC/IX |
| | | 80 Old MINIX |
| | | 81 Linux/MINIX |
| | | 82 Linux swap |
| | | 83 Linux native |
| | | 85 Linux extended |
| | | 93 Amoeba |
| | | 94 Amoeba BBT |
| | | A5 FreeBSD |
| | | A6 Open BSD |
| | | A7 NETSTEP |
| | | A9 NetBSD |
| | | B7 BSDI fs |
| | | B8 BSDI swap |
| | | C7 Syrinx |
| | | DB CP/M |
| | | E1 DOS access |
| | | E3 DOS R/O |
| | | EB BeOS fs |
| | | F2 DOS secondary |
| | | FF BBT |
+------+-----+-------------------------------------------------------------+
| 05h |Byte | 此分割結束之磁頭編號 |
+------+-----+-------------------------------------------------------------+
| 06h |Byte | 此分割結束之磁區編號 (6 bits) |
| | | 最高的 2 個 bits(bit6-7), 為磁柱編號的 bit8-9 |
+------+-----+-------------------------------------------------------------+
| 07h |Byte | 此分割結束之磁柱編號 (10 bits) |
| | | bit8-9 放在位移值 06h 的 bit 6-7 |
+------+-----+-------------------------------------------------------------+
| 08h |DWord| 此分割區前之磁區總數 |
+------+-----+-------------------------------------------------------------+
| 12h |DWord| 此分割之磁區總數 |
+------+-----+-------------------------------------------------------------+

partition table 的entry (一個parititon) 的structure 定義在 COMMON\OAK\INC\bootpart.h

typedef struct _PARTENTRY {
BYTE Part_BootInd; // If 80h means this is boot partition
BYTE Part_FirstHead; // Partition starting head based 0
BYTE Part_FirstSector; // Partition starting sector based 1
BYTE Part_FirstTrack; // Partition starting track based 0
BYTE Part_FileSystem; // Partition type signature field
BYTE Part_LastHead; // Partition ending head based 0
BYTE Part_LastSector; // Partition ending sector based 1
BYTE Part_LastTrack; // Partition ending track based 0
DWORD Part_StartSector; // Logical starting sector based 0
DWORD Part_TotalSectors; // Total logical sectors in partition
} PARTENTRY;


Part_BootInd 的value 也定義在 bootpart.h;

// Flags for Part_BootInd
#define PART_IND_ACTIVE 0x1
#define PART_IND_READ_ONLY 0x2
#define PART_IND_HIDDEN 0x4


其中Filesystem 定義在 COMMON\OAK\INC\bootpart.h

#define PART_UNKNOWN            0
#define PART_DOS2_FAT 0x01 // legit DOS partition
#define PART_DOS3_FAT 0x04 // legit DOS partition
#define PART_EXTENDED 0x05 // legit DOS partition
#define PART_DOS4_FAT 0x06 // legit DOS partition
#define PART_DOS32 0x0B // legit DOS partition (FAT32)
#define PART_DOS32X13 0x0C // Same as 0x0B only "use LBA"
#define PART_DOSX13 0x0E // Same as 0x06 only "use LBA"
#define PART_DOSX13X 0x0F // Same as 0x05 only "use LBA"

// CE only partition types for Part_FileSystem

#define PART_CE_HIDDEN 0x18
#define PART_BOOTSECTION 0x20
#define PART_BINFS 0x21 // BINFS file system
#define PART_XIP 0x22 // XIP ROM Image
#define PART_ROMIMAGE 0x22 // XIP ROM Image (same as PART_XIP)
#define PART_RAMIMAGE 0x23 // XIP RAM Image
#define PART_IMGFS 0x25 // IMGFS file system
#define PART_BINARY 0x26 // Raw Binary Data

Reference
http://www.pczone.com.tw/vbb3/thread/39/50519/
MBR and partition table

kezeodsnx 發表在 痞客邦 PIXNET 留言(1) 人氣()


留言列表 (1)

發表留言
  • sakbk
  • 不上來看一下 都不知道叫我兔哥哩