Sunday 7 October 2012

Netbooting NetBSD in KVM

So, I feel the need to netboot various OSes again. Because I can.

Output to serial is most convenient, my MIPS box is serial only, and besides I have no space for a bunch of extra monitors.

In the IA32 case, the (very very nice, though old) Diskless NetBSD howto directs me to use "pxeboot_ia32_com0.bin".

Problem #1: since NetBSD 4 or so, this isn't in base.tgz anymore.

David Laight points out that it can be created like so using the netbsd installboot(8) command. Though I have no NetBSD yet.

Ah well. I'll boot a more normal NetBSD on KVM and create that, then. Quick DHCPD setup:

subnet 10.50.1.0 netmask 255.255.255.0 {
    range 10.50.1.200 10.50.1.250;
}
host kvm-netbsd-ia32 {
  hardware ethernet 22:22:22:22:00:00;
  next-server 10.50.1.1;                        # TFTP / NFS host
  filename "/netbsd-5/pxeboot_ia32.bin";        # Path on TFTP server

  option root-path "/storage/nfs/ia32/netbsd-5.1.2/root"; # Path on NFS server
                                                          # FreeBSD pxe can use IP:path here, I believe, NetBSD just uses next-server.
}

... not so fast.

ISC DHCPD, current KVM's iPXE netboot firmware and NetBSD's pxeboot doesn't like each other.

* iPXE sends a DHCP request with dhcp_client_identifier (option 61) set to 01-ethernet mac address, loads pxeboot_ia32.bin from tftp and runs it.
* pxeboot_ia32.bin sends a simpler DHCP request without dhcp_client_identifier via PXE_UDP_WRITE. pxeboot_ia32.bin takes care to use the lease it knows about from the PXE environment as source IP, it just wants to ask for some more options.
* ISC DHCPD wants to assign a new address, since this apparently is another client (no dhcp_client_identifier), and assigns that as unicast destination.
* iPXE ignores the return unicast packet apparently sent to somebody else entirely.
* pxeboot_ia32.bin gets no response and gives up.

ISC DHCPD has a special case for BOOTP clients, and will give out an old lease if the hardware address matches even though they don't send any client-id. But we aren't BOOTP, we're just fragile followup-DHCP-in-PXE.

The least icky way out here seems to be patching DHCPD to ignore dhcp_client_identifier mismatches. (CMU DHCPD has a runtime option for it, btw) But oh, the tentacles, ISC source isn't known for its sanity...

hack for isc dhcp 4.2.4

So at this point I'm doing a traditional
  pxe rom (iPXE 1.0 as shipped with modern qemu/kvm, or whatever PXE rom my old VIA Mini-ITX is running)
  => tftp loads pxeboot second stage
  => pxeboot loads kernel via simplified nfs
  => kernel boots a nfsroot system

The smart & modern way is of course to load the netbsd kernel directly from iPXE. But I'm betting that's too easy to be any fun.


Anyway, qemu-kvm in ubuntu precise has fun bugs that doesn't let the NetBSD kernel find any PCI devices. Like, for instance, the network card. So the boot stops with netboot interface not found.

Fixed in current debian and upstream qemu. A rebuild of QEMU seems to be in order.

apt-get source qemu-kvm
apt-get build-dep qemu-kvm
cd qemu-kvm-1.0+noroms/debian/patches
wget -O 'pci-fix-corrupted-pci-conf-index-register-by-unaligned-write.patch' "http://git.qemu.org/?p=qemu.git;a=commitdiff_plain;h=cdde6ffc27517bdf069734fbc5693ce2b14edc75"
echo pci-fix-corrupted-pci-conf-index-register-by-unaligned-write.patch >> series
cd ..
dch -i
cd ..
dpkg-buildpackage -b -uc
cd ..
dpkg -i qemu-kvm_1.0+noroms-0ubuntu14.2eib1_amd64.deb qemu-utils_1.0+noroms-0ubuntu14.2eib1_amd64.deb qemu-common_1.0+noroms-0ubuntu14.2eib1_all.deb

et voila!

Whee, I have a working NetBSD!
Current invocation: kvm -boot n -localtime -net nic,vlan=0,macaddr=22:22:22:22:00:00 -net tap,vlan=0,ifname=tap0,script=no,downscript=no

Now then, in netbsd (After changing root's shell to /bin/sh instead of the traditonal csh abomination)

cd /usr/mdec
cp ./pxeboot_ia32.bin ./pxeboot_ia32_com0.bin
installboot -e -oconsole=com0 -ospeed=0 ./pxeboot_ia32_com0.bin

So far, so good. Drop our new binary in, and boot kvm with no VGA and a serial console:

kvm -boot n -localtime -net nic,vlan=0,macaddr=22:22:22:22:00:00 -net tap,vlan=0,ifname=tap0,script=no,downscript=no -vga none -nographic

knan@sarevok:/storage/current/netboot$ ./kvm-ia32-netbsd.sh

>> NetBSD/x86 PXE Boot, Revision 5.1 (from NetBSD 5.1.2)
>> Memory: 623/391904 k
Press return to boot now, any other key for boot menu
Starting in 0 seconds.    
PXE BIOS Version 2.1
Using PCI device at bus 0 device 2 function 0
Ethernet address 22:22:22:22:00:00
10090076+518916+618576 [521184+509293]=0xbb2988
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 5.1.2 (GENERIC) #0: Thu Feb  2 17:22:10 UTC 2012
    builds@b6.netbsd.org:/home/builds/ab/netbsd-5-1-2-RELEASE/i386/201202021012Z-obj/home/builds/ab/netbsd-5-1-2-RELEASE/src/sys/arch/i386/compile/GENERIC
[...]
Sun Oct  7 15:54:24 UTC 2012

NetBSD/i386 (netbsd5) (console)

login: root

Yay!

(Todo: train creaky old pxeboot_ia32.bin to retry DHCP via broadcast if unicast fails.)