Automated install of Fedora 18 ARM on a Samsung Google Chromebook

Posted: March 31st, 2013 | Filed under: Fedora | Tags: , , , , , | 23 Comments »

Back in November last year, I wrote about running Fedora 17 ARM on a Samsung Google Chromebook, via an external SD card. With Fedora 18 now out, I thought it time to try again, this time replacing ChromeOS entirely, installing Fedora 18 ARM to the 16GB internal flash device. Igor Mammedov of the Red Hat KVM team, has previously written a script for automating the install of Fedora 17 onto the internal flash device, including the setup of chained bootloader with nv-uboot. I decided to take his start, update it to Fedora 18 and then extend its capabilities.

If you don’t want to read about what the script does, skip to the end

ChromeOS bootloader

The Samsung ARM Chromebook bootloader is a fork of u-boot. The bootloader is setup todo “SecureBoot” of Google ChromeOS images only by default. There is no provision for providing your own verification keys to the bootloader, so the only way to run non-ChromeOS images is to switch to “Developer Mode” and sign kernels using the developer keys. The result is that while you can run non-ChromeOS operating systems, they’ll always be a second class citizen – since the developer keys are publically available, in developer mode, it’ll happily boot anyone’s (potentially backdoored) kernels. You’re also stuck with an annoying 30 second sleep in the bootloader splash screen which you can only get around by pressing ‘Ctrl-D’ on every startup. The bootloader is also locked down, so you can’t get access to the normal u-boot console – if you want to change the kernel args you need to re-generate the kernel image, which is not so much fun when troubleshooting boot problems with new kernels.

The Chromebook bootloader can’t be (easily) replaced since the flash it is stored in is set read-only. I’ve seen hints in Google+ that you can get around this by opening up the case and working some magic with a soldering iron to set the flash writable again, but I don’t fancy going down that route.

It is, however, possible to setup a chained bootloader, so that the built-in uboot will first boot nv-uboot, which is a variant of the bootloader that has the console enabled and boots any kernel without requiring them to be signed. We still have the annoying 30 second sleep at boot time, and we still can’t do secure boot of our Fedora install, but we at least get an interactive boot console for troubleshooting which is important for me.

ChromeOS Partition Layout

Before continuing it is helpful to understand how ChromeOS partitions the internal flash. It uses GPT rather than MBR, and sets up 12 partitions, though 4 of these (ROOT-C, KERB-C, reserved, reserved) are completely unused and 2 are effectively empty (OEM, RWFW) on my system.

# Device            Label      Offset    Length     Size
# /dev/mmcblk0p1  - STATE        282624  11036672   10 GB
# /dev/mmcblk0p2  - KERN-A        20480     16384   16 MB
# /dev/mmcblk0p3  - ROOT-A     26550272   2097154    2 GB
# /dev/mmcblk0p4  - KERN-B        53248     16384   16 MB
# /dev/mmcblk0p5  - ROOT-B     22355968   2097154    2 GB
# /dev/mmcblk0p6  - KERN-C        16448         0    0 MB
# /dev/mmcblk0p7  - ROOT-C        16449         0    0 MB
# /dev/mmcblk0p8  - OEM           86016     16384   16 MB
# /dev/mmcblk0p9  - reserved      16450         0    0 MB
# /dev/mmcblk0p10 - reserved      16451         0    0 MB
# /dev/mmcblk0p11 - RWFW             64      8192    8 MB
# /dev/mmcblk0p12 - EFI-SYSTEM   249856     16384   16 MB

The important partitions are

  • KERN-A – holds the 1st (primary) kernel image
  • KERN-B – holds the 2nd (backup) kernel image
  • ROOT-A – ChromeOS root filesystem to go with primary kernel
  • ROOT-B – ChromeOS root filesystem to go with backup kernel
  • EFI-SYSTEM – EFI firmware files – empty by default
  • STATE – ChromeOS user data partition

Notice from the offsets, that the order of the partitions on flash, does not match the partition numbers. The important thing is that STATE, ROOT-A and ROOT-B are all at the end of the partition table.

Desired Fedora partition layout

The goal for the Fedora installation is to delete the ROOT-A, ROOT-B and STATE partitions from ChromeOS, and replace them with 3 new partitions:

  • ROOT – hold the Fedora root filesystem (ext4, unencrypted, 4 GB)
  • BOOT – hold the /boot filesystem (ext2, unencrypted, 200 MB)
  • HOME – hold the /home filesystem (ext4, LUKS encrypted, ~11 GB)

The /boot partition must sadly be ext2, since the nv-uboot images Google provide don’t have ext4 support enabled, and I don’t fancy building new images myself. It would be possible to have 1 single partition for both the root and home directories, but keeping them separate should make it easier to upgrade by re-flashing the entire ROOT partition, and also avoids the need to build an initrd to handle unlock of the LUKS partition.

Chained bootloader process

The KERN-A and KERN-B partitions will be used to hold the chained nv-uboot bootloader image, so the built-in bootloader will first load the nv-uboot loader image. nv-uboot will then look for a file /u-boot/boot.scr.img file in the EFI-SYSTEM partition. This file is a uboot script telling nv-uboot what partitions the kernel and root filesystem are stored in, as well as setting the kernel boot parameters. The nv-uboot image has an annoying assumption that kernel image is stored on the root filesystem, which isn’t the case since we want a separate /boot, so we must override some of the nv-uboot environment variables to force the name of the root partition for the kernel command line. The upshot is that that the boot.scr.img file is generated from the following configuration

