2015年2月22日 星期日

extlinux 多重開機分解動作教學

為什麼開機程序要分那麼多步? 從 windows 移民到 linux 的第一步, 最頭痛的就是如何安裝/設定開機管理員, 讓 windows 及各種不同版本的 linux 和平共存。 本文用 finnix 開機光碟練習把 extlinux 開機管理員安裝到隨身碟上。 建議在 「不用的舊電腦」 上面練習, 不會有 「被覆蓋/不能開機」 的風險。 等你很習慣手動把親朋好友的任何資料隨身碟 (或隨身硬碟) 變成 finnix 開機隨身碟, 未來要在自己的硬碟上面安裝開機管理員, 也就變得輕而易舉了。

不想學細節的讀者可以改用 mbootu2 它把 「灌 MBR、設定開機分割、安裝 extlinux」 幾個動作打包在一起, 可以直接把一顆隨身碟變成開機隨身碟, 並且不會動到隨身碟內原來的資料。

Linux 熟手請看粗體字還有 「安裝 extlinux 及外掛模組」、 「設定開機選單」、 「總結」 這幾節即可。 另外也推薦強大但有點難設定的 grub2 給熟手。

一、 行前準備

  1. 準備一支沒在用的隨身碟, 至少 512MB。
  2. 燒一片 阿貴版 finnix 開機光碟
  3. 準備兩部電腦: 「退休機」 上面已無任何有用資料, 就算毀了也沒關係, eeepc 的等級 ok; 「觀察機」 專門拿來測試隨身碟是否可以成功開機, 可以是你平常工作的機器。 所以觀察機的 BIOS 必須支援隨身碟開機; 或者更理想的是: 在觀察機上面安裝 qemu-kvm (一個指令啟動, 免設定!) 這樣重開機比較快, 而且你還可以繼續在觀察機上面做其他事情。

[2/26 更新: 如果你用 ckhung15c 版之後的阿貴版 finnix, 裡面已安裝 qemu。 請把本文所有 kvm ... 指令改成 qemu-system-x86_64 -enable-kvm ... 即可。]

二、 開機流程基本概念

硬碟分割與開機流程 首先複習一下 硬碟分割的觀念 (重要!) 然後了解一下電腦開機的大致流程:

  1. 位於主機板的 BIOS 取得控制權, 決定要把控制權交給哪一顆硬碟/光碟/隨身碟 (或網路)。
  2. 某顆硬碟上的 Master Boot Record (MBR) 取得控制權, 決定要把控制權交給哪一個分割。
  3. 某個分割上的 Volume Boot Record (VBR) 取得控制權、 印出選單、 讓使用者選擇要把控制權交給哪一個 kernel 檔並交代特殊要求。

「從 BIOS 接手, 一直到某個 kernel 接手」 負責安排這一切流程的那支程式, 本身其實獨立於任何作業系統之外, 並且會把自己安裝到 MBR 與 VBR 裡面去。 這支程式稱為 boot loader 開機管理員。 Linux 提供很多不同的選擇: grub legacy (0.97)、 grub 2、 lilo、 syslinux 都是常見的 boot loader。 詳見 boot loader 比較表

以下的實作要採用 extlinux。 它跟 makebootfat、 isolinux 等等開機管理員都用到 syslinux 的程式碼。 或者可以說, extlinux 算是 syslinux 的一個分枝。 關於開機流程更詳細的解釋請見:

  1. Linux Boot Loaders Compared by L.C. Benschop: 2003 年很舊的文件, 關於各家軟體的資訊有些過時, 但整體而言觀念解釋得很清楚。
  2. 開機流程與 Boot Loader by 陳柏菁: 很詳細的中文解釋

三、 切割及格式化隨身碟

  1. 用 finnix 光碟啟動退休機。
  2. ls /dev/?d? 查看退休機看見哪些軟碟/硬碟/隨身碟。 fd0 是軟碟、 sda 是硬碟或隨身碟。 比方說我們看到的是 /dev/sdv 好了。
  3. fdisk -s /dev/sdv 確認一下隨身碟的大小。
  4. fdisk -l /dev/sdv 查看隨身碟切割的狀況。 通常隨身碟出廠時, 只會切一個主要分割。

