ECE497 Project: Multiple Partitions via U-boot

Team members: Michael J. Yuhas, Jack Ma

Executive Summary
The goal of this project is to give the U-boot boot-loader the ability to mount different partitions on start-up. This would allow the user to dual-boot the beagle board by controlling the boot sequence with a user button or RS-232 link.

There are two principal parts to this project: finding a method to create a multiboot mmc card, and creating a command in U-Boot to simplify the process of booting multiple partitions for the user. We have successfully completed both parts in this project and have found a method create and boot from a multi-partition mmc card on the Beagle Board.

If we had more time, we would like to research further into booting from USB devices. Initially, our projects scope included booting from external USB devices, but we were not able to make any progress with this goal.

We feel that this project was successful in that we achieved the primary goals we set out to accomplish. In addition, we learned many new things about the inner workings of boot-loaders, solid state storage devices, and the way the kernel boots during startup.

Installation Instructions
These instructions will guide you through the installation of our modified U-boot boot-loader.

If you do not yet have git installed see the instruction on EBC Exercise 07.

Open a terminal on your host machine and pull our git repository:

host$ git clone git@github.com:albertlee5/project.git host$ cd project/

To compile the code for our project you will have to source two shell scripts that set certain environmental variables and the cross-compiler toolchain:

host$ source ~/.oe/environment-oecore host$ source ~/.oe/crossCompileEnv.sh

Before you can build our installation, you will need to configure some variables so that the make file knows exactly what platform U-boot will use. First you need to unconfigure any previous settings and then have make configure itself for the Beagle Board.

host$ make unconfig host$ make omap3_beagle_config

Now you should be able to make our project:

host:/project$ make

Next copy the resulting MLO, uboot.img, and uboot.bin to the boot partition of your mmc-card and rename the corresponding existing files so they don't interfere at startup. The beagle should now boot with our modified bootloader.

Note: follow the instructions in the section below if you ran into some problems during make. The errors described are caused by a problem in the files we pushed to the repository. Although we believe we fixed the problem, we only have two machines with which to test this, so we included the remedy below as a precaution.

If make fails with an error such as "System not Configured" or the like, there are several commands you will have to run to fix this. This is caused because the copy on the repository may contain some temporary files that were native to the editors host machine, but will not work with your configuration. We will have to remove several files so that make will re-generate them for your machine. In the terminal type:

host:/project$ rm -rf include/autoconf.mk host:/project$ rm -rf include/autoconf.mk.dep

This removes some auto-configuration files from the include directory. We will also need to remove a number of .depend files created by make. (Note that simply typing make clean will not remove these since they were not created with your Makefile). The following commands perform a batch remove of these files, and then check to see if the removal was successful:

host:/project$ find. -name .depend | xargs rm -rf host:/project$ find. -name .depend.* | xargs rm -rf host:/project$ find. -name .depend host:/project$ find. -name .depend.*

The last two commands should return no output. Now try using make to compile U-boot.

