Labels

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

Thursday, 19 June 2014

USB Logitech microphone support in Kazam on Linux

I had an issue where my USB Logitech microphone would not show up in the Kazam Screencast application.  Linux sound record could see the microphone, and I could record audio through sound recorder from the microphone, but Kazam could not.

I ended up creating a loopback Pulse Audio device using:

pactl load-module module-null-sink sink_name=Virtual1    
pactl load-module module-loopback latency_msec=1 sink=Virtual1 

In Kazam, I would select Sound from speakers (not sound from microphone):



In preferences, for Speakers, select the microphone.



Now the sound recording will be relayed through the microphone to Kazam.  There won't be any speaker output, so there will be no feedback.


Wednesday, 4 June 2014

Which filesystems I use and why

I've been frequently asked which filesystems I prefer.  I decided to put together a post discussing my filesystems of choice and general analysis of the criteria.

Windows VMs/KVMs etc

Obvious choice is NTFS.  In KVM, the NTFS filesystem is stored in a QCOW2 container (allowing the filesystem to be easily resized/extended and snapshots/clones reduce data storage consumption).

Raspberry Pi / Beagle Bone Black / Cubieboard

read-only EXT4 with journaling off

I generally turn journaling off (by running tune2fs -O ^has_journal /dev/sda) to preserve the flash and SD write health of my media.  I have literally killed genuine SanDisk premium SD cards with "active" Raspberry Pi systems that had journaling on.

I prefer to make my partitions read-only, with using tempfs to store writes.  If I want write to be persistent, I store the data on a secondary EXT4 writable partition.  However, the root and boot partitions, I keep read-only unless I'm performing an upgrade on the system.  By keeping the filesystem as read-only, I avoid corrupting the SD card with bad writes caused by bad power sources, overclocking or improper shutdown.  I found even with reliable power sources, no overclocking and always ensuring safe shutdown, my SD card would become corrupt over time (just generally less often -- say over 6 months instead of 6 weeks, but corrupt neither-less).  I have seen several exhaustive tests done by other Raspberry Pi users that conclude the same -- that only read-only filesystems on SD cards will prevent corruption.

Debian-based Linux Systems on SSD

EXT4 

I use the mounting parameters rw,errors=remount-ro,user_xattr,noatime,discard that reduce unnecessary update of inodes when accessing files.  The discard enables TRIM support and should be enabled for as long as your drive supports it (hdparm -I /dev/sda | grep TRIM).  If you enable discard and your drive doesn't support it, you'll have data loss.

EXT4 has better support than previous versions (EXT2, EXT3), even though there is increased journaling in EXT4 (that can reduce the lifespan of SSD drives).  If you have frequent writes and have means to mitigate the risk of data loss in system crashes/etc, then consider turning journaling off (tune2fs -O ^has_journal /dev/sda).

I reduce the amount of writes to SSD by using various tempfs (stored in RAM) for logging, tmp and caching.  I use the find -mtime command to identify files that are frequently written to (in most cases, for unnecessary reasons).  I then schedule startup, suspend/hibernate and shutdown routines that sync these tempfs to disk.  I store everything from system logs and google chrome / Mozilla configuration and cache directories to RAM.

Debian-based Linux Systems on slow hard drives

XFS

I have one Sony VAIO system that uses a 1.8" 4200rpm SATA hard drive.  A really slow hard drive benefits from the speed advantages of XFS.  One should note that data loss can become and issue for system crashes/etc.  You can consider mounting the XFS filesystem as read-only, and use tempfs to store writes to be synced to disk in a safe fasion (similar to the Raspberry Pi setup). 


Linux Containers / LXC and Linux Based VMs/KVMs

BTRFS 


For any system that you use kernel 3.9 or greater, you should consider using BTRFS to store your operating system.  BTRFS allows you to "snapshot" and clone your LXC/VM with minimum data duplication.  Similar to QCOW2 (in KVM) and snapshots in VMware, BTRFS will help you reduce your LXC/VM disk consumption.  

NAS units (such as DNS 323)

EXT4 with SAMBA and NFS

