硬碟定址概說

傳統上一般說來定址的方法有古老的C/H/S (cylinder/head/sector)的方法,也就是說硬碟上的pin 腳位,我們傳進去這三個值,硬碟裡面的晶片會自動幫我們轉換到硬碟上一個區塊(block)上去作讀寫。這是最早的根據硬碟實體(硬碟片數量就是cylinder, 讀寫頭數目head)製作的定址方法,以前ATA只定義24bit (H(8b)S(6b)C(10b)), ATA-2定義28bit (H(4b)S(8b)C(16b)),由於一個硬體讀寫sector傳統上512B,所以ATA的硬碟最多只有8G,ATA-2的硬碟最多只有128G。這限制了硬碟的總大小與使用者對不同廠家硬碟的使用。不同廠家硬碟的C/H/S不同,那就要寫不同的程式控制。所以後來提出LBA (Logical Block Addressing)方法,就是不管了,只要給我一個數目,內部轉換是硬碟廠家自己的事,在ATA-6的規格裡面可以定址到48bit, 就是248 Byte。基本上後來的硬碟都能用LBA了。不同廠家的geometry是不一樣的,也就是同樣是80G的硬碟,但可以由不同的CHS總數來達成,這讓要找到真正的LBA定址困擾,所以CHS與LBA有公式做轉換,而且跟當初定義硬碟的geometry head跟sector有關:

LBA = (c * GH + h) * GS + (s - 1)

例如geometry (255,63,xxx) 的(32, 33, 0)的LBA值,就是(0 * 255 + 32) * 63 + (33 - 1) = 2048,通常這就是linux fdisk所切的第一partition位置。

新的usb drive, SSD等已經沒有CHS了,甚至連sector都有定義4k的讀寫。geometry是由OS 跟driver去跟硬碟詢問得到的,最早在DOS由int 13去問硬碟,所以當用virtual machine時,geometry是由virtual machine回報給OS的。由於現在都用LBA,現在已經沒有真正physical 上的geometry意義,像fdisk還可以自己高興隨便定義 (所以在用fdisk等工具時如果無聊自己去定義geometry,不同的話,根據公式轉出的CHS值也會不同,就是要轉換正確LBA,然後bootloader, OS driver大家都同意就好)。總之現在只是邏輯上計算的值,而唯一可能看到的地方是MBR裡面partition的定義,那個也基本無意義了,我猜所有的bootloader應該都是用LBA去跟硬碟要boot sector,除了DOS會來看,所以只對要裝DOS的硬碟有意義。

MBR與硬碟確認

MBR(master boot record)是指如果有很多顆硬碟構成的系統,那MBR就是第一個硬碟上的第一個sector(傳統上CHA的 sector從1開始,不是0,有的bios有bug),在LBA的addressing中,就是LBA 0
BIOS裡面可以設定Boot order,那什麼是第一個硬碟呢,他會根據硬體上的回報來決定,所以不是固定的尤其在SAN的環境中可以指定SANBOOT時,即使是現在的PC環境中也有usb硬碟有可能會變成第一個硬碟。所以為了確保開機的disk是哪一個,不隨著變換disk而變化,這些無論怎樣都是根據某一個特定的獨一無二的資訊來確認硬碟,但是這個資訊寫在哪裡呢?有效範圍到哪裡呢?例如全世界的硬碟有可能都獨一無二的辨識,還是只有lab內還是只有目前這台硬碟呢?目前Linux提供下列方式。

  • /dev/disk/by-id       : 硬碟公司出廠
  • /dev/disk/by-label   : filesystem支援的,必須寫在filesystem內的特定地方。
  • /dev/disk/by-path    : PCI硬體的識別
  • /dev/disk/by-uuid    : filesystem支援的,必須寫在filesystem內的特定地方。

其中by-label其實是filesystem有支援才行,是per partition的,可以用

  • mkfs -L
  • mkswap -L
而by-uuid是那個filesystem建造時,他有放進去才有沒有放就沒有。所以像DOS FAT等老filesystem沒有支援uuid跟label就沒有。所以用filesystem的工具
  •  
  • blkid /dev/hda1
  • dumpe2fs -h /dev/hda1 : -h 表示只要看header就好
 
