iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0
自我挑戰組

30 天 hypervisor 入門系列 第 26

Day 26 GRUB 在 Hypervisor 上啟動

  • 分享至 

  • xImage
  •  

前幾天,我已經完成 BIOS 初始化、磁碟 I/O 模擬等。今天的目標,是讓虛擬機真正載入 GRUB,讓開機流程第一次跨過韌體這一層,進入可互動的 bootloader。

建立 GRUB 磁碟映像

為了讓 Hypervisor 能啟動 GRUB,我們需要一顆可以開機的映像檔。
映像檔必須同時包含:

  • MBR(stage1)
  • GRUB stage2 loader
  • 一個 minimal 的 grub.cfg
IMG=build/grub-demo.img
SIZE=64M
MNT=/mnt/grubdemo

# 建立空白磁碟與分割
mkdir -p "$(dirname "$IMG")" && sudo truncate -s "$SIZE" "$IMG"
sudo parted -s "$IMG" mklabel msdos
sudo parted -s "$IMG" mkpart primary ext2 1MiB 100%

# 格式化並掛載
LOOP=$(sudo losetup --find --show --partscan "$IMG")
sudo mkfs.ext2 -F "${LOOP}p1"
sudo mkdir -p "$MNT" && sudo mount "${LOOP}p1" "$MNT"

# 放入最小 grub.cfg
sudo mkdir -p "$MNT/boot/grub"
sudo tee "$MNT/boot/grub/grub.cfg" >/dev/null <<'EOF'
set timeout=10
set default=0
menuentry "GRUB demo" {
    echo "Hello from GRUB running on our hypervisor!"
    sleep --interruptible 5
}
EOF

# 安裝 GRUB 到 MBR
sudo grub-install --target=i386-pc \
  --boot-directory="$MNT/boot" \
  --modules="normal biosdisk part_msdos ext2" \
  "$LOOP"

sync && sudo umount "$MNT" && sudo losetup -d "$LOOP"
echo "GRUB demo image ready at $IMG"

老實說,這段原本我打算自己搞。看了一些資料感覺有點繁瑣,這裡就用 codex 幫我生成,效果還不錯。

啟動 GRUB

接著重複之前的工作,不過我們把載入的檔案從 boot.bin 改成 grub.img,也就是透過 grub-install 製作的 GRUB 映像檔。以下是輸出結果:
https://ithelp.ithome.com.tw/upload/images/20251010/20178814dr9jCAhbgY.png
BIOS 完成初始化後,透過虛擬化的 ATA 模組發出 read LBA=0 請求,成功讀取 MBR。接著控制權交給 GRUB,這時它嘗試向某些 I/O port 寫出除錯訊息。
目前 Host 僅實作少數必要的 port,所以當 GRUB 調用尚未實作的 port,例如這裡的 0x00DB 時,Hypervisor 會在終端輸出:

[host] unhandled IO port 0x00db dir=out size=1 count=1

並停止 Guest,這個 log 用於提醒這是沒有實現的 I/O 操作。接下來我們的任務是根據 log 一步一步擴充這些 I/O 操作,讓 GRUB 真的可以跑起來。


上一篇
Day 25 在 QEMU 上把 GRUB 跑起來
系列文
30 天 hypervisor 入門26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言