|
From: | Stefan Dösinger |
Subject: | Netboot Linux on Intel Macs via EFI (long) |
Date: | Fri, 17 Feb 2012 09:03:28 +0100 |
User-agent: | KMail/4.7.4 (Linux/3.2.1-gentoo-r2; KDE/4.7.4; x86_64; ; ) |
Hi, I'm writing this mail mostly to document my efforts for others who try to achieve a similar goal. If any Grub experts find a way to improve my solution I'm open to suggestions :-) My goal was to boot a Linux system via the network(nfsroot, ...) on my Intel Macs without placing any additional boot media like cdroms, usb mass storage or placing data on the built-in disk. If you don't mind using boot cds, stop reading now and load iPXE from a cdrom and follow the normal PC netboot tutorials out there. It is much easier. I'm not explaining the the basics of netbooting, like how to set up your dhcp and tftp server. There are many (PC-focused) tutorials out there. Luckily the Mac EFI implementation supports network booting. It can be triggered in the following way: 1) Select network boot in the OSX boot settings. 2) Hold down the N key when powering the mac on 3) Hold down the option key when powering the mac on, then press N when the menu comes up. Unfortunately the firmware has some quirks, and the first task is to set up dhcpd to return a reply that makes the firmware happy. I've attached my dhcpd.conf, the magic is in the 'class "AppleNBI-i386"' definition. Some background read can be found at http://en.wikipedia.org/wiki/Boot_Service_Discovery_Protocol This allows you to deliver one .efi program to the target machine, specified by the "filename" setting. The Mac firmware will download it from the tftp server specified by the "next-server" setting. The next issue is that some Macs have a 32 bit EFI, and others have a 64 bit EFI, and the vendor-class-identifier doesn't explicitly say so. Apple has universal EFI binaries for that, but apparently grub cannot build them. Thus I select the macs I have that need a 32 bit binary with the model info in the vendor-class-identifier. This has the potential to get ugly when more exceptions are added. To build the efi binaries I essentially followed the EFI building instructions out there. However, you have to link all necessary modules ino the .efi binary as you won't be able to load any additional modules for a while. Here are my build command lines for i386: ./configure --with-platform=efi --target=i386 ./grub-mkimage -d grub-core/ -O i386-efi -o /tftproot/grub/bootia32.efi part_gpt hfsplus fat ext2 normal chain boot configfile linux loadenv echo search loadbios video_fb videotest pci efi_gop efi_uga font gfxterm font memdisk tar tftp reboot efinet --prefix=/boot/grub -m /path/to/memdisk/memdisk.tar Yes, some of those modules are not necessary, like the hfsplus stuff and ext2 driver. I found them helpful for debugging though. Next issue: Grub finds the efi network interface efinet0, but the Mac firmware apparently doesn't offer the PXE protocol, so you can't autoconfigure the interface and have your prefix on the tftp server. Luckily the memdisk can help here. My memdisk merely contains a boot/grub/grub.cfg file with the following content: net_bootp configfile (pxe)/grub/grub.cfg Interestingly bootp and tftp work, even though pxe as a whole doesn't. Also, by default net_bootp configures the IP, but doesn't set the default tftp server name. The attached bootp-hack.diff hack changes that. Alternatively you can hardcode the server IP into the config file(and thus bootloader binary) like this: configfile (pxe:192.168.5.1)/grub/grub.cfg I considered that ugly, so I looked for a better way. I'll contact the development list regarding the hack. Okay, from there on it is pretty simple and mostly follows the mac efi booting tutorials that explain booting from disk. My (pxe)/grub/grub.cfg file is attached. The loadfont and terminal_output gfxterm statements are necessary to make the efifb framebuffer work after the kernel has loaded. If your kernel instantly uses a GPU-specific framebuffer driver(e.g. KMS radeon, intel or nouveau) you may be able to skip it. For instructions on how to create unicode.pf2 see https://wiki.archlinux.org/index.php/GRUB2 . One other neat thing I came across while working on this: Notice that the kernel parameters do not contain a nfsroot parameter. The kernel gets that parameter from dhcp as well, via the root-path option in dhcpd.conf. I hope some fellow out there in the world finds this useful. If you have any suggestions or questions please CC me, I'm not subscribed to the mailing list. Some random notes: 1) You may want to get the wiki up again, a wiki would be a better place for tutorials like this 2) When I debugged the PXE services in efinet.c, it took me a while to realize that grub_efi_net_config is not called if there's any compiled in module that may provide a prefix(e.g. memdisk) 3) I tried chainloading grub from iPXE in the hope that iPXE provides a working PXE protocol, but this didn't work. 4) There's net_get_dhcp_option which allows me to retrieve the dhcp server ip, or next-server, I don't know because they are the same in my setup. (iface=efinet0:dhcp, number=3, description=hex). Unfortunately this returns a hexadecimal number which (pxe:server) doesn't understand. This may be another way to get rid of the bootp hack. And no, description=string does not return "192.168.5.1", it just returns "(". Adding a format option like "ip" that does that might be a workable solution though. 5) I suspect net_bootp does not set default_server_name etc because it is only called from the command line or a config file, and never in an attempt to find the prefix. 6) Next plan: Use grub instead of syslinux's menu.c32 for my standard PC side setup so I can share the config file, and thus the kernel command line. Cheers, Stefan Dösinger
dhcpd.conf
Description: Text document
bootp-hack.diff
Description: Text Data
grub.cfg
Description: Text document
signature.asc
Description: This is a digitally signed message part.
[Prev in Thread] | Current Thread | [Next in Thread] |