而by-id可以用udev內的工具
  • /lib/udev/scsi_id -g -s /block/sdc

由此看來其實最保險的是硬體上的資訊,可是卻會發生可能讀不到的情形。

Partition (Volume)與檔案系統

partition是一個硬碟上可以再做切割的單位,現在講的都是符合當年PC Microsoft定義的partitions,一個partition可以用不同的檔案系統裝上完全不一樣的作業系統。目前MBR上512bytes/partition的定義是這樣子的。

 
MBR裡面有64bytes的primary partition資料,共有四個,由上面定義可以看得出來,用CHS的方法定義的partition無法超過8G,這時bytes (123)跟bytes(567)可以使用tuple (1023, 254, 63),也就是(HSC => fe, ff,ff),來表示不要使用傳統CHS了,改用8~15的LBA資訊來找到partition位址,而如果CHS有值,也是根據真正LBA值跟geometry去拼湊轉換出來的值。剩下446bytes就是OS dependent的bootstrap程式碼,通常這就是各boot manager/boot loader安裝時寫入的地方。電源打開後,電腦裡面有EEPROM,裡面藏著BIOS跟一些程式碼,CPU從這地方執行後,到最後去找boot device然後把bootstrap放到該放的記憶體上,並且把執行權交給他,bootstrap知道怎麼load kernel,然後整個系統就起來了。

除了primary partiton還有logical partition,這都是因為當年DOS/Windows下的C: D: E:......的產物,不管如何也就是如果只有4個partition實在是太少,所以在primary partition下再指向一個新sector,這樣的partition是logical partition,logical partition可以一直串下去,也就是一個primary partiton當成一串logical partition的頭,像link list一樣的串下去。

Linux中對MBR/partition的設定為

# fdisk /dev/hda

裡面可以設定active partition (也就是booting partition),還有各partition的filesystem type。
而一個實體的partition,就是一個block device的基本單位例如/dev/sda1, /dev/sda2....,在後來使用軟體層的partition,有人給另一個名字叫volume,基本上把他們看成一樣層的操作單位就好。

Partition alignment

傳統上的硬體都是以512 bytes為單位來存取磁盤的資料,這跟很多的管理一樣,少了performance不好,多了,可能會浪費空間(例如有的config檔案可能就寥寥幾個字元),但因為目前的應用都偏向大檔案,所以慢慢有4k的硬體存取單位被提出來,所以切割partition時如果能以4k的倍數切割,則有提升效率的好處,另外新的solid state drive,由於他的讀寫跟傳統磁性材料不同,不同chip,不同作法能力都不一樣,所以通用的切割是1M的partition alignment,目前linux上的0 ~ 2048 (1M)起始就是這樣來的。

Chainload

不同的partition的第一個sector其實都是可以藏boot loader的,不管是MBR,還是一般partition。所以每個boot loader如果作的好的話,他可以把控制權交給下個partition的code去boot,這可以一直chainload下去。每個512 byte都可以是一段某個OS boot loader。再由這個 boot loader去load OS。

GPT 與boot bios partition

在傳統MBR中,我們可以看到他的資料結構極限,LBA有4bytes, 32bits, 單位是512B,總共是41bits,所以 MBR的硬碟大小與所能定義的partition大小為2TB,但是現在市面上已經有超越3T的硬碟出現了,所以GPT (GUID Partition Table) 被提出來去boot 那些超過2TB的Partition。如果開機boot loader沒有在2T以後就不要緊。GPT的極限在9.4ZB(9.4 x 1021 ) . 當然一開始的boot manager/boot loader也必須能認得GPT格式的資料,才能chain boot到那個超過2T後的partition。請看Wikipedia上的GPT格式與支援的OS。Linux下的工具為

# gdisk /dev/sda

或者GUN parted
 
# parted /dev/sda

當然GRUB 2, syslinux, 或者GRUB 1 + 96 patch也能開GPT的資料結構。
 
