Porting Linux to MPC860SR Processor Card

Porting Linux to MPC860SR Processor Card
Feb 2003
Sepherosa Qiao, Laudney Ren
Preface Porting Linux to MPC860SR Processor Card
Preface
The following "dummy" Makefile can serve as a guide for this paper.
Makefile
CROSS = powerpc-linux-
KERN_VERSION = 2.4.18
UBOOT_VERSION = 0.2.0
# ’kermit’ also works.
# ’minicom’ is not recommended.
SERIAL_APP = cu
TOOLS = $(CROSS)gcc $(CROSS)gdb $(CROSS)binutils $(CROSS)glibc
APP = uClibc-0.9.16 busybox-0.60.5 tinylogin-1.4 utelnetd-0.1.4 udhcp-0.9.8
IPSPOOF ?= n
.ifeq ($(IPSPOOF),y)
APP += iptables-1.2.6a
.endif
working_environment:$(SERIAL_APP) cvs_server tftp_server dhcp_server /
nfs_server
Setup $ˆ
boot_loader kernel ramdisk:$(TOOLS)
Build $ˆ
boot_loader:u-boot-$(UBOOT_VERSION)
Port $< to MPC860SR Processor Card
kernel:Linux-$(KERN_VERSION)
Port $< to MPC860SR Processor Card
ramdisk:$(APP)
Build $ˆ
Setup $ˆ
Make up $@
.PHONY:all
all:working_environment boot_loader kernel ramdisk
Burn boot_loader kernel ramdisk to flash
Figure of Preface
Makefile
Sepherosa Qiao, Laudney Ren
Feb. 2003
Table of Contents Porting Linux to MPC860SR Processor Card
Table of Contents
1 Setup Working Environment ...............................................1
2 Build Cross Toolchains ........................................................4
3 Port U-boot ..........................................................................12
4 Port Linux Kernel 2.4.18 .....................................................41
5 Prepare RAMDisk ...............................................................52
6 Bibliography ........................................................................57
Setup Working Environment Porting Linux to MPC860SR Processor Card 1
Setup Working Environment
We hav e two PC running Debian Linux. CodeWorrior’s MetroTRK is the original monitor
in the flash of the Motorola MPC860SR Processor Card. Unless used together with Code-
Worrior’s IDE, all MetroTRK could do is to print some readable but useless messages, a hint for
the proper function of the serial line.
Setup Serial-line Application
Accessing the target board on a remote console via the serial line is the precondition to the
porting process. Choosing the right serial-line communication application and setting it up properly
is the first step. cu is the application chosen, which is included in the uucp package. Its
configuration files are shown in Figure 1.1 and Figure 1.2.
/etc/uucp/sys
system S0@19200
port serial0_19200
time any
Figure 1.1
/etc/uucp/sys
/etc/uucp/port
port serial0_19200
type direct
device /dev/tty0
speed 19200
hardflow false
Figure 1.2
/etc/uucp/port
/dev/tty0 under Unix is equivalent to COM1 under Windows. (When we tested cu
with MetroTRK, all 19200 above should be substituted by 57600 ). cu must be run by normal
users. The connection is started by issuing the following command:
user@box:˜$ cu S0@19200
Connected. will be printed to once the connection has been successfully established.
S0@19200 must be the same as indicated after system item in /etc/uucp/sys. As already
mentioned above, when cu is with MetroTRK, S0@57600 is used instead. For further information
of cu, please refer to its manual page.
Setup CVS Server
To better manage the development process, one CVS servers is set up on a PC and two
modules are imported into the repository: one for Linux kernel and the other for u-boot. For further
information of CVS, Please refer to its info page.
Setup Working Environment Porting Linux to MPC860SR Processor Card 2
Setup NFS, TFTP, DHCP Server
The last step of the porting process is to create a RAMDisk containing the entire system
(kernel, shell, application) for the target board. Before that, to facilitate constant debugging, the
Linux kernel is downloaded to the target board from a TFTP server, and a DHCP server; the
root file system is mounted on the target board from a NFS server.
NFS server’s configuration file is shown in Figure 1.3.
/etc/exports
...
/opt/root 192.168.0.253(rw,no_root_squash)
...
Figure 1.3
/etc/exports
/opt/root is the mount point of the root file system of Linux on the target board.
192.168.0.253 is the IP address of the ethernet network interface on the board. rw means
the root file system is both readable and writable for the board. no_root_squash means that
uid 0 (uid of root) on the target system is not to mapped to the anonymous uid on the NFS server.
This option is essential for the mounting command to succeed, because it’s executed by Linux
kernel as root. For further information about the format of /etc/exports, please refer to its manual
page.
After the configuration file of NFS server is modified, the following command is run by
root to make the changes take effect:
root@box:/etc/init.d# ./nfs-common restart&&/
./nfs-user-server restart
TFTP server’s configuration file is shown in Figure 1.4.
/etc/inetd.conf
...
tftp dgram udp wait root /usr/bin/tcpd /usr/sbin/in.tftpd -s /tftpboot
...
Figure 1.4
/etc/inetd.conf
/tftpboot is the directory on TFTP server that contains the Linux kernel image for
the target board. Adding the above line to /etc/inetd.conf makes inetd daemon listen for incoming
TFTP requests.
These changes take effect when the following command is run:
root@box:/etc/init.d# ./inetd restart
DHCP server’s configuration file is shown in Figure 1.5.
Setup Working Environment Porting Linux to MPC860SR Processor Card 3
/etc/dhcpd.conf
subnet 192.168.0.0 netmask 255.255.255.0 {
option routers 192.168.0.254;
option subnet-mask 255.255.255.0;
host procard { hardware ethernet 52:54:AB:54:82:5E;
fixed-address 192.168.0.253;
option root-path "/opt/root";
option host-name "procard";
next-server 192.168.0.254;
filename "pImage";
}
}
Figure 1.5
/etc/dhcpd.conf
hardware ethernet is the MAC address assigned to the target board’s ethernet
NIC. It can be decided arbitrarily but it must not coincide with the MAC address of any other
NIC connected to the same network. fixed-address is the same IP address in the NFS
server configuration file. option root-path is the root file system in the NFS server configuration
file. next-server is the IP address of the NFS server and TFTP server. filename
is the Linux kernel image residing in the direcotory pointed out by the TFTP server configuration
file. For further information on the format of /etc/dhcpd.conf, please refer to its manual
page.
The following command must be executed by root to restart the DHCP server.
root@box:˜# kill -9 ‘cat /var/run/dhcpd.pid‘;dhcpd
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 4
Build Cross Tools
All the development is done on i386 PC but the target board is of PowerPC architecture.
Therefore, necessary cross toolchains must be built first.
Enough space must be reserved for the building process. Lots of disk space will be taken
by the temprory files generated during the process.
Build Cross Binary Utilities
Binary utilities must be built first, including the binary stream generator as and link editor
ld. as is called when gcc tries to generate relocatable code, and ld is called when gcc tries to
generate executable files or shared libraries. Due to this dependency, the order of the buiding
process is clear.
In order to build the binary utilities without any dependency error, bison, yacc and flex
must be installed beforehand.
We chose the latest version of binutils package, 2.13.90.0.16. In the top level of the
source code directory, run the following commands:
# ./configure --prefix=somewhere_u_prefer /
--target=powerpc-linux
# make&&make install
--prefix has following effects: the executable files generated will be put under somewhere_
u_prefer/bin/. For a list of options that binutiles-2.13.90.0.16 package provides,
you can issue ./configure --help.
Build GCC (The First Pass)
Choosing the proper version of gcc to build cross compiler is critical. After having
patched gcc-3.x serveral times and tried desperately with it for a night, we finally turned to
gcc-2.95.3. It is more cross-compilation-friendly than gcc-3.x. Following commands are issued:
# ./configure --prefix=somewhere_u_prefer --enable-shared /
--enable-language=c --with-newlib --target=powerpc-linux
# make&&make install
--prefix option had better be the same as the one used for binutils. For further information
about the configuration options that gcc-2.95.3 package provides, you can refer to
gcc-2.95.3_src_dir/install/configure.html.
From now on, we just suppose that the --prefix option are the same in binutils and
gcc, and call it tool_dir. Before moving forward, we edited ˜/.bash_profile and ˜/.bashrc
to add tool_dir/bin/ to the environment variable PATH. We ran the following command
to make the change take effect immediately:
# . ˜/.bash_profile
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 5
Build Glibc
Linux kernel 2.4.18 source codes are patched for PowerPC architecture first, (The patch
and kernel source codes are all Debain Linux packages. Their package names are kernelsource-
2.4.18 and kernel-patch-2.4.18-powerpc.) since glibc depends on the kernel header files.
Patching is done by patch command with -pnum option only. For further information of patch,
please refer to its manual page.
Choosing glibc version is also important. glibc-2.3.x can’t work with gcc-2.95.x, then the
choice available is glibc-2.2.5. glibc-linuxthreads-2.2.5 is also built into glibc to enable threads
in application. Given glibc-Linux-threads tarball is just one directory level above the source
code directory of glibc, the following commands are run:
# ln -s ur_kernel_src_dir/include/asm /
tool_dir/powerpc-linux/include/asm
# ln -s ur_kernel_src_dir/include/Linux /
tool_dir/powerpc-linux/include/Linux
# tar zxvf ../glibc-linuxthreads-2.2.5.tar.gz
# CC=powerpc-linux-gcc AR=powerpc-linux-ar /
RANLIB=powerpc-linux-ranlib /
./configure --host=powerpc-linux --enable-add-ons /
--with-headers=tool_dir/powerpc-linux/include --prefix=tool_dir
# make&&make install_root=tool_dir/powerpc-linux install
CC, AR and RANLIB are the macros defined in the configure. Defining them before running
./configure causes the default value of CC, AR and RANLIB to be overrided by the value
specified.
Caution!
install_root option in the last command must be specified or Linux will be messed up, and
any execution of dynamicly linked program will fail.
Build Gcc (the Second Pass)
After having built glibc, we rebuild gcc to make it recognize which glibc it should use.
Following commands are run under the top source code directory of gcc:
# make distclean
# ./configure --prefix=tool_dir --target=powerpc-linux /
--enable-shared --enable-threads
# make&&make install
The first command, make distclean is run for a brand new start by cleaning all the object
files generated in the previous compilation and some files generated by configure. From then on,
we could use gcc to build application that needs the glibc for PowerPC architeture.
Build gdb
There is an BDM port on the board for debugging. mpcbdm from Bdm for Gdb project on
Sourceforge adds BDM support to gdb. Now it supports gdb-5.0. This package contains the following
files: mpcbdm.c, mpcbdm.h, Flash.dev, mpc.init and Makefile.in.
A little change is made to mpcbdm.c to fix a small bug. The change is shown in Figure
2.1.
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 6
mpcbdm.c
1946 int n;
1947 char *p;
1948
1949 for(p = pch; *p ; ++p) *p = toupper(*p);
1950
1951 for(n = 0; sprnames[n].name; ++n)
1952 {
Figure 2.1
mpcbdm.c
1949
Before changing, this line looked like following:
for (p = pch; *p ;) *p++ = toupper(*p);
It is the common sence for programmers not to predict the execution order of the operations on
the left or right hand of ’=’.
Flash.dev is written from scratch, since it largely depends on the hardware (flash ROM).
It is difficult to write the Flash.dev, for the lack of document. But since the original Flash.dev is
for AM29LV160DB, which is quite similar to our flash ROM, we retrieve the document of
AM29LV160DB from AMD official web site and try to figure out how to write Flash.dev based
on it.
The first part of our Flash.dev is shown in Figure 2.2.
Flash.dev
1 .device AM29LV017B
2 {
3 .size 2M
4 .width 8
5 .sector AM29LV017B
6 .idoffset 16
7 .algorithm AMD4
8 }
Figure 2.2
Flash.dev
1˜8
This is the overall section. It should be a good idea to keep the string after .device to
be the same as that after .sector. .size 2M indicate that this is a 2 Mbytes flash.
.width 8 means that the bandwidth for our flash is 8 bits. .sector AM29LV017B and
.algorithm AMD4 are the sections that will be shown in the following figures. The usage of
.idoffset tag had not been clearly documented in the original Flash.dev comments. After
having compared the original Flash.dev’s .idoffset 12 and contents of .section
AM29LV160DB with a table on [7] page 12, we found out that the value after .idoffset is
the sector group id’s smallest bit number, which is 12 for AM29LV160DB but is 16 our flash,
AM29LV017B. So in our Flash.dev, .idoffset 16 appears instead of .idoffset 12.
The second part of Flash.dev is .section AM29LV017B, which is shown in following
figure.
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 7
Flash.dev
10 .section AM29LV017B
11 {
12 0x00,0x000000,0x00ffff,
13 0x01,0x010000,0x01ffff,
14 0x02,0x020000,0x02ffff,
15 0x03,0x030000,0x03ffff,
.. ...
41 0x1d,0x1d0000,0x1dffff,
42 0x1e,0x1e0000,0x1effff,
43 0x1f,0x1f0000,0x1fffff
44 }
Figure 2.3
Flash.dev
10˜44
After the above comparation, we also figured out the layout of .section
AM29LVxxxXX. It looks like the following:
sector_id, start_addr, end_addr
The sector_id above is the hexadecimal value which is equal to the five bit long binary value
whose highest bit is A20, while lowest bit is A16. A20, A19, A18, A17, and A16 are shown
in the table on [7] page 9. The start_addr and end_addr are also shown clearly in the
last column of the table on [7] page 9.
Figure 2.4 shows the third part of Flash.dev
Flash.dev
46 .algorithm AMD4
47 {
48 .reset w0x0:0xf0
49 .ident w0x0:0xaa, w0x0:0x55, w0x0:0x90,
50 c0x000:0x01, c0x001:0xc8, w0x000:0xf0
51 .write w0x0:0xaa, w0x0:0x55, w0x0:0xa0, w%A:%D,
52 t%A:0x0040, r%A:%D
53 .erase w0x0:0xaa, w0x0:0x55, w0x0:0x80, w0x0:0xaa,
54 w0x0:0x55, w%I:0x30, t%A:0x0040, r%A:0xffff
55 .clear w0x0:0xaa, w0x0:0x55, w0x0:0x80, w0x0:0xaa,
56 w0x0:0x55, w0x0:0x10, t%A:0x0040, r%A:0xffff
57 .cfast w0x0:0xaa, w0x0:0x55, w0x0:0xa0
58 .fast AMD4
59 }
Figure 2.4
Flash.dev
46˜59
From the comments of the original Flash.dev, w stands for write, r is the short hand of
read, c means compare (not as it is documented in the comments), and toggle is represented by
t. Every tag (.e.g .write ) is composed of a sequence of commands. Each command has
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 8
the following format:
[wrct]addr:data
One of the four actions must be specified. data can be in hexadecimal form or just %D,
which means the data you want to write or the data you expected to read. But as to t, data
means the mask that will be logical AND with the data on the addr. addr have other two
forms than hexadecimal form. %A and %I can also be addr. Although they all mean address,
%A means the address to read and write while %I means the address to verify or erase.
All sequences of commands were formed according to [7] page 19 table 8. All unspecified
contents from that table were set to 0x0. t will suspend the execution until the test result is
stable. r will report error if the data is not on addr. So combination of t and r can be
used to verify the result of previous commands. Some verification were added to the end of certain
command sequence. .fast AMD4 is correponding to the following .fastxx AMD4
sections, which are binary streams and were left untouched ( xx is the bandwidth of the flash, as
to ours, it is 8).
Like Flash.dev, mpc.init, which is a command file of gdb, was also drasticly changed according
to the [1] and [2]. For further information of gdb command file and gdb, you can refer to
its info page. Figure 2.5 shows what gdb will execute when it is started.
mpc.init
377 Init
378 SetupProc
379 ProCardMem
380 Flash
Figure 2.5
mpc.init
377˜380
Init, SetupProc, ProCardMem, and Flash are all macros defined in
mpc.init. Each of them is shown in Figuer 2.6, Figure 2.7, Figure 2.8, and Figure 2.9.
mpc.init
360 define Init
361 set mpcbdm_adapter 2
362 set mpcbdm_relaxed 1
363 set mpcbdm_fbuf 0xff002000
364 set mpcbdm_fflash off
365 set mpcbdm_verbose 0x4000
366 target mpcbdm 0
367 mpcbdm spr SYPCR = 0xffffff88
368 mpcbdm spr ICTRL = 0x00000007
369 mpcbdm spr DER = 0x2002000f
370 set $sp=0x01ffffff
371 end
Figure 2.6
mpc.init
361˜365
Set the information that will be used by gdb. After line 363, mpcbdm_fbuf points to
the start of MPC860 CPM’s Dual Port RAM, because IMMR will be mapped to
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 9
0xff000000 in SetupProc.
366
Start debugging and reset the processor according to the README.txt in the original
mpcbdm package.
367˜370
Setup some debugging registers of processor. The values assigned to these registers were
calculated according to [1] and [2]. Please pay attention to line 370. This line sets the stack
pointer, usually the r1 according to [3] and [4], to the end of the physical memory. This action is
very important to start the programme using the stack, when operating system is not running on
the board.
Figure 2.7 shows macro SetupProc.
mpc.init
251 define SetupProc
252 echo *** setting up processor/n
254 mp spr MSR = 0x00001002
256 mp spr SRR1 = 0x00001002
257 mp spr IMMR = 0xff000000
259 mp spr SIUMCR = 0x00632a00
261 mp spr SYPCR = 0xffffff88
263 mp spr SCCR = 0x02000000
265 mp spr PLPRCR = 0x00000000
266 mp spr ICTRL = 0x00000006
268 mp spr DER = 0x2002000f
269 mp spr IC_CST = 0x04000000
271 mp spr DC_CST = 0x04000000
273 mp spr IC_CST = 0x0a000000
274 mp spr DC_CST = 0x0a000000
275 mp spr IC_CST = 0x0c000000
276 mp spr DC_CST = 0x0c000000
277 mp spr DEC = 0x7fffffff
278 mp spr TBSCR = 0x00030000
280 end
Figure 2.7
mpc.init
254˜278
Setup some critical registers of processor.
257˜259
Map IMMR to 0xff000000, as indicated above. It should never be mapped below
0xc0200000, since after Linux starts, it will map memory address below 0xc0000000 to user
space address. If you map IMMR between 0xc0000000 and 0xc0200000, you will take the risk
of massing up the Linux kernel. So we mapped the IMMR as recommended in the [1] to
0xff000000. SIUMCR was generated according to [1] page x and [2].
269˜276
Here are three pairs of cache manipulating commands. First pair disables data cache and
instruction cache. Second one unlocks two caches for the next pair. The third invalidates two
caches unlocked by previous pair. It is very important to perform these tasks, since after power
on the two caches are filled with garbage. If we didn’t swap them out, something unpredictable
would have happened during any programme execution.
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 10
Figure 2.8 shows macro ProCardMem.
mpc.init
27 define ProCardMem
32 echo *** setting up memory/n
39 mpcbdm spr BR0 = 0xffe00401
44 mpcbdm spr OR0 = 0xffe00954
47
48 mpcbdm spr OR5 = 0xfe000200
49 mpcbdm spr BR5 = 0x00000081
50 mpcbdm spr MSTAT = 0x00000400
51 mpcbdm spr MAMR = 0x9c822111
52
55 mpcbdm spr MDR = 0xfffff004
56 mpcbdm spr MCR = 0x0000a108
.. ...
234 mpcbdm spr MDR = 0xffffffff
235 mpcbdm spr MCR = 0x0000a03f
237 end
Figure 2.8
mpc.init
39˜44
Set the Base and Option register for flash. Pay attention the order of the two operation.
For bank 0 Base register must be set before Option register, while for other banks, Option register
should be set before Base register. Flash start address is mapped to 0xffe00000.
48˜49
Set up Base and Option register for memory. The order of the setting must be reiterated
here. Memory is just mapping to the start of the 4G address, 0x0, and is configure to use UPMA.
Value of MSTAT and MAMR were also calculated according to [2]. This is just starting of initialization
of memory.
55˜253
Initialize memory and various memory operation by writing the UPMA RAM. The specified
MCR and MDR values are from [1].
Macro Flash is shown in Figure 2.9.
mpc.init
243 define Flash
244 echo *** loading flash conf/n
245 mp flash conf 0xffe00000 1 AM29LV017B
246 end
Figure 2.9
mpc.init
245
Map the flash start address to 0xffe00000, as mentioned in ProCardMem, which is
known by gdb now. This line interacts with the Flash.dev to initialize the flash and related flash
operation.
Build Cross Toolchains Porting Linux to MPC860SR Processor Card 11
After having changed all these files, we copied mpcbdm.c, mpcbdm.h, and Makefile.in to
gdb-5.0_src_dir/gdb/ and Linux.tm to gdb-5.0_src_dir/gdb/config/powerpc/. Under sources directory
of gdb, following commands were executed:
# ./configure --prefix=tool_dir --target=powerpc-linux
# make&&make install
Then we copied Flash.dev and mpc.init to where we would run powerpc-linux-gdb. To
use the bdm with gdb, following command will be issued:
# powerpc-linux-gdb -x mpc.init
Port U-boot Porting Linux to MPC860SR Processor Card 12
Port U-boot
Boot loader is critical to every operating system. There are various boot loaders for Linux.
For Intel acchitecture, LILO and GRUB will both be good choices, while under PowerPC architecture
yaboot is popular. But for our embedded PowerPC architecture, u-boot was chosen,
which is a project on Sourceforge. The letter ’u’ in its name stands for ’universal’.
Overview of U-boot
U-boot resides in the very beginning of the flash, but its start point offsets 0x100 from the
start of the flash, since there is the place CPU will start execution. After its execution, u-boot
will initialize CPU and several board’s peripherals, creat some critical data structures which will
be used by kernel, and load itself into the top of the memory.
When control is tranfered into u-boot’s in-memory code, it will initialize the interrupts
and the rest peripherals. Then it will wait for commands, which will be received from UART, or
boot the kernel image with ramdisk image according to the information compiled into it and the
information which is added to the above two images by its mkimage.
If u-boot receives the command to boot the kernel image or it is used to boot the kernel
image directly, it will uncompress the kernel, load it to the start of the memory, and give the control
to the kernel. Then kernel will continue execution without the intervention of u-boot.
U-boot Main Function Relationship
Only when you understand art-of-the-state code of u-boot, can you change its code and
make it server your purpose.
Function Location
file functions
cpu/mpc8xx/start.S _start
relocate_code
trap_init
cpu/mpc8xx/cpu_init.c cpu_init_f
cpu_init_r
cpu/mpc8xx/cpu.c checkcpu
upmconfig
lib_ppc/board.c board_init_f
board_init_r
init_func_ram
common/main.c main_loop
common/env_flash.c env_init
board/procard/procard.c checkboard
initdram
initsdram
_initsdram
testdram
move32
board/procard/flash.c flash_init
Table 3.1
Port U-boot Porting Linux to MPC860SR Processor Card 13
Figure 3.1 shows the main function relationship of u-boot. The location of each function
in Figure 3.1 is shown in Table 3.1.
_start
cpu_init_f board_init_f
initialize
CPU clock
env_init
initialize
console display
checkcpu
checkboard
init_func_ram
initdram
initsdram
_initsdram
upmconfig testdram
move32
relocate_code
board_init_r
trap_init
flash_init
cpu_init_r
initialize various things
e.g. networks main_loop
Figure 3.1 U-boot function relationship
Each ecllipse represents a function, or a procesure if you wish. The shallow shaded ellipses
are functions which we changed, thoroughly rewrote or newly added. The deep shaded ellipses
are intermediate nods of the main execution flow. Main execution flow is shown by curved
dashed arrow. Other arrows are used to shown the function call relationship. Each dashed box
represents a bunch of functions perform the action indicated in it.
In this chapter, a detailed analysis of the functions represented by the shallow shaded ellipses
will be presented, while there is only a brief discription of other functions available here.
For thorough analysis of u-boot code, you can refer to Apendix A.2.
Port U-boot Porting Linux to MPC860SR Processor Card 14
U-boot Main Function Discription
When the board is power on, it will start execution at address 0x100. Before flash is
mapped to 0xffe00000, this address points to the 0x100 offset from the start of flash, _start’
s cold boot code is located there. _start will first map IMMR to what we specified with a
macro in procard.h, whose value is 0xff000000. Why we chose this value is declared in previous
chapter. Before proceeding, one important concept must be clarified here:
For MPC860, data will appear same at every 0x100000 address interleave.
So after initializing several critical registers, u-boot clears and disables data and instruction
cache, then jumps to 0xffexxxxx to continue execution. 0xxxxxx is the address of the next 32bits
binary code following the jump instruction. Since 0xffe00000 is just 0xffe times of 0x100000,
the data appear on 0xffexxxxx is just same of that on 0xxxxxx. The intention to do this jump is
that u-boot will map flash to 0xffe00000 in near future, and the link time u-boot address was also
0xffe00000.
Flow control is handled to cpu_init_f(). The last character f indicates this piece
of code is execution in the flash. The other main finctions also follow this name style. After setting
several registers which are mapped in IMMR, cpu_init_f() maps flash to 0xffe00000
by setting BR0 and OR0 as indicated before. Other important thing cpu_init_f() accomplished
is resetting the CPM. It is critical to set CPM registers afterwards. If this is not done,
later assigning values to CPM registers will fail silently, until you see that u-boot is hanging up.
Heeding cpu_init_f(), board_init_f() begins. As shown in Figure 3.1, this
function perform a lot of initialization. It uses an array of function pointer to call the functions
shown on the right side in Figure 3.1. After reaching the end of the array, board_init_f()
initialize a very important data structure, which will be used by the kernel and has type gd_t. Before
the last line in board_init_f() (not before return), it calls reloacte_code().
relocate_code() is an assembly language procesure. It maybe seems strange that
relocate_code() is called with parameters. Since compiler is created according [10], so if
our usage of the registers is conformed to [10], then everything is ok. Half of relocate_
code() executes in the flash, and the other executes in sdram. It copies the u-boot code
to sdram then jumps its counter parter in sdram to continue execution.
board_init_r() is called from relocate_code(). Like indicated above, r
stands for executing in sdram. It is the longest function among all the functions we described before.
It initializes various peripherals, including console display, networks, flash, and so on.
Other important task performed by board_init_r() is initializing a data structure, which is
a brief copy of gd_t. This data structure is used by u-boot only. This non-return function will
call main_loop() in while loop.
main_loop will wait for the input from console, analysis the input, and perform the
corresponding task, or boot the kernel with ramdisk straight forward. Which action to perform is
according to procard.h, the configuration file.
Discription of the Changed U-boot Functions
Since board related functions are grouped together under board/board_name directory,
what we need to do was to creat board/procard directory, and add our own board specific files
there.
Port U-boot Porting Linux to MPC860SR Processor Card 15
Although changes were made mainly to our own directory, some changes were still made
to the related files loacted in other directory to reflect our board’s special property. This is shown
in Figure 3.2.
board.c
218 #ifndef CONFIG_PROCARD
219 puts ("DRAM: ");
220 #endif
221
222 if ((gd->ram_size = initdram (board_type)) > 0) {
223 #ifndef CONFIG_PROCARD
224 print_size (gd->ram_size, "/n");
225 #else
226 printf ("SDRAM: 32 MB/n");
227 #endif
228 return (0);
229 }
Figure 3.2
board.c
218˜227
For our board, no dram exists, but other may have, conditional compile is useful here.
The macro CONFIG_PROCARD is defined in procard.h.
The following functions were thoroughly rewritten, which reside in procard.c or flash.c
under directory board/procard.
procard.c
18 #include <common.h>
19 #include <config.h>
20 #include <mpc8xx.h>
23
24 #define _NOT_USED_ 0xFFFFFFFF
29
30 int checkboard (void)
31 {
32 printf ("MPC860 Processor Card/n");
33 return 0;
34 }
Figure 3.3
procard.c
30˜34
Nothing to do but print the identicational information of our board. This application interface
must be provided for board_init_f() always calls it.
Figure 3.4 shows some macro definitions before functions, which initialize memory.
Their value are same as their counter part in mpc.init, which is described in the previous chapter.
Port U-boot Porting Linux to MPC860SR Processor Card 16
procard.c
38 #if defined(CONFIG_SDRAM_100MHZ)
39
40 #define SDRAM_OR5VALUE 0xfe000200
41 #define SDRAM_BR5VALUE 0x00000081
42
43 #define SDRAM_MPTPRVALUE 0x0400
44
45 #define SDRAM_MAMRVALUE 0x9c822111
46
47 #define SDRAM_MARVALUE 0x02000088
48
49 #define SDRAM_MCRVALUE0 0x0000a008
50 #define SDRAM_MCRVALUE1 0x8000a008
51 #define SDRAM_MCRVALUE2 0x0000a000
.. ...
90
91 #else
92 #error CONFIG_SDRAM_100MZ must be configured
93 #endif
Figure 3.4
procard.c
38
CONFIG_SDRAM_100MZ must be defined, or an error message like the one on line 92
will be printed during the preprocessing procesure of the compiler. It is much better than generating
an error and terminating after a long time compiling, just because of lack of some macro
definitions. CONFIG_SDRAM_100HZ is defined procard.h.
39˜51
Some macros are defined, whose values are used to initialized memory control registers.
Several pieces of code are omitted here, since we will describe them when we reach
_initsdram().
procard.c
182 long int initdram(int board_type)
183 {
184 if(!initsdram(0, 0)) {
185 return 0x2000000;
186 } else
187 while(1);
188 }
Figure 3.5
procard.c
182˜185
No dram exists, so we call initsdram() directly to initialize our sdram.
186˜188
We will NEVER reach here.
Port U-boot Porting Linux to MPC860SR Processor Card 17
procard.c
170 int initsdram(uint base, uint *noMbytes)
171 {
172 if(!_initsdram(0, 32)) {
173 return 0;
174 } else {
175 _sdramdisable();
176 return -1;
177 }
178 }
Figure 3.6
procard.c
170
noMbytes is not used in our board and should not be referenced (it points to the start
of physical memory, but there are no meanful data for us now).
171˜173
Call _initsdram() for real memory initialization.
174˜177
We will NEVER reach here.
It looks strange that we made function call in the this fashion. Since the original code
was from board/fads, we just kept all the APIs that existed in the original file. And this fashion
also keep the code logical tidy. This would not incur a lot of performance penalties, because we
could rely on compiler’s optimization function when --fomit-frame-pointer is specified
to gcc. The function call penalty is reduced to minimal.
There are several important data structures that we must mentioned here before going on.
They are shown in Figure 3.7 and Figure 3.8
8xx_immap.h
477 typedef struct immap {
478 sysconf8xx_t im_siu_conf; /* SIU Configuration */
479 pcmconf8xx_t im_pcmcia; /* PCMCIA Configuration */
480 memctl8xx_t im_memctl; /* Memory Controller */
481 sit8xx_t im_sit; /* System integration timers */
482 car8xx_t im_clkrst; /* Clocks and reset */
483 sitk8xx_t im_sitk; /* Sys int timer keys */
484 cark8xx_t im_clkrstk; /* Clocks and reset keys */
485 vid823_t im_vid; /* Video (823 only) */
486 lcd823_t im_lcd; /* LCD (823 only) */
487 i2c8xx_t im_i2c; /* I2C control/status */
488 sdma8xx_t im_sdma; /* SDMA control/status */
489 cpic8xx_t im_cpic; /* CPM Interrupt Controller */
490 iop8xx_t im_ioport; /* IO Port control/status */
491 cpmtimer8xx_t im_cpmtimer; /* CPM timers */
492 cpm8xx_t im_cpm; /* Communication processor */
493 } immap_t;
Figure 3.7
8xx_immap.h
Port U-boot Porting Linux to MPC860SR Processor Card 18
477˜493
This is the framework of the IMMR. It is the memory mapping for operating the register
in C language convetion. Registers that perform specific functions are group together and have
their own type.
Then we should proceed to see the data structure of im_memctl, which is used in
_initsdram(). It is shown in Figure 3.8
8xx_immap.h
66 typedef struct mem_ctlr {
67 uint memc_br0;
68 uint memc_or0;
69 uint memc_br1;
70 uint memc_or1;
71 uint memc_br2;
72 uint memc_or2;
73 uint memc_br3;
74 uint memc_or3;
75 uint memc_br4;
76 uint memc_or4;
77 uint memc_br5;
78 uint memc_or5;
79 uint memc_br6;
80 uint memc_or6;
81 uint memc_br7;
82 uint memc_or7;
83 char res1[0x24];
84 uint memc_mar;
85 uint memc_mcr;
86 char res2[4];
87 uint memc_mamr;
88 uint memc_mbmr;
89 ushort memc_mstat;
90 ushort memc_mptpr;
91 uint memc_mdr;
92 char res3[0x80];
93 } memctl8xx_t;
Figure 3.8
8xx_immap.h
66˜93
Every member has a name memc_XXX, while the XXX stands for the register name that
the member represents. res[n] represents the reservered space of IMMR.
Something must be declared here. Under various delivery of Unix, int is 32bits and short
is 16bits. Then you can compare the above structure to [2], you will see they are matched seamlessly.
When the above two structures are used, assigning a value to a register is handled just like
assigning a value to a C language variable. All detailed operations like that in [3] and [4] are
handled by the compiler and hidden from C language programmer.
Port U-boot Porting Linux to MPC860SR Processor Card 19
Figure 3.9 shows the first part of _initsdram().
procard.c
95 int _initsdram(uint base, uint noMbytes)
96 {
97 int i, j = 0;
98 volatile immap_t *immap = (immap_t *)CFG_IMMR;
99 volatile memctl8xx_t *memctl = &immap->im_memctl;
100
101 int testdram(void);
102
103 if(noMbytes != 32)
104 {
105 return -1;
106 }
107
112 memctl->memc_mptpr = SDRAM_MPTPRVALUE;
113 memctl->memc_mamr = SDRAM_MAMRVALUE;
114
115 memctl->memc_or5 = SDRAM_OR5VALUE;
116 memctl->memc_br5 = SDRAM_BR5VALUE;
Figure 3.9
procard.c
98˜99
Force type converting. The CFG_IMMR is 0xff000000 as defined in procard.h. All the
registers that control the memory operation , can be accessed through memctl. memctl
and immap are decorated with volatile. It’s important to decorate variables of this type
with volatile to prevent compiler optimizing them, which may be a desaster. All the macros
(except CFG_IMMR ) used here and in the following figure are shown in Figure 3.4.
Figure 3.10 shows the second part of _initsdram().
procard.c
118 retry: for (i=0;i<14;i++) {
119 memctl->memc_mdr = sdram_init_table[i];
120 memctl->memc_mcr = (SDRAM_MCRVALUE0 + i);
121 }
122
123 udelay(200);
124 memctl->memc_mar = SDRAM_MARVALUE;
125 udelay(1);
126 memctl->memc_mcr = SDRAM_MCRVALUE1;
127 udelay(200);
128
129 upmconfig(SDRAM_MCRVALUE2, (uint *)sdram_table,
130 sizeof(sdram_table)/sizeof(uint));
131
132 udelay(200);
Figure 3.10
procard.c
Port U-boot Porting Linux to MPC860SR Processor Card 20
118˜132
Initialize the memory and its related operation. sdram_init_table and
sdram_table are shown in the following two figures.
procard.c
53 const static uint sdram_init_table[]=
54 {
55 /* initialization. (offset 8 in upm RAM) */
56 0xfffff004, 0x0ffcc004, 0xfffff004, 0xfffff034,
57 0x0fac0034, 0xfffff004, 0xfffff004, 0x0ffc3084,
58 0xfffff004, 0xfffff004, 0xfffff004, 0xfffff004,
59 0xfffff084, 0xfffff407 };
Figure 3.11
procard.c
53˜59
The value of this table is used to fill Memory Data Register. It is used to initialize memory.
Its contents are the same as their counter part in Flash.dev.
procard.c
61 const uint sdram_table[] =
62 {
63 /* single read. (offset 0 in upm RAM) */
64 0xfffffc04, 0x0f0cfc04, 0x0ffff804, 0x01bf7004,
65 0x0ffdd000, 0x1ffff447, 0x0ffffc04, 0x1ffffc07,
66
67 /* burst read. (offset 8 in upm RAM) */
68 0xfffffc04, 0x0f0cfc04, 0x0ffff804, 0x00ff3004,
.. ...
88 /* exception. (offset 3c in upm RAM) */
89 0xffffec07, 0xffffffff, 0xffffffff, 0xffffffff };
Figure 3.12
procard.c
52˜89
This array is used as a parameter to upmconfig(). Its contents are assigned to
Memory Data Register, as that of sdram_init_table. It is used to initialize memory operations,
that MPC860 can perform on sdram. Its value and order are same as its counter part in
Flash.dev.
Figure 3.13 shows upmconfig(), which uses the above array to initialize the memory
operation.
This function can be replaced with the code in Figure 3.10 between line 118 to line 121.
But the function call panelty may be somewhat helpful here, since the hardware errata mentioned
in the following piece of code.
Port U-boot Porting Linux to MPC860SR Processor Card 21
cpu.c
398 void upmconfig (uint upm, uint * table, uint size)
399 {
400 uint i;
401 uint addr = 0;
402 volatile immap_t *immap = (immap_t *) CFG_IMMR;
403 volatile memctl8xx_t *memctl = &immap->im_memctl;
404
405 for (i = 0; i < size; i++) {
406 memctl->memc_mdr = table[i];
407 memctl->memc_mcr = addr | upm;
408 addr++;
409 }
410 }
Figure 3.13
cpu.c
398
The first parameter passed to upmconfig() is SDRAM_MCRVALUE2, a macro
shown in Figure 3.4.
400˜410
This code are almost same as that in Figure 3.10 between line 118 to line 121.
Figure 3.14 shows the last part of _initsdram().
procard.c
134 if (testdram() < 0) {
135 if (j++ < 3) {
139 goto retry;
140 } else {
141 printf("Failed to initialize SDRAM!/n");
142 printf("Hanging.../n");
143 while(1);
144 }
145 }
146
150 return 0;
151 }
Figure 3.14
procard.c
134˜151
This piece is used to solve the following hardware errata.
There was a strange thing when we cold booted the board, it always hang. After having
traced the u-boot step by step, we found out the hanging happened when the u-boot tried to jump
into memory to continue execition. The place where it wanted to jump was supposed to contain
proper code. But if the board was cold booted, there was nothing execept garbage. If the board
was warm booted, everything went just as expected. But one kind of cold booting would lead the
u-boot to work correctly, that was after board’s cold booting we cut off the power and powered it
on immediately. Since lack of eletronic equipments, we just guessed that the problem was located
in unsteadness of occilation.
Port U-boot Porting Linux to MPC860SR Processor Card 22
Although the above errata is hardware related, we solved it by software method--- After
the initialization, u-boot tests the sdram. If the test failed, u-boot will reinitialize the sdram. The
reinitialization is allowd to perform at most three times. If all three initializations fail, u-boot
will hang in _initsdram(). So this causes a lot of NEVER reached code in several pervious
figures. On the other words, _initsdram() always returns successfully, or it nev er returns.
It is really fortunate this method works. The memory is always initialized twice when the
board is cold booted, and is initialized once when the board is warm booted, just as we expected.
Figure 3.15 shows the function testing the sdram after it is initialized.
procard.c
197 int testdram (void)
198 {
199 unsigned long testvec=0x01010101;
200 unsigned long recvec=0;
201
205 move32(&testvec,0x01fbe328);
206 move32(0x01fbe328,&recvec);
207
208 if (recvec!=testvec) {
212 return (-1);
213 }
214
218 return (0);
219 }
Figure 3.15
procard.c
199
Hope that the garbage in the sdram does not have the same value.
205˜206
Choose the start address to which u-boot will copy itself from flash to test. After having
traced u-boot for several times, we got this value.
move32() is shown in Figure 3.16, which is a local function.
procard.c
192 static void move32(unsigned long *src,unsigned long *dest)
193 {
194 *dest = *src;
195 return;
196 }
Figure 3.16
procard.c
192˜196
The parameters position is conformed to that of ANSI C memory operation. It seems that
inline assembly code will be better, but since compiler will perform a smart job on this simplest
code, no assembly language is needed to be involved.
Port U-boot Porting Linux to MPC860SR Processor Card 23
Figure 3.17 shows some important variables and macros for flash.
flash.c
18 #include <common.h>
19 #include <mpc8xx.h>
20
21 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
22
23 #if defined(CFG_ENV_IS_IN_FLASH)
24 # ifndef CFG_ENV_ADDR
25 # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
26 # endif
27 #endif
Figure 3.17
flash.c
21
This array contains flash information of each bank. For our board,
CFG_MAX_FLASH_BANKS is 1, which is defined in procard.h.
23˜27
This piece of conditional compile code is the most important in this file.
CFG_ENV_IS_IN_FLASH is defined in procard.h, but CFG_ENV_ADDR is not defined, so uboot
will calculate the environment variables’ start address for us in this file.
CFG_FLASH_BASE is 0xffe00000 and CFG_ENV_OFFSET is 0x9000, which are also defined
in procard.h. HowCFG_ENV_OFFSET was generated will be shown when the explanation of
ld script is reached.
flash.c
39 unsigned long flash_init (void)
40 {
41 int i;
42
43 for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
44 {
45 flash_info[i].flash_id = FLASH_UNKNOWN;
46 flash_info[i].sector_count = 32;
47 flash_info[i].size = 0x200000;
48 }
49
50 return (0x200000);
51 }
Figure 3.18
flash.c
43˜48
CFG_MAX_FLASH_BANKS is 1, as indicated in the above figure. We provideed only
several necessary information to u-boot about our flash. Assigning FLASH_UNKNOW to
flash_id member of flash_info_t structure will result some operation on flash to fail.
Because we had mpcbdm to perform flash operation, flash function of u-boot was not used.
However, its APIs must be provided, or link error would be generated although compile would be
passed successfully.
Port U-boot Porting Linux to MPC860SR Processor Card 24
50
The return value is the size of flash. Although flash function is not used, failure of
flash_init() will finally cause the u-boot to hang.
Since we never used the flash function that provided by u-boot. All the APIs provided by
our flash.c are all empty actions and always return fail. These vain APIs are shown in the Figure
3.19.
flash.c
59 void flash_print_info (flash_info_t *info)
60 {
61 if (info->flash_id == FLASH_UNKNOWN)
62 {
63 printf ("missing or unknown FLASH type/n");
64 return;
65 }
66 }
81 int flash_erase (flash_info_t *info, int s_first, int s_last)
82 {
83 return (1);
84 }
93 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
94 {
95 return (2);
96 }
Figure 3.19
flash.c
61
As mentioned above, FLASH_UNKNOWN causes this action to fail.
83,95
No matter what parameters are delivered, these two function always fail.
Procard.h
As you can see from the previous section, a lot of critical macros are defined in procard.
h. procard.h is also the new file we added, which is located in include/configs. We created
it based on fads.h, which had been made for a board similar to ours.
First part of procard.h is shown in Figure 3.20.
procard.h
26 #ifndef __CONFIG_H
27 #define __CONFIG_H
.. ...
310 #endif
Figure 3.20
procard.h
Port U-boot Porting Linux to MPC860SR Processor Card 25
26,27,310
This is the common method used in head files, which prevents muti-including of the same
head file.
Some important macros which define the cpu type and board type are shown in Figure
3.21.
procard.h
29 //#define DEBUG 1
30
35 #include <mpc8xx_irq.h>
36
37 #define CONFIG_8xx 1
38 #define CONFIG_MPC860 1
39 #define CONFIG_PROCARD 1
Figure 3.21
procard.h
29
This line is commented out, but it is still worth to mention it here. When it is uncommented,
a lot of debug information will be printed, during u-boot running. It is a convient way to
judge the wide area where bug is located. It also helped us to solve the hardware errata mentioned
in the previous section.
35
This file includes some macros defining the value which will be assigned to interrupt related
registers.
37˜39
CONFIG_8xx is not originally appear in the fads. Why it must be specified here is that
we must keep the gd_t data structure same between kernel and u-boot. CONFIG_PROCARD is
newly added for our board. You can see its usage in the previous section.
Figure 3.22 shows the SMC configure. For our board, console is linked to SMC1.
procard.h
41 #define CONFIG_8xx_CONS_SMC1 1
42 #undef CONFIG_8xx_CONS_SMC2
43 #undef CONFIG_8xx_CONS_NONE
44 #define CONFIG_BAUDRATE 19200
Figure 3.22
procard.h
41˜43
We undefined other console related SMC configure in order that other head file define
them accidentally.
44
Baudrate of the board is set to 19200, which is the same value used in cu configuration
files. This macro is used not only by console which is linked to SMC1, but also by ethernet control
chip which is linked to SCC1.
Port U-boot Porting Linux to MPC860SR Processor Card 26
Figure 3.23 shows the cpu clock frequency configure.
procard.h
48 #define MPC8XX_FACT 10
49 #define MPC8XX_XIN 5000000
56 #define CONFIG_8xx_GCLK_FREQ 50000000
Figure 3.23
procard.h
48˜49
These two macros are obsoleted, no file in u-boot use them anymore. We kept them just
to indicate how the following cpu clock frequency is constituted.
56
This macro is used to initialize the gd_t data structure, which is used by the kernel. Its
value is calculated out according to [1].
Figure 3.24 shows the boot command configuration.
procard.h
59 #define CONFIG_BOOTDELAY -1
64 #define CONFIG_BOOTCOMMAND "run flash_ram"
65 #undef CONFIG_BOOTARGS
66
67 #define CONFIG_EXTRA_ENV_SETTINGS /
68 "nfsargs=setenv bootargs root=/dev/nfs rw " /
69 "nfsroot=$(serverip):$(rootpath)/0" /
70 "ramargs=setenv bootargs root=/dev/ram rw/0" /
71 "addip=setenv bootargs $(bootargs)" /
72 "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" /
73 ":$(hostname):$(netdev):off/0" /
74 "flash_nfs=run nfsargs addip;" /
75 "bootm $(kernel_addr)/0" /
76 "flash_ram=run ramargs addip;" /
77 "bootm $(kernel_addr) $(ramdisk_addr)/0" /
78 "net_nfs=bootp;run nfsargs addip;bootm/0" /
79 "kernel_addr=ffe00800/0" /
80 "ramdisk_addr=ffe00000/0" /
81 ""
Figure 3.24
procard.h
59,64˜65
CONFIG_BOOTDELAY means after how many seconds u-boot should run the command
defined by CONFIG_BOOTCOMMAND, and -1 means to disable the auto-boot function. Since
this command needs no extra arguments, CONFIG_BOOTARGS is undefined.
68˜80
Every environment variable of u-boot is ended with /0.
79˜80
kernal_addr and ramdisk_addr indicate the two images’ location in flash.
These two environment variables of u-boot would affect how to hardwire the two images into
Port U-boot Porting Linux to MPC860SR Processor Card 27
flash in the last stage of the porting.
68˜69
nfsargs is an runable environment variable defined to set another environment variable
bootargs, which is passed to the kernel as argument when booting the kernel. The definition
here will let the kernel mount the root file system using nfs protocol through network. It
was useful when we were testing ramdisk image.
70
Beside nfsargs, ramargs is another runable environment variable setting
bootargs for kernel. But it is used to let the kernel mount root file system on a ramdisk image
instead of using nfs protocal through network. It was used to auto-boot Linux kernel, after we
finished testing kernel and ramdisk image.
71˜73
addip initializes the network environment with the information either from DHCP
server we had set or from the hardwired information. This information is appended to
bootargs in order to be delivered to kernel as boot argument, since Linux can configure IP
layer directly at kernel level without help of ifconfig.
There are three kinds of booting method:
load kernel from network and mount the root file system using nfs protocol through
network;
load kernel from flash and mount the root file system from ramdisk;
load kernel from flash and mount the root file system using nfs protocol through network.
These three methods are defined in the following three macro.
78
After this environment variable’s execution, following actions are carried out:
All the information the board needs is gotten through DHCP server. U-boot initializes
environment variables according to this information;
Based on the above information, u-boot will get the kernel through TFTP server and
load it into the location defined by CFG_LOAD_ADDR in the sdram;
U-boot prepares the boot argument for kernel according its environment variables;
Kernel will be booted with the boot argument u-boot delivered to it.
The first two actions are achieved by bootp. The third action is performed by run nfsargs
addip. bootm takes over the last action. This is the first booting method. We
used it when testing the kernel and ramdisk.
76˜77
Some task like above will be performed
Based on the information hardwired in the flash, u-boot will initialize the boot argument
for kernel;
U-boot load the kernel from flash into the location defined by CFG_LOAD_ADDR in
the sdram;
Kernel is booted with the argument prepared by the u-boot.
The first two action are achieved by run ramargs addip. The third action is achieved by
boot $(kernel_addr) $(ramdisk_addr). This is the second booting method,
which was used to accomplish the auto-boot after kernel and ramdisk tests were finished.
Port U-boot Porting Linux to MPC860SR Processor Card 28
74˜75
This is the third booting method, which was never used by us.
81
A null string is used to indicate the end of the extra environment variables.
procard.h
88 #undef CONFIG_WATCHDOG
89
91 #undef CONFIG_MAC_PARTITION
92 #undef CONFIG_DOS_PARTITION
93 #undef CONFIG_ISO_PARTITION
94 #undef CONFIG_ATAPI
95 #undef CONFIG_IDE_8xx_PCCARD
96 #undef CONFIG_IDE_8xx_DIRECT
97 #undef CONFIG_IDE_LED
98 #undef CONFIG_IDE_RESET
Figure 3.25
procard.h
88
From [1], our board have no hardware implemented watchdog, which is configured by
CONFIG_WATCHDOG. So CONFIG_WATCHDOG is undefined.
91˜98
Since we had no concept of partition on our flash, all macro concerning partition types
are undefined. No IDE or ATAPI sockets exists on our board, so all IDE or ATAPI related
macros are also undefined.
Figure 3.26 shows the ethernet configuration for our board.
procard.h
105 #define CONFIG_SCC1_ENET 1
106 #undef CONFIG_FEC_ENET
112 #if defined(CONFIG_SCC1_ENET) && defined(CONFIG_FEC_ENET)
113 #error Both CONFIG_SCC1_ENET and CONFIG_FEC_ENET configured
114 #endif
115
116 #define CONFIG_ETHADDR 52:54:ab:54:82:5e
Figure 3.26
procard.h
105˜106
SCC1 is used as the ethernet and no Fast Ethernet Controller (FEC) exists on our board.
112˜114
SCC1 ethernet and FEC can’t coexist. If they both defined, an error message on line 113
will be printed during the preprocessing and the compiler is terminated.
116
As indicated in Chapter 1 last section, ethernet address can’t be chosen randomly. In order
to utilize the DHCP server’s services, we configured the ethernet address the same value as
that in Figure 1.5
Port U-boot Porting Linux to MPC860SR Processor Card 29
Figure 3.27 shows the IP network configuration, which was used after the kernel and
ramdisk passed the thorough test.
procard.h
118 /*
119 #define CONFIG_IPADDR 192.168.0.253
120 #define CONFIG_NETMASK 255.255.255.0
121 #define CONFIG_SERVERIP 192.168.0.254
122 #define CONFIG_GATEWAYIP 192.168.0.254
123 #define CONFIG_HOSTNAME procard
124 */
Figure 3.27
procard.h
118,124
As you can see when we were testing the kernel, these macro were commented out, since
the u-boot got this information from DHCP server. But when u-boot is used to auto-boot, we let
all the IP network information hardwired instead of depending on DHCP server for it.
119˜123
All value assigned to macro is same as its counter part in Figure 1.5, the configuration file
of DHCP server.
U-boot command line properity configuration is shown in Figure 3.28.
procard.h
127 #include <cmd_confdefs.h>
128
132 #undef CFG_LONGHELP
133 #define CFG_PROMPT "=>"
135 #define CFG_CBSIZE 256
139 #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)
140 #define CFG_MAXARGS 16
Figure 3.28
procard.h
127
This header file includes macro CONFIG_COMMANDS definition, which defines how
many commands that u-boot can recognize.
132˜140
Detailed information about u-boot command line help is useless, so we undefined it here.
CFG_PROMPT will be printed as the prompt of u-boot command line. CFG_CBSIZE is the
maximum size of one command including the arguments and white space seperators. CFG_PBSIZE
is the size of the buffer used by printf(). As about why plus 16 bytes addition to
CFG_CBSIZE and sizeof(CFG_PROMPT) is that when debugging the parser of command,
some information other than command and prompt will be printed. Maximum number of arguments
that one command can accept is CFG_MAXARG-1, since this macro’s value also inclueds
the command itself.
Port U-boot Porting Linux to MPC860SR Processor Card 30
Figure 3.29 shows the micellanious configuration setting of u-boot.
procard.h
141 #define CFG_BARGSIZE CFG_CBSIZE
142
143 #define CFG_MEMTEST_START 0x00000000
144 #define CFG_MEMTEST_END 0x01ffffff
145
146 #define CFG_LOAD_ADDR 0x00100000
147
148 #define CFG_HZ 1000
149
150 #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
Figure 3.29
procard.h
141
The size of the boot argument that will be passed to kernel is assigned the same size of
the command line. This surely will be enough.
143˜144
These two macros are used to test the whole sdram. But for our board testing one word is
enough to judge whether the sdram’s initialization is successful or not, so they are never used.
146
U-boot will load the kernel image made by mkimage to 1 Mbytes of sdram. This value is
used by bootp and bootm commands of u-boot.
147
This macro is used to initialize the interrupts of MPC860.
150
This table provides all the values of baudrate that we could change between them interactively
when u-boot is started. We nev er used this function.
Figure 3.30 shows some IMMR related configuration.
procard.h
161 #define CFG_IMMR 0xff000000
162 #define CFG_IMMR_SIZE ((uint)(64 * 1024))
167 #define CFG_INIT_RAM_ADDR CFG_IMMR
168 #define CFG_INIT_RAM_END 0x2f00
169 #define CFG_GBL_DATA_SIZE 64
170 #define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
171 #define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
Figure 3.30
procard.h
161˜162
IMMR is mapped to 0xff00000. All IMMR size is 64K.
167˜168
When the sdram is not initialized, u-boot is using part of Dual Port Ram of IMMR as
Port U-boot Porting Linux to MPC860SR Processor Card 31
temporary stack, which must be used with care for some overlapping problem.
169˜171
CFG_GBL_DATA_OFFSET must be a little larger than gd_t structure, but 64 bytes is
the largest size that gd_t could be. CFG_INIT_SP_OFFSET is assigned the same value as
CFG_GBL_DATA_OFFSET. It seems that the temporary gd_t structure will be overlapped
with the temporary stack. But stack grows downward,while gd_t is allocated upward. So overlapping
will not happen, although their start address is the same one.
procard.h
178 #define CFG_SDRAM_BASE 0x00000000
179
180 #define CFG_FLASH_BASE 0xffe00000
182 #define CFG_FLASH_SIZE ((uint)(2 * 1024 * 1024))
183
184 #define CFG_MONITOR_LEN (272 << 10)
185 #define CFG_MONITOR_BASE CFG_FLASH_BASE
186 #define CFG_MALLOC_LEN (384 << 10)
187
193 #define CFG_BOOTMAPSZ (8 << 20)
Figure 3.31
procard.h
178˜182
Sdram start address should always be mapped to 0x0, while flash start address is mapped
to 0xffe00000 as recommended by [1]. Our flash size is 2 Mbytes.
184˜186
U-boot’s base address (not execution start point) is the same value as the flash start address.
We reserved 272Kbytes for u-boot’s data, code, and bss section. 384Kbytes are reserved
following u-boot’s sev eral sections as heap, used by u-boot’s malloc() function.
193
Before the Linux kernel own initialization, only 8 Mbytes memory is mapped. In order to
make the gd_t structure retrievable by Linux kernel, we must put it in the lowest 8 Mbytes. This
limit is defined by CFG_BOOTMAPSZ.
procard.h
197 #define CFG_MAX_FLASH_BANKS 1
198 #define CFG_MAX_FLASH_SECT 32
199
200 #define CFG_FLASH_ERASE_TOUT 120000
201 #define CFG_FLASH_WRITE_TOUT 500
Figure 3.32
procard.h
197˜201
Some flash related macros. Our board has only one flash bank, and the flash sector number
is 32 according to [7]. CFG_FLASH_ERASE_TOUT and CFG_FLASH_WRITE_TOUT is
never used, since we didn’t implement flash function of u-boot.
Port U-boot Porting Linux to MPC860SR Processor Card 32
Figure 3.33 shows the environment variables configuration.
procard.h
203 #define CFG_ENV_IS_IN_FLASH 1
204 #define CFG_ENV_OFFSET 0x9000
205 #define CFG_ENV_SIZE 0x400
206 #define CFG_ENV_SECT_SIZE 0x40000
Figure 3.33
procard.h
203˜206
How the value of CFG_ENV_OFFSET is calculated out will be shown when ld script is
reached. 1 Kbytes environment variables’ size is surely large enough to hold all of them that we
defined. CFG_ENV_SECT_SIZE is the sector size of flash, according to [7] it is 64Kbytes.
Various macros that define several registers value is shown in Figure 3.34.
procard.h
222 #define CFG_SYPCR 0xffffff88
228 #define CFG_SIUMCR 0x00632a00
234 #define CFG_TBSCR 0x0003
241 #define CFG_PISCR (PISCR_PS | PISCR_PITF)
247 #define CFG_PLPRCR 0
255 #define SCCR_MASK SCCR_EBDF11
256 #define CFG_SCCR 0x02000000
263 #define CFG_DER 0
279 #define CFG_PRELIM_OR_AM 0xff800000
284 #define CFG_OR_TIMING_FLASH /
285 (OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_3_CLK | OR_TRLX)
287 #define CFG_OR0_PRELIM 0xffe00954
288 #define CFG_BR0_PRELIM 0xffe00401
293 #define CFG_MAMR_PTA 0x9c
298 #define CFG_MAMR 0x9c001000
Figure 3.34
procard.h
222˜298
All the values of these macros were calculated according to [1] and [2].
procard.h
211 #define CFG_CACHELINE_SIZE 16
.. ...
305 #define BOOTFLAG_COLD 0x01
306 #define BOOTFLAG_WARM 0x02
307
308 #define CONFIG_SDRAM_100MHZ 1
Figure 3.35
procard.h
Port U-boot Porting Linux to MPC860SR Processor Card 33
211
All MPC860 cpu cache line size is 16 bytes.
305˜306
These two macros are used by board_init_f() to initialize the bd_t structure,
which is only used by u-boot and is an brief copy of gd_t structure.
308
This macro must be specified or error will be generated as indicated in Figure 3.4.
Configure the Ethernet Card
Each board’s ethernet control chip has it own linking method to SCC or FEC of MPC860.
For our board, ethernet control chip is linked to SCC1. The file including the pin linkage information
is in include/commproc.h.
Figure 3.36 shows our board’s specific information added to this file.
commproc.h
426 #if defined(CONFIG_MPC860) && defined(CONFIG_PROCARD)
430 #define PROFF_ENET PROFF_SCC1
431 #define CPM_CR_ENET CPM_CR_CH_SCC1
432 #define SCC_ENET 0
433
434 #define PA_ENET_RXD ((ushort)0x0001)
435 #define PA_ENET_TXD ((ushort)0x0002)
436 #define PA_ENET_TCLK ((ushort)0x0800)
437 #define PA_ENET_RCLK ((ushort)0x0200)
438
439 #define PB_ENET_TENA ((uint)0x00001000)
440
441 #define PC_ENET_CLSN ((ushort)0x0010)
442 #define PC_ENET_RENA ((ushort)0x0020)
443
444 #define PC_ENET_LBK ((ushort)0x0800)
445
446 #define SICR_ENET_MASK ((uint)0x000000ff)
447 #define SICR_ENET_CLKRT ((uint)0x0000002f)
448
449 #endif
Figure 3.36
commproc.h
426,449
This set of macros is used only when CONFIG_MPC860 and CONFIG_PROCARD are
both defined.
430˜432
PROFF_SCC defines the parameter ram offset of SCC. Since ethernet control chip is
linked to SCC1 so PROFF_SCC1 is assigned to PROFF_SCC. PROFF_SCC1 is also defined
in commproc.h, whose value is 0x0. SCC_ENET is an index in an array of SCC register
set. Since the ethernet control chip use SCC1, 0 is assigned to the macro.
Port U-boot Porting Linux to MPC860SR Processor Card 34
434˜447
All the macros’ values were calculated out according to [1], and kernel’s header file
commproc.h’s comments.
Ld Script
Ld script is a powerful method to arrange the sections in elf format. Each board has its
own ld script. Since the memory of the embedded operating system is always small, how to arrange
the section to fully utilize the memory is important. We generated the ld script based on
fads’s. For more information of ld script you can refer to ld’s info page.
Figure 3.37 shows the part of the ld script that was changed.
u-boot.lds
54 .text :
55 {
59 cpu/mpc8xx/start.o (.text)
60 cpu/mpc8xx/traps.o (.text)
61 common/dlmalloc.o (.text)
62 lib_ppc/ppcstring.o (.text)
63 lib_generic/vsprintf.o (.text)
64 lib_generic/crc32.o (.text)
65 lib_generic/zlib.o (.text)
66 lib_ppc/cache.o (.text)
67 lib_ppc/time.o (.text)
68
69 . = env_offset;
70 common/environment.o (.ppcenv)
71
72 *(.text)
73 *(.fixup)
74 *(.got1)
75 }
Figure 3.37
u-boot.lds
54˜67
This part defines arrangement of the text section of u-boot. The first eight relocatable
file’s text section are put at the very first of the executable binary file of u-boot. Their total
size is almost 36 Kbytes, as Figure 3.33 line 204 shows. This value was gotten by using objdump
with -h option. For further information about objdump, you can refer to its manual page
or info page.
69˜70
The address after the above eight relocatable files’ text section is set to env_offset,
which has the value CFG_ENV_OFFSET. Assigning CFG_ENV_OFFSET to
env_offset is done in common/environment.c, which will be shown in the following figures.
The contents at this location is the ppcenv section of common/environment.o. This is not the
standard section name of elf format. Creating this section is also performed in environment.c.
72˜74
The rest relocatable files’ text section is followed by all relocatable files fixup section.
Section got1 of all relocatable files is put at the end of the u-boot’s text section.
Port U-boot Porting Linux to MPC860SR Processor Card 35
Figure 3.38 shows the first part of environment.c.
environment.c
24 #include <config.h>
25 #include <environment.h>
26
31 #if defined(__APPLE__)
33 # define SYM_CHAR "_"
34 #else
35 # define SYM_CHAR
36 #endif
37
42 #if defined(ENV_IS_EMBEDDED)
.. ...
199 #endif
Figure 3.38
environment.c
31˜36
For us, SYM_CHAR is defined as null, not white space.
42˜199
This is the main part of environment.c. ENV_IS_EMBEDDED is generated from the
macro we defined in Figure 3.33.
Figure 3.39 shows how ENV_IS_EMBEDDED generated. These are all done in environment.
h.
environment.h
40 #if defined(CFG_ENV_IS_IN_FLASH)
41 # ifndef CFG_ENV_ADDR
42 # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
43 # endif
.. ...
56 # if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && /
57 (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN)
58 # define ENV_IS_EMBEDDED 1
59 # endif
.. ...
63 #endif
Figure 3.39
environment.h
40˜63
CFG_ENV_ADDR is 0xffe09000, which is surely conformed to the two conditions listed
on line 56 and 57. So ENV_IS_EMBEDDED will be defined.
Figure 3.40 shows the main part of environment.c.
Port U-boot Porting Linux to MPC860SR Processor Card 36
environment.c
49 #if (defined(CONFIG_PROCARD) || /
.. ...
56 defined(CONFIG_TRAB)) && /
57 defined(ENV_CRC)
59 # define __PPCENV__ __attribute__ ((section(".ppcenv")))
60 # define __PPCTEXT__ __attribute__ ((section(".text")))
.. ...
70 #endif
71
75 #define GEN_SYMNAME(str) SYM_CHAR #str
76 #define GEN_VALUE(str) #str
77 #define GEN_ABS(name, value) /
78 asm (".globl " GEN_SYMNAME(name)); /
79 asm (GEN_SYMNAME(name) " = " GEN_VALUE(value))
80
96 env_t environment __PPCENV__ = {
97 ENV_CRC,
98 #ifdef CFG_REDUNDAND_ENVIRONMENT
99 1,
100 #endif
101 {
102 #if defined(CONFIG_BOOTARGS)
103 "bootargs=" CONFIG_BOOTARGS "/0"
104 #endif
... ...
168 #ifdef CONFIG_EXTRA_ENV_SETTINGS
169 CONFIG_EXTRA_ENV_SETTINGS
170 #endif
171 "/0"
172 }
173 };
183
192 unsigned long env_size __PPCTEXT__ = sizeof(env_t);
193
197 GEN_ABS(env_offset, CFG_ENV_OFFSET);
Figure 3.40
environment.c
49˜56, 70
CONFIG_PROCARD is defined in procard.h. ENV_CRC is defined during link time. Its
value is assigned by envcrc tool comming along with u-boot, but it has a critical error. We will
explain it in the following secition.
59˜60,96
__attribute__ is the gcc specific modifier. Here they are used to put variables
modified by it into specific section in the paranthese. So environment will be put into ppcenv
section, while it should be put into data section according to standards.
75˜77,197
When these macro are expanded at line 197, they will yield the following two lines:
.globl env_offset
env_offset = CFG_ENV_OFFSET
Port U-boot Porting Linux to MPC860SR Processor Card 37
The variable env_offset is used in ld script and is assigned CFG_ENV_OFFSET.
Envcrc
This is the tool that generates crc, which will be used to make sure that the on flash uboot
is not damaged during hardwiring. But it has a serious errata.
Let’s first take a look in Figure 3.40.
98˜100
We didn’t define CFG_REDUNDAND_ENVIRONMENT at all. But when generating the
crc, envcrc does NOT differenciate it. We added some code to its source file (tools/envcrc.c) to
let it make some sence to CFG_REDUNDAND_ENVIRONMENT.
The first part of code we added to it is just the same code in FIgure 3.39. The second part
is shown in Figure 3.41.
envcrc.c
57 #ifdef CFG_REDUNDAND_ENVIRONMENT
58 # define ENV_HEADER_SIZE (sizeof(unsigned long) + 1)
59 #else
60 # define ENV_HEADER_SIZE (sizeof(unsigned long))
61 #endif
Figure 3.41
envcrc.c
57˜61
ENV_HEADER_SIZE, which is used to calculate the crc, is adjusted according to
CFG_REDUNDAND_ENVIRONMENT.
Makefile --- the Arranger
It maybe seems strange that all the files use macro configured in procard.h but nev er include
it. They just include config.h, in which procard.h is included. This is not achieved by hand
editing but by mkconfig, which is invoked by Makefile.
Figure 3.42 shows what we do to Makefile in the top directory of u-boot.
Makefile
.. ...
304 procard_config:unconfig
305 @./mkconfig $(@:_config=) ppc mpc8xx procard
.. ...
Figure 3.42
Makefile
304˜305
These two lines were added to let Makefile work for us. Target procard_config depends
on target unconfig, which is invoked first before action of target procard_config
Port U-boot Porting Linux to MPC860SR Processor Card 38
is taken. The action of taget procard_config is to execute a shell script, whose name is
mkconfig. It is executed with four arguments, although it can be executed with five arguments at
most. During its execution no message will be echoed, even though it contains echo shell buildin.
The first argument passed to mkconfig is the target name striped the _config pattern.
Figure 3.43 shows the target unconfig
Makefile
.. ...
178 unconfig:
179 rm -f include/config.h include/config.mk
.. ...
Figure 3.43
Makefile
178˜179
The action of this target removes all the files that created by mkconfig.
Figure 3.44 shows the first part of mkconfig.
Makefile
1 #!/bin/sh -e
11 APPEND=no
12
13 while [ $# -gt 0 ] ; do
14 case "$1" in
15 --) shift ; break ;;
16 -a) shift ; APPEND=yes ;;
17 *) break ;;
18 esac
19 done
20
21 [ $# -lt 4 ] && exit 1
22 [ $# -gt 5 ] && exit 1
23
24 echo "Configuring for $1 board..."
25
26 cd ./include
27
31 rm -f asm
32 ln -s asm-$2 asm
33 rm -f asm-$2/arch
34 ln -s arch-$3 asm-$2/arch
Figure 3.44
Makefile
1
Every shell script should include this line.
11
This environment variable means that include/config.h should be recreated.
Port U-boot Porting Linux to MPC860SR Processor Card 39
13˜19
Process the arguments. If the first argument is -a, then include/config.h will be generated
by appending to the current one. mkconfig shifts the arguments until the first non-option argument
is met.
21˜22
The number of non-option arguments should be four or five, or mkconfig will exit with 1,
which means the execution failed.
26˜34
Changing directory has no effect after the shell script is finished. mkconfig will make
some links with common name to architecture specific directory name. For our board include/
asm will be linked to include/asm-ppc, while include/asm/arch will be linked to include/
arch-mpx8xx. Using this technique every source file can just use the common name, architecture
specific information is handled apparently to them.
Second part of mkconfig is shown in Figure 3.45.
mkconfig
39 echo "ARCH = $2" > config.mk
40 echo "CPU = $3" >> config.mk
41 echo "BOARD = $4" >> config.mk
42
43 [ "$5" ] && echo "VENDOR = $5" >> config.mk
Figure 3.45
mkconfig
39˜43
config.mk is created in include/ with several macros that will be used by Makefile in the
top directory of u-boot. If the fifth argument of mkconfig is specified, it is expected to be the
vendor sepcific information. For our board, we didn’t use it.
mkconfig
48 if [ "$APPEND" = "yes" ]
49 then
50 echo >> config.h
51 else
52 > config.h
53 fi
54 echo "/* Automatically generated - do not edit */" >>config.h
55 echo "#include <configs/$1.h>" >>config.h
56
57 exit 0
Figure 3.46
mkconfig
48˜53
For our board line 52 will be executed, which creats an empty config.h in include/. The
following two line in the quotion mark are the contents of config.h. If we reach here, our execution
is successful, which is indicated by the 0 exit status.
The last part included in Makefile is our board specific link time address for u-boot,
which is specified in board/procard/config.mk. It is shown in Figure 3.47
Port U-boot Porting Linux to MPC860SR Processor Card 40
config.mk
28 TEXT_BASE = 0xffe00000
29 OBJCFLAGS = --set-section-flags=.ppcenv=contents,alloc,load,data
Figure 3.47
config.mk
28
Linker editor’s -T option argument value is defined here. It is the link time address for uboot.
What’s Next
Following command was issued under source directory of u-boot:
# make procard_config && make
Tw o version of u-boot were created. One was in pure binary format, while the other was in elf
format.
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 41
Port Linux 2.4.18
There is an excellent patch for Linux on PowerPC architecture. But some work was done
in order to reflect the specific property of our board, and to work parallelly with the porting process
of u-boot.
Linux Kernel Source Code Orginization
Linux
arch ppc
boot
configs
include
asm-ppc
Linux
net
drivers
fs
init
ipc
kernel
lib
mm
scripts
Figure 4.1
The modern operating system’s seperation of the architecture dependend code from the
architecture undependend code makes the porting process focus only on the former. In the above
figure, work was mainly done in the top two directories, arch/ppc and include. From now on except
intentionally noted all directories are rooted in source code directory of Linux kernel.
Top lev el Makefile
A little changes were made to top level Makefile of Linux source code so that it would
use the PowerPC configuration set and the compiling process would use the cross tools we had
prepared.
These changes were limitted to the first several macro definitions. The definition of
ARCH was change to ppc abruptly. This change would make kernel be able to be configured
for PowerPC on our two IA-32 architecture computer. Another change was assigning powerpc-
linux- to CROSS_COMPILE macro. Since the tools defined to compile kernel source
code have the following format:
TOOL = $(CROSS_COMPILE)tool_name
this change would force the compilation to use our cross tools.
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 42
Config.in
One of the rules in the top level Makefile allows the kernel to be configured using menu.
This rule’s name is menuconfig. This rule will first build an application, lxdialog, located
in scripts/lxdialog/. This application can draw menu according to the arguments specified in its
command line. Then the rule invokes a bash script scripts/Menuconfig with arch/ppc/config.in as
argument. This bash script will perform the function of lexical analyzor and parser, the result of
the syntax analysis on arch/ppc/config.in will be used to generate the command line arguments of
lxdialog. So the menu is generated according to arch/ppc/config.in.
Now it’s clear that changing arch/ppc/config.in can make our board be configurable.
There are also other config.in spreaded out in the subdirectories of arch/ppc, they were also
changed accordingly.
The first config.in changed is located in arch/ppc. Changed part is shown in Figure 4.2.
config.in
67 if [ "$CONFIG_8xx" = "y" ]; then
68 define_bool CONFIG_SERIAL_CONSOLE y
69
70 choice ’Machine Type’ /
71 "RPX-Lite CONFIG_RPXLITE /
72 RPX-Classic CONFIG_RPXCLASSIC /
73 BSE-IP CONFIG_BSEIP /
74 FADS CONFIG_FADS /
75 TQM823L CONFIG_TQM823L /
76 TQM850L CONFIG_TQM850L /
77 TQM855L CONFIG_TQM855L /
78 TQM860L CONFIG_TQM860L /
79 FPS850L CONFIG_FPS850L /
80 TQM860 CONFIG_TQM860 /
81 SPD823TS CONFIG_SPD823TS /
82 IVMS8 CONFIG_IVMS8 /
83 IVML24 CONFIG_IVML24 /
84 SM850 CONFIG_SM850 /
85 MBX CONFIG_MBX /
86 Procard CONFIG_PROCARD /
87 WinCept CONFIG_WINCEPT" Procard
97 fi
Figure 4.2
config.in
86˜87
If CONFIG_8xx has been chosen, a lot of board types will be prompted. All of the
board types are listed in choice section. The left column lists the board name that will be
shown to end user, while the right column lists the macros that will be defined for kernel if the
corresponding board type is chosen. Line 86 was added for our board, and line 87 was changed
to make our board the default choice.
Some lines in the above config.in tell us where the other related config.in is located.
These lines are all started with source token. So after having searched the above config.in, we
found that another config.in located in arch/ppc/8xx_io/ is relevant to our board.
Almost no chnage was made to that file. Only one comment which will be displayed during
make menuconfig process, was added to make the configuration less confusion. The
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 43
following line was added between line 20 and line 21 of the orginal file:
comment ’Default using SMC1 for UART’
The reason to add this comment is that after having read the source code of the UART driver, we
found out that if CONFIG_SMC2_UART is not defined, then SMC1 will be used as default.
Make Life Easier
There is one rule, whose name is board_name_config, in arch/ppc/Makefile. Using
this rule, configuartion will be much easier than using make menuconfig. We also
made our board configurable using this rule, in order to make end user’s life much easier.
Work was mainly based on arch/ppc/configs/mbx_defconfig. This file was copy to top
level directory and saved as .config. make menuconfig was issued to make some changes to
.config:
1) Plantform support -> Machine Type was changed to Porcard
2) Block devices -> RAM disk support and Block devices -> Initial
RAM disk (initrd) support were chosen
3) Networking options -> Packet socket was chosen
4) Networking options -> IP:DHCP support was chosen
5) Charater devices -> Unix98 PTY support was chosen
File systems -> /dev/pts file system for Unix98 PTYs was chosen
6) MPC8xx CPM options -> SCC used for Ethernet was changed to SCC1
7) MPC8xx CPM options -> Use SMC2 for UART was deselected
The reason for these changes are as follows:
1) Our board type. This option item is available only after the above changes were made to the
config.in.
2) Our whole system will be reside in RAM disk,
3) udhcpd will use packet socket.
4) When testing kernel with u-boot, we used kernel level IP configuration with a DHCP server.
5) utelnetd depends on these.
6) Our board has no FEC and Ethernet control chip is linked to SCC1.
7) Default is to use SMC1 as indicated in the comment line we added, and our board using
SMC1 as console.
After having been changed, .config was copied to arch/ppc/configs/ and saved as procard_defconfig.
Now end user can just type:
# make procard_config && make oldconfig
to configure the kernel with the configuration set we had made for them.
Simple Boot Loader
In order to allow work to proceed parallelly, a simple boot loader had been worked out
before porting u-boot was finished. This boot loader was just used to test whether the kernel
malfunctions or not.
This simple boot loader is the first stage boot loader. It ran totally in flash. The kernel
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 44
and the second stage boot loader, which is included in the kernel source, were loaded into the
memory by first stage boot loader. Having taken its size into consideration, we wrote it with assembly
language. Since it is no more than a temporary tool, we do not show its code here. But
its function is briefly described below.
It was mainly devided into 2 parts:
1) Initialize cpu and memory.
2) Copy second stage loader and kernel into memory.
3) Transfer the control to second stage boot loader.
The first part is done in mpc8xx_init processure. This procesure takes the following
actions:
1) Initialize IMMR and serveral other registers.
2) Call init_clk procesure, which initializes the baudrate for the whole board.
3) Call init_cache_mmu. This processure disables two cache line (data and command),
invalidates them, and enables them again.
4) Call init_memc processure to initialize the UPM and coreponding memory operation.
5) Call vector_reloc to copy all the interrupt vectors into the very first location of the
memory.
All these actions listed are self-explanation. But several notes still should be added here. First,
when the boot loader started to run at its VMA? It is the time when the execution flow return
from processure init_clk. The other, vector_reloc is not as necessory as it seems
like here, since the first stage boot loader never utilizes the interrupt handlers nor does the second
stage loader. And after being uncompressed, kernel will replace all the existing interrupt vectors
with its own. We did so, just in order to conform to the MPC860 standard startup programme requirements.
The second part is accomplished by procesure main. This processure performs the
following tasks:
1) Print some welcome message.
2) Call reloc_kernel to copy the second stage boot loader and kernel into memory.
One important point needed to be mentioned --- the first task performs by main --- CPM must
be reset before being used.
It seems that this boot loader can work well, but it is far from to be put into formal work.
The reason are as follows: It can only boot the kernel from flash and it deeply depends on the
kernel and second boot loader’s size. Every time kernel is changed, all three images, first stage
boot loader, second stage boot loader, and gzipped kernel image must be re-hardwiring to flash.
This action is really time consuming, and is least desirable. Due to this drawback, this boot loader
had just been used before u-boot’s porting was finished.
Port Kernel
The first place to take a look is include/asm-ppc/. A file named procard.h was created. It
is included in include/asm-ppc/mpc8xx.h, which will be shown in Figure 4.4. The newly created’s
contents are shown in the following figure.
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 45
procard.h
1 #ifdef __KERNEL__
2 #ifndef __ASM_PROCARD_H__
3 #define __ASM_PROCARD_H__
4
5 #include <Linux/config.h>
6 #include <asm/ppcboot.h>
7
8 #define IMAP_ADDR ((uint)0xff000000)
9 #define IMAP_ADDR ((unit)(64*1024))
10
11 #define NR_8259_INTS 0
12
13 #endif /* __ASM_PRPCARD_H__ */
14 #endif /* __KERNEL__ */
Figure 4.3
procard.h
5˜6
include/Linux/config.h is generated according to .config by make dep. The latter is
created by make menuconfig. After make dep include/asm is a soft link to include/
asm-ppc. include/asm-ppc/ppcboot.h includes the definition of bd_t structure, which will
be introduced later.
8˜9
Define the IMMR mapping and its size according to [2],
11
Only the MBX board uses 8259 chip as its interrupt controller.
mpc8xx.h
11 #ifdef __KERNEL__
12 #ifndef __CONFIG_8xx_DEFS
13 #define __CONFIG_8xx_DEFS
14
15 #include <Linux/config.h>
16
17 #ifdef CONFIG_8xx
18
19 #ifdef CONFIG_PROCARD
20 #include <asm/procard.h>
21 #endif
22
23 #ifdef CONFIG_MBX
24 #include <asm/mbx.h>
25 #endif
.. ...
95 #endif /* CONFIG_8xx */
96 #endif /* __CONFIG_8xx_DEFS */
97 #endif /* __KERNEL__ */
Figure 4.4
mpc8xx.h
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 46
19˜21
CONFIG_PROCARD and CONFIG_8xx are defined in include/Linux/config.h. Other
CONFIG_boardname are not defined. So previous created file is included here.
The next thing we did was to change the file used to configure the network chipset linkage.
This file is include/asm-ppc/commproc.h. The changed part is shown as follows.
commproc.h
385 /*** Procard *************************************************/
386 #ifdef CONFIG_PROCARD
387
388 #define PA_ENET_RXD ((ushort)0x0001)
389 #define PA_ENET_TXD ((ushort)0x0002)
390 #define PA_ENET_TCLK ((ushort)0x0800)
391 #define PA_ENET_RCLK ((ushort)0x0200)
392
393 #define PB_ENET_TENA ((uint)0x00001000)
394
395 #define PC_ENET_CLSN ((ushort)0x0010)
396 #define PC_ENET_RENA ((ushort)0x0020)
397
398 #define PC_ENET_LBK ((ushort)0x0800)
399
400 #define SICR_ENET_MASK ((uint)0x000000ff)
401 #define SICR_ENET_CLKRT ((uint)0x0000002f)
402
403 #endif
Figure 4.5
commproc.h
388˜401
As mentioned early, all these macros were generated according to [1] and the comments
within this file.
All the configuration changing was finished here. Next was the second stage boot loader.
Its source code is located in arch/ppc/boot. arch/ppc/boot/Makefile was first changed.
Makefile
30 subdir-y := lib common procard
.. ...
37 NONBOOT := lib common
38
40 BOOTDIRS = $(filter-out $(NONBOOT), $(subdir-y))
.. ...
48 BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
49
50 $(BOOT_TARGETS): vmapus lib/zlib.a images/vmLinux.gz maketools
51 ifneq ($(BOOTDIRS),)
52 for d in $(BOOTDIRS); do $(MAKE) -C $$d $@; done
53 endif
Figure 4.6
Makefile
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 47
30
This is the changed line. procard was newly added to replace the original simple.
37˜40
After these several lines, BOOTDIRS are procard, which we would create later.
51˜52
make -C lib, make -C common and make -C procard are issued to execute
make target in $(BOOTDIRS) repectively.
arch/ppc/boot/procard/ was created according to arch/ppc/boot/mbx/. head.S, m8xx_tty.c,
misc.c, embed_config.c and Makefile were copied from the latter directory to the former one.
The main functions in these files are shown in following table.
file name function
head.S The entry point of the second stage boot
loader is included in it. Relocate itself
and decompress the gzipped kernel image.
Initial bd_t is also located in it.
m8xx_tty.c Initialize SMC1 for console output.
Various print functions are included.
misc.c Include only one function decompress_kernel().
embed_config.c Fillin the bd_t structure for specific board
Table 4.1
First change was made to head.S. Since the initial value of bd_t is board specific. The
changed part is shown in the following figure.
head.S
234 #ifndef CONFIG_MBX
235 local_bd_info:
236 .fill 16,4,0
237 #endif
Figure 4.7
head.S
234˜237
local_bd_info have the type of bd_t *. Having checked the include/asm-ppc/ppcboot.
h, we found that the size of bd_t for our configuration, with only CONFIG_8xx set, is
64bytes, taking padding of the structure also into consideration. Before embed_config,
local_bd_info is not used. So it is safe and convenient to make it all zero filled. embed_
config in the embed_config.c will take care of the initialization of the structure.
embed_config is shown in Figure 4.8
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 48
embed_config.c
30 static ushort def_enet_addr[] = { 0x5254, 0xab54, 0x825e };
31
32 #if defined(CONFIG_PROCARD)
33
34 embed_config(bd_t *bd)
35 {
36 u_char *cp;
37 int i;
38
39 bd->bi_memstart = 0;
40 bd->bi_memsize = (32 * 1024 * 1024);
41
42 bd->bi_flashstart = 0xffe00000;
43 bd->bi_flashsize = (2 * 1024 * 1024);
44
45 bd->bi_immr_base = 0xff000000;
46
47 /* 192.168.0.253 */
48 bd->bi_ip_addr = 0xc0a800fe;
49
50 cp = (u_char *)def_enet_addr;
51 for (i=0; i<6; i++) {
52 bd->bi_enetaddr[i] = *cp++;
53 }
54
55 bd->bi_intfreq = 50000000;
56 bd->bi_busfreq = 50000000;
57 bd->bi_baudrate = 19200;
58 }
59
60 #endif /* PROCARD */
Figure 4.8
embed_config.c
30
Change the ethernet address to what we had planned. It is same as that in Figure 1.5.
34˜58
Initialize various members of bd_t according to [1] and [2].
The original author’s intention was to make gzipped kernel image and this second stage
boot loader stick together. This way would make one hardwire-ready image. But this would introduce
some tricky but urgly binary operation. So we seperated the second stage boot loader
from the gzipped kernel image. Thus we changed misc.c.
The changed part is shown in Figure 4.9.
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 49
misc.c
78 decompress_kernel(unsigned long load_addr, int num_words,
unsigned long cksum, bd_t *bp)
79 {
80 int timer, zimage_size = ZIMAGE_SIZE;
.. ...
140 zimage_start = (char *)0x0018a000;
... ...
244 gunzip(0, 0x400000, zimage_start, &zimage_size);
... ...
248 }
Figure 4.9
misc.c
80
ZIMAGE_SIZE is defined at compile time.
140
The second stage loader is smaller than 40Kb (0xa000). After being loaded into memory,
the second stage loader will reloacte itself to 0x00180000 (its VMA), no matter where we first
load it (This is LMA. We use same LMA as VMA). Given this, we put the gzippped kernel image
at 0x00180000+0xa000 by assigning 0x18a000 to zimage_start.
244
Call gunzip() as parameter the artifacted zimage_start.
Next comes arch/ppc/boot/procard/Makefile, The first part of it is shown as follows.
Makefile
27 ifeq($(CONFIG_PROCARD),y)
28 SIZE := ../utils/procard_size
29 else
30 SIZE := ../utils/size
31 endif
32
33 LIBS := ../lib/zlib.a
.. ...
36 ifdef CONFIG_8xx
37 ZLINKFLAGS := -T $(TOPDIR)/arch/$(ARCH)/vmLinux.lds -Ttext 0x00180000
38 OBJECTS := head.o m8xx_tty.o
39 CFLAGS += -DCONFIG_8xx
40 endif
.. ...
48 OBJECTS += ../common/misc-common.o misc.o ../common/string.o
49 OBJCOPY_ARGS = -O elf32-powerpc
.. ...
71 ifeq ($(CONFIG_PROCARD),y)
72 CFLAGS += -DCONFIG_PROCARD
73 OBJECTS += embed_config.o
74 endif
Figure 4.10
Makefile
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 50
28
Since we used different way of compiling and binary operation from the original one, we
should assign different value to SIZE. procard_size and size are bash scripts. Contents
of procard_size will be shown later when we describe the binary operation.
34
Use the ld script located in the upper directory to link the sceond stage boot loader. Its
VMA is 0x00180000, which is same as its LMA in our case (the LMA is determined in the first
stage loader).
After this section of Makefile, the contents of OBJECTS and LIBS is determined and
never changed. All the object files are generated using the old-fashioned suffix rules of make.
The second part of Makefile is shown in Figure 4.11.
Makefile
121 zvmLinux: ../images/vmLinux.gz $(OBJECTS) $(LIBS)
122 $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 /
123 -DZIMAGE_SIZE=‘sh $(SIZE) $<‘ -c -o misc.o misc.c
124 $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
125 $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment /
126 --add-section=image=$< $@.tmp ../images/$@.embedded
127 rm -f $@.tmp
128
129 zvmLinux.bin: zvmLinux.embedded
130 $(OBJCOPY) -O binary $< $@
131 rm -f $<
Figure 4.11
Makefile
122˜123
misc.c was treated specially. Since its variable zimage_size, shown in Figure 4.9,
depends on the value of macro ZIMAGE_SIZE at compile time. This macro defines the size of
the gzipped kernel image. Here $(SIZE) is, as mentioned in Figure 4.10, procard_size,
whose contents are shown as follows:
#!/bin/sh
ls -l --block-size=1 $1|gawk ’{print $5}’
The execution result of this bash script is the size of the ../images/vmLinux.gz
124
Link according to the macros shown in Figure 4.10. The linking process will generate an
ELF for Pow erPC image, whose name is vmLinux.tmp.
125˜126
Use one of binary utilities, objcopy, to generate the final result, zvmLinux.embedded.
It removes .comment section of the vmLinux.tmp and uses the contents of ../images/
vmLinux.gz to fill the final result’s .image section. __image_begin and __image_
end which are defined in ld.script for programme use will also be upadated by objcopy
automaticly.
129˜130
Again use objcopy to generate the binary format for the second stage boot loader, whose
name is zvmLinux.bin. Since the binary format does not support user defined section
Port Linux 2.4.18 Porting Linux to MPC860SR Processor Card 51
name (e.g. .image ), the output is stripped off all user defined section, which is exactly what
we wanted.
What’s next
The rest of the tasks are to compile first and second stage boot loader, and kernel, then to
hardwire them to board’s flash. To compile the kernel run the following commands under Linux
source code top level directory:
# make procard_config && make oldconfig
# make dep
# make zvmLinux.bin
The files we were interested in are:
1) binary format first stage boot loader, whose name is init860.bin. (located in our own working
directory)
2) binary format second stage boot loader, whose name is zvmLinux.bin (located in Linuxsrc/
arch/ppc/boot/images/)
3) gzipped kernel image vmLinux.gz (located in Linux-src/arch/ppc/boot/images/)
The following figure shows the contents of the flash after haveing been hardwired to:
0 64K 128K 2048K
Figure 4.12
The first shaded part contains init860.bin, the second shaded part contains zvmLinux.bin, and the
last shaded part contains vmLinux.gz. The rest parts of flash are unused.
Prepare RAMDisk Porting Linux to MPC860SR Processor Card 52
Prepare RAMDisk
This is really trivial work comparing to the previous one we have described. So you can
take a rest and then go on reading. For further information about RAMDisk, you can refer to
ramdisk.txt in Linux source code’s Documentation directory.
Build uClibc
At this point of porting process, we figured out that glibc 2.2 is somewhat too large for
our board. Although RAMDIsk will be gzipped, it is still impossible to put a 7Mb libc.so into
only 2Mb flash (If we take boot loader and gzipped kernel image into consideration, the available
space for RAMDisk is about 1.3Mb). Then we turned to uClibc, whose total size is only 400Kb
including libcrypt and other libs. As about why it is so small, you can refer to the FAQ on its official
web site.
What we had to do was to change the Rules.mak in the source code. CROSS = powerpc-
linux- was added just as what we had done to Linux source code’s Makefile. After having
read the Makefile located in uClibc’s source code, we found that it has a excellent menu configuration
system which is similar to that of Linux, so make menuconfig should be run.
The following configurable options were changed:
1) Target Architecture Feature and Options ---> Linux kernel header
location was changed to our patched Linux source code’s include/ directory.
2) Networking Support ---> Remote Procedure Call (RPC) support was
chosen.
3) Library Installation Options ---> uClibc development environment
directory was change to /opt/Linuxppc/Linuxppc/uclibc-Linux/, where the binary
output of uClibc would be put.
make install was issued then. Besides the libc and other library, uClibc also provides
another set of compilation and binary tools. We used them in the rest of the utilities building
process.
Build the Rest of the Utilities
The rest of the utilities are:
1) busybox: It has init, shell and a set of base system utilities.
2) tinylogin: Login and authentication programme.
3) udhcpd: Simple DHCP server.
4) utelnetd: Simple TELNET server.
All the changed part were confined to their source code’s Makefile. The common
changes were adding CROSS = powerpc-uclibc- to Makefiles, except udhcp’s. udhcp
uses CROSS_COMPILE = powerpc-uclibc- instead.
The rest changes were made to busybox and tinylogin. Changed contents were almost
same for these two utilities:
1) USE_SYSTEM_PWD_GRP were changed to false, in order to use the working computer’s
/etc/passwd.
Prepare RAMDisk Porting Linux to MPC860SR Processor Card 53
2) LDFLAGS were also changed. These two utilities use gcc to pass flags to linkor ld, but the
original writer of the Makefile seems to mangle the flags of gcc and flags of ld. That’s why LDFLAGS
were changed. The value of LDFLAGS after having been changed were
-Wl,-s,-warn-common. The original value had been -s -Wl,-warn-common.
busybox can be configured to support a fine tuned set of base system utilities, not all of
what it provided. To perform this configuration just editted Config.h in the source code of busybox.
Uncomment the utilities wanted and comment out the unwanted ones.
Then run make install in source code directory of busybox and tinylogin, and run
make all in source code directory of udhcpd and utelnetd. In the former two, directories,
whose names are _install, will be created. These newly created are composed of directories,
whose organization conforms to standard UNIX base system directories layout.
Prepare to Hardwire
Prepare the RAMDisk material with the following command:
$ dd bs=1024 count=1024 if=/dev/zero of=./ramdisk_image
This command will create a 1Mb zero filled mountable image. It can be mounted on any mount
point with following command:
# mount -o loop -t ext2 ./ramdisk_image mounnt_point
mount_point should be /opt/root according to Figure 1.5. Then we just copied the contents
of _install located in busybox’s source code to mount_point. We also copied the binary
output of tinylogin, udhcpd, and utelnetd to the corresponding directories in mount_point :
binary outputs of udhcp and utelnetd were copied to sbin/, while binary output and the soft link
of tinylogin were copied to bin/.
As about the output of uClibc, the action taken to to deal with them was somewhat different
from the three utilities mentioned above. Our uClibc output was in /opt/Linuxppc/uclibc-Linux/
lib/. We created such a directory structure in mount_point, copied all files from the former
to the latter, and then replaced the lib/ directory of the RAMDisk with a soft link, whose
name is also lib/, to /opt/Linuxppc/uclibc-Linux/lib/. The reason for doing thses are as follows:
All binary output of utilities we have built so far will search /opt/Linuxppc/uclibc-Linux/lib/ for
the dynamic linking libraries that they need, since they were all compiled with powerpc-uclibcgcc,
which sets the run time library search path to /opt/Linuxppc/uclibc-Linux/lib/. This default
action of powerpc-uclibc-gcc was determined when configuration of uClibc was done. And all
utilities were linked with out flags -rpath dir, which is used to set the run time library
search path to dir. The lib/ soft link was created just to keep the top level directories organization
conforming to the standard.
Next is the various configuration files in etc/ of mount_point:
1) The sample udhcpd’s configuration file, whose name is udhcpd.conf, was copied from its
source code’s sample/ directory.
2) After having changed our root password to MPC860, we deleted some not used entry in working
computer’s /etc/passwd and then copied it to etc/ in mount_point.
Prepare RAMDisk Porting Linux to MPC860SR Processor Card 54
3) etc/inittab in the RAMDisk was totally rewritten. It contains the following two lines:
::sysinit:/etc/rc
ttyS0::respawn:/bin/login
The first line means that script etc/rc in the RAMDisk will be executed at system initial time.
The second line means that bin/login of the RAMDisk, which is a soft link to tinylogin, will be
executed on our only console. The second line will not be run until the execution of etc/rc finished.
The contents of etc/rc in the RAMDisk is shown in the following figure.
rc
1 #!/bin/sh
2
3 /sbin/ifconfig lo 127.0.0.1
4
5 # mount /proc so "reboot" works
6 /bin/mount -t proc proc /proc
7 /bin/mount -t devpts devpts /dev/pts
8
9 echo /n
10 /sbin/utelnetd -p 23 -i eth0 -l /bin/login -d
11 /sbin/udhcpd &
Figure 5.1
rc
3
Assign the loop back device conventional IP address.
6˜7
Mount two special file systems. The first one is used to minitor and tune the system. It
also provide an convenient interface for some application (e.g. ps uses this interface). The second
one is used by utelnetd.
10˜11
Start the TELNET server and DHCP server according to the documents in their source
code. TELNET server invoked by utelnetd will deamonize itself, while DHCP server invoked
by udhcpd will not do so. So we added & to deamonize it. Th reason that we deamonize
udhcpd is as follows: After starting, udhcpd will never return. This will result in untermination
of rc script, which means that /bin/login will never be executed according to what we mentioned
above. That will prevent end user from loginning, which is not what we wanted.
Last thing to do was to copy the device files to dev/ in RAMDisk from our working computer.
The needed device files are: tty[0-4], ttyS[0-4], console, null and ptmx. They were all
copied using cp -a command. They are mainly used by utelnetd and console device driver.
Then the RAMDisk could be unmounted.
After having been throughly tested, vmLinux in the top level Linux source and
ramdisk_image were copied to a directory, say ˜/imagedir. mkimage loacted in the source directory
of u-boot was also copied to this directory. The following Makefile was created in ˜/imagedir.
Prepare RAMDisk Porting Linux to MPC860SR Processor Card 55
Makefile
1 ARCH = ppc
2
3 GZIP = gzip
4 OBJCOPY = powerpc-linux-objcopy
5 MAKEIMG = ./mkimage
6 OBJCOPY_ARGS = -O binary -R .note -R .comment -S
7
8 IMG_ARGS := -A $(ARCH) -O Linux -C gzip -d
9 KERNEL_IMG_ARGS := $(IMG_ARGS) -T kernel -a 0 -e 0 -n "Linux Kernel Image"
10 RAM_IMG_ARGS := $(IMG_ARGS) -T ramdis -n "Ramdisk Image"
11 GZIP_ARGS = -9
12
13 pImage: Linux.bin.gz
14 $(MAKEIMG) $(KERNEL_IMG_ARGS) $< $@
15 rm -f Linux.*
16
17 Linux.bin.gz: Linux.bin
18 $(GZIP) $(GZIP_ARGS) $<
19
20 Linux.bin: vmLinux
21 $(OBJCOPY) $(OBJCOPY_ARGS) vmLinux Linux.bin
22
23 pRamdisk: ramdisk_image.gz
24 $(MAKEIMG) $(RAM_IMG_ARGS) $< $@
25
26 ramdisk_image.gz: ramdisk_image
27 $(GZIP) $(GZIP_ARGS) $<
Figure 5.2
Makefile
1˜27
mkimage will append some information before the headers of gzipped images. This information
is used by u-boot to recognize the image type and take action accordingly. For further
information about how to use mkimage, you can refer to the README in the source code directory
of u-boot.
Following command can be issued in ˜/imagedir to get the hardwire-ready images:
$ make pImage && make pRamdisk
What’s Next
Hardwire binary format u-boot image and above two images to flash accords to the layout
shown in Figure 5.3.
Prepare RAMDisk Porting Linux to MPC860SR Processor Card 56
0 384Kb 1024Kb 2048Kb
Figure 5.3
The first shaded part contains binary image of u-boot. The second shaded part contains
pImage. The last shaded part contains pRamdisk.
Bibliography Porting Linux to MPC860SR Processor Card 57
Bibliography
[1] MPC860 Processor Card User’s Manual Motorola Inc.
[2] MPC860 PowerQUICC Family User’s Manual Motorola Inc.
[3] The MPC860 PowerQUICC TRAINING CDROM Motorola Inc.
[4] The MPC860 PowerQUICC TRAINING Book Motorola Inc.
[5] Programming Environments Manual For 32-Bit Implementations of the PowerPC Architecture
Motorola Inc.
[6] PowerPC Microprocessor Family: The Programmer’s Reference Guide Motorola Inc.
[7] Am29LV017B AMD Inc. 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值