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 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/
  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.

Installing Fedora 17 ARM on a Samsung Google Chromebook

Posted: November 30th, 2012 | Filed under: Fedora, libvirt, Virt Tools | Tags: , , , | 9 Comments »

Today I purchased one of the lovely new ARM based Samsung Google Chromebooks. While ChromeOS is very slick, I don’t have much interest in running that, I got this machine to serve as a dev machine for doing ARM work on libvirt and related projects. Not co-incidentally, this machine has the ARM Cortex A-15 CPU which is the architecture targeted by the new KVM for ARM work.

Obviously the first task at hand is to actually get Fedora onto the machine. Fortunately Christopher Hewitt has been here already and wrote up some notes for Fedora 17 on Google+. The notes look good, but when you look, the first step in installing Fedora is to use an Ubuntu host to build a SD card. So what follows is my slightly tweaked instructions for doing the same starting from a Fedora 17 host.

Building the bootable SD card

We don’t want to blow away ChromeOS entirely, so this guide is focused on booting using an SD Card. I have a bunch of 8 GB SD cards for my SLR, so one of those is re-purposed for this task.

Creating partitions & filesystems

The first part of the process is to create the partitions and root filesystem. All the instructions below are to be run as root on the Fedora 17 host.

  1. Insert the SD card in the host machine, let GNOME automount it, and then look to see what device it is
    # df
    Filesystem                              1K-blocks       Used Available Use% Mounted on
    rootfs                                  151607468  127703344  16202828  89% /
    devtmpfs                                  1958948          0   1958948   0% /dev
    tmpfs                                     1970892        284   1970608   1% /dev/shm
    tmpfs                                     1970892       1656   1969236   1% /run
    /dev/mapper/vg_t500wlan-lv_root         151607468  127703344  16202828  89% /
    tmpfs                                     1970892          0   1970892   0% /sys/fs/cgroup
    tmpfs                                     1970892          0   1970892   0% /media
    /dev/sda1                                  198337     126585     61512  68% /boot
    /dev/mmcblk0p1                            7753728    7668960     84768  99% /run/media/berrange/NIKON D90

    So in this case, I see the device is /dev/mmcblk0 (ignoring the p1 suffix which is the partition number)

  2. Take a look at the SD card and double-check there are no important files still on it, then unmount it. I found a few photographs that I hadn’t transferred, so happy I checked
  3. Being a nice modern platform, the Chromebook doesn’t want no stinkin’ MS-Dos partition table. This is a GPT world we live it. Using parted we re-format the SD Card with a GPT table (well, ok, if you must know, this creates a MS-Dos partition table too for back compat)
     # parted /dev/mmcblk0
    GNU Parted 3.0
    Using /dev/mmcblk0
    Welcome to GNU Parted! Type 'help' to view a list of commands.
    (parted) mktable gpt                                                      
    Warning: The existing disk label on /dev/mmcblk0 will be destroyed and all data on this disk will be lost. Do you want to continue?
    Yes/No? yes                                                               
    (parted) quit                                                             
    Information: You may need to update /etc/fstab.
  4. Now time to create 3 partitions, 2 for storing kernels, and one for storing the filesystem. You could just create 1 for the kernel, if you don’t care about having a backup sane kernel for emergencies
    ## gdisk /dev/mmcblk0
    GPT fdisk (gdisk) version 0.8.4
    Partition table scan:
      MBR: protective
      BSD: not present
      APM: not present
      GPT: present
    Found valid GPT with protective MBR; using GPT.
    Command (? for help): x
    Expert command (? for help): l
    Enter the sector alignment value (1-65536, default = 2048): 8192
    Expert command (? for help): m
    Command (? for help): n
    Partition number (1-128, default 1): 1
    First sector (34-15523806, default = 8192) or {+-}size{KMGTP}: 
    Last sector (8192-15523806, default = 15523806) or {+-}size{KMGTP}: +16M
    Current type is 'Linux filesystem'
    Hex code or GUID (L to show codes, Enter = 8300): 7f00
    Changed type of partition to 'ChromeOS kernel'
    Command (? for help): n
    Partition number (2-128, default 2): 2
    First sector (34-15523806, default = 40960) or {+-}size{KMGTP}: 
    Last sector (40960-15523806, default = 15523806) or {+-}size{KMGTP}: +16M
    Current type is 'Linux filesystem'
    Hex code or GUID (L to show codes, Enter = 8300): 7f00
    Changed type of partition to 'ChromeOS kernel'
    Command (? for help): n
    Partition number (3-128, default 3): 3
    First sector (34-15523806, default = 73728) or {+-}size{KMGTP}: 
    Last sector (73728-15523806, default = 15523806) or {+-}size{KMGTP}: 
    Current type is 'Linux filesystem'
    Hex code or GUID (L to show codes, Enter = 8300): 
    Changed type of partition to 'Linux filesystem'
    Command (? for help): w
    Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
    Do you want to proceed? (Y/N): y
    OK; writing new GUID partition table (GPT) to /dev/mmcblk0.
    The operation has completed successfully.
  5. With that out of the way, it is time to format the filesystem on the 3rd partition, and ext4 is the choice we’re going for here
    # mkfs.ext4 /dev/mmcblk0p3 
    mke2fs 1.42.3 (14-May-2012)
    Discarding device blocks: ^C76960/1931259
    [root@t500wlan ~]# 
    [root@t500wlan ~]# mkfs.ext4 /dev/mmcblk0p3 
    mke2fs 1.42.3 (14-May-2012)
    Discarding device blocks: done                            
    Filesystem label=
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    Stride=0 blocks, Stripe width=0 blocks
    483328 inodes, 1931259 blocks
    96562 blocks (5.00%) reserved for the super user
    First data block=0
    Maximum filesystem blocks=1979711488
    59 block groups
    32768 blocks per group, 32768 fragments per group
    8192 inodes per group
    Superblock backups stored on blocks: 
    	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
    Allocating group tables: done                            
    Writing inode tables: done                            
    Creating journal (32768 blocks): done
    Writing superblocks and filesystem accounting information: done
  6. A filesystem isn’t too interesting, unless it has some data in it. Lets download a suitable Fedora 17 ARM filesystem archive and copy its data across
    # wget
    # mount /dev/mmcblk0p3 /mnt
    # cd /mnt
    # tar Jxvf /root/Fedora-17-armhfp-xfce.tar.xz

    When unpacked, the filesystem will consume about 2.4 GB of space, so a 8GB SD card isn’t strictly needed – a 4GB one would suffice.

  7. The core F17 image is now installed on the SD card, so unmount the card. The next step will move onto the ChromeBook
    # umount /dev/mmcblk0p3