這邊有個問題就是傳統舊的bios firmware,不認得GPT格式,他只會load MBR的第一個sector進來,並且把執行權交給第65bytes開始的地方,可是後來系統愈複雜,446 bytes的code已經無法支撐,之前Intel等商業公司就用了EFI規格,多切了一個FAT partition 把一些東西丟到這個FAT EFI partition (稱為EFI system partition,如果用efi booting的,則通常mount /boot/efi),所以使用新的GPT partition table的能力也在這裏面。為了讓舊機器也能使用GPT,GRUB 2 建立一個新的叫bios boot partition, 但不是像EFI一樣,而是像MBR 一樣,他這partition裏面是binary code,每一個GPT partition都有一個GUID, bios boot partition的ID就是21686148-6449-6E6F-744E-656564454649, ASCII字串就是Hah!IdontNeedEFI ,一般EFI partition要求100M, GRUB 2的boot bios partition目前差不多30k左右而為了將來擴充與boundary alignment, 1M就足夠。所以目前的gdisk, parted的切法是 MBR, 然後因為新的SSD alignment跳了2048個512 sector (1MB),然後在2048 ~ 4096(1MB) 就是給boot bios partition用的。

Boot manager/Boot loader

現在的boot loader程式通常也會是boot manager了,也就是他能管理partition來load不同的kernel,作不同的系統開機。現在的boot manager/loader很厲害,能從不同地方boot系統,一般還有光碟跟網路pxeboot,光碟很像一般的硬碟,標準是El Torito,也就是在特定的LBA上去讀boot loader,pxeboot為網卡上的rom firmware裡面藏有程式,電腦硬體開機後,會去把週邊設備上的firmware load到記憶體中執行,然後向網路發出DHCP request,並獲得ip以及DHCP option中的tftpserver跟bootfile。然後再對TFTP server要求bootfile。所以一般boot loader都會提供不同boot device的boot loader,我們只要想辦法讓系統抓到他們就好。

GRUB Legacy (0.97)

grub的好處是他是個boot manager也同時是Hurd, Linux, FreeBSD, OpenBSD, NetBSD等OS的boot loader,也可chain load其他的OS,而在做Linux Boot Loader時,他的好處是他認得幾種file system,所以他只需要做一次的install,然後upgrade或者新加的kernel檔案,只要改configuration file就好,不像LiLO必須每次都要重新執行lilo ,把新的kernel檔案對CHS的對應寫進第一個boot sector中,也就是檔案跟硬體的對應,GRUB可以從他認得的file system中獲知,但是LiLO不行。GRUB現在不僅有硬碟的loader也有了pxeboot跟CD的loader了。
 
GRUB可以讀不同的filesystem所以一般作法就是切個partition,並且mount在/boot上,裡面放了linux kernel/initrd還有grub的conf檔,grub會有辦法讀到這些東西,轉換檔案與block device的C/H/S,然後真的到block device上去讀出來。所以grub的內部命令都是針對/boot這個partition操作的。
 
GRUB有一個command shell,在boot失敗時,會跳進這個shell裡面來,他提供了一些grub 命令,可以想辦法重新boot,很像以前太陽的機器一樣,太陽的機器有個Ok prompt,OS掛掉,都可以進到這裡面來作一些事情,在console mode時很方便,可以reboot等等的。在一些高階點的PC server也有類似的LOM(Light out management)。GRUB的code也是free的,所以我想可以把GRUB寫進BIOS firemware中,這可以把PC做的像以前Sun的機器。

即使grub如此,GRUB在變化的SCSI/SAN環境中還是需要重新執行grub-install
 
常用的grub命令
  • grub> kernel (hd0,0)/vmlinuz
  • grub> initrd (hd0,0)/initrd.gz
  • grub> root (hd1,2) ->指定第二台硬碟的第三partition是root
  • grub> boot -> 啟動kernel
這個(hd0,0)是grub識別disk partition的方法,其他的partition可能(hd0,1) ....(hd0)指的是bus上的第一台硬碟,(hd0,0)指的是第一台硬碟的第一個primary partition。GRUB寫進的可能地方有MBR, partition, 光碟也有pxeboot的bootloader。用tab鍵可以補全。
 

硬碟MBR

使用範例,小心,不要隨便拿來玩系統上的,不熟的人會掛掉系統
  • #grub-install /dev/sda 來安裝grub的code到MBR上去,也可以
  • #grub-install /dev/sda1 裝到partition上去
