Making a Linux Kernel for the Puppeteer Arm processor. To create the kernel we need a copy of the Linux kernel source code. If we want to do any useful work with the Linux Operating System once we have it on the Puppeteer boards we also need facilities such as a compiler (with its associated libraries) and utilities such as the ability to login and perform housekeeping. To set up these extra facilities we need even more source code!
Since the standard Linux source code is designed for a simple PC (probably i386!) we need to patch it to be able to deal with the physical devices (UARTs etc) that exist with our processor. These patches will also be source code.
There are no kernel source code patches specifically for the Puppeteer board so we will need to get a patch for a similar board and manually patch this ourselves! The patch we will use is actually for a Pangolin system.
To get all this source code we use the internet. Get the following compressed (tarred and/or zipped) files from the sites indicated. The easiest place to store them is in your top-level directory (/home/netlab/myname) this could save a lot of typing later! Note that a .tgz file is basically one that has been compressed by tar then by gzip i.e. a .tar.gz file!
uClibc-0.9.20.tgz www.uclibc.org Small C lib – gcc!
busybox-0.60.5.tgz www.busybox.net Linux utilities
tinylogin-1.4.tgz www.busybox.net Login facility
Once you have all these files de-compress them (except the patch!). Each one will create its own subdirectory, e.g. tar –zxvf linux-2.4.18.tgz will produce the directory /home/netlab/myname/linux if done in the home directory.
The Pangolin patches need to be applied to the kernel source code before we do anything else. We can unzip the patches and apply them at the same time by
gzip –cd patch-2.4.18-rmk7 | patch –p0
Note that the patch also expects the source to be in a subdirectory called linux.
Building the kernel To produce a fully working kernel for a specific processor is a complicated process. We not only need to allow for the main processor (the Arm processor for us) but for all its associated minor processors used for i/o etc. This complicated system is dealt with by the use of makefiles and files with sets of extra rules for these makefiles. Not only that we need makefiles to makemakefilesfor our specific system layout, i.e. we need to configure our system. This is done either by manually editing special configurationfiles or makefiles or by using special makefiles that allow us to generate the configuration and makefiles we need.
The patches we installed have done some of the work in setting things up for the Pangolin system we now need to modify things even further. In our linux source directory is the patched Makefile. This needs to be manually edited to indicate the Arm architecture and make use of our cross compiler. In /home/netlab/myname/linux type:
emacs Makefile &
Comment out the line starting ARCH := ‘ … uname –d … ‘ by placing a # at the line start. Add a new line:
ARCH := arm
Indicate that we are to use our Arm cross compiler by editing:
CROSS_COMPILE = /usr/local/arm/2.95.3/bin/arm-linux-
(or wherever the arm cross compiler lives!). Note that the word gcc is appended in a later statement within the Makefile!
Save the modified Makefile and now use it to alter the configuration to suit the Pangolin system as in the worksheet. Still in the linux directory, type:
and activate all the changes indicated on the worksheet.
Save the changes and exit menuconfig. We have now changed a .config file (you can look at it using more!) and the linux/Makefile.
Modifying the Pangolin configuration. So far we have modified the Linux kernel configuration files to deal with the Pangolin system. The Puppeteer system is different, for instance it uses its memory allocation and UARTs in a different way. The next stage is to edit the Pangolin configuration to suit our particular layout. We need to edit where the boot operation places the code for the kernel, the processor identifier used in the boot process and details of the memory and UARTS available.
Boot data is in the directory /home/netlab/myname/linux/arch/arm/boot.
Edit the Makefile in this directory by adding a new decision at the end of all the others (as on the worksheet). This gives the relocation address, the text address (where the code actually goes) and the block store segment address (where data goes) for our version of the Pangolin system.
The processor identifier is set up in an assembler file called head.S as one of the first things it does. Edit the file head.S file in the boot sub-directory compressed. Comment out the two lines at the label 1: and add the lines shown on the worksheet.
We need to edit the board specific stuff to allow for the facilities on the Puppeteer boards. This is done by editing the file /home/netlab/myname/linux/arm/mach-sa1100/pangolin.c as shown on the worksheet. This file gives details of the memory banks, (their number, start address and size). It also has address details of Flash memory and the FPGA. The last thing we do in this file is to comment out the references to PCMCIA.
Since the Puppeteer system uses serial port 1 for its default communication whereas the Pangolin system uses port 3 you may need to edit /home/netlab/myname/linux/include/asm/arch-sa1100/uncompess.h as well. See the end of the worksheet!
Once all these alterations have been made, checked and saved we are ready to compile the Linuxsource code to produce an Arm version of the kernel that we can download onto the boards. This is achieved by issuing the following commands in the directory /home/netlab/myname/linux:
This will produce lots of output and is rather slow and is best done on Kenny!
The make clean command is really only needed if this is not our first attempt!
If you want to keep a copy of the output (just in case you need to peruse it for errors) type script makeout before performing the three make operations. Type exit when the operations have finished. This creates a file called makeout with a copy of the verbose screen output!
Before we can download our newly created Arm Linux kernel we need to convert the compressed image into the necessary .bin format. So in directory /home/netlab/myname/linux/arch/arm/boot/compressed type the command
elf2bin vmlinux vmlinux.bin
Download this onto the Puppeteer board to see if your build has been successful!
If there is a problem check all your edits and the options for the make menuconfig and try again.
If the worst happens start completely again by deleting the source code etc and unpack it again. To delete all the source code, go to /home/netlab/myname and issue the command
rm –rf linux
to recursively (-r) delete all the files and subdirectories of the linux directory without prompting (-f).
Building a library and Linux utilities. Now we have an operating system that we can load we will build a library and system utilities such as gcc, shells, tar etc. Since there is not much memory space on the Puppeteer board we need to use cut-down versions of the normal libraries and utilities used for the Arm processor. These are supplied by uClibc in their reduced library set together with BusyBox and TinyLogin.
The uClibc Library. In your top-level directory (/home/netlab/myname) decompress the uClibc tgz file. The act of decompressing will automatically produce a subdirectory for the source code. Type
tar –zxvf uClibc-0.9.20.tar.gz
In the new uClibc-0.9.20directory there is a Makefile and a set of rules (Rules.mak) that we need to edit. Enter the uClibc directory and edit the Rules.mak file so that the library build will use our Arm cross compiler, i.e. edit to give:
CROSS = /usr/local/arm/2.95.3/bin/arm-linux-
An appendix gcc is added by a later statement in Rules.mak. Save this file, type
to configure the library for use with the Puppeteer board. Follow the selections shown on the worksheet. Note that:
1. The target architecture is the Arm SA1100 i.e. StrongArm (although this may not work so you may need to use GenericArm instead!)
2. The linux kernel source tree is /home/netlab/myname/linux
3. The library installation information requests details for four items, only two of these needs to be changed.
The first item requests where the uClibc library will be placed on the target (the Puppeteer board) i.e. /lib on the file system we have to create.
The second item requests the location of the uClibc development library source code on our machine. This is where we are going to place our new library functions i.e. /home/netlab/myname/uClibc-0.9.20.
Having made the changes to the configuration we can build the library by typing
This makes wrappers for the GNU compiler and loader and stores them in a subdirectory, /home/netlab/myname/uClibc-0.9.20/extra/gcc-uclibc. Unfortunately programs for the archiver (ar) and object stripper (strip) do not seem to be produced (check the directory!). Later we will set up symbolic links to our original versions of these functions (until I find a better way!) because they will be needed when building some of the other utilities.
BusyBox. This is a cut-down version of the Linux facilities that we can use on the Puppeteer boards. At your top-level decompress BusyBox, i.e. at /home/netlab/myname type
tar –zxvf busybox-0.60.5.tar.gz
to create the busybox-0.60.5 source directory.
This directory has its own Makefile file to describe the build process. To configure the options to be built the Config.h file must be manually edited. Take a look at this file. It is full of #defines indicating what facilities will be needed in our BusyBox. Facilities can be added/removed quite easily as you can see from the comments! Do not edit the Config.h file you could try this at a later time if your present efforts are successful!
We need to edit the Makefile to indicate the cross compiler to use. This time we need to use the one we just created in uClibc-0.9.20/extra/gcc-uClibc, so edit the file to produce
CROSS = /home/netlab/myname/uClibc-0.9.20/extra/gcc-uClibc/arm-uclibc-
The gcc is again added by a later statement.
Having made this change we can build BusyBox with
If this fails because the archiver (arm-uclibc-ar) and stripper (arm-uclibc-strip) cannot be found we must set up symbolic links for them. In the directory /home/netlab/myname/uClibc0.9.20/extra/gcc-uClibc, issue the following commands
ln –s /usr/local/arm/arm-linux-uclibc/bin/gcc-uclibc-ar arm-uclibc-ar
TinyLogin. This comes from the same supplier as BusyBox and has to be set up in the same way. Decompress it at your top-level with
tar –zxvf tinylogin-1.4.tgz
Enter the new directory, /home/netlab/myname/tinylogin-1.4, and inspect the Config.h file to see what facilities will be built in. Modify the Makefile in the same way as the BusyBoxMakefile and then
Creating a Root File System.
We have now created all the programming facilities we need to accompany our operating system. Now we must create a file system into which we can place these facilities and allow the operating system to control the actions of the processor and its peripherals.
Since we cannot work on the Puppeteer board directly we must make a dummy system, which we can later put on the boards. We will use a file that we can mount as if it is an external file system. At our top level we can create such a file by
dd if=/dev/zero of=rootfs bs=1k count=8192
This uses /dev/zero as an input file (it actually supplies lots of zeroes making it easier to compress for later downloading onto the boards). From this input source we create an output file called rootfs with a block size of 1k and with 8192 blocks.
This rootfs is simply an empty file (well full of zeroes!). We need to format it to the ext2 type file system used by linux-2.4.xx, so type
/sbin/mke2fs –F –m0 –i 2000 rootfs
as indicated on the worksheet.
We need to be able to mount this file as if it is a separate file system and then create the subdirectories we need. To discover what systems we can mount look in the file /etc/fstab. This file lists all the file systems that are mountable, some are automatically mounted at boot time some are mountable by users. There should be a line something like
/tmp/imagefile /loop ext2 noauto,user,rw 0 0
This shows that we (a user) can mount a local file (/tmp/imagefile) as if it is a directory called /loop. So we need to copy our dummy file system to /tmp as imagefile, i.e.
cp rootfs /tmp/imagefile
and mount it by
We can now cd /loop and use mkdir to populate it with directories as on the worksheet.
Once the directories have been established we can populate them. First we create the bare bones /dev directory items. Go to this directory, i.e. cd /loop/dev and ask your tutor to give you root access (administrator access) so that you can issue the mknod commands as on the worksheet.
Now we can plant the uClibc library, BusyBox and TinyLogin facilities in their required directories.
make PREFIX=/loop install_target
make PREFIX=/loop install
make PREFIX=/loop install
These commands cause make to execute the install script and copy their executables etc to the relevant directories in /loop. Generally this sort of thing is done by root (the administrator) so you may get some messages saying that you must be root to do certain operations. We may be able to overcome this!
Usually when we make install yet another script is executed. This is called install.sh. Enter the tinylogin-1.4 directory and use emacs to inspect the install.sh script. Notice that it starts with a line or two to detect whether the user is root or not, comment out these lines so we do not need to be root. The last line of this script performs an operation that also needs to be root, comment out this line as well. Add the line
install –m 755 tinylogin $prefix/bin/tinylogin || exit 1
Save the modified install.sh and try make PREFIX=/loop install again. It should work.
We have overcome some problems during all this work rather than solving them but it gets us started! Unmount the file system and copy it back to your own area for safety!
mv /tmp/imagefile /home/netlab/myname/rootfs
Creating a downloadable version of the root file system. See the worksheet for the next stage, i.e. installing the root file system. You might prefer to use the following version of the Makefile for producing the compressed root file system image. Note that you must set the variable SYSTEM to the name of your uncompressedrootfs. The compressed output of the Makefile will be this SYSTEM name with a .comp extension!
Make sure that fake.c, rootfs.lds, Makefile and a copy of your rootfs image are all in the same directory, e.g. in /home/netlab/myname/filesys. So that if any errors occur you can recover your rootfs without too much effort!
# Based on linux/arch/arm/boot/compressed/Makefile and Craig’s mods.
# Create a compressed root file system image.
# SYSTEM is the name of the rootfs to compress.
# The output of this script will have an extension .comp added!
SYSTEM = rootfs CROSS_COMPILE = arm-linux-
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
FAKE = fake.o
GZFLAGS = -9
CFLAGS = -O2 -mapcs-32 -march=armv4 -mtune=strongarm1100 -mshort-load-bytes -msoft-float -fpic -c -o
RF_LDFLAGS = -p -X -T rootfs.lds
LIBGCC := $(shell $(CC) --print-libgcc-file-name)
# finally, link bits to make the downloadable compressed form
all: $(FAKE) piggy.o rootfs.lds
$(LD) $(RF_LDFLAGS) $(FAKE) piggy.o $(LIBGCC) -o $(SYSTEM).comp # second, zip up the file system to become piggy.gz, and
# make a relocatable form of this binary as piggy.o