Menu Bar

Thursday 16 October 2014

Booting From SD Card

To avoid wearing out the internal NAND Flash, it is convenient to install the OS on an SD card and boot from that.  It is easily replaced if it ever wears out, and is easy to back up.
The card does not need to be very big: the NAND flash is only 512M.  I used an 8G Class-6 SDHC card made by A-Data. 
The steps are:
  1. Find out what name your system calls the raw SD card device
  2. Format and partition the SD card
  3. Create a filesystem on the SD card
  4. Mount the new card
  5. Copy over the OS from the NAND Flash
  6. Change the uBoot settings to boot from the SD card
  7. Save some wear&tear on the SD card

 Get Name of Raw SD Card Device

Insert the SD card, wait a second or two, then type 'dmesg' to see what it got called:
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 SD 7.46 GiB
mmcblk0: p1
The name 'mmcblk0' is the raw device name of the SD card.  Various commands to follow will reference the SD card via the path '/dev/mmcblk0' which is a reference to the raw device, and not any filesystem that might be present on the device.

Format/Partition the SD card

Now that you know the device name, if you need to format/partition the card, use the 'fdisk' command to do the following:
root@sheevaplug:~# fdisk /dev/mmcblk0
press "o"         This will create a new partition table
press "n"         This asks to create a new partition
press "p"         The new partition will be the primary partition
press "1"         The new partition will be partition #1
press enter       Use the default value for the first cylinder
press enter       Use the default value for the last cylinder
press "a"         Make parition 1 bootable
press "1"        
press "w"         Make the changes to the SD card permanent

Create a Filesystem

There is a lot of discussion about what filesystem to use on an SD card.  You can google that topic and find a lot of opinions.  I chose ext2 because it is perceived to perform less writes to the SD card than other filesystems.  This can be important since SD cards (like any Flash-based memory device) have a finite number of writes that can be performed before they quit working. 
The following command creates an ext2-based filesystem.  Notice that the mkfs command accesses the SD card through the raw device since the filesystem does not exist yet:
root@sheevaplug:~# mkfs -t ext2 /dev/mmcblk0p1

Mount the SD Card

Now that a filesystem is on the card, you can mount it.  The first step is to create a directory somewhere that will act as the top-level directory for everything in the card.  In this case, I chose /mnt/sdcard:
root@sheevaplug:~# mkdir /mnt/sdcard
The next step actually mounts the card.  The 'mount' command takes two parameters: the path to the raw device, and the name of the top-level directory where the card will appear in the overall filesystem:
root@sheevaplug:~# mount /dev/mmcblk0p1 /mnt/sdcard/
At this point, it is time to see if everything worked.  Use the 'df' (disk freespace) command:
root@sheevaplug:/mnt/sdcard# df
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 256740 0 256740 0% /lib/init/rw
varrun 256740 36 256704 1% /var/run
varlock 256740 0 256740 0% /var/lock
udev 256740 112 256628 1% /dev
tmpfs 256740 0 256740 0% /dev/shm
rootfs 472848 152836 315172 33% /
/dev/mmcblk0p1 7703068 17456 7294312 1% /mnt/sdcard

Notice that the last entry says that there is a large amount of freespace on /mnt/sdcard. 

Copy OS Files from NAND

Now it is time to do something will all that space.  We start by copying all the files over from the NAND Flash onto the SD card.  This takes a bit of time.  In my case, it took about 75 seconds:
root@sheevaplug:/mnt/sdcard# time cp -ax / /mnt/sdcard

real 1m14.949s
user 0m0.400s
sys 0m24.820s
Once the main copy is complete, do one more copy to get the device files copied as well.  This one takes no time at all:
root@sheevaplug:/mnt/sdcard# cp -a /dev /mnt/sdcard/
Now check the filesystem to see how much space we used.  This time, I used the '-h' parameter to 'df' to display the results in 'human readable' terms.  It is more convenient:
root@sheevaplug:/mnt/sdcard# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 251M 0 251M 0% /lib/init/rw
varrun 251M 36K 251M 1% /var/run
varlock 251M 0 251M 0% /var/lock
udev 251M 112K 251M 1% /dev
tmpfs 251M 0 251M 0% /dev/shm
rootfs 462M 150M 308M 33% /
/dev/mmcblk0p1 7.4G 284M 6.7G 4% /mnt/sdcard
You can see that we are using 284 megabytes of the 7.4G available on the SD card.  There is 6.7G remaining.

