Migration to bad block tolerant builds
From Openmoko
Migration of u-boot and the kernel to a version with bad block table (BBT) support. Note that, unless you're one of the very earliest OpenMoko developers, your system already uses Bad Block Tables, and you don't need to do the migration described on this page.
We'll use the same terminology and environment as described in the Building OpenMoko from scratch guide. Please read the sections Roles, Directory layout, Environment Variables, Permissions, and Assumptions
Building from the sources
This is optional. Skip to Migration to bad block tolerant builds#Installation if you are using pre-built images
Before we start
Please have a look at the Prerequisites sections of the build instructions. We need "git", "subversion", "quilt", and a communications program like "xc" or "minicom".
Get the right repository version
(Role: BUILD)
The badblock handling code is only in comparably recent versions of the repository and have not been merged into openmoko-devel-image.
We will first describe how to build u-boot and the kernel from scratch. If you don't want to do this, please skip ahead to section "Upgrading the boot loader".
Environment
(Role: BUILD)
To build kernel and u-boot, we need the arm-linux toolchain (binutils, gcc, etc.) This toolchain is built when you do the Building OpenMoko from scratch.
If you don't have the Building OpenMoko from scratch toolchain, you can either copy it from buildhost.openmoko.org (directory /space/fic/openmoko/gta01/tmp/cross), or you can skip this step, and use a pre-built binaries for u-boot and kernel.
http://buildhost.openmoko.org/OM2007.1/tmp/gta01/deploy/images/ has suitable images, e.g., u-boot_nand-gta01bv3-20070212200121.bin. (Please make sure to pick the right u-boot binary for your board revision.)
If the toolchain was built according to Building OpenMoko from scratch:
export PATH=$OMDIR/build/tmp/cross/bin:$PATH
If you copied the toolchain from buildhost, use:
export PATH=/space/fic/openmoko/gta01/tmp/cross:$PATH
Checking out the OpenMoko tree
Revision 906 of the OpenMoko tree contains all the features we need for bad block handling, yet is still compatible with the "stable" builds described in Building OpenMoko from scratch.
- If this is a new tree (then proceed with Building OpenMoko from scratch ):
cd $OMDIR svn co -r 906 https://svn.openmoko.org/ openmoko
- If you already have checked out a tree:
cd $OMDIR/openmoko svn update -r 906
Building u-boot
(Role: BUILD)
We check out the latest version from the git repository, apply a number of local patches, and then configure and build u-boot.
cd $OMDIR git clone git://www.denx.de/git/u-boot.git cd u-boot QUILT_PATCHES=$OMDIR/openmoko/trunk/src/target/u-boot/patches \ quilt push -a chmod +x board/neo1973/split_by_variant.sh
- Choose the name of your platform. Possible choices are gta01v3_config, gta01v4_config, gta01bv2_config and gtab01v3_config
make ARCH=arm gta01bv2_config
- Run the build. The result is called "u-boot.bin"
make ARCH=arm
Building the kernel
(Role: BUILD)
We use the kernel.org 2.6.17.14 kernel as our basis. After applying all the Neo-specific patches, we add brand-new Bad Block Table support.
Note that you need "mkimage" from the u-boot build.
cd $OMDIR
- Get the upstream source
wget http://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.14.tar.bz2 tar xfj linux-2.6.17.14.tar.bz2
- Apply the OpenMoko patches
cd linux-2.6.17.14 QUILT_PATCHES=$OMDIR/openmoko/trunk/src/target/kernel/patches quilt push -a
- Configuration, with a few last-minute updates.
cp $OMDIR/openmoko/trunk/oe/packages/linux/linux-gta01/defconfig-fic-gta01 \ .config make ARCH=arm CROSS_COMPILE=arm-linux- oldconfig
- Build
make ARCH=arm CROSS_COMPILE=arm-linux-
- We use a special image format for u-boot.
arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin gzip -f -9 linux.bin $OMDIR/u-boot/tools/mkimage -A arm -O linux -T kernel -C gzip \ -a 30008000 -e 30008000 -n "Kernel Image GTA01Bv2" -d linux.bin.gz uImage
Building sjf2410
(Role: BUILD)
The version of sjf2410 (the program to program NAND Flash via JTAG) built as part of the OpenMoko build process may be fairly old, so we build and later use the latest version in SVN.
make -C $OMDIR/openmoko/trunk/src/host/sjf2410-linux
Installation
Preparing the microSD card
(Role: CARD)
Since (V)FAT support in u-boot is marginal, we want to use an ext2 file system on the microSD card. If you have not yet converted your card, please have a look here.
cd $OMDIR mount /dev/uba1 /mnt/tmp cp u-boot/u-boot.bin /mnt/tmp cp linux-2.6.17.14/uImage /mnt/tmp umount /mnt/tmp
Upgrading the boot loader
(Role: LAB)
As a first step in making the upgrades, we replace the u-boot boot loader. There are three possible approaches for doing this:
- from an already installed, operational u-boot
- over JTAG, while properly handling bad blocks
- over JTAG, without handling bad blocks
'1.' is preferred, but is only available if we already have a boot loader, and if we don't suffer any problems while making the upgrade. '2' is currently under investigation. '3' works, as long as the few blocks occupied by the boot loader are intact.
Flashing a boot loader into a bricked device
(Role: LAB)
We start by flashing a new boot loader via JTAG. If you already have a good boot loader, you can skip this step.
First, obtain a u-boot binary with BBT support. We assume the u-boot binary is in $OMDIR/u-boot/u-boot.bin
Furthermore, you need a recent version of sjf2410-linux, e.g., the one we built above.
cd $OMDIR ( echo 0; echo 0; echo 0; echo 3; ) | openmoko/trunk/src/host/sjf2410-linux/sjf2410 -b -f u-boot/u-boot.bin
This takes about 12 minutes. The option -f specifies which file to load and the option -b tells sjf2410 to skip bad blocks.
Going from old (non-BBT) to new (with BBT) u-boot
(Role: LAB)
Next, we upgrade from an old boot loader (without BBT support) to a new one, which has BBT support.
If you are already running a sufficiently new boot loader, you can skip this step. If in doubt, there is no harm in doing this "upgrade". You can find out whether your boot loader is new enough with the "nand createbbt" command. If the command is recognized, you already have a "new" boot loader. (Press [N] to abort the command now.)
| WARNING: If you lose power from now on, or enter any commands incorrectly, you may brick your Neo, in which case you have to go back to the previous section, and flash the boot loader again through JTAG. |
Everything from now on is through the serial console.
- Connect to the target
xc -l /dev/ttyS0 -t
- Reset the Neo by power-cycling it (see also Building OpenMoko from scratch )
- Then press a button to enter the u-boot prompt. If you can't get a prompt, your machine may be bricked. See above for recovery from that state.
- First, we load the new u-boot from microSD into RAM
GTA01Bv2 # mmc GTA01Bv2 # ext2load mmc 0 0x32000000 u-boot.bin
- We now erase the NAND Flash region occupied by u-boot, and write
the new u-boot binary to it.
GTA01Bv2 # nand erase
- Press [Y] [Enter] to confirm the operation.
GTA01Bv2 # nand write.e 0x32000000 0 ${filesize}
Creating the Bad Block Table
(Role: LAB)
We now boot our BBT-capable u-boot and create the bad block table. This will erase all NAND Flash content, so we will have to write u-boot to Flash a second time.
- Reset the Neo, either by power cycling, or, if you're already in u-boot, with:
GTA01Bv2 # reset
- Press any key on the serial console to enter the prompt. Note that the startup messages of u-boot should have said something like this:
U-Boot 1.1.6 (Feb 7 2007 - 21:49:14) DRAM: 128 MB NAND: Bad block table not found for chip 0 Bad block table not found for chip 0 64 MiB *** Warning - bad CRC or NAND, using default environment
All these warnings tell us that the NAND is nice and clean, just how we want it. There are two bad block table messages, because the bad block table is mirrored.
Like before, we load the new u-boot binary (so that, if there are problems loading that one, we won't find out about them after just having erased our NAND Flash).
GTA01Bv2 # mmc GTA01Bv2 # ext2load mmc 0 0x32000000 u-boot.bin
- We now generate the bad block table. The NAND Flash is erased when doing this.
GTA01Bv2 # nand createbbt
This takes about one minute. The output will look like this:
Create BBT and erase everything ? <y/N> Skipping bad block at 0x03ff0000 Skipping bad block at 0x03ff4000 Skipping bad block at 0x03ff8000 Skipping bad block at 0x03ffc000 Creating BBT. Please wait ...Bad block table not found for chip 0 Bad block table not found for chip 0 Bad block table written to 0x03ffc000, version 0x01 Bad block table written to 0x03ff8000, version 0x01
"Skipping bad block" refers to the area reserved for the BBT, which is protected by marking it as bad blocks. Then we look again for the bad block table, and then finally create the table.
If "nand createbbt" fails with a message like "No space left to write bad block table", you may have data in the bad block table area, which needs to be removed first. See section "Removing the bad block table" below. You may still wish to write back u-boot now (the next step), to avoid having to restore it though JTAG.
- u-boot was erased in the process. Write it back again.
GTA01Bv2 # nand write.e 0x32000000 0 ${filesize}
Removing the bad block table
(Role: LAB)
You normally neither have to nor want to do this. However, if the NAND Flash ends up in a particularly twisted state, you may have to clear the zone in which the BBT is stored.
| WARNING: This also removes factory-set bad block information ! Use with extreme caution and only if you absolutely have to ! |
We first generate a file with size 64 kB full of 0xFF bytes. Erased NAND is also set to 0xFF, so when we write this, the NAND will appear empty. (We could of course just erase the NAND, but sfj2410 does not support erasing without also writing data.)
cd $OMDIR dd if=/dev/zero bs=1k count=64 | tr '\000' '\377' >64kFF
Now, we overwrite the BBT area, clearing any bad block markers on those blocks in the process.
( echo 0; echo 0; echo 4092; echo 2; ) | openmoko/trunk/src/host/sjf2410-linux/sjf2410 /f:64kFF
We don't need the 0xFF file anymore.
rm 64kFF
You can now either Flash a new boot loader (if there is none), or reset the Neo and proceed with one of the steps above, from the u-boot installed on it.
Partition sizing
(Role: LAB)
The last step is to calculate the sizes and offsets of the partitions in NAND Flash, taking into account any space occupied by bad blocks, and to update the environment accordingly.
The new partitions are calculated with the following command:
GTA01Bv2 # dynpart
This command prints the sizes of the partitions, including any space consumed by bad blocks, it also sets the environment variable mtdparts accordingly, and it makes the partition offsets available by partition name for "nand write.e" and friends. We will use the latter in the next section.
Please have a look at the output of "dynpart". Since the size of the first partition (u-boot) depends on the number of bad blocks of your flash in that region, you also have to update the environment offset in the NAND Flash. The gory details can be found here. The environment offset has to be equal to the size of the u-boot partition. For example, if there is one bad block in the u-boot partition, the environment moved from offset 0x30000 to 0x34000, which is set as follows:
GTA01Bv2 # dynenv set 0x34000 45 4e 56 30 - 00 40 03 00
"dynenv set" prints what it thinks it wrote. However, if an environment offset was before, the old value may prevent the new value from being stored correctly. Therefore, please check the result with:
GTA01Bv2 # dynenv get 0x00034000
If the value shown does not correspond to the one set earlier, the first block of the NAND Flash has to be re-initialized. This can be accomplished with "nand erase u-boot" or with de-bricking procedure. In the former case, you need to re-flash the boot loader. In case this isn't possible at that moment, you will doubtlessly enjoy the opportunity to familiarize yourself a little more with the aforementioned de-bricking procedure.
| NOTE: If you have a non-default environment offset, i.e., different from 0x30000, you must set the environment offset whenever the boot loader partition is erased, i.e., whenever you update the boot loader. |
If you had to change the environment offset, you now need to restart u-boot for the change to take effect, then proceed with the remaining steps in the next sections:
GTA01Bv2 # reset
Updating the environment
(Role: LAB)
We pass the partition information to the kernel through the "mtdparts" boot parameter. An environment variable with the same name, containing the parameter as used on the kernel parameter line, was produced by "dynpart", and will be stored in the persistent environment.
GTA01Bv2 # setenv bootargs_base ${bootargs}
GTA01Bv2 # setenv bootcmd setenv bootargs \${bootargs_base} \${mtdparts}\; nand read.e 0x32000000 kernel\; bootm 0x32000000
Since we may have restarted the system since we last used "dynpart", we run it again to set "mtdparts". It is safe to run "dynpart" as many times as you wish.
GTA01Bv2 # dynpart
Last but not least, we save the environment variables in NAND Flash:
GTA01Bv2 # saveenv
Populating the remaining partitions
(Role: LAB)
During the upgrade, we have wiped out anything that was stored in the NAND Flash. So we need to write a new kernel and a new root file system now. Note that, even if we had not wiped them out, the location and size of partitions may have changed, and any old kernel or root file system would now be stored at the wrong place.
We assume that the kernel is called "uImage":
GTA01Bv2 # ext2load mmc 0 0x32000000 uImage
GTA01Bv2 # nand write.e 0x32000000 kernel ${filesize}
We assume the root file system is called "rootfs.jffs2":
GTA01Bv2 # ext2load mmc 0 0x32000000 rootfs.jffs2
GTA01Bv2 # nand write.e 0x32000000 rootfs ${filesize}
Done already
Congratulations ! You have finished another level of the OpenMoko text adventure.