內定會去/boot/grub找menu.lst,不過可以在grub-install 加上--boot-directory的選項指定。

光碟

genisoimage 主要就是用 -b來指定bootloader是哪個檔案而已,genisoimage會按照El Torito標準放到該放的第17 sector去。GRUB Legacy的是在stage2_eltorito,必須有個假的dvd root。可以自己下載來compile,裡面有stage2_eltorito,要不有裝grub在系統上就是在/usr/lib/grub/i386-pc裡面。
  • menu.lst跟硬碟一樣,放在~dvd_root/boot/grub/menu.list
  • 把光碟bootstrap放到 ~dvd_root/boot/grub/stage2_eltorito
# genisoimage -r -J -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table dvd_root > cd_grub.iso

PXEboot

  • pexboot的loader在/usr/lib/grub/i386-pc/pxegrub,把這個放到tftp server上面去,並且在dhcpd.conf的bootfile設定。
  • ~tftpboot/boot/grub/menu.lst是內定的configuration檔。

boot selector configuration 檔

Grub不僅可以開機也能作boot selector,多種stage2 loader的選擇menu,主要是去讀一個 /boot/grub/menu.lst 或者 /boot/grub/grub.conf的檔案,格式為
 
簡單menu.lst範例
 

menu.lst

default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.14-1.1644_FC4)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.14-1.1644_FC4 ro root=LABEL=/ rhgb quiet
        initrd /boot/initrd-2.6.14-1.1644_FC4.img
        title Fedora Core (2.6.11-1.1369_FC4)
root (hd0,0) 
        kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/ rhgb quiet
        initrd /boot/initrd-2.6.11-1.1369_FC4.img
title Windows XP
        map (hd0,0) (hd1,2) 
        map (hd1,2) (hd0,0)
        rootnoverify (hd1,2)
        chainloader +1
title Windows Install 
        map (hd0,0) (hd1,2) 
        map (hd1,2) (hd0,0)
        rootnoverify (hd1,2)
        chainloader (hdc)+1

 
所有的英文參數
 

GRUB 2 (1.99)

grub出了新的第二版,非常的強大,強大到太複雜了。整體架構跟原本的grub已經完全不一樣,主要他能支援不同CPU,不同boot device,不同啟動環境,連蘋果xnu都能boot了,所以任意組合太多了,新的grub主要把主體booting code拆成很多部份,然後用一些工具程式產生使用者想要的開機image。假設在PC環境下,package名稱應該是grub-pc.
  • 跟device有關的img,也就是stage1的bootstrap,目前有boot.img  cdboot.img  diskboot.img lnxboot.img  pxeboot.img,在/usr/lib/grub/i386-pc/
  • grub內部命令處理的主體code,kernel.img,也在/usr/lib/grub/i386-pc下
  • 其他特殊相關module : 例如讀取ext2檔案系統的code就獨立成為一個模組,chain load的也是一樣。如果系統有裝gurb 2 pacakge,通常會裝到/usr/lib/grub/下面去。目前有好多module,有filesystem的,有chainload的,有load背景,有i18n的等等。
GRUB下載 ,最好用
git clone git://git.savannah.gnu.org/grub.git
得到最新的code。他的source code需要真的compile才會產生bootloader,不像syslinux的下載來就有binary。需要flex, bison兩個package來compile。最後在grub-core目錄裡面有boot.img  cdboot.img  diskboot.img lnxboot.img  pxeboot.img等。這些就是跟device有關的img,而要做出一個可以boot的image,要用grub-mkimage命令來做出各種不同的booting image。每次的grub-mkimage就是把stage1.img + kernel.img + 想要的module整合成一塊新的可開機image檔。這個主要是grub 2不光光支援不同的device的stage1,他還支援不同的CPU,所以後來變這麼多種組合。否則的話,因為無論怎樣前兩個一定都是各種不同的binary,幹麼不做給user就好,而最後那個模組,也就把他寫進grub.cfg檔就好。
 
grub-mkimage跟grub-setup是所有工具的基本所在,grub-mkimage會根據參數建造出一個core.img,然後加上各個bootstrap就是真的可以boot的image檔。例如grub-mkrescue這個創造iso的工具是用shell寫得,打開來看,他下面有命令是類似這樣的
 