Boot From SD Card

Finally, to the heart of the matter.  This step requires using the JTAG serial cable that came with the SheevaPlug.  Reboot the SheevaPlug using the 'reboot' command.  As the machine reboots, hit the 'return' key to interrupt the boot process and remain in the uBoot command shell.
Define a new boot command to explain how uBoot should try to boot from an MMC card (another name for an SD card), as well as the NAND flash:
 setenv bootcmd_nand 'setenv bootargs $(bootargs_console) $(mtdpartitions) $(bootargs_root); nand read.e 0x00800000 0x00100000 0x00400000; bootm 0x00800000'
setenv bootargs_root_mmc 'root=/dev/mmcblk0p1'
setenv bootcmd_mmc 'setenv bootargs $(bootargs_console) $(mtdpartitions) $(bootargs_root_mmc); mmcinit; ext2load mmc 0 0x800000 /boot/uImage; bootm 0x800000'
The long commands from the previous examples need to be cut&pasted as one long input line.
Now, change the actual boot command to ask uBoot to first try to boot from the SD card.  If that fails, uBoot will fall back to boot from the NAND Flash. This provides a bit of redundancy if the SD card goes missing:
setenv bootcmd 'run bootcmd_mmc; run bootcmd_nand;'
Note that the 'setenv' changes you just made are not permanent until you type a 'saveenv' before booting the device.  The advantage of not typing 'saveenv' the first time is that if you do something wrong, you will not trash your environment.  At this point, you should try booting to make sure everything works, by simply typing 'boot'.  Once you are sure that everything works, repeat the 'setenv' steps (above), and type 'saveenv' before you type 'boot'.
Typing 'boot' with the SD card in place should get you something like this:
Marvell>> boot
SDHC found. Card desciption is:
Manufacturer: 0x1d, OEM "AD"
Product name: "SD ", revision 1.0
Serial number: 2068
Manufacturing date: 10/2009
CRC: 0x00, b0 = 0


2620504 bytes read
## Booting image at 00800000 ...
You can see that the boot is occuring from the SDHC card, which is what you wanted.
After the boot completes, you can log into linux and type another 'df -h' command:
root@sheevaplug:~# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 251M 0 251M 0% /lib/init/rw
varrun 251M 36K 251M 1% /var/run
varlock 251M 0 251M 0% /var/lock
udev 251M 112K 251M 1% /dev
tmpfs 251M 0 251M 0% /dev/shm
rootfs 7.4G 284M 6.7G 4% /
root@sheevaplug:~#
Now you can see that the root file system (rootfs) is mapped to the SD card due to its sheer spaciousness.
Once you have booted from the SD card, get back into uBoot, pull out he SD card, and type 'boot'. You should see that the SD boot attempt fails, followed by uBoot booting from the NAND.

Save Wear&Tear on the SD card

As mentioned earlier, all Flash-based devices will eventually wear out since the flash can only be written a finite number of times.  To minimize the number of write operations to flash under linux, google will tell you that there are lots of opportunities.  In my case, I took the most minimal steps to minimize wear.  This approach simply tells linux to not bother updating the access time for files whenever they are read.  This can have some drawbacks for certain linux apps, but I don't care.  Therefore, I edited /etc/fstab to add a line as follows:
rootfs / rootfs rw,noatime 0 0
That did the trick.  Use the 'mount' command to make sure that 'noatime' shows up for the rootfs:
root@sheevaplug:~# mount
rootfs on / type rootfs (rw,noatime)
That's it!
It will be worth it in the end.

No comments:

Post a Comment

Tricks and Tips