|
Step one (backup) - Step two (partitions) - Step three (filesystems) - Step four (install find) - Step five (copy) - Step six (test) - Step seven (delete)
2003-10-26
This is a re-write of the 2003-7-4 version of this document, which
contained some inaccuracies. I have also now discovered a better way to do
this (I am also now using a 256MB SD card rather than the 128MB MMC I had
then).
I am writing this after having successfully managed to move the /usr and
/home directories on my iPAQ 3870 to a 256MB Secure Digital (SD) card. It was
an interesting and sometimes painful journey, so I thought I'd write
down how I did it in the hope that I can save others at least some of
the pain. Note that to the best of my knowledge and as of this writing, only
the MMC/SD slot on the 3800-series iPAQ's is supported by the Familiar
kernel.
If you're interested in why I did this, how I decided to do it,
and/or what I was trying to acheive, there's some background
here.
My "initial" hardware and software setup was an iPAQ 3870 flashed with
bootgpe2-v0.7.1-h3600.jffs2, upgraded to kernel 2.4.19-rmk6-pxa1-hh26 from
http://www.handhelds.org/feeds/2.4.19 and to Familiar unstable from
http://familiar.handhelds.org/familiar/feeds/unstable/packages/armv4l.
These upgrades were done in October 2003. The kernel upgrade is necessary to
get the latest MMC/SD card support, but you probably don't need to
upgrade to Familiar unstable (and it can be a little tricky to do so).
Before I get into any of the "what I did" part, I should mention that
it's possible to boot my iPAQ to a state where the serial console is up
and running (so I can log in and do/fix stuff) without my SD card inserted.
Hopefully this means that if you get into a mess setting this up, you
should be able to pull out your card and reboot successfully, provided
that you only move the same bits of your filesystem to your
MMC/SD card as I did. I can also put up the USB network interface (or
Bluetooth, although I haven't actually tried that yet) and do an NFS mount
(with -o nolock). The X Window system (and consequently GPE) will NOT run on
my iPAQ without the SD card, however (although I did manage to keep the GPE
boot-up splash screen, as you'll see below).
I did everything as root. I don't do this on my desktop machine, but
on a device as personal as my PDA, I don't really bother much about
distinguishing my normal user from the root user, especially for this sort
of thing. Of course, you do actually NEED to be root to do a lot of the
things involved in setting this up.
What follows on this page is a fairly complete discussion of the steps
involved in setting up your "MMC/SD-enhanced filesystem". If you just want
some "1. do this, 2.do that" instructions, go here.
My objective here was twofold: free up some space in the on-board
flash by moving parts of the filesystem to the SD card, and set things up so
that a lot of the newly installed files will go to the SD card too. Keeping
this in mind, I had a look at the existing filesystem's directory
structure. To make this easier, and as a backup, I copied the root
filesystem to a directory on my desktop machine. There are several ways
to do this, but some work better than others.
A simple
# cp -a /. /some/mount/point
won't work because you'd get into a loop copying /some/mount/point/. to
/some/mount/point/some/mount/point/. and so on. The way I copy root
filesystems on desktop machines is
# cd /
# find . -xdev | cpio -pmv /some/mount/point
The -xdev tells find not to descend into "other filesystems" mounted below
the base directory (the root directory, in this instance). The find command
produces a list of filenames that is passed to the cpio command, which runs
verbosely (listing filenames as it goes - I use this option so I can see
where it's up to; -v) in "copy-pass mode" (-p), preserving file modification
times (-m). At the time of writing, cpio is not available as a "standard"
ipkg, but the Debian ARM version can be installed on an iPAQ. Also, the
Busybox version of find doesn't support the -xdev option, so you need to
install the full version, which does come in an ipkg.
Since installing cpio and the non-Busybox version of find on the iPAQ
was a bit of a fiddle (although I did succeed and I used find later on),
and because having a backup in JFFS2 form can be useful in the event of a
reflash, I think that the best thing to do is copy your root filesystem to
your desktop machine as a jffs2 file. The easiest (but not the best -- see
below) way to do this is to use bootldr's "save root" command to upload the
entire flash partition over the serial link. You can achieve the same end
from the Linux (as opposed to bootloader) command line. See this page for more about that. As the root
partition fills almost all of the 32MB (on my 3870) of flash memory, this
upload takes some time. You get the entire partition, including any garbage
and any unused blocks. This leads to a file that is too big for the current
version of bootldr (I'm using 2.21.11) to re-flash back into the flash
memory.
Thankfully, there is a way to create a new jffs2 image containing no
unnecessary garbage or unused blocks (a few unused blocks are needed for
JFFS2 to actually work properly). So, step one is
to backup your existing root filesystem as a jffs2 image and copy the jffs2
file to your desktop computer.
# mkfs.jffs2 --root=/ --eraseblock=262144 --pad
--output=/where/to/save/RootBackup.jffs2
This file will be quite large (well over ten megabytes unless you don't
even have a GUI installed on your iPAQ), so it may not fit in your iPAQ's
on-board flash. You want to copy the file to your desktop machine anyway,
so if you can create it there directly (through an NFS mount or whatever),
you avoid having to transfer the file separately. Other options are to
create the file on your MMC/SD card or a CF card and use that to transfer it
to your desktop machine (you'll obviously need a suitable card reader for the
desktop machine), or to pipe the output of mkfs.jffs2 over a serial link
using zmodem or some such (see this page for
some instructions on zmodem piping). Phew! You now have a backup of your
system as it stands. If this file is not too big, you'll be able to re-flash
it to your iPAQ if anything goes wrong. How big is too big? I don't know, but
I have successfully re-flashed a 20MB file, and I think the smallest one I've
tried that failed was 24MB. Apparently you can use "load root <addr>"
to re-flash the partition in stages after splitting your jffs2 image into two
(or more) files, and the bootloader has a "copy" command that can
(apparently) be used to copy a file from a CF card to a flash partition.
Remember that apart from backing up the iPAQ's root filesystem, I also
wanted to be able to browse through it using the tools available on my
desktop computer. To do that, I need my desktop computer to be able to read
the JFFS2 filesystem. This is not as simple as it may seem, because JFFS2
only works with Memory Technology Devices (MTD). To access a simple file
(your jffs2 image file) as an MTD, you need to set up a loopback device and
then "pretend" that this loopback device is an MTD. Support for all this must
be in your kernel (and modules). If you don't think you're up to kernel
building or just don't want to bother, you can skip this part as it's just convenient, not required.
Depending on your distibution, you may already have the necessary kernel
support (although it's unlikely because MTDs are rarely used with desktop
computers). The files you need for MTD are mtdcore.o, mtdblock.o and
blkmtd.o. Probably the easiest way to see if you have these is
# find /lib/modules -iname '*mtd*'
If none of the above-mentioned files is listed by this find command, you will
need to do some kernel configuration and module- or even kernel-building. If
blkmtd.o is listed but mtdcore.o is not, then mtdcore is almost certainly
compiled into your kernel, and you're OK on the MTD front. JFFS2 support is
much simpler. The only module you need is jffs2.o, and it might be compiled
into your existing kernel if you have MTD support (remember JFFS2 only works
with MTD, so you're not likely to find a kernel that has JFFS2 but not MTD
support). For the loopback device, you just need loop.o, which may very
well be compiled into your kernel, as it's a handy little thingummy.
I'm not going to go into a complete tutorial on configuring and compiling
a custom kernel, as this has been done and much better than I could do it
(e.g.
http://www.ibiblio.org/mdw/HOWTO/Kernel-HOWTO and
http://www.linuxchix.org/content/courses/kernel_hacking). If you're using
menuconfig (xconfig is presumably similar), the options you need are (I
recommend compiling them all as modules - blkmtd MUST be a module):
- Memory Technology Devices (MTD) ->
- Memory Technology Device (MTD) support this is
mtdcore]
- Caching block device access to MTD devices
[mtdblock]
- Self-contained MTD device drivers ->
- MTD emulation using block device
[blkmtd]
- Block devices ->
- File systems ->
- Journalling Flash File System v2 (JFFS2)
support
I also set "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" to 1, but I
don't think I've ever referred to the output produced by it.
If you don't use devfs, you will need to create nodes for your loopback
device and MTD block device (unless you already have them).
# mknod /dev/loop0 b 7 0
# mknod /dev/mtdblock0 b 31 0
Once you've got your kernel and device nodes straightened out, and assuming
the kernel bits are all modules, do this
# modprobe loop
# modprobe mtdblock
(the above will also load mtdcore, because mtdblock requires it)
# losetup /dev/loop0 /path/to/RootBackup.jffs2
(use '/dev/loop/0' if you have devfs)
# insmod blkmtd erasesz=256 device=/dev/loop0
# mount -r -t jffs2 /dev/mtdblock0 /some/mount/point
(this should load the jffs2 module for you)
At this point, you should be able to access the files contained in your
jffs2 image. Note that it's a really bad idea to write to the jffs2
filesystem because there's not really any space left in it and it would
corrupt your backup. That's why I specified the read-only option (-r) in
the mount command. I actually copied the contents of the JFFS2 filesystem
into a directory in my desktop machine's root filesystem so that I could
leave the image file alone and avoid ever needing to re-do all the hoopla
of setting up to re-mount the JFFS2 filesystem. By the way, to unmount
and cleanup, do this
# umount /some/mount/point
# rmmod blkmtd
# losetup -d /dev/loop0
# rmmod mtdblock mtdcore loop
Once I had desktop access to a duplicate of my iPAQ's
filesystem, I used my file manager to look at the amount of space used by the
files in each directory. The whole shebang is 25.8MB. Of this, /usr is
18.7MB. Since this is also where many of the files installed by packages go,
I started out here. The first thing I tried (when I was still using an MMC)
was copying the entire contents of /usr to a card partition, then mounting
the card parition over the top of the existing /usr directory. This didn't work.
My iPAQ locked up. After resetting, I wondered if it was some problem with
doing the mount on a "running" system, so I tried setting up the mount in
/etc/fstab so it would happen at boot time. This didn't work either. I
still am not sure why. Anyway, there are some advantages to only moving
sub-directories of /usr, so I did that on the MMC. Thanks to a message
posted to the
Familiar mailing list by Tony Godshall, I have since discovered that
making /usr a symlink the SD card partition's mount point seems to work
well. I also decided to put /home on the SD card to give me plenty of room
for my personal data etc.
Once I knew what I was going to move to the SD card, I was ready to
partition it. Since I have plenty of room (for my purposes) on my SD card, I
just split it half (one half for /usr, the other for /home). For
step two you'll need fdisk (or some other
partitioning software)
# ipkg install fdisk
According to IpkgFind (as at 2003-10-26), the fdisk package is available
from a variety of feeds: stable, unstable, 0.5.2, 0.6 base, 0.6.1 base, and
0.7 base.
Partitioning the MMC/SD card is pretty straightforward. First enter the
command
# fdisk /dev/mmc/disc
You should see a prompt from fdisk, probably preceeded by a warning about
the number of cylinders on the "disc". Press 'P', then 'Enter' to see the
current partition table, as well as some information about the layout of the
disc. You may want to take note of the size of a cylinder, as this is the
basic unit of size for a partition. A new MMC/SD card usually has a single
Windoze partition filling all of the available space. You will need to delete
this partition before you can create your own partitions. Press 'D', 'Enter',
'1', 'Enter' to delete the first partition. If you have more than one
partition on your card, you probably want to delete the others too ('D',
'Enter', '2', 'Enter', etc).
To start creating your first new partition, press 'N' then 'Enter'. Your
first partition will be a primary partition, so press 'P', 'Enter'. The first
partition is number 1 (surprise, surprise), so press '1', 'Enter'. This
partition will start at the beginning of the card, cylinder 1. Fdisk should
offer cylinder 1 by default, so you can just press 'Enter'. Next, fdisk
needs to know how big to make the partition. There are a number of ways you
can specify this. The most general-purpose approach is to decide what size you
want the partition to be (in megabytes for this example), type '+', then the
size you want, then 'M' (for megabytes), then press 'Enter'. I actually tend
to specify my partition sizes in cylinders, but I'm not going to go into that
here.
If you are going to use all the available space on your SD card, and you
want no more than four partitions, I'd advise making them all "primary"
partitions. If you want more than four partitions or you want to leave some
space available on your SD card, make up to three primary partitions then
set up the remainder of your space as an extended partition (which in turn
contains all the rest of your "real" partitions). See the fdisk man page on
your desktop machine if you want more information about fdisk. Once you've set
up all the partitions you need, press 'W', 'Enter' to write the new partition
table to the card. This will also exit from fdisk, loading the new
partition table into the kernel in the process. If you enter
# ls /dev/mmc
you should see "disc part1 part2... partn" with a "partx"
for each partition you created with fdisk (except the extended
parition).
Before you can start copying files to these new partitions, you need to do
step three: create filesystems on your partitions.
What sort of filesystem you use is up to you. I chose to use ext2 because it
supports long filenames and a full set of permissions, but the modules and
utilities required to support it don't take up much room. You can install ext2
filesystem support like this
# ipkg install ext2-modules
# ipkg install e2fsprogs
To create an ext2 filesystem on the first partition, use this command
# mkfs.ext2 /dev/mmc/part1
then simply repeat for your other partition(s) (changing part1 to
part2 then part3 if you have one, and so on).
Later on, we are going to need the complete (as opposed to busybox) version
of the find command. Since this is installed in /usr/bin (which obviously is
under /usr), we want to install it before copying the contents
of /usr to an MMC/SD card partition. Step four:
install find. This command SHOULD work.
# ipkg -force-overwrite install find
The -force-overwrite option is required because we need to overwrite
(replace) the busybox find. If you get the message "Cannot find package find"
from the above command, then you'll probably have to do something like
this
# ipkg -force-overwrite install
http://familiar.handhelds.org/familiar/releases/v0.7/base/armv4l/find_4.1-2_arm.ipk
This example downloads find's ipkg file from the Familiar 0.7 base feed.
This seems to be necessary because ipkg gets "confused" either by the fact
that find is already being provided by busybox, or by the fact that the same
version of the find ipkg file is available from multiple feeds.
At this point I was ready to mount the SD card partitions and start step five: copying files. I used the cp command for
copying. I've noticed in the past that using the asterisk wildcard with
cp can lead to it skipping "hidden" files (whose names begin with a
full-stop), but I think that using a full-stop to specify that an entire
directory is to be copied avoids this problem. I only mounted one partition
at a time, partly so that I could lazily use almost identical commands for
each copying task and partly to avoid any chance of getting confused about
what was mounted where, etc.
# mount -t ext2 /dev/mmc/part1 /mnt/card
# cp -a /usr/. /mnt/card
# umount /mnt/card
# mount -t ext2 /dev/mmc/part2 /mnt/card
# cp -a /home/. /mnt/card
# umount /mnt/card
Unfortunately, this does not result in a "perfect" copy because there may
be some symbolic links that use relative paths. Some of these will no longer
work because from /usr the relative path ".." is equivalent to the absolute
path "/" (the root directory), but from /mnt/card the relative path ".." is
equivalent to the absolute path "/mnt". This is a tricky problem to
solve because you can't just blindly add an extra ../ to every symlink. A
symlink like ../dest in a directory like /usr/x/y will still be OK when
copied (as ../dest) to /mnt/card/x/y, so you don't want to change it into
../../dest. The only way I know of to be absolutely certain that these are all
fixed properly is to do it by hand (or change the mount point to a top-level
directory). You can use your newly-installed find command to get a list of
all of the relative symlinks (except ones that do not start with "..", which
will only refer to files in the same directory, or in a sub-directory under
the link's directory).
# mount -t ext2 /dev/mmc/part1 /mnt/card
# find /mnt/card -lname '..*'
On my system, the vast majority of these are in the bin sub-directory. You can
use the following command to look at the destinations of these
links.
# ls -l `find /mnt/card -lname '..*'`
On my iPAQ, this shows that they are all links back to the /bin directory,
and all but two of them (bin/passwd and bin/vlock) are links to
/bin/busybox. I first turned them all into absolute symlinks to
/bin/busybox, then fixed the two links to /bin/tinylogin by hand.
# for FNAME in `find /mnt/card -lname '*busybox'`; do ln -sf
/bin/busybox $FNAME; done
# ln -sf /bin/tinylogin /mnt/card/bin/passwd
# ln -sf /bin/tinylogin /mnt/card/bin/vlock
Luckily, I had no relative symlinks under /home. You can use the same
procedure as above to check this on your system. Just replace part1 with part2
in the mount command, and change all the instances of /mnt/card to
/mnt/card2, or unmount /dev/mmc/part1 first so you can mount part2 at
/mnt/card (you could mount part2 "over the top" of part1, but this would
be asking for trouble).
The card-based filesystems are now ready for step
six, testing. I edited the file /etc/sysconfig/hotplug (if you don't
have this file, edit /etc/hotplug/mmc.agent instead) and changed this
line
MMC_MOUNT_OPTIONS="-t auto -o sync"
to this
MMC_MOUNT_OPTIONS="-t ext2 -o sync,noatime"
Specifying the filesystem type (ext2) instead of auto just prevents the
operating system from trying other filesystem types (and failing). I have
added the noatime option to reduce the number of writes to the card's flash
memory at the expense of not having a valid "access time" field in my
directory entries.
It is also a good idea to run fsck on your partitions before you mount
them. To do this, you need to edit /etc/hotplug/mmc.agent, adding these
two lines
umount $device
/sbin/fsck.ext2 -p $device
after this existing line
echo flash on $device > /dev/console
The umount command just ensures that the system doesn't think that the
partition is still mounted (as sometimes happens when the card is ejected).
Now remove and re-insert the card to ensure that your partitions are
correctly auto-mounted by hotplug. You may need to wait a while for the
fsck(s) to complete, especially if you have a high capacity card. Check the
output of
# cat /etc/mtab
You should have a line like this
/dev/mmc/part1 /mnt/card ext2 rw,sync,noatime 0 0
for each partition. Only /dev/mmc/part1 has no digit after /mnt/card. The
other partitions should have matching "part" and "card" digits.
The fsck command above can cause problems during boot-up because the rest
of the boot-up process does not wait for the fsck to complete. What I have at
the moment (but I'm not sure it's the best solution) is this extra line near the
end of /linuxrc
/usr/bin/MMCWait.sh
Immediately before the last two existing lines
echo "Executing /sbin/init..."
exec /sbin/init $*
This runs a script to wait for the MMC/SD card to be fsck'd and mounted
before transferring control to init.
The /usr/bin/MMCWait.sh script follows and is available here for your convenience ;)
Remember to put this in the root filesystem's /mnt/card so it will be
there before the SD card is mounted. It's a good idea to put it on the
card as well in case of odd boot-up timing and for the resume script
below...
#! /bin/sh
echo "Waiting for card fsck and mount"
card_mounted=none
while test "$card_mounted" = "none" ; do
if grep 'part1' /etc/mtab ; then
card_mounted=1
else
if ps | grep 'fsck.ext2' - >
/dev/null ; then
sleep
2
else
sleep
2
if ps |
grep 'fsck.ext2' - > /dev/null ; then
sleep 2
else
card_mounted=error
fi
fi
fi
done
while test "$card_mounted" = "1" ; do
if grep 'part2' /etc/mtab ; then
card_mounted=2
else
if ps | grep 'fsck.ext2' - >
/dev/null ; then
sleep
2
else
sleep
2
if ps |
grep 'fsck.ext2' - > /dev/null ; then
sleep 2
else
card_mounted=error
fi
fi
fi
done
if test "$card_mounted" = "error" ; then
echo "Fewer than two MMC/SD card partitions mounted."
fi
There is also a related issue when you resume from a
suspend. Sometimes the resume scripts need stuff from /usr/bin, so it's
a good idea to use this MMCWait script at resume time too. I have a
file called R20mmc in /etc/resume-scripts. It looks like this (and is
available here)
#! /bin/sh
sleep 3
C=0
while test $C -lt 5 ; do
if ls /dev/mmc/part* > /dev/null; then
echo MMC/SD card detected >
/dev/console
/usr/bin/MMCWait.sh >
/dev/console
rm /usr/bin/crap*
C=0
while ! mv /usr/bin/[
/usr/bin/crap$C ; do
C=$(($C
+ 1))
done
C=5
ln -s /bin/busybox
/usr/bin/[
exit 1
else
sleep 2
fi
C=$(($C + 1))
done
echo MMC/SD card not detected > /dev/console
I should probably explain what all this is about, so here goes. The
first line (after #! /bin/sh) is just a sleep to give the kernel a
chance to sort itself out. I don't think it actually needs to be as
long as 3 seconds, I've just been too lazy to try other values.
Next I set up to make up to five attempts at detecting the MMC or SD
card. Again, this is probably overkill.
if ls /dev/mmc/part* > /dev/null; then
This line just checks for the existence of any MMC/SD card partitions
echo MMC/SD card detected >
/dev/console
report that we found something
/usr/bin/MMCWait.sh > /dev/console
wait for the partitions to be checked and mounted (the check will
usually just come straight back "clean").
rm /usr/bin/crap*
Now this is where it gets interesting ;)
I have a recurring problem where the symlink /usr/bin/[ repeatedly gets
screwed up somehow. The code below renames /usr/bin/[ to /usr/bin/crapx
where x is a number starting from 0 and ascending until these renamed
files eventually get deleted by the above command. The trouble is that
when this weirdness happens the "crap" file can't be deleted until the
next reboot -- it just returns an "Input/output error".
C=0
while ! mv /usr/bin/[ /usr/bin/crap$C ; do
C=$(($C + 1))
done
this loop just keeps upping C until it finds a filename that is not in
use.
C=5
This would force the main loop to exit (because we've found the MMC/SD
card, so we're done) by setting the loop variable to the loop's limit.
In actual fact, I quit from the script soon anyway.
ln -s /bin/busybox /usr/bin/[
This re-creates the /usr/bin/[ link that got renamed above. At the
moment I don't know what causes this weird error with it and this is
the only fix for it I've come up with so far.
exit 1
All done. Go bye-byes.
else
sleep 2
This is what to do if the MMC/SD card is not found: wait two seconds and
try again. That means that if there really is no MMC/SD card then this
script will wait around for ten seconds (five loops of two seconds
each).
fi
C=$(($C + 1))
increment the loop variable.
I also have a simple /etc/suspend-scripts/S60mmc suspend script that
tries to unmount the MMC/SD card partitions, but I don't think this
helps much
#! /bin/sh
umount /home/shared
for PART in /mnt/card* ; do
umount $PART
done
The umount /home/shared is for my NFS mount point because (a) it needs
to be unmounted anyway because the network will go down on suspend, and
(b) because it is mounted under /home it would block the SD card
partition mounted at /home from unmounting.
The boot up process needs some things from /usr/bin before the MMC/SD card
gets mounted, so these need to be made available somehow. As it turns out,
they are all symlinks to /bin/busybox (at least they are with a "standard"
Familiar installation -- if you've installed the "full" version of any of
the app's that busybox contains then you might have some extra work to do
here). There are at least two ways to handle this situation. You can move the
symlinks to /bin, which should mostly be OK because /bin is usually in PATH.
However, if a script (or anything else, for that matter) specifies an
absolute path to the symlink (ie "/usr/bin/someprogram" instead of just
"someprgram"), then the symlink still needs to be in /usr/bin.
Before the MMC/SD card gets mounted, /mnt/card is normally just an empty
directory. Since /usr will soon be a symlink to /mnt/card, you can just put
copies of the busybox symlinks in a new directory, /mnt/card/bin. As symlinks
are so small, I just copied all the links in /usr/bin that point to
/bin/busybox rather than fiddle about working out which ones are actually
required.
To make the root filesystem's version of /mnt/card accessible (instead
of the contents of the MMC/SD card's partition), you can either
"remount" the root filesystem at an additional mount point, or you can unmount
the card partition. The quickest way to unmount it is just to eject the card.
Alternatively, you can just use an umount command.
# umount /mnt/card
As we discovered above, some of these links are relative rather than
absolute, so a simple copy won't give us what we want. I kind of "re-created"
all the links as absolute links like this
# mkdir /mnt/card/bin
# for FNAME in `find /usr/bin -lname '*busybox'`; do FNAME=`basename $FNAME`;
ln -s /bin/busybox /mnt/card/bin/$FNAME; done
Now you can remount your MMC/SD card partition (or just re-insert the
card).
# mount -t ext2 -o sync,noatime /dev/mmc/part1 /mnt/card
For safety's sake, I kept the original /usr intact, but under a different
name, until I was sure the new system was working properly. I used the name
usr.hide.
# mv /usr /usr.hide
I then created a new /usr symlink to the mount point for my SD card
partition.
# ln -s /mnt/card /usr
And the same thing for /home
# mv /home /home.hide
# ln -s /mnt/card2 /home
The "acid test" is to see if you can now reboot your iPAQ properly.
# shutdown -r now
If something horrendous happens and you can't boot up the iPAQ, just remove
the MMC or SD card and reset the iPAQ. Any attempts to mount the MMC/SD card
partitions will then fail, leaving you with your original root filesystem
intact (except with /usr and /home "hidden). Once the iPAQ boots up
successfully, you can "unhide" /usr and/or /home then reinsert your card (if
necessary) and fix your problem(s).
If you're running GPE, then the following message (or something similar)
probably appears in your boot-up log, and your GPE splash screen is gone.
/etc/rcS.d/S00bootsplash: 27: /usr/bin/gpe-bootsplash: No such file or
directory
This is not so easily fixed because the gpe-bootsplash program depends on
several libraries, amounting to about 630 kilobytes. Fortunately, you can do
without the splash screen, or you can revert to an older method of displaying
it. If you really want to keep your splash screen and load it the "new" way,
here's what you need to do. First mount /dev/root (the root filesystem
device) at a "secondary" mount point so you have access to the root
filesystem's version of the /mnt/card directory. I use /mnt/hda in this
example because I wasn't using a CF card at the time.
# mount /dev/root /mnt/hda
Then copy gpe-bootsplash to the root filesystem's /mnt/card/bin.
# cp /usr/bin/gpe-bootsplash /mnt/hda/mnt/card/bin
The gpe-bootsplash program also needs some libraries from /usr/lib, so you'll
need a lib sub-directory under the root filesystem's /mnt/card.
# mkdir /mnt/hda/mnt/card/lib
Here are the commands for copying the libraries required by the version of
gpe-bootsplash on my system.
# cp /usr/lib/libgdk_pixbuf-2.0.so.0 /mnt/hda/mnt/card/lib
# cp /usr/lib/libgobject-2.0.so.0 /mnt/hda/mnt/card/lib
# cp /usr/lib/libgmodule-2.0.so.0 /mnt/hda/mnt/card/lib
# cp /usr/lib/libglib-2.0.so.0 /mnt/hda/mnt/card/lib
You will also need to create a directory for the image file and copy it
over.
# mkdir /mnt/hda/mnt/card/share
# mkdir /mnt/hda/mnt/card/share/gpe
# cp /usr/share/gpe/splash.png /mnt/hda/mnt/card/share/gpe
And finally, unmount the secondary "copy" of the root filesystem.
# umount /mnt/hda
The old-style gpe-bootsplash.sh script is much simpler to set up. Create
a file /etc/init.d/gpe-bootsplash.sh that looks like this
#!/bin/sh
case $1 in
'start')
DIR=/usr/share/gpe/bootsplash
FN=`cat /proc/hal/model`.gz
gunzip -c < $DIR/$FN > /dev/fb0
;;
'stop')
;;
*)
esac
Since you will obviously know what model iPAQ this is going to run on, you
could get rid of the DIR and FN stuff and just put "gunzip -c <
/usr/share/gpe/bootsplash/3800.gz > /dev/fb0", for example.
Of course, you will need the 3800.gz (or whatever) file, too. This has to
go in a sub-directory under the root filesystem's /mnt/card.
# mount /dev/root /mnt/hda
# cd /mnt/hda/mnt/card
# mkdir share
# mkdir share/gpe
# mkdir share/gpe/bootsplash
# cp /path/to/3800.gz share/gpe/bootsplash
# cd /
# umount /mnt/hda
The "/path/to/3800.gz" above needs to be replaced with the real path to your
gzipped image file. I only have a copy of the 3800.gz file, which you can
download here. If you display this on some other models
it will be upside down and it is a slightly older image than
the current version of GPE uses (it says "GPE 2" instead of "GPE 2.1". You
could put this file in a different directory (perhaps one that is not under
/usr or /home) and change the gpe-bootsplash.sh script to match, but I
prefered to keep it in its original location (well, kind of anyway).
The only thing left to do is fix the symlink /etc/rcS.d/S00bootsplash
# ln -sf /etc/init.d/gpe-bootsplash.sh
/etc/rcS.d/S00bootsplash
and make sure that your script is executable.
# chmod +x /etc/init.d/gpe-bootsplash.sh
Now that these bits of my filesystem were working from the SD card, I could
go ahead with step seven, and delete them from the
on-board flash's filesystem.
# rm -r /usr.hide
# rm -r /home.hide
And that's it!
|