I use alt-f firmware on my DNS 323 units, so my NAS units do support EXT4.  A lot of older NAS units or DNS 323 units running on official firmware, may not support EXT4.  In those cases I use EXT3, and as I upgrade firmware on the NAS or replace it with a more capable NAS, I convert to EXT4.  The journaling of EXT4 provides the best means of preventing data loss besides moving to a filesystem such as BTRFS or ZFS.  My NAS units, even with modern open-source and community driven firmware like alf-f, does not support BTRFS or ZFS due to hardware limitation (memory and CPU required to support "tomorrow's filesystems").  I mitigate risk of data loss due to corruption by maintaining offline mirror drives for each NAS drive.

Samba shares enabled for sharing with Windows and XBMC on Raspberry Pi and NFS for mounting the drives on Linux systems.

Comments about BTRFS and ZFS

I really believe that BTRFS and ZFS will be the filesystems for the future.  BTRFS is highly being developed on and is meant to share a lot of the benefits and features of ZFS but without the licensing restrictions.  If you have situations/applications where you can't run newer versions of the Linux kernel, then you should avoid BTRFS -- it's always best to only use BTRFS on systems with at least kernel 3.9.  

ZFS is an Oracle created filesystem that has great data integrity (to guard against bit rot and data corruption), built in encryption and compression and data deduplication (great for snapshoting and cloning).  ZFS has been ported to Linux using either native kernel modules or by FUSE.  There are licensing issues as ZFS isn't licenses under GPL, and therefore, the implementation has stripped out features and is not as stable as the original Sun Solaris implementation.  Being that the original Oracle implementation is 64-bit, the linux native kernel modules are only compiled for amd64, so if you need to support 32-bit systems, you should not consider ZFS.  Further, ZFS needs a fair amount of RAM (4GB) to manage.  Also, if you often run/use the latest Linux kernel versions, you may have issues as you have to wait for the native kernel modules to be updated for your kernel release -- due to licensing restrictions, they don't come bundled with the kernel, so you need to wait for the support community to update the modules afterwards.  I've been using kernel 3.13 for 6+ months, and I still don't have ZFS kernel modules that work on my kernel version.

ZFS also has embedded support for Samba and NFS -- that is, the filesystem can be automatically shared, without any additional configuration, simply by enabling sharesmb or sharenfs.

BTRFS is a good compromise to ZFS -- to gain some of the features without dealing with some of the problems.  Both would be considered "non-production" at this point.  Don't store critical data on them without having good mechanisms in place to safe guard against being inflicted by bugs that often pop-up in bleeding-edge development work.


Tuesday, 3 June 2014

Map Suspend & Hibernate to shortcut keys

One of the issues I recently encountered when upgrading to Linux Mint Debian Edition (LMDE) Update Pack 8 (UP8) is the loss of functionality of the suspend and hibernate keys.  At first I was under the impression that it was just an issue on my Thinkpad, but I discovered the issue existed on all the system that I upgraded.  It's a known issue and was identified in this bug: https://bugs.launchpad.net/linuxmint/+bug/1276678

There might be other workarounds to resolving the issue, but I took this as a good opportunity to finally mapping out a new suspend/hibernate key combination that I could use across all my systems.  The FN-F4 for suspend and FN-F12 may be universal on all Thinkpads, but my Vaio and Ultrabook use different suspend and hibernate keys, thus my finger-memory sometimes slips up.

To tackle both problems, I decided create a common shortcut key for each function across all my systems.  Because the FN keys tend to be tied to hardware routines, I settled on SHIFT+F4 for suspend and SHIFT+F12 for hibernate.

The first step to tackle was writing a suspend and hibernate script that could be invoked by my user ID without having to provide a sudo password.

I added the following two lines to my /etc/sudoers file.

durdle t420-ssd = (root) NOPASSWD: /usr/sbin/pm-hibernate
durdle t420-ssd = (root) NOPASSWD: /usr/sbin/pm-suspend

Substitute durdle with your user ID, and t420-ssd with our hostname.

You may find that you need to change the file  /etc/sudoers  to have write permissions before you can edit it (doing a  chmod 740 /etc/sudoers before updating the file and a chmod 440 /etc/sudoers after updating the file, will do the trick).