Getting the Chromebook into Developer Mode

Before moving onto the next stage, the ChomeBook must be in Developer Mode.

  1. Booting into Recovery Mode is the first thing todo. This requires holding down the Esc and Refresh keys, while pressing the Power key.
  2. It should now display a nice scary message that the installation is broken. This is of course a lie, so ignore it.
  3. Pressing Ctrl-D now will start the switch into Developer Mode.
  4. It should now display a less scary message asking if you want to turn off verification. We do indeed want todo this, so press Enter.
  5. The ChromeBook will reboot and tell you that verification is disabled.
  6. Wait a short while, or press Ctrl-D, and it’ll display another message that it is transitioning to Developer Mode.
  7. Erasing local data can take a while, so be patient here. Strangely, there’s a crude ascii art progress bar along the top of the screen here, while everything else remains pretty & graphical.

Copying the ChromeBook ARM kernels

Fedora 17 doesn’t come with a suitable kernel for the Cortex A-15 CPU, so this step grabs the one already present in ChromeOS.

  1. Assuming the ChromeBook is now booted in Developer Mode, insert the SD card.
  2. Bring up a croshprompt by typing Ctrl-Alt-T
  3. From here, run ‘shell’ which gives you a bash session.
    crosh> shell
    chronos@localhost / $
  4. Become the root user
    $ sudo su -
    localhost ~ #
  5. The kernel image has the boot arguments embedded in it, and these need to be changed for Fedora. This involves a fun little command which bundles up the vmlinuz file, config args and boot keys into one magic image
    # cd /tmp
    # echo “console=tty1 debug verbose root=/dev/mmcblk1p3 rootwait rw” > /tmp/config
    # vbutil_kernel –pack /tmp/newkern –keyblock /usr/share/vboot/devkeys/kernel.keyblock –version 1 –signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk –config=/tmp/config –vmlinuz /boot/vmlinuz-3.4.0 –arch arm
  6. Assuming that worked, the new kernel image can copied across to the new SD card partitions created earlier
    # dd if=/tmp/newkern of=/dev/mmcblk1p1
    # dd if=/tmp/newkern of=/dev/mmcblk1p2
    # rm /tmp/newkern /tmp/config
  7. Having the kernels in a partition isn’t much use, unless you mark those partitions as bootable
    # cgpt add -i 1 -S 1 -T 5 -P 10 -l KERN-A /dev/mmcblk1
    # cgpt add -i 2 -S 1 -T 5 -P 5 -l KERN-B /dev/mmcblk1

    This says try to boot from the first partition 10 times, then fallback to trying the second partition 5 times. This fallback behaviour is handy if you want to test out custom kernel builds, and have an escape route for when it all goes belly up.

  8. Much of the ChromeOS kernel is built as modules, so those also need to be copied across to the filesystem image
    cp -rf /lib/modules/* /media/removable/External\ Drive\ 1/lib/modules/
    cp -rf /lib/firmware/* /media/removable/External\ Drive\ 1/lib/firmware/
  9. Even in Developer Mode, the Chromebook will ignore the SD/USB card when booting, unless explicitly told to look at them
    # crossystemm dev_boot_usb=1

    It might print out a couple of warnings, but those can be ignored – it will have done what is required.

  10. Xorg will work fine out of the box, but the TouchPad sensitivity can do with improving
    # cat > /media/removable/External\ Drive\ 1/etc/X11/xorg.conf.d/50-touchpad.conf <<EOF
    Section "InputClass"
      Identifier "touchpad"
      MatchIsTouchpad "on"
      Option "FingerHigh" "5"
      Option "FingerLow" "5"

    Some other guides suggest copying across the Xorg drivers and, but I wanted to keep my system as vanilla & open source as possible

  11. For sound to work, copy the alsa profiles across too
    # cp -a /usr/share/alsa/ucm/ /media/removable/External\ Drive\ 1/usr/share/alsa/ucm

    WARNING: Under no circumstances use ‘alsamixer’ to adjust setting on your ChromeBook. Multiple people have reported (with pictures) melting/burning out the speakers (no seriously, you can kill the hardware)

  12. Set things up so that the alsa settings are loaded on startup
    # cat > /media/removable/External\ Drive\ 1/etc/rc.d/rc.local <<EOF
    alsaucm -C DAISY-I2S set _verb HiFi
    # chmod +x /media/removable/External\ Drive\ 1/etc/rc.d/rc.local

    Note that some instructions miss off the ‘set _verb HiFi’ part of this command line. My experiance is that audio did not work unless that was set.

  13. The final thing todo is configure the root password and user account
    # mount -o remount,suid,exec /media/removable/External\ Drive\ 1/
    # chroot /media/removable/External\ Drive\ 1/
    # passwd
    ...enter new root password...
    # mkdir /home/guest
    # rsync -a /etc/skel/ /home/guest
    # chown -R guest:users /home/guest
    # usermod -d /home/guest -g users guest
    # exit
    # umount /media/removable/External\ Drive\ 1/

That’s it, you’re now ready to rock-n-roll. Power-cycle the Chromebook, and when the initial boot screen appears press Ctrl-U to boot from the SD card.

First impressions of Fedora 17 on the Chromebook

Writing these instructions was interrupted part way through, when I began to realize that the TrackPad on my Chromebook was faulty. I didn’t work at all on first boot of ChromeOS, but second time around it was working fine, so I thought nothing of it. It just got worse & worse from then on though. Looking at the kernel dmesg logs showed the hardware did not even appear visible 60% of the boot attempts. It is probably just a loose cable inside, but I didn’t fancy opening up the case, so I took it back to PC World for an exchange. Thankfully the 2nd unit worked flawlessly.

The first annoying thing to discover is that it is only possible to boot custom distros on the ChromeBook while in Developer Mode. This means that at every power-on, the boot screen pauses 30 seconds with a scary warning. AFAICT, there is no ability to sign the kernel images, such that you can boot in Release Mode, without the warning. So before distros have even done any work, it appears guaranteed that their user experience will be worse that ChromeOS on this hardware. Thankyou “verified boot”.

Booting up Fedora 17 is significantly slower than booting ChromeOS. While some of this might be Fedora’s fault, I’m not prepared to lay any blame here, since I’m comparing booting from the internal drive for ChromeOS, vs booting from an SD-Card for Fedora. It just isn’t a fair comparison unless I can get Fedora onto the internal drive. It also isn’t as pretty, though again that is mostly my fault for not using graphical boot with Fedora.

If the procedure above is followed, you will get a pretty functional Fedora 17 XFCE desktop environment. Since I skipped the part others recommend about copying over the binary Xorg driver for the graphics card, X performance isn’t going to win any benchmarks though. Playing youtube video in firefox with HTML5, in a smallest video size consumes 95% CPU time. I expect proper graphics drivers would help that significantly.

In anycase I’m not doing any of this for Xorg / graphics performance. This is primarily going to be a dev machine which I remotely access for doing libvirt work

The hope is that when Fedora 18 is released for ARM, there will be a remix done specifically for the new ChromeBook which will simplify the setup process, use a normal Fedora kernel, and just generally “do the right thing”. I may well try to re-do this image using a F18 alpha filesystem as the source instead.