接下來, 請想好你的隨身碟希望切成幾塊、 各有多大。 建議第一分割 (primary partition 1) 的 type 設成 C (W95 FAT32 LBA)。 這個格式夠舊, 幾乎所有的作業系統都認得。 未來可以把它當成資料檔分割, 讓各種版本的 windows 與 linux 在此交換資料。 另外, 我會把各種版本的 linux 分別放在各自獨享的 logical partitions 裡面。

然後參考以下任一篇文章來切割你的隨身碟:

  1. 聯成電腦劉冠麟老師: 規劃您的Linux磁碟空間工具-fdisk
  2. 朝陽資工王德譽老師: 新增一顆硬碟
  3. gtwang: 替 Linux 新增硬碟(磁碟分割、格式化與掛載)
  4. Gentoo Linux 文件-- 準備磁碟

結束後, 用 fdisk -l /dev/sdv 再確認一次切割成功。 格式化每個 dos/windows 分割, 例如 mkfs -t vfat /dev/sdv1 、 也格式化每個 linux 分割, 例如 mkfs -t ext4 /dev/sdv5 。 [2016/12/17 注意: 根據 官網, 因為新版的 mke2fs 預設啟用 "64bit" 新功能, 而 extlinux 目前還不支援, 所以必須這樣拒絕啟用 64bitmkfs -t ext4 -O \^64bit /dev/sdv5 。]

四、 拷貝 finnix

  1. df 查看已掛載的分割。
  2. mount /dev/sdv1 掛載資料分割。
  3. df 再次查看已掛載的分割。 會多出一列。 注意它的總容量 (1k-blocks 欄位)、 已使用空間 (Used 欄位)、 尚可使用空間 (Available 欄位)。 也注意到 finnix 把它掛載在 /media/sdv1 這個目錄 (Mounted on 欄位)。
  4. cp -a /cdrom /media/sdv1/finnix-xyz 把整張 finnix 光碟拷貝到 /media/sdv1 底下, 依據 finnix 的版本命名一個新的目錄。 (這樣以後若想安裝新版的 finnix 才不會亂掉。)
  5. df 再次查看已掛載的分割, 及每個分割所使用掉的空間。

如果希望將來你的隨身碟能夠 毫邁帥氣裸奔, 那就還要:

  1. cd /media/sdv1/finnix-xyz
  2. perl -pe 's# # finnix-xyz/#' md5sums > ../md5sums (請把 finnix-xyz 改成你當初拷貝 finnix 的目錄名稱)

最後 cd ; umount -a ; df 卸載所有分割, 並且確認 df 已經看不到 /dev/sdv1 /dev/sdv5 等等隨身碟上的分割, 然後才拔出隨身碟。

五、 安裝 extlinux 之前的各種開機錯誤訊息

拿隨身碟來啟動觀察機裡的 qemu-kvm 虛擬機kvm /dev/sdx 有可能看到幾種不同的錯誤訊息, 以下分別討論。 (但如果你直接用觀察機本身硬體開機, 看到的訊息可能不太一樣, 因為各家的 BIOS 會印不同的訊息。)

如果虛擬機開機時看到: Booting from Hard Disk... 那表示這顆隨身碟的 MBR 毀了; 虛擬機的 BIOS 印出這個訊息之後, 就停在這裡, 沒有下文。 可以直接暴力關掉觀察機的虛擬機視窗。 把隨身碟插回退休機, 不需要掛載。 ls -l /usr/lib/EXTLINUX/ (沒有這個目錄嗎? 請先用 dpkg -L extlinux 找到正確的目錄) 看到有三個常用的 mbr 檔。 把最常用的那一個寫進隨身碟: dd < /usr/lib/EXTLINUX/mbr.bin > /dev/sdv bs=440 count=1 正常來講, 隨身碟買來, 內建的 MBR 就是 ok 的, 應該不需要這一步。 [超過 2T 的硬碟需要改採用 gpt 格式, 所以需要多一步: sgdisk /dev/sdv --attributes=1:set:2 詳見 這篇。]