Next, I decided to create shortcut scripts in my ~/bin/ folder.  This will allow me to quickly suspend and hibernate from the command line and allow me to easily tie the two routines to the Autokey program.

My two scripts resemble as follows:

~/bin/hibernate.sh 
sudo /usr/sbin/pm-hibernate

~/bin/suspend.sh 
sudo /usr/sbin/pm-suspend

If you can't use the pm-hibernate or pm-suspend programs to hibernate or suspend, you can substitute your equivalent calls.  Or if you need to add wrappers around them, these shell scripts are the place to put them.  Previous to kernel 3.13, my Vaio need some additional system calls before calling pm-hibernate, in order to ensure a proper hibernate.  I place those calls in my hibernate.sh.

I use a program called Autokey for various shortcuts and keyboard macros.  If you don't normally use Autokey, you will need to ensure that it starts up on boot up.  You can do this by calling it in your "Startup Applications" list.


The program is fairly self explanatory.  You will create two new scripts, enter the following, substituting your username in, and then assigning the Hotkey <shift>+<f4> and Hotke <shift>+<f12>:

for suspend:
import os
os.system('/home/durdle/bin/suspend.sh')

for hibernate:
import os
os.system('/home/durdle/bin/hibernate.sh')

That's it!  Now when you press SHIFT+F4, your system should suspend and when you press SHIFT+F12, your system should hibernate, all without entering a password.

Tuesday, 8 April 2014

Fixing ipod touch / iphone support in LMDE after Update Pack 8

Since upgrading to Update Pack 8 (UP8) in Linux Mint Debian Edition (LMDE), I'm no longer able to mount my ipod Touch 2G 3.1.3 or iphone 3GS 6.1.4. Both devices used to appear as a mounted device when plugged in, and I could use gtkpod to sync to. Since the upgrade, when I plug in either device, I get a DBUS timeout error. The devices appear as unmounted, and when I try mount them via caja, I get a DBUS timeout error.

dmeg has the following output:

usb 6-1: new high-speed USB device number 3 using ehci-pci
usb 6-1: New USB device found, idVendor=05ac, idProduct=1294
usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 6-1: Product: iPhone
usb 6-1: Manufacturer: Apple Inc.
usb 6-1: SerialNumber: <<>>
ipheth 6-1:4.2: Apple iPhone USB Ethernet device attached
usbcore: registered new interface driver ipheth
IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
pool[5534]: segfault at 300000003 ip 00007fc287ff8cd6 sp 00007fc283ffbc50 error 6 in libimobiledevice.so.4.0.1[7fc287fed000+1a000]
pool[5558]: segfault at 300000003 ip 00007f61bd848cd6 sp 00007f61b984bc50 error 6 in libimobiledevice.so.4.0.1[7f61bd83d000+1a000]


I found a solution posted at http://beautifulajax.dip.jp/?p=536.

In a nutshell, I downloaded the following 4 files:

libusbmuxd1_1.0.7-2_amd64.deb
libimobiledevice2_1.1.1-4_amd64.deb
fuse-utils_2.9.0-2+deb7u1_all.deb
ifuse_1.0.0-1+b1_amd64.deb 
 from:
https://packages.debian.org/en/wheezy/ifuse
https://packages.debian.org/en/wheezy/fuse-utils
https://packages.debian.org/en/wheezy/libimobiledevice2
https://packages.debian.org/en/wheezy/libusbmuxd1
Install by each of the 4 by running dkpg, such as:

sudo dpkg -i libusbmuxd1_1.0.7-2_amd64.deb sudo dpkg -i libimobiledevice2_1.1.1-4_amd64.deb sudo dpkg -i fuse-utils_2.9.0-2+deb7u1_all.deb sudo dpkg -i ifuse_1.0.0-1+b1_amd64.deb 

Create a mount point, such as /mnt/iphone:
sudo mkdir /mnt/iphone
sudo chmod 777 /mnt/iphone/

To mount the iphone / ipod touch, connect the device and run:

ifuse /mnt/iphone/

To unmount the iphone / ipod touch, run:

umount /mnt/iphone/