The Multi-Partition Creator Script
Before you can dual-boot your Beagle Board, you will need an mmc card with multiple partitions. Surprisingly, a Google search reveals that there are few, if any people who have accomplished this. (Please note that the SuperJumbo package for the Beagle Board by Always Innovating uses a different method to switch between OS's while the board is powered on). To remedy this issue, we have created a script that will set up an mmc card with U-boot and multiple Angstrom partitions. We based our script on the OMAP3 SD Booting script created by Slim Logic Ltd. which can be found at the following url: http://www.slimlogic.co.uk/2011/05/omap3-sd-booting/. If you would like to see the modifications we made to achieve multi-boot, please view the 'Theory of Operation' section below.

First, download our script here.

Before you can run the script, you will have to change the permissions so that it will be executable:

host$ sudo chmod 777 parititioning.sh

Now run the script with no arguments. You should receive the below output message:

host$ sudo ./partitioning.sh Usage: partitioning.sh

Now plug the mmc card into your host machine and determine which name the host computer assigns to it.

host$ dmesg | tail

There should be a few lines talking about mounting a disk and giving it the name sdx where x is any letter for the drive. Now that we know the name of the disk, we can run our script:

host$ sudo ./partitioning.sh /dev/sdx

Your drive now has four partitions on it, three of which can serve as a root file system for linux. The first partition is FAT32 and will serve as the boot sector where U-boot lives. Now, copy your MLO, u-boot.bin, u-boot.img, and uimage to the boot sector of your mmc card. Also, obtain a copy of the root file system for Angstrom. Due to the the size limitations of uploads, we cannot provide this, but if you follow the instruction here to build a normal Angstrom MMC card and then sudo copy all the files in Narcissus-rootfs to your computer, you will have a bootable root file system.

I Have Multiple Partitions, Now What?
Now put the sd card in your beagle board and fire it up. Be sure to plug a cable from the serial port on the beagle board to some kind of connection on the computer. Instructions to do this can be found here.

Once byobu is opened, and you have U-boot running, enter the following command:

U-boot # jack

The command with no parameters should display a list of partitions on the mmc card. Now choose some partition x and boot.

U-boot # jack x

The Beagle Board should now boot to whichever file system you have selected.

Highlights
Our project gives the Beagle Board the ability dual boot from and sd card. The project combines a script for setting up an sd card with multiple partitions with a user-friendly method of multi-booting with U-boot. After many hours of online research, we believe that our project is the first documented project of its kind for the Beagle Board. Although our system currently only works with the Angstrom distribution of Linux, it lays the groundwork for dual-booting multiple OS's such as Ubuntu and Android.

Theory of Operation
This section will describe how we accomplished our project and detail some of the challenges we faced while we worked.

Partition Script
Initially we tried to manually create a multi-partitioned sd card from which to boot, however, we soon ran into many problems. At first, we manually partitioned the disk into a 128MB boot sector and divided the rest of the space evenly between two ext2 partitions. We then copied files from a working sd card to populate the partitions. The initial problem was that we performed did not perform a sudo copy and that some files were left behind, but when we tried this strategy on previously unformatted cards, we discovered that there was something else wrong with this method.

Before we could continue, we had to learn little bit about how static memory is addressed in a hard disk or any other form of longterm storage. It turns out that data is still allocated into sectors, cylinders and heads, just like in the early days of computing. An in depth description can be found here. We learned that for a FAT32 file system, there are 512 bytes in each sector, and 63 sectors in each head. There is a maximum number of 255 permitted heads for one device. This means that to deal with larger file systems, the number of cylinders must change. We played around with the command line tool fdisk to get an idea of partition a sd card with this format. Because the process was fairly complex, we decided to write a script to do our job for us.

Rather than reinventing the wheel, we found a website who had already written a script to partition an sd card for a single partition of Angstrom Linux. We used this script as the basis for our creation which will create four partitions on a single sd card. The first partition is used for boot, meaning the remaining three partitions can be used as the root file system in an OS.

U-boot Modifications
Initially, we wanted to prove that we could multi-boot in U-boot just from the command line as a proof of concept. After creating a multi-partition sd card (see above section), we discovered a method of booting to separate partitions. This involves starting U-boot, and first, listing all the available partitions on the detected mmc device. Next, we had to determine which partitions were bootable and then pass that partition to the ext2load command. Analysis of the ext2load command showed us that this command calls the bootm command, which intern calls the boot command. Each of these commands generates a set of parameters for the next one down the chain allowing the user to go from a high level of abstraction to a very low level of operations. We played with the booting commands and environmental variables and determined the best way to select a boot partition was to follow the following commands:

U-boot # mmc part U-boot # setenv pnum X U-boot # setenv mmcroot /dev/mmcblk0pX rw U-boot # setenv loaduimage ext2load mmc 0:X ${loadaddr} /boot/uImage U-boot # boot

In the above commands, 'X' is an arbitrary ext2 partition number that exists on our mmc card. Basically, we are resetting the location that U-boot chooses to look for the uImage file (kernel), and the partition that the kernel will mount as root.

This process takes long time to perform by hand, so we thought it would be neat to create a user command that would add another layer of abstraction.

After some research, we found instructions on how to create a command in U-boot, but the article was written entirely in Chinese. The webpage which gave us insight into how to add a command to u-boot is http://hi.baidu.com/282409975/blog/item/527f5ce996cf77ddd539c9b9.html. From here, we further explored how we could invoke a command within command. Luckily we had Jack in our group. The following is a high level description of the process of adding a user defined command to U-boot.

First, you must add your command.c file to the common folder using the naming scheme, cmd_ .c. You must also include the following headers in your file:


 * 1) include 
 * 2) include  //CONFIG_CMD_JACK
 * 3) include  //U_BOOT_CMD

The common.h loads libraries native to all U-boot source code. The command.h and config.h load globals that commands will need to be recognized by U-boot. It is important to note that stdio.h and stdlib.h are not supported by the tool chain we will be using.

In addition, we must define our command in the Makefile, the header for the Omap3 Beagle Board, and the config_cmd_all.h that contains a list of all commands.

./common/Makefile:COBJS-$(CONFIG_CMD_JACK) += cmd_jack.o ./include/configs/omap3_beagle.h:#define CONFIG_CMD_JACK ./include/config_cmd_all.h:#define CONFIG_CMD_JACK

We named our command jack and created a cmd_jack.c file in the common directory. In the cmd_jack.c file, we needed to create some functions to execute when the command is called. The do_jack function is the main function that will be executed every time the command is called. We also needed to add a call to U_BOOT_CMD(jack,0,1,do_jack,"Test Program.\n"); that would run every time somebody ran help on the jack command.

To call other commands from the U-boot, we discovered the run_command("string to run", flag); command to let us access pre-written commands. We also discovered that although stdio.c was not in the toolchain, we could use sprintf to parse variables into strings. Theses commands gave us the tools we needed to take the above command list and automate them under a single unified user command.

Difficulties Using the Git Repository
The installation section describes some steps that must be taken if the git repository that someone pulls is bad. We discovered that a number of .depend files are created every time a user runs make on U-boot, and if this user pushes there directory to git, the .depends will cause problems for users with other machine configurations. To solve this, we discovered an includes file in git that would allow us to include and exclude certain files while do a git push. We believe we have solved this problem, but just in case, the work-around is located above.

Conclusions
We found this project very interesting because it gave us an in depth look into the way a boot-loader works. We saw how to add commands, and learned how the boot-loader actually determines what to do when a user enters a command. We also learned about the way memory is addressed in long term storage and learned about how it affects different file system schemes.

We feel that future additions to this project could include the following:

1.) The ability to boot from USB (We tried to look into this, but did not make much progress)

2.) The usage of the user button to select a boot partition at start-up

3.) The ability to boot into different operating systems. (Our code should support this, but we did not have time to test it).