Labels

lego (12) Linux (39) pi (20) Thinkpads (4)

Tuesday, 21 January 2014

Re-purposing Old SD Cards for Booting a Raspberry Pi off USB

My server pi machine has a SanDisk Ultra 32GB card for which has a standard Raspbian install.  I found shortly after putting the system together, that I found it more stable to run the linux directly off the attached USB hard drive (for which I always mount).  I created a linux OS-partition on the USB drive (size 16GB).  I rsynced the OS from the SD card to the USB OS-partition.

The design of the Raspberry Pi insists on booting off the SD card.  Once the system is bootstrapped, it can boot of USB or SD card.  The bootstrap partition is very small (59MB).  There is no sense using a full 32GB card just for bootstrapping.

I found an old 32MB (yes, Megabytes) micro-SD card and an even smaller, 16MB SD card.  The bootstrap partition on the standard image 32GB card is actually 18MB.  However, with inspection, I noticed there is a 9MB kernel_emergency boot image contained on it.  I would hazard a guess that this boot image would be booted from as a "safe-mode" option if an upgrade (or other activity) causes the default kernel boot image to become inoperable (the default kernel boot image is only 2.8MB).  If I exclude the kernel_emergency boot image, I'll be able to fit the partition on the SD card without an issue.

Backup the Data off the 32GB SD Card


Looking at the data from the 32GB SD card:

Disk /dev/mmcblk0: 31.9 GB, 31914983424 bytes
4 heads, 16 sectors/track, 973968 cylinders, total 62333952 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00014d34

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880    62333951    31105536   83  Linux

The MBR is stored at /dev/mmcblk0, the bootstrap partition is a FAT partition (/dev/mmcblk0p1), and the linux OS-partition is /dev/mmcblk0p2.

Reminder that the dd command will most likely require root access -- so run them as root or use sudo.  When copying an OS-partition, as I've done below, run the rsync using root or use sudo, to ensure all the root-restricted files are transfered.

Backup the MBR


The first step is to backup the MBR off the 32GB SD card.

This can be accomplished by running dd:

dd if=/dev/mmcblk0 of=/u01/sd_pi_mbr.iso bs=512 count=1
The MBR is actually a 512MB sector at /dev/mmcblk0.  This is where the boot sector is, along with the partition table.  Depending on the card reader you are using, it'll either appear as the preceeding device, but it could also appear as a /dev/sda, etc device.  Run fdisk -l to verify the device [ensure that you are not selecting the wrong device].

A little background information on the MBR.  The bootstrap part of the MBR is contained in the first 446 bytes (this explains one of the restore commands that follows).  The partition table data is stored in the proceeding 64 bytes (unless the destined SD card is identical in size and partition layout, we won't restore this part of the MBR).  The MBR signature is the last 2 bytes (again, the destined SD card is identical in size and partition layout, we won't restore this part of the MBR).

Backup the Bootstrap Partition


The second step is to backup the bootstrap partition off the 32GB SD card.

This can be accomplished by running dd:

dd if=/dev/mmcblk0p2 of=/u01/sd_pi_boot.iso
In my case, I'll be modifying the existing bootstrap to exclude the kernel_emergency.img.  Therefore, I ended up mounting /dev/mmcblk0p1 and copy the contents of the filesystem to a folder called sd_pi_boot, excluding the kernel_emergency.img.  The resulting is a folder < 10MB in size, which will clearly fit on my 16MB SD card.

Backup the OS-Partition

You'll need to copy the OS-partition over to the eventual destination device eventually.  In my case, it'll be a USB hard drive, and not the SD card.  You can either use dd to take a backup of the image (dd if=/dev/mmcblk0p2 of=/u01/sd_pi_os.iso) or you can copy the files.  I've copied it to the destination location using rsync.  I could also make a image backup and restore of the filesystem using dd and then resize the partition to occupy the entire destination partition size, but I find it faster and with fewer steps to just mound the filesystem on the SD card and using the rsync -avix command to create a mirror copy of the filesystem [reminder to use root or sudo].


Format and Partition the Destination SD Card


The first step is to ready your SD card.  Format the card with a MBR using a Disk Utility to fdisk.  Then create a FAT partition on the card using the same tool (in my case with the 16MB card, I create a partition the full size of the card).

Restore the MBR


The next step is to restore the MBR onto the new SD card.

This can be accomplished by running dd:

dd if=/u01/sd_pi_mbr.iso of=/dev/mmcblk0 bs=446 count=1
Take note of the bs parameter of 446.  Because the new card is of different size (and different partition sizes) then the original, we restore the "bootstrap" part of the MBR only -- we don't want to overwrite the partition table or MBR signature that we created in the proceeding step.

Restore the OS-Partition to your USB device [or other destination]

You'll need to copy the OS-partition over to the eventual destination device.  In my case, it'll be a USB hard drive, and not the SD card.  Either use dd to restore the filesystem image or use the rsync -avix command to create a mirror copy of the filesystem from your backup [reminder to use root or sudo].

Restore the Bootstrap Partition


The next step is to restore the bootstrap partition.

This can be accomplished by running dd:

dd if=/u01/sd_pi_boot.iso of=/dev/mmcblk0p2
In my case, I'll be modifying the existing bootstrap to exclude the kernel_emergency.img.  Therefore, I use copy over the files from a backup folder sd_pi_boot instead of using dd.

I end up with a bootstrap partition containing the following files:

bootcode.bin  cmdline.txt  config.txt  fixup_cd.dat  fixup.dat  fixup_x.dat  issue.txt   kernel.img  start_cd.elf  start.elf  start_x.elf

Modify the OS-Partition Boot Parameter



On the resulting SD card, I need to instruct the bootstrap where to load the OS-partition on boot up.  These startup details are contained in the file cmdline.txt.

The original file contains the following:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

The OS-partition, more formally known as the root partition, is noted as /dev/mmcblk0p2, which was the original location.  This parameter will need to be updated with the new destination.  In my situation, I restored this to a USB hard drive.  It was not the primary partition on the drive (as it was added after the drive was originally partitioned).  Therefore, in my case, the partition is  /dev/sda3.  If it is your primary partition on the first hard drive connected to the Raspberry Pi, then it'll most likely be /dev/sda1 instead.

My resulting cmdline.txt is as follows:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/sda3 rootfstype=ext4 elevator=deadline rootwait



That's it!  Now perform a sync command (to ensure the write buffers are flushed to the SD card when you eject it), and then safely unmount the partitions on the SD card and eject the SD card from your computer.  Plug it into the Raspberry Pi along with your USB hard drive [or other device containing your new OS-partition].  When you power on the Pi, it should start accessing the partition containing your OS-partition within 3 seconds of receiving power.  In my case, my system is headless (without screen), so I use the LEDs to confirm what is happening.  I notice the hard drive LED starts blinking read (as opposed to green) within 2 seconds of the Pi being powered on, validating that I've done everything properly, and that the Raspberry Pi was able to read the new SD card, boot using the MBR, and bootstrap using the bootstrap partition, and begin booting off the OS-partition.  If you don't see the same result, validate firstly by examining the screen for any errors.  Most likely your cmdline.txt isn't linking to the OS-partition properly.  If you receive SD-card errors, first validate the structure of the SD-card is correct, and that you didn't eject/unmount before the changes were written completely to the card.