MBR ok; 未指定由哪個分割開機 如果虛擬機開機時看到 "operating system load error" 然後虛擬機試著想從別的裝置 (軟體及網路) 開機, 這表示忘了設定 active partition。 請回到 fdisk 那一步, 把隨身碟第一分割設定為 active。

qemu 指令下錯了: 不能從一個分割開機! 如果虛擬機開機時看到 "Booting from Hard Disk... boot error" 這表示你在啟動虛擬機時, 給錯參數: 應該指定整顆硬碟或隨身碟 (/dev/sdx) 而不是一個分割 (/dev/sdx5)。 若要啟動單一分割, 則必須 在 qemu 命令列上指定 vmlinuz 跟 initrd.img

MBR 想把控制權交給第一分割的 VBR,
但這個 VBR 是空的 如果看到 "This is not a bootable disk. Please insert a bootable floppy and press any key to try again ..." 那麼恭喜! 你可以進入下一節了。 這表示 MBR 想把控制權交給第一分割的 VBR, 但這個 VBR 是空的。

六、 安裝 extlinux 及外掛模組

關掉觀察機的虛擬機視窗。 把隨身碟插回退休機,

  1. mount /dev/sdv1
  2. df 觀察一下空間使用狀況。
  3. cp -a /usr/lib/syslinux /media/sdv1/ 把 extlinux 所需要用到的設定檔、 圖片檔、 外掛模組等等複製到隨身碟第一分割的 syslinux/ 子目錄裡面去。
  4. df 確認 /media/sdv1 多使用了好幾 MB。
  5. extlinux -i /media/sdv1/syslinux 真安裝 extlinux!

卸載隨身碟、 重開觀察機的虛擬機。 不論是進入圖形模式但無法開機, 或是停留在文字模式並且看見 syslinux 的錯誤訊息, 都算是有進展, 可以直接進入下一節。

七、 設定開機選單

extlinux 已安裝成功! 但找不到設定檔 extlinux -i /media/sdv1/syslinux 這個指令有兩個效果: (1) extlinux 會找到這個目錄所在分割, 把自己裝進它的 (/dev/sdv1 的) VBR (2) 將來開機程式碼會在這個目錄底下尋找設定檔。 它優先尋找 extlinux.conf , 其次尋找 syslinux.conf。 右圖的開機錯誤訊息顯示 extlinux 已成功安裝, 但找不到設定檔。 (WARNING: No configuration file found)

