Making Partitions and setting up ubuntu
Remember the Recovery stick that was made earlier in the guide? This is where it comes in handy, these commands change the partition sizes on the SSD of the CR-48 and if you screw up you can reboot and it tells you to use a recovery stick. That is why you have to make it, plus it is handy if you just want Chrome OS back for good. Since you did the preparations before hand you can just jump right in to resizing the partitions and continuing if you ever mess up.
First go to the CR-48 terminal, then login as as usual and type .
To prevent the lock screen from logging you out of VT2, leave Chrome OS parked on the login screen. To prevent the backlight from dimming while in VT2, run
Code:
sudo initctl stop powerd
.
Take a look at the SSD layout. It should be something like this (the UUID values will all be different, of course):
Code:
localhost ~ # cgpt show /dev/sda
start size part contents
0 1 PMBR (Boot GUID: 045E5C92-6F57-9B46-BDCC-99BFF876E469)
1 1 Pri GPT header
2 32 Pri GPT table
266240 22622208 1 Label: "STATE"
Type: Linux data
UUID: 1844A16D-AEC9-7C4B-9553-C3EB4814F6BB
4096 32768 2 Label: "KERN-A"
Type: ChromeOS kernel
UUID: D176DC60-81F1-654E-8953-E3D28019738C
Attr: priority=3 tries=0 successful=1
27082752 4194304 3 Label: "ROOT-A"
Type: ChromeOS rootfs
UUID: 0193CA51-DA12-9847-A715-C90433E55F60
36864 32768 4 Label: "KERN-B"
Type: ChromeOS kernel
UUID: F1A2C65C-CC22-FF4A-A8BC-67BA233F3D40
Attr: priority=0 tries=15 successful=0
22888448 4194304 5 Label: "ROOT-B"
Type: ChromeOS rootfs
UUID: B3361FB5-4DAC-9344-B7E5-870B7AC5FEA1
34 1 6 Label: "KERN-C"
Type: ChromeOS kernel
UUID: B6954485-4295-9749-956A-C315B01FB684
Attr: priority=0 tries=15 successful=0
35 1 7 Label: "ROOT-C"
Type: ChromeOS rootfs
UUID: 5B5202B5-F74B-714E-9538-ADE56B2E5662
69632 32768 8 Label: "OEM"
Type: Linux data
UUID: 84971802-0D1C-504B-9CB5-DEA896F0AD3F
36 1 9 Label: "reserved"
Type: ChromeOS reserved
UUID: 77375DA6-8F07-704A-BBF4-2BCA662BFDFF
37 1 10 Label: "reserved"
Type: ChromeOS reserved
UUID: 6880F478-EB05-8B4B-B951-94A96076263E
38 1 11 Label: "reserved"
Type: ChromeOS reserved
UUID: 12DDC236-8FDF-4049-9A2D-10FAB17D3AA9
233472 32768 12 Label: "EFI-SYSTEM"
Type: EFI System Partition
UUID: 045E5C92-6F57-9B46-BDCC-99BFF876E469
31277199 32 Sec GPT table
31277231 1 Sec GPT header
The units are 512-byte disk sectors.
On Chrome OS there are several bootable images, each composed of a kernel and a root filesystem (rootfs). For a given image, the kernel and rootfs are stored on a pair of consecutive partitions. Two of these images, Image-A and Image-B, are for official Chrome OS:
KERN-A and ROOT-A on partitions /dev/sda2 and /dev/sda3
KERN-B and ROOT-B on partitions /dev/sda4 and /dev/sda5
When the Chrome OS autoupdater downloads a new image (every six weeks or so, as new versions are pushed out), it alternately stores it in Image-A and Image-B - whichever image isn't currently running. The autoupdater even runs in developer mode, as long as we are running an official Chrome OS image.
For Ubuntu, we'll use the currently unassigned Image-C, composed of KERN-C and ROOT-C on partitions /dev/sda6 and /dev/sda7, respectively.
However, initially they are too small so, first we need to grow them by stealing from the upper half of the stateful partition, STATE (/dev/sda1). Initially, STATE is 22622208 512-byte sectors, or just under 11 GB. From this we'll set aside 16 MB for KERN-C, and 5 GB for ROOT-C.
Code:
umount /mnt/stateful_partition
Code:
cgpt add -i 1 -b 266240 -s 12103680 -l STATE /dev/sda
Code:
cgpt add -i 6 -b 12369920 -s 32768 -l KERN-C /dev/sda
Code:
cgpt add -i 7 -b 12402688 -s 10485760 -l ROOT-C /dev/sda
Using these values ensures that only the original STATE partition is affected.
Now the partition table should look something like this (changes in bold):
Code:
localhost ~ # cgpt show /dev/sda
start size part contents
0 1 PMBR (Boot GUID: 045E5C92-6F57-9B46-BDCC-99BFF876E469)
1 1 Pri GPT header
2 32 Pri GPT table
266240 12103680 1 Label: "STATE"
Type: Linux data
UUID: 1844A16D-AEC9-7C4B-9553-C3EB4814F6BB
4096 32768 2 Label: "KERN-A"
Type: ChromeOS kernel
UUID: D176DC60-81F1-654E-8953-E3D28019738C
Attr: priority=3 tries=0 successful=1
27082752 4194304 3 Label: "ROOT-A"
Type: ChromeOS rootfs
UUID: 0193CA51-DA12-9847-A715-C90433E55F60
36864 32768 4 Label: "KERN-B"
Type: ChromeOS kernel
UUID: F1A2C65C-CC22-FF4A-A8BC-67BA233F3D40
Attr: priority=0 tries=15 successful=0
22888448 4194304 5 Label: "ROOT-B"
Type: ChromeOS rootfs
UUID: B3361FB5-4DAC-9344-B7E5-870B7AC5FEA1
12369920 32768 6 Label: "KERN-C"
Type: ChromeOS kernel
UUID: B6954485-4295-9749-956A-C315B01FB684
Attr: priority=0 tries=15 successful=0
12402688 10485760 7 Label: "ROOT-C"
Type: ChromeOS rootfs
UUID: 5B5202B5-F74B-714E-9538-ADE56B2E5662
69632 32768 8 Label: "OEM"
Type: Linux data
UUID: 84971802-0D1C-504B-9CB5-DEA896F0AD3F
36 1 9 Label: "reserved"
Type: ChromeOS reserved
UUID: 77375DA6-8F07-704A-BBF4-2BCA662BFDFF
37 1 10 Label: "reserved"
Type: ChromeOS reserved
UUID: 6880F478-EB05-8B4B-B951-94A96076263E
38 1 11 Label: "reserved"
Type: ChromeOS reserved
UUID: 12DDC236-8FDF-4049-9A2D-10FAB17D3AA9
233472 32768 12 Label: "EFI-SYSTEM"
Type: EFI System Partition
UUID: 045E5C92-6F57-9B46-BDCC-99BFF876E469
31277199 32 Sec GPT table
31277231 1 Sec GPT header
At this point we should destroy the STATE partition contents, because otherwise at the next boot the startup scripts may notice that it's corrupted and will erase it using the old size (obtained from dumpe2fs) and not the new one. Best to be safe and just zap it now. This will take a couple of minutes to run:
Code:
dd if=/dev/zero of=/dev/sda bs=131072 seek=1040 count=47280
To speed up SSD access, we use a block size of 131,072 bytes (128 KB), which aligns with the SSD erase size.
And now reboot so that the startup script recreates the required files in the stateful partition. This will do a safe wipe first, so you'll have to wait a bit (again).
Once it boots enter the terminal, then connect the USB Flash drive or Card reader with the card in it.
First find what drive it is before you mount it
When you find the drive name, mount it
Code:
mount /dev/xxx /media
Then flash the rootfs by typing in this DD command, remember if you ever screw up you can always restore it with the USB restore stick.
Code:
dd if=/media/rootfs.bin of=/dev/sda7
Once it completes, unmount the drive
Code:
umount /dev/XXX /media
then take it out.
You can see that it worked by mounting the new rootfs and looking around:
Code:
mount /dev/sda7 /tmp/urfs
While we're looking, let's copy the cgpt tool into Ubuntu's rootfs. Make sure it's executable. We'll need this later.
Code:
cp /usr/bin/cgpt /tmp/urfs/usr/bin/
Code:
chmod a+rx /tmp/urfs/usr/bin/cgpt
We'll need to copy all the kernel modules too.
Code:
cp -ar * /tmp/urfs/lib/modules/
That should do it.
You can now move on to editing your kernal and booting into Ubuntu or the linux distro of your choosing.
Configure the kernel
Continue on from the last step, this is still from the CR-48.
The next step is to copy the currently running Chrome OS kernel to KERN-C (/dev/sda6). Remember, an image consists of a kernel and a rootfs on consecutive partitions. So, to figure out which kernel is running, we can check which partition is currently mounted as the rootfs:
If this prints (ROOT-A), then our kernel is on /dev/sda2 (KERN-A).
If this prints (ROOT-B), then our kernel is on /dev/sda4 (KERN-B).
Assuming our kernel is on (KERN-A), copy it to /dev/sda6 (KERN-C):
Code:
dd if=/dev/sda2 of=/dev/sda6
Now we need to change the kernel command line to use our Ubuntu rootfs instead of a Chrome OS rootfs. For this, we'll use make_dev_ssd.sh, located here. The latest version has options to change individual kernel command lines. You also need to haev the common.sh file. So download it here. Make two blank files in a folder of your choosing, then paste the code for each file. Then name them appropriately. (IE, the file with the script for common.sh is named common.sh)
Use scp to copy it from your host to the stateful partition of the Cr-48.
NOTE THE "." after the directory
Code:
cd /mnt/stateful_partition
Code:
scp USER@HOST:/some/path/to/latest/make_dev_ssd.sh .
Code:
scp USER@HOST:/some/path/to/latest/common.sh .
Extract the existing kernel command line from KERN-C, and save it to a file named foo.6 (the .6 extension is added by the script):
Code:
sh ./make_dev_ssd.sh --partitions '6' --save_config foo
The default Chrome OS kernel command line looks something like this:
Code:
quiet console=tty2 init=/sbin/init add_efi_memmap boot=local rootwait ro noresume noswap i915.modeset=1 loglevel=1 cros_secure kern_guid=%U tpm_tis.force=1 tpm_tis.interrupts=0 root=/dev/dm-0 dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=1 dm="vroot none ro,0 1740800 verity /dev/sd%D%P /dev/sd%D%P 1740800 1 sha1 50adbfb72bb1efda0c1a86dcd1c1d6a0b46726d1" noinitrd
The only editor on the Cr-48 is qemacs, so open foo.6 with qemacs:
Edit the file to look like this:
Code:
console=tty1 init=/sbin/init add_efi_memmap boot=local rootwait ro noresume noswap i915.modeset=1 loglevel=7 kern_guid=%U tpm_tis.force=1 tpm_tis.interrupts=0 root=/dev/sda7 noinitrd
Then save (Ctrl-x Ctrl-s) and exit (Ctrl-x Ctrl-c). qemacs occasionally gets confused, so double-check to be sure you have the right content:
Finally, use make_dev_ssd.sh to replace the kernel command line in KERN-C:
Code:
sh ./make_dev_ssd.sh --partitions '6' --set_config foo
The kernel command line is part of the kernel partition, and the entire partition must be cryptographically signed in order to work. We can't replace the command line part without affecting the entire kernel partition. The script will save a backup copy before replacing the partition content, but we shouldn't need it.
Setting boot priority
At this point we should have the following situation:
Image-A is an official Google Chrome OS which can boot either in normal mode or dev-mode.
Image-B is (or will be after the first autoupdate) another official Google Chrome OS which can boot either in normal mode or dev-mode.
Image-C is Chrome OS kernel with a modified command line and an Ubuntu rootfs, which can only boot in dev-mode.
Next, we adjust the priority among the images so we can try out our Ubuntu image. The image priority is an attribute of its kernel partition. Run
Code:
cgpt show /dev/sda again
, to see the kernel priorities:
NOTE THIS WONT BE THE ONLY THING THAT SHOWS UP
Code:
localhost ~ # cgpt show /dev/sda
...
4096 32768 2 Label: "KERN-A"
Type: ChromeOS kernel
UUID: D176DC60-81F1-654E-8953-E3D28019738C
Attr: priority=3 tries=0 successful=1
...
36864 32768 4 Label: "KERN-B"
Type: ChromeOS kernel
UUID: F1A2C65C-CC22-FF4A-A8BC-67BA233F3D40
Attr: priority=0 tries=15 successful=0
...
12369920 32768 6 Label: "KERN-C"
Type: ChromeOS kernel
UUID: B6954485-4295-9749-956A-C315B01FB684
Attr: priority=0 tries=15 successful=0
The priority determines the order in which the BIOS tries to find a valid kernel (bigger is higher, zero means don't even try). The tries field is decremented each time the BIOS tries to boot it, and if it's zero, the kernel is considered invalid (this lets us boot new images without looping forever if they don't work). The successful field overrides the tries field, but is only set by the OS once it's up and running.
Let's change the priority of KERN-C to 5:
Code:
cgpt add -i 6 -P 5 -T 1 -S 0 /dev/sda
This makes KERN-C the highest priority, but only gives us one chance to boot it. That way if it doesn't work, we're not completely stuck.
If you reboot now, you should come up in Ubuntu! Note that Computer Science Standard Answer #1 applies: It Works For Me™
If something went wrong and Ubuntu crashes or you powered off, the tries field for KERN-C will have been decremented to 0 and you'll fall back to booting Chrome OS.
Assuming that Ubuntu booted and you could log in, go to Applications->Accessories->Terminal to get a shell, and run
Code:
sudo cgpt add -i 6 -P 5 -S 1 /dev/sda
This will mark the Ubuntu kernel as valid, so it will continue to boot next time.
Now you can switch back and forth between the official Chrome OS release and Ubuntu just by flipping the dev-mode switch. Going from dev-mode to normal mode erases STATE (/dev/sda1), but much more quickly. Going from normal to dev-mode again would normally do a slow erase of /dev/sda1, but since we're booting Ubuntu that doesn't happen.
This works because although KERN-C has the highest priority, it isn't signed by Google. In dev-mode that's okay, but in normal mode it will be rejected by the BIOS. Since we've set the successful flag to 1, the BIOS won't mark it invalid but will just skip it each time. This makes the normal-mode boot time slightly longer, but only by a second or two.
Of course you could also switch between images from within dev-mode just by manually setting the priorities with cgpt before rebooting.
Note that if the normal image autoupdates, it will probably change the kernel priorities so that Image-C is no longer the highest and the next time you switch to dev mode, you will
a) have a long wait,
b) still be running Chrome OS, and
c) have to use cgpt to raise the KERN-C priority again.
But, because autoupdate only switches between Image-A and Image-B, the Ubuntu kernel and rootfs shouldn't be affected.
Bookmarks