DHCPサーバ無しでArchLinuxをiPXEブートに挑戦

この記事はArch Linux Advent Calender 2015の10日目です。

* DHCPサーバ無しでArchLinuxをiPXEでブートすることはできないようで、この壁を乗り越える！

## 参考

* [ipxe.iso](https://releng.archlinux.org/pxeboot/) DHCPサーバがある場合、公式イメージ使えば良い。
* [iPXE - open source boot firmware [buildcfg:ping_cmd]](http://ipxe.org/buildcfg/ping_cmd)
* [GitHub - antonym/netboot.xyz: Multiple Operating System iPXE Installer](https://github.com/antonym/netboot.xyz)


# ipxeビルド

* 公式のipxeがダメならビルドすればいいじゃないの

```bash:
git clone git://git.ipxe.org/ipxe.git
cd ipxe/src
```

```bash:パッケージが不足している場合以下を入れる
apt-get install -y liblzma-dev genisoimage syslinux isolinux
```

```bash:make
make
```

* Pingを有効にする場合[Ping command](http://ipxe.org/buildcfg/ping_cmd)を参考に`config/general.h`を修正する。

```diff:config/general.h
- //#define PING_CMD              /* Ping command */
+ #define PING_CMD              /* Ping command */
```

```bash:bin/ipxe.usbにmyscript.ipxeを含めて生成
make bin/ipxe.lkrn EMBED=myscript.ipxe
make bin/ipxe.usb EMBED=myscript.ipxe
make bin/ipxe.iso EMBED=myscript.ipxe
```

## myscript.ipxe

* GRUBに渡されるパラメータは以下ファイル
    * http://releng.archlinux.org/pxeboot/boot/cfg/arch64.cfg

```bash:myscript.ipxe
#!ipxe

#################
#network settings
#################
set dns 8.8.8.8
set net0/netmask 255.255.255.0
echo -n IP address: && read net0/ip
echo -n Default gateway: && read net0/gateway

#################
:boot_menu
#################
menu
    item arch_jp      ArchLinux x86_64 jp mirror
    item arch_us      ArchLinux x86_64 us mirror
    item ipxe_dhcp    DHCP
    item ipxe_ifopen  ifopen net0 (for static ip.)
    item ipxe_config  Enter iPXE config
    item ipxe_shell   Enter iPXE shell

choose --default config --timeout 30000 target && goto ${target}

#################
# menu
#################
:ipxe_dhcp
    dhcp
    goto boot_menu

:ipxe_ifopen
    ifopen net0
    goto boot_menu

:ipxe_config
    config
    goto boot_menu

:ipxe_shell
    shell
    goto boot_menu

:arch_jp
    echo ip=${net0/ip}::${net0/gateway}:${net0/netmask}
    # ftp.jaist.ac.jp => 150.65.7.130
    set source http://150.65.7.130/pub/Linux/ArchLinux/iso/latest
    kernel ${source}/arch/boot/x86_64/vmlinuz archiso_http_srv=${source}/ archisobasedir=arch ip=${net0/ip}::${net0/gateway}:${net0/netmask}
    initrd ${source}/arch/boot/x86_64/archiso.img
    boot

:arch_us
    echo ip=${net0/ip}::${net0/gateway}:${net0/netmask}
    # mirrors.abscission.net => 107.191.116.135
    set source http://107.191.116.135/archlinux/iso/latest
    kernel ${source}/arch/boot/x86_64/vmlinuz archiso_http_srv=${source}/ archisobasedir=arch ip=${net0/ip}::${net0/gateway}:${net0/netmask}
    initrd ${source}/arch/boot/x86_64/archiso.img
    boot
```

インターネットに接続できない場合はifopen net0が必要。
[iPXE - open source boot firmware [cmd:ifopen]](http://ipxe.org/cmd/ifopen)


## initrd.imgを解読する方法

* [archiso/README.bootparams at master · djgera/archiso](https://github.com/djgera/archiso/blob/master/docs/README.bootparams)
* [[arch-releng] [RFC] [PATCH] [archiso] Add DNS resolver support to archiso_pxe_common](https://lists.archlinux.org/pipermail/arch-releng/2011-November/002176.html)

```bash:archiso.imgのダウンロード
wget http://ftp.jaist.ac.jp/pub/Linux/ArchLinux/iso/latest/arch/boot/x86_64/archiso.img
```

```bash:archiso.imgの展開
mv archiso.img archiso.cpio.gz
xz -d archiso.cpio.gz
mkdir tmp && cd tmp
cpio -id < ../archiso.cpio
```

* [Archiso (Nederlands) - ArchWiki](https://wiki.archlinux.org/index.php/Archiso_%28Nederlands%29)
* [archiso.git - The official archiso scripts repo](https://projects.archlinux.org/archiso.git/)
    * grubに`dns`引数追加するパッチが必要じゃないかな

# Grub2で起動確認

* [Arch Linux - Netboot Live System](https://releng.archlinux.org/pxeboot/)

```bash:/etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.

menuentry 'Arch Linux Netboot Environment' {
  set root='(hd0,1)'
  linux16 /ipxe.lkrn
}
```

```bash:
update-grub
```

# Qemuで動作確認

```bash:ipxe.lkrnからブートする場合
qemu-system-x86_64 -m 1G -kernel bin/ipxe.lkrn \
  -net nic -net user
```

```bash:ISOイメージからブートする場合
qemu-system-x86_64 -boot d -cdrom bin/ipxe.iso \
 -net nic -net user
```

![pxe1.png](https://qiita-image-store.s3.amazonaws.com/0/25728/a25b0566-14bb-ac67-c74a-5d875ea08d29.png)

![pxe2.png](https://qiita-image-store.s3.amazonaws.com/0/25728/5b6ea2a3-ec6d-a6ff-d1bc-2ac1041c7928.png)

![pxe3.png](https://qiita-image-store.s3.amazonaws.com/0/25728/e2844758-3292-a3f7-6cb3-9d06e28bbb0b.png)

![pxe4.png](https://qiita-image-store.s3.amazonaws.com/0/25728/eb97dcb3-40e9-7875-d9cb-5845af2793a4.png)

* dnsが0.0.0.0になるんだよね・・・

![pxe5.png](https://qiita-image-store.s3.amazonaws.com/0/25728/1caed930-adfe-d684-c7c8-c54c457a2a1c.png)

* boot完了


```bash:起動完了したらresolv.confを作る。
echo nameserver 8.8.8.8 > /etc/resolv.conf
```

# まとめ

* iPXEイメージはたったの`1MB`。
* ipxe.usbイメージを/dev/sdaにddすればブートする手軽さ。