setenv kernelpart 2                                                                                                                               
setenv rootpart 1                                                                                                             
setenv cros_bootfile /vmlinux.uimg                                                                                                                
setenv regen_all ${regen_all} root=/dev/mmcblk0p3                                                                          
setenv common_bootargs                                                                                                                            
setenv dev_extras console=tty1 lsm.module_locking=0 quiet      

The actual kernel to be booted is thus ‘/vmlinux.uimg’ in the /boot partition of the Fedora install. There is no Fedora kernel yet that boots on the ARM ChromeBook, so this is a copy of the kernel from the ChromeOS install. Hopefully there will be official Fedora kernels in Fedora 19, or at least a re-mix with them available. The lsm.module_locking=0 argument here is needed to tell the ChromeOS kernel LSM to allow kernel module loading.

Installation process

With all this in mind, the script does its work in several stages, requiring a reboot after each stage

  1. Running from a root shell in ChromeOS (which must be in developer mode), the filesystem in the ROOT-B partition is deleted and replaced with a temporary Fedora ARM filesystem. The KERN-A and KERN-B partitions have their contents replaced with the nv-uboot image. The kernel image from ChromeOS is copied into the Fedora root filesystem, and the keyboard/timezone/locale settings are also copied over. The installation script is copied to /etc/rc.d/rc.local, so that stage 2 will run after reboot. The system is now rebooted, so that nv-uboot will launch the Fedora root filesystem
  2. Running from rc.local in the temporary Fedora root filesystem, the ROOT-A and STATE partitions are now deleted to remove the last traces of ChromeOS. The ROOT and BOOT partitions are then created and formatted. The contents of the temporary Fedora root filesystem are now copied into the new ROOT partition. The system is now rebooted, to get out of the temporary Fedora root filesystem and into the new root.
  3. Running from rc.local in the final Fedora root filesystem, the ROOT-B partition is now deleted to remove the temporary Fedora root filesystem. In the free space that is now available, a HOME partition is created. At this point the user is prompted to provide the LUKS encryption passphrase they wish to use for /home. The ALSA UCM profiles for the ChromeBook are now loaded and the ALSA config saved. This will help avoid users accidentally melting their speakers later. An Xorg config file is created to configure the touchpad sensitivity, firstboot is enabled and the root account is locked. Installation is now complete and the system will reboot for the final time.
  4. The final system will now boot normally. There will be a prompt for the LUKS passphrase during boot up. Unfortunately the prompt text gets mixed up with systemd boot messages, which I’m not sure how to fix. Just keep an eye out for it. Once the key is entered boot up will complete and firstboot should launch allowing the creation of a user account. Since the root account is locked, this user will be added to the wheel group, giving it sudo privileges.

If everything went to plan, the ChromeBook should now have a fully functional Fedora 18 install on its internal flash, with the XFCE desktop environment. Compared to running off an external SD card, the boot up speed is quite alot faster. The time to get to the desktop login screen is not all that much longer than with ChromeOS (obviously I’m ignoring the pause to enter the LUKS passphrase here).

Some things I’m not happy with

  • Only /home is encrypted. I’d like to figure out how to build an initrd for the ChromeOS kernel capable of unlocking a LUKS encrypted root filesystem
  • The boot up is in text mode. I’d like to figure out how to do graphical boot with plymouth, mostly to get a better prompt for the LUKS passphrase
  • The image is not using GNOME 3. I much prefer the GNOME Shell experience over the “traditional” desktop model seen with XFCE / GNOME 2 / etc

Running the script

You run this script AT YOUR OWN RISK. It completely erases all personal data on your ChromeBook and erases ChromeOS itself. If something goes wrong with the script, you’ll likely end up with an unbootable machine. To fix this you’ll need an SD card / USB stick to follow the ChromeOS recovery procedures. I’ve been through the recovery process perhaps 20 times now and it doesn’t always go 100% smoothly. Sometimes it complains that it has hit an unrecoverable error. Despite the message, ChromeOS still appears to have been recovered & will boot, but there’s something fishy going on. Again you run this script AT YOUR OWN RISK.

  1. Download http://berrange.fedorapeople.org/install-f18-arm-chromebook-luks.sh to any random machine
  2. Optionally edit the script to change the FEDORA_ROOT_IMAGE_URL and UBOOT_URL env variables to point to a local mirror of the files.
  3. Optionally edit the script to set the ssid and psk parameters with the wifi connection details. If not set, the script will prompt for them
  4. Boot the ChromeBook in Developer Mode and login as a guest
  5. Use Ctrl+Alt+F2 to switch to the ChromeOS root shell (F2 is the key with the forward arrow on it, in the usual location you’d expect F2 to be)
  6. Copy the script downloaded earlier to /tmp in the ChromeOS root and give it executable permission
  7. Run bash /tmp/install-f18-arm-chromebook-luks.sh
  8. Watch as it reboots 3 times (keep an eye out for the LUKS key prompts on boots 3 and 4.
  9. Then either rejoice when firstboot appears and you subsequently get a graphical login prompt, or weep as you need to run the ChromeOS recovery procedure.

The script will save logs from stages 1 / 2 / 3 into /root of the final filesystem. It also copies over a couple of interesting log files from ChromeOS for reference.