$ grub-mkimage -O i386-pc -o core.img --prefix=/boot/grub/ iso9660 biosdisk multiboot
 
其中iso9660 biosdisk multiboot就是放進需要的模組。說穿了就是用kernel.img加上這些將來會自動load的模組形成一個core.img,然後將來再加上cdboot.img或者pxeboot.img來形成新的開機image。
 
跟前面版本的一些重要的差異
  • 硬碟名改變  不再由(hd0)開始,改由(hd1)表示第一硬碟
  • 設定檔改變  不再是menu.lst,改叫grub.cfg,因為已經不再單純是作menu了,並且有一個grub-mkconfig命令幫忙產生。手動也是可以啦。
  • 命令改變     由於GRUB 2已經不再單純的只boot linux,所以以前的kernel命令改成linux這個命令。其他的命令變得很多很複雜,也可以寫script等等。
GRUB2 雖然很強大,但他還是不能隨便boot別的image,很奇怪,例如我從grub2的cd bootloader起來後,要再去別的cd bootloader就不行,他的chainload好像只能在硬碟而已,不像syslinux可以亂boot.

硬碟與USB MBR

使用範例,小心,不要隨便拿來玩系統上的,不熟的人會掛掉系統,一樣用grub-install這個命令,多了grub-setup命來來設定參數
 
# grub-install /dev/sdb
# grub-install --modules 'fat ext2' /dev/sda1
# grub-setup --root-device='(hd0,1)' /dev/sdb
 
grub.cfg跟一堆模組一樣內定放在/boot/grub/下面,也是可以用--boot-directory改變。要裝在usb上,先把usb mount上/mnt,用上--root-directory這個選項

# grub-install --root-directory /mnt /dev/sdb

這時會在/mnt/boot/grub下產生跟/boot/grub類似的檔案,但這時要自己去寫/mnt/boot/grub/grub.cfg。常用就兩個選項
 
  • --directory : 告訴 grub-install 去哪找i386-pc的模組來組裝。內定是/usr/lib/grub/i386-pc
  • --root-directory : 最後裝的目的地。會放在這個目錄的boot/grub下。

光碟

$ grub-mkimage  -O i386-pc -o core.img --prefix=/boot/grub/ iso9660 biosdisk multiboot lnxboot
$ cat /usr/lib/grub/i386-pc/cdboot.img core.img > eltorito.img
 
跟硬碟上的一樣,gurb.cfg還有模組放在~dvd_root/boot/grub/下面,不過可以看出來用--prefix可以改變內定的grub.cfg位置。
 
最後這個eltorito.img就是要給genisoimage使用的,也就是以前的stage2_eltorito,也就是跟syslinux的isolinux.bin類似的效果。
 
$ genisoimage -hfs -r -J -b boot/grub/eltorito.img -no-emul-boot -boot-load-size 4 -boot-info-table dvd_root > cd_grub.iso

PXEboot

pxeboot的image也可以像光碟那樣建造,
 
$ grub-mkimage -O i386-pc-pxe -o core.img --prefix=/boot/grub pxe pxeboot multiboot lnxboot
 
不過我們可以用他提供的一個grub-mknetdir來
 
$ /sbin/grub-mknetdir -O i386-pc-pxe -o tftpboot
 
就可以得到一個新目錄tftpboot,裡面有boot/grub/i386-pc,然後裡面有很多*.mod,還有一個core.0,這個就是grub的pxeboot檔,在DHCP的bootfile就是要填上這個。
 
有兩個要注意的
  • 模組檔*.mod內定要放在~tftpboot/boot/grub/i386-pc/下面,所以如果沒有的話,是沒有辦法讀到模組啟動。
  • grub.cfg檔內定在~tftpboot/boot/grub/grub.cfg

boot selector configuration檔

Grub 2的configuration檔統一改名/boot/grub/grub.cfg更棒,可以有條件判斷,然後load相關的對應模組。可以說是很像EFI的。在硬碟光碟上為/boot/grub/grub.cfg,在pxeboot上為~tftpboot/boot/grub/grub.cfg。
 
簡單grub.cfg範例
 

grub.cfg for grub 2

set default=0
set timeout=5
 