Fixing Disappearing Network Manager from LMDE after Update Pack 8

One of the issues I witnessed on one of my Linux Mint Debian Edition (LMDE) system, after performing Update Pack 8 was that the network icon

would disappear from the notification bar.  This would make it extremely difficult to manually switch between access points (automatic was fine and transparent, such as if you need to connect to a new access point, or select a particular hot spot among multiple known/saved access points.

The notification icon is actually a program called nm-applet.

When I started it manually, it would exit with the following error:

** (nm-applet:27520): WARNING **: Could not initialize NMClient /org/freedesktop/NetworkManager: Rejected send message, 2 matched rules; type="method_call", sender=":1.92" (uid=1000 pid=27520 comm="nm-applet ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination="org.freedesktop.NetworkManager" (uid=0 pid=4075 comm="/usr/sbin/NetworkManager ")
** Message: applet now removed from the notification area
** Message: applet now embedded in the notification area
** Message: applet now removed from the notification area

The issue is that /etc/dbus-1/system.d/org.freedesktop.NetworkManager.conf gets reset with Update Pack 8.

To resolve the issue, make a backup of the file /etc/dbus-1/system.d/org.freedesktop.NetworkManager.conf  and modify the file by replacing all of the deny entries with allow.  Easiest way is to open vi, and enter :%s/deny/allow  to automatically switch all the occurrences.  Next time you reboot, nm-applet will stay alive.  You'll also be able to manually start nm-applet in the meanwhile.

Friday, 7 March 2014

Debugging XBMC Plugins

I've been learning XBMC plugin development over the past few months.  I thought it would be a good time to review my remote debugging configuration.  When I had started setting up a debugging environment, I discovered the information available was fragmented and obsolete.

A helpful source is HOW-TO:Debug Python Scripts with Eclipse.  I will refer to it throughout.

Development Environment (IDE)


You can do a lot with just using gedit (with it's python syntax highlighting).  But when things get more complicated, you'll need a place to debug.  An IDE that I've used before, on Java and Perl projects, was Eclipse.  Eclipse has a PyDev plugin available, that can be easily installed through the Updates (Help...Install New Software), which is required to add Python integrated functionality to Eclipse.  Because I didn't have Eclipse installed on my particular current system, I decided to opt for downloading LiClipse instead.  It is "lightweight" and has PyDev already installed. You'll need a Python interpreter installed -- not an issue on most Linux systems.  XBMC also uses your native Linux Python interpreter.

Refer to section 2 in HOW-TO:Debug Python Scripts with Eclipse for setting up PyDev within XBMC.

Setup Workspace

I have all my XBMC plugins located in a particular development folder named development/xbmc.  I simply setup my workspace to this folder.  For each plugin, represented by single subfolder for each (such as XBMC-pluginname), I simply go to File -> New, PyDev Project.  Give the project the appropriate name (XBMC-pluginname), select Python for Project type.  Select Grammar Version 2.7.  For Interpreter, select Default. Click on the "Click here to configure an interpreter not listed".  In the upper right pane, click the Quick Auto-Config, which will configure an interpreter for you.  If you have multiple Python Interpreters installed, repeat until the required version is created.

Before clicking the Finish button, change the radio button to "Don't configure PYTHONPATH (to be done manually later on)".


Refer to section 3 in HOW-TO:Debug Python Scripts with Eclipse for more assistance.  This part of the Wiki is out-of-date, however.

Setup Pysrc (for remote-debugging)

If you want to remote-debug your plugin (that is step through your code while running), you will need to do some further setup.  First, you need to locate the pysrc library files that came with your PyDev install.  If you do a (find . | grep pysrc) from within your Eclipse install, you should find them located in plugins org.python.pydev_3... folder.  Mine were located at ./plugins/org.python.pydev_3.3.3.201401272005/pysrc/.

Next, you'll need to find the global library location for you Python interpreter.   You can do so by running the following:

python -c "from distutils.sysconfig import *; print(get_python_lib())"
My path was /usr/lib/python2.7/dist-packages.  Copy the pysrc folder into this noted folder (you'll need to be root).  

You'll also need to create an empty file called __init__.py within this pysrc folder ( /usr/lib/python2.7/dist-packages/pysrc).  This will allow XBMC transverse into it.

Modify Your XBMC Plugin

To enable remote-debugging to your application, you will need to add some code to your plugin (say into your default.py, below the import statements).  Code I've put in mine resemble this:

try:
    remote_debugger = addon.getSetting('remote_debugger')
    remote_debugger_host = addon.getSetting('remote_debugger_host')

    # append pydev remote debugger
    if remote_debugger == 'true':
        # Make pydev debugger works for auto reload.
        # Note pydevd module need to be copied in XBMC\system\python\Lib\pysrc
        import pysrc.pydevd as pydevd
        # stdoutToServer and stderrToServer redirect stdout and stderr to eclipse console
        pydevd.settrace(remote_debugger_host, stdoutToServer=True, stderrToServer=True)
except ImportError:
    sys.stderr.write("Error: " + "You must add org.python.pydev.debug.pysrc to your PYTHONPATH.")
    sys.exit(1)
except :
    pass
The code will look for the parameter "remote_debugger" and "remote_debugger_host" in your settings.xml file.  If neither is found, an exception will be thrown, and the debugging will be disabled.  This will allow you to maintain one version of your code.  You could use a constant variable instead, but then you'd need to set it somewhere.  I see others implementing a variable like REMOTE_DEBUG and then setting it True or False in the same class, but if you forgot to switch it to False, and push your code out, it'll fail if someone deploys it.  I found my approach elegant, as the debugger code will be inactive unless the user adds the following two lines to their settings.xml:

    <setting id="remote_debugger" value="true" />
    <setting id="remote_debugger_host" value="localhost" />

The remote_debugger_host allows you to use a remote system for debugging, rather than using the same machine.  This allows you to debug your plugin on a Raspberry Pi and debug it using your laptop.  If you are debugging on the same device (laptop running XBMC), then you can leave this as localhost.  Otherwise, change it to your IP of your debugging machine.

The above code was adapted from  HOW-TO:Debug Python Scripts with Eclipse .


Raspberry Pi for Debugging


Just like you setup pysrc earlier on your computer, if you want to run your plugin from a device, such as Raspberry Pi, to remote-debug, you'll need to copy the pysrc folder, found earlier, to your Raspberry Pi.  Follow the same steps under Setup Pysrc, copying the source folder from your computer with Eclipse or LiClipse installed, to your device.  In my case, my Raspberry Pi used the same dist-packages folder (so I copied to usr/lib/python2.7/dist-packages/pysrc).

You may need to add port 5678 to your computer's firewall to allow inbound connections from your debugging device.


Adding PyDev Debugger to your View


There are several ways of accomplishing this.  I prefer going to Window -> Customize Perspective, selecting Command Groups Availability and checkboxing "PyDev Debug".  This will add a PyDev menu with the buttons "Start Debug Server" and "Stop Debug Server" to my Eclipse menu.


Actually Doing the Remote-Debugging...


To start the debugger, I flip to Debug Perspective, and then click the Start Debug Server from PyDev menu.  In the Debug Server window, you'll see "Debug Server at port: 5678". 

Now you can open XBMC.  If you have the remote-debugger code added to your plugin AND have the remote_debugger and remote_debugger_host set in settings.xml, if you try to load the plugin in XBMC, it should try to communicate to the Eclipse debugger.  If it fails to connect to the debugger, it'll push a 110 Connection Failed to the xbmc.log file.  If you see a "You must add org.python.pydev.debug.pysrc to your PYTHONPATH" error, that means the pysrc isn't accessible on your XBMC device (did you add the pysrc folder to the dist-packages folder?  did you include an empty __init__.py  file within that directory?).

If it is working, XBMC should "halt" while your debugger is passed control.  In the Debug panel, you should see an unknown with MainThread show up.  This represents the session running on your XBMC device.  You can now step through the code using standard debugging techniques.  You can also simply "Resume" (F8) to continue running to completion the plugin.



Refer to HOW-TO:Debug Python Scripts with Eclipse for further advise on debugging.

Have fun :) 

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.