rpi-update ate my SD card

Preamble

Some time ago, I'd re-configured the Raspberry Pi to use a USB stick as the root directory, by changing the default kernel boot parameters in /boot/cmdline.txt to this:

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

The vital addition is root=/dev/sda2. The rationale is to reduce the usage of the SD card, which has a reputation for dying a lot faster than a USB stick.

Where did my modules go?

I noticed an issue shortly after I'd performed an apt-get update && apt-get upgrade of the Raspberry Pi. The little script I had to take pictures using USB camera, a Logitech C270, failed to work, complaining that no /dev/video0 existed. And it was right. Hmm, what had the upgrade done? The USB camera was detected by the module uvcvideo. Except that, according to lsmod, there were no modules loaded at at all. uname -a showed me I was running a 3.6.11 kernel, yet in /lib/modules I only had modules for 3.6.25. How did this happen?

After some research, I belatedly realised than the kernel image and associated modules for Raspbian was actually updated by a process called rpi-update, not via apt-get. However, this doesn't explain how I ended up with a mismatch; had I run rpi-udpate when /dev/sda2 was not mounted and forgotten? Well, it is possible. Anyway, should be a simple fix then. I ran rpi-update, which appeared to work without problem. On reboot however, I could not ssh to the pi. The console messages showed me:

  PANIC: VFS: Unable to mount root fs on unknown-block(179,2)

I pulled the SD card and mounted it on the Debian system. fdisk showed this:

  [mark@amber:~] sudo fdisk /dev/sdf

  Command (m for help): p

  Disk /dev/sdf: 4025 MB, 4025483264 bytes
  4 heads, 16 sectors/track, 122848 cylinders, total 7862272 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: 0x0007b745

  Device Boot         Start         End      Blocks   Id  System
  /dev/sdf1            2048     2490234     1244093+   e  W95 FAT16 (LBA)
  /dev/sdf2         2490368     7796735     2653184   85  Linux extended
  /dev/sdf3         7796736     7862271       32768   83  Linux
  /dev/sdf5         2498560     2621439       61440    c  W95 FAT32 (LBA)
  /dev/sdf6         2629632     7796735     2583552   83  Linux

Now that didn't look right. We now have this setup:

  /dev/sdf1 (aka /dev/mmcblk0p1)  boot/recovery partition
  /dev/sdf3 (aka /dev/mmcblk0p3)  settings partition (related to noobs?)
  /dev/sdf5 (aka /dev/mmcblk0p5)  boot partition (unused)
  /dev/sdf6 (aka /dev/mmcblk0p6)  root partition

When booted, /dev/mmcblk0p1 is mounted as /boot on the runnning system.

I had a spare pi SD card; it looked like this:

  Disk /dev/sdf: 15.9 GB, 15931539456 bytes
  64 heads, 32 sectors/track, 15193 cylinders, total 31116288 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: 0x0002c262

  Device Boot         Start         End      Blocks   Id  System
  /dev/sdf1            8192      122879       57344    c  W95 FAT32 (LBA)
  /dev/sdf2          122880    31116287    15496704   83  Linux

More digging around. The standard layout of the SD card has the first partition (mmcblk0p1) as the boot partition (kernel images etc), while mmcblk0p2 is the root filesystem. Except that, the kernel should be using /dev/sda2 as the root fs. OK, the first partition did indeed contain all the standard boot images, but no cmdline.txt. Ah, then the kernel must be falling back to the default root partition of /dev/mmcblk0p2, which clearly was not going to be happy with a Linux extended partition. I copied cmdline.txt (with the root redirection to /dev/sda2) from /dev/sdf5 to /dev/sdf1 and re-inserted the SD card back into the PI and booted.

Successful boot!

Addendum

From this post on the Raspberry Pi site it appears you can drop a file called autoboot.txt in the first partition, which then tells the boot process to use a different partition as the boot partition. The contents should look like:

  boot_partition=5

And this does indeed seem to work.