set gfxmode=640x480
set scrdir=/gyoza/bootscr
set localedir=/gyoza/locale
set prefix=/boot/grub
 
# 切割多個cfg檔並且叫用的module
insmod configfile
# 使用背景圖檔的模組與命令
insmod vbe
insmod vga
insmod gfxterm
insmod video
insmod jpeg
 
terminal_output gfxterm
loadfont $scrdir/unicode.pf2
background_image $scrdir/bg/cisco_duck.jpg
 
submenu 'Install System' {
        configfile $prefix/cfg/iso_install.cfg
}
submenu 'Run Live System' {
        menuentry 'Ubuntu' {
            linux   /boot/ubuntu/vmlinux
            initrd  /boot/ubuntu/initrd
        }
        menuentry 'Knoppix' {
            linux   /boot/knoppix/vmlinux
            initrd  /boot/knoppix/initrd
        }
}
 
menuentry 'GNU/Linux, Redhat with 2.6.39.2' {
        insmod ext2
        set root=(hd1,2)
 
        linux   /boot/vmlinux-2.6.39.2 root=/dev/sda2 ro
        initrd  /boot/initrd-2.6.39.2.gz
}
 
# 可以直接打中文
menuentry '中文選單' {
        insmod linux
}
 
所有的英文參數
 

GRUB Shell

grub 2的shell命令比以前多,但主要麻煩的是help這個命令模組不再是自動就有的,必須有一開始創造image時有放進去,不然就是gurb的目錄下有help.mod,這時要用insmod先load help進來才有

grub 2的啟動是當初在core.img裡面會先embedded一點點的cfg,用grub-install跟grub-setup去設定root跟prefix這兩個變數,通常是用search.fs_uuid xxxxxxxx root來設定root,然後內部會自動去insmod normal這個模組,並且用上normal命令來讀取grub.cfg,進到所謂的normal mode,但是如果讀不到就會進到rescue mode,這時grub本身內建的命令只有四個
  • ls 看檔案在哪裡, ls (hd0)/boot,要使用ls必須grub能讀得懂filesystem,所以grub-install時最好都先加上--modules 'fat ext2'兩種filesystem
  • insmod load模組用的,通常ls (hd0,1)/boot/grub下看到有哪些mod檔,就用insmod來load
  • set/unset 用來看變數值與變數的設定,不像bourne shell,必須用set var=xxx來設定
所以要先重設root, prefix然後執行insmod normal, normal來執行自己寫的grub.cfg。

其他的命令都會跟著相對應的mod檔案才有,例如boot linux用的boot linux initrd在linux.mod load進來後才有的。
 
還有其他保留字跟很多內定變數
  • 類似shell的for in; do done, while ; do done, if elif else fi, case esac
  • menuentry title { cmds }

syslinux

syslinux是一個很常用在光碟上與pxeboot的bootloader,但是其實他也有硬碟上的loader,只是很奇怪的是大部分硬碟用grub,光碟跟pxeboot用syslinux,主要是syslinux很久以前就能隨便由一個stage1 bootloader到另一個stage1 loader,GRUB不允許真是很奇怪。在syslinux.zytor.com下載,然後解開。裡面有各種的stage1 loader. 去下載來後解開,core裡面有mbr.bin, isolinux.bin, pxelinux.0。syslinu 4.x 不像GRUB 2太複雜到支援其他的CPU跟platform, 所以他沒有必要搞得那麼複雜,所以直接提供i386上的bootstrap就好,isolinux.bin, pxelinux.0都直接可以拿來用。syslinux是在bootloader上用模組的先驅,他提供自己的api,並在這個基礎上,提供了一些模組在com32目錄下,例如能load multiboot的mboot.c32,能夠讀懂menu命令產生menu的menu.c32,或者能解讀jpg檔使用背景圖片的vesamenu.c32等等。

硬碟MBR

mbr/mbr.bin是硬碟MBR bootloader, 然後用syslinux這command把Linux loader
  • dd if=mbr.bin of=/dev/sda 
  • syslinux /dev/sda1
會在根目錄多放進一個ldlinux.sys的檔案。

光碟