請把 extlinux.conf 範例檔以及退休機上的 /cdrom/boot/syslinux/*.jpg 拷貝到 /media/sdv1/syslinux 。

設定檔後半段, 每一組 label/kernel/append 指令代表一個開機選項。 這些語法可以從眾家 linux 安裝光碟某處的某個設定檔 (例如 boot/isolinux/isolinux.cfg) 拷貝過來、 修改路徑。 (記得嗎? extlinux/isolinux/syslinux 系出同門) 設定檔第一句的 default 指定了要從哪一個選項開機。

最重要的三件事是 kernel 的路徑、 initrd 的路徑、 還有 root 位於哪個分割區。 前兩者的路徑相對於 sdv1 的根目錄。 建議善用 ls、 tab 鍵、 剪貼, 這樣比手打更不容易出錯。

除了以一般正常方式啟動 linux 之外, extlinux 還可以啟動光碟映像檔 (.iso): kernel 設成 memdisk, initrd 設成 .iso 檔的路徑, 並且在 append 後面加上 「iso raw」, 類似這樣:

label clonezilla
        menu label Clonezilla live
        kernel memdisk
        append initrd=/clonezilla-live-2.5.0-25-amd64.iso iso raw

但這會把整張光碟都載入記憶體裡, 所以需要較大的記憶體。 這種情況下, 如果是隨身碟開機, 那麼開完機之後, 隨身碟就可以拔走了。 從 這裡 學來的; 也請見 syslinux 官網文件

想要啟動 windows, 請見 chainloading

當你在 extlinux.conf 裡面養了很多隻 linux 之後, 可能會想要學習更多 menu 的語法

八、 設定開機畫面的背景圖片

設定檔裡的這一句 menu background cloud-city.jpg 是在設定背景圖片。 假設你有一張 flower.jpg 背景圖檔。 請用 ImageMagick 套件的 convert 指令把它轉成 extlinux 預設接受的大小與格式: convert -interlace none -resize 640x480 flower.jpg flower-extlinux.jpg。 成功之後, 可以在 extlinux.conf 裡面加一句 menu resolution 1024 768 並且改試 1024x768 的圖檔。

找不到某個外掛模組的錯誤訊息 但其實 extlinux 本身並沒有 「載入圖片」 的功能。 這功能需要靠一個外掛模組 vesamenu.c32 來完成。 所以還需要加這一句 ui vesamenu.c32

這些外掛模組的程式碼放在哪裡呢? 這一句 path modules/bios/ 就是在指定外掛模組所在路徑。 因為當初我們安裝在 /dev/sdv1 分割的 /syslinux 子目錄底下, 所以 extlinux 懂得去 /syslinux/modules/bios/ 底下尋找 vesamenu.c32 。 我們採用的是傳統的 BIOS 模式, 所以 efi32/ 跟 efi64/ 兩個子目錄其實可以刪掉。 但模組之間有相依性, 所以 bios/ 底下其他的模組請勿刪除。 詳見 syslinux library modules

版本太舊, 不認得 path 指令 注意: syslinux/extlinux 5.0 之後的版本才有 path 指令。 較舊的版本會印出 「Unknown keyword in configuration file: path」。 這時請刪掉 path 指令, 並直接將 *menu.c32 拷貝到 extlinux.conf 同一目錄下即可。

如果看到 「Failed to load COM32 file ...」 之類的訊息, 表示找不到外掛模組或外掛模組版本不合。 除了檢查 ui 跟 path 這兩句之外, 也請確認: 模組檔跟 extlinux 指令必須來自同一個版本! 例如我先前在甲版 linux 上面用 syslinux 製作開機隨身碟, 但卻把乙版 linux 的模組檔拷貝到隨身碟上, 即使路徑正確、 檔案有找到, 也會出現相同的錯誤訊息。

九、 總結

長久以來我一直在用 grub 0.97。 因為 grub2 的設定太複雜, 所以一直不想學。 但是 grub 0.97 快要被淘汰了, 於是被逼著學 extlinux。 (主要參考 Akkana Pec 的這篇。) 它等於是改良版的 syslinux -- 可以安裝在 fat、 ntfs、 ext2/3/4、 ... 等等各種檔案系統的分割上。 對 linux 熟手而言, extlinux 超簡單, 只需要做三個動作: (1) 確認 MBR 裡面有標準的啟動程式碼 (2) extlinux -i /path/to/dir 把 extlinux 安裝到 VBR (3) 寫好設定檔, 放在 /path/to/dir。 如果需要背景圖, extlinux 比 grub 0.97 方便且自由度較高; 設定檔的語法跟機制又比 grub2 簡單很多。 至於開機命令列編輯 (按 tab 鍵進入編輯模式; 按 Esc 鍵離開) 等等基本功能也都不輸 grub。 所以我捨棄了 mk-boot-usb 所採用的 grub 0.97, 改拿 extlinux 重寫了 mbootu2

2 則留言:

  1. 這一篇可以參考下:
    http://www.kenming.idv.tw/building_the_usb_multiboot-01_use_grub2

    不得不使用 Grub2 的原因是因為它支援 Legacy BIOS / EFI 方式最為完整;倒是不曉得 extlinux 有否支援 UEFI ? (沒爬文不知道)。

    回覆刪除
  2. 你好 你介紹的文章很棒 但我遇到問題導致無法開機 可以請教你嗎? 請盡快回復我 感恩

    回覆刪除