isolinux.bin是光碟的linux boot loader,用genisoimage裡面的選項把他寫進去光碟。必須先造一個假的dvd_root根目錄,把所有dvd檔案copy進去。裡面作個isolinux目錄,把isolinux.bin跟isolinux.cfg放到裡面。
  • geoisoimage -b isolinux/isolinux.bin dvd_root > dvd.iso

PXEboot

pxelinux.0是pxe boot的Linux boot loader,就是pxelinux.0,一樣要放到tftp server上的tftp根目錄去,redhat在/tftproot, debian在/var/lib/tftproot,tftproot下建立一個pxelinux.cfg的目錄,裡面有個檔案叫default就是跟syslinux.cfg類似的conf檔案。其實pxelinux的conf檔可以指定特定的mac, ipv4去讀特定的conf檔,只是我很少這麼作。

boot selector configuration檔

syslinux的loader執行後,會去找一個configuration檔,這是可以選擇不同的stage2 loader的選擇menu。這個檔的檔名根據boot device不同分別為
  • syslinux/syslinux.cfg
  • isolinux/isolinux.cfg
  • pxelinux.cfg/default
簡單格式範例

syslinux.cfg

PROMPT 0
TIMEOUT 30

label debian
  menu LABEL Debian 6.0
  kernel debian/linux
  append initrd debian/initrd.gz

label fedora
  menu LABEL Fedora 13
  kernel fedora/vmlinuz
  append initrd fedora/initrd.gz
 
所有的參數也是很多,基本的
  • syslinux   linux/syslinux是個32位元的執行檔,如果要64位元的要自己編譯。基本參數,應該要會的。
  • memdisk memdisk/memdisk可以模擬一個假disk,可以用來boot floppy或者iso image. 他這主要是攔截BIOS int 13到自己的處理routine來,不過現在的OS通常一load完前面,就進protect mode,所以int 13就失效,就看不到被int 13 mapping的drive,所以用這開iso還是有點麻煩。
  • menu      com32/menu/menu.c32跟vesamenu.c32是可以有漂亮的menu bar跟圖形介面模組。
  • mboot     com32/mboot/mboot.c32是可以用來boot所有支援multiboot規格的kernel。包括Linux, BSD, Solaris, ESX都有。
  • chain       com32/chain/chain.c32 是可以boot其他partition 512bytes 或其他的bootloader,這通常用來boot windows等其他bootloader。

syslinux 5

syslinux version 5.0以後也開始跟grub 2一樣玩起堆疊模組,主要是支援越來越多越來越複雜,code要重複使用等,不同地方有

  • ldlinux.c32 多出一個ldlinux.c32,並要跟ldlinux.sys, isolinux.bin, pexlinux.0等放在一起
  • 其他重要的libraries, libcom32.c32 libgpl.c32 liblua.c32 libutil.c32 libmenu.c32可以跟gurb 2一樣需要的才load。
    • 可以用syslinux --directory /syslinux --install /dev/sdb1來安裝到/syslinux去。
  • 其他功能的像vesamenu.c32在上面的c32有load進來,才能被load起來。目前的dependancy

ipxe

pxeboot的原理很簡單就是網路卡上有一顆ROM,裡面有程式,就是買卡裡面就自然藏有的程式,就是firmware,電腦一開機後,會自動根據一些已經定好的規則跳到這些mapping到ROM上的程式執行,pxeboot的firmware要懂DHCP然後得到IP 與tftpserver IP跟bootloader,然後懂TCP/IP stack,跟tftpserver要到那個bootloader,下載後就放到特定位址,交給他執行。因為每家晶片控制方法不同,所以firmware都是硬體公司根據晶片spec寫出藏在自家卡上的(當然晶片公司都有demo公版,台灣很多公司就是拿來改改字串就叫研發)。ipxe是一個opensource的project,他嘗試根據市面上所有的spec,寫出一個可以適用很多晶片的pxe firmware,越寫越大,現在還能boot SAN HBA, iSCSI等, 而且如果原本的網路卡上沒有firmware,還可以從usb, 光碟等地方叫ipxe出來,他會想辦法去控制網路卡來得到遠端的bootloader然後開機。

ipxe 現在是qemu裡面的訂定pxe firmware,除了能自動pxeboot外,跟grub一樣可以用Ctrl-B進到他的交談模式,裡面也是一堆命令,然後這些命令也能做成script形式,讓ipxe起來後去下載來自動執行。本來pxe firmware也只是stage 1的loader,但慢慢的ipxe越寫越複雜,跟grub, syslinux一樣,也都能當成stage2的loader,也能直接boot linux kernel。

下載回來編譯出來有src/bin/{ipxe.lkrn,ipxe.usb, ipxe.iso, ipxe.pxe}可以拿來用。

命令

跟 grub2/syslinux 有很多很像,如果有的命令沒有出現的話,那就是在build的時候沒有進去,例如console命令,目前是修改src/config/general.h src/config/console.h再重新build,同樣他能boot的種類能力也在config/general.h設定,像能boot其他的pxe image這種能力,不知道將來會不會也變成像grub2/syslinux5一樣全部動態模組化,再自己load.

  • dhcp                       去要個 IP 回來
  • route                       看 ip, netmask 與 router 是誰
  • kernel/imgload        這跟grub/syslinux的kernel一樣,由於他有網路功能,所以直接kernel http://xxx.xxx/linux就下載kernel回來了。
  • initrd/imgfetch         這跟initrd命令一樣,同樣也可http下載。
  • boot/imgexec          這跟grub2的boot一樣,跳到image去執行。
  • chain                       chain load另一個loader,例如chain pxelinux.0,這主要可以叫用遠端一個ipxe script回來執行,chain http://xxx.xxx.xxx/myboot.ipxe。
  • imgargs                   給image的參數,相當於syslinux的append

 

  • set                          改變變數值。
  • config                      很有趣,可以全螢幕去改變內定的mac, ip, next-server等變數值。
  • isset                        條件判斷
  • iseq                         條件判斷

所有命令

變數

跟 dhcpd.conf 有很多很像,這跟 grub2 一樣跟命令結合後,script 裡面可有判斷式,if 之類的與goto跳躍,甚至可以請遠端 server script 產生一個ipxe script 還回來執行。例如 chain http://xxx/boot.php?next-server=10.0.2.100&filename=mypxe.0

  • mac                         機器的mac address
  • next-server               這就是tftpserver ip
  • filename                   這就是dhcp option裡面那個filename, bootfile.

 

所有內定變數

使用script

  • 內定使用可以直接在build binary時就放進去  =>  make bin/undionly.kpxe EMBED=myscript.ipxe ,這個kpxe檔要拿來燒在ROM上的。
  • ipxe提供linux kernel/initrd形式的檔案,ipxe.lkrn (編譯的話在bin/ipxe.lkrn) 給grub2/syslinux的kernel 使用

    GRUB2範例

    直接在kernel上使用
    =================
    title iPXE
      kernel (hd0,0)/ipxe.lkrn dhcp && chain http://bootserver/boot.php
    
    用initrd叫本地端script
    =====================
    title iPXE
      kernel (hd0,0)/ipxe.lkrn
      initrd myscript.ipxe
    
  • 如果已經在跑了,趕快按Ctrl-B進到命令模式,就可以自己進去使用命令chain http://myboot.ipxe去下載來跑。ipxe有個linux範例在 http://boot.ipxe.org/demo/boot.php

menu範例

ipxe.cmd範例

#!ipxe

:start
menu Gyoza/OS multi-installation
item --gap Linux:
item debian     Debian stable 64 bit net install
item fedora     Fedora20 64 bit net install
item
item --gap Windows:
item win7       Windows 7
item win2k8     Windows 2008 Server
item
item --gap tools
item shell              ipxe shell
item
item back               Go Back
choose os && goto ${os}

:shell
shell
goto start

:debian
dhcp || goto debian
kernel http://192.168.11.101/downloads/linux
initrd http://192.168.11.101/downloads/initrd.gz
boot

:fedora
chain http://192.168.11.101/fedora.ipxe
 
:back
exit

主要就是用menu定義大標題,item後第一個是id第二個是title,用choose把選擇的id設定到os這個變數去,並且跳到${os}這裡面的id去,如果是debian,就一直要拿到dhcp得到的ip,然後去拿kernel, initrd最後boot。
arrow
arrow
    全站熱搜

    BB 發表在 痞客邦 留言(0) 人氣()