Skip to content
Snippets Groups Projects
README 86.7 KiB
Newer Older
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK


Boot Linux:
-----------

The "bootm" command is used to boot an application that is stored in
memory (RAM or Flash). In case of a Linux kernel image, the contents
of the "bootargs" environment variable is passed to the kernel as
parameters. You can check and modify this variable using the
"printenv" and "setenv" commands:


	=> printenv bootargs
	bootargs=root=/dev/ram

	=> setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2

	=> printenv bootargs
	bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2

	=> bootm 40020000
	## Booting Linux kernel at 40020000 ...
	   Image Name:	 2.2.13 for NFS on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 381681 Bytes = 372 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK
	   Uncompressing Kernel Image ... OK
	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
	Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
	time_init: decrementer frequency = 187500000/60
	Calibrating delay loop... 49.77 BogoMIPS
	Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
	...

If you want to boot a Linux kernel with initial RAM disk, you pass
the memory addresses of both the kernel and the initrd image (PPBCOOT
format!) to the "bootm" command:

	=> imi 40100000 40200000

	## Checking Image at 40100000 ...
	   Image Name:	 2.2.13 for initrd on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 335725 Bytes = 327 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK

	## Checking Image at 40200000 ...
	   Image Name:	 Simple Ramdisk Image
	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
	   Data Size:	 566530 Bytes = 553 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 00000000
	   Verifying Checksum ... OK

	=> bootm 40100000 40200000
	## Booting Linux kernel at 40100000 ...
	   Image Name:	 2.2.13 for initrd on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 335725 Bytes = 327 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK
	   Uncompressing Kernel Image ... OK
	## Loading RAMDisk Image at 40200000 ...
	   Image Name:	 Simple Ramdisk Image
	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
	   Data Size:	 566530 Bytes = 553 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 00000000
	   Verifying Checksum ... OK
	   Loading Ramdisk ... OK
	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
	Boot arguments: root=/dev/ram
	time_init: decrementer frequency = 187500000/60
	Calibrating delay loop... 49.77 BogoMIPS
	...
	RAMDISK: Compressed image found at block 0
	VFS: Mounted root (ext2 filesystem).

	bash#

Boot Linux and pass a flat device tree:
-----------

First, U-Boot must be compiled with the appropriate defines. See the section
titled "Linux Kernel Interface" above for a more in depth explanation. The
following is an example of how to start a kernel and pass an updated
flat device tree:

=> print oftaddr
oftaddr=0x300000
=> print oft
oft=oftrees/mpc8540ads.dtb
=> tftp $oftaddr $oft
Speed: 1000, full duplex
Using TSEC0 device
TFTP from server 192.168.1.1; our IP address is 192.168.1.101
Filename 'oftrees/mpc8540ads.dtb'.
Load address: 0x300000
Loading: #
done
Bytes transferred = 4106 (100a hex)
=> tftp $loadaddr $bootfile
Speed: 1000, full duplex
Using TSEC0 device
TFTP from server 192.168.1.1; our IP address is 192.168.1.2
Filename 'uImage'.
Load address: 0x200000
Loading:############
done
Bytes transferred = 1029407 (fb51f hex)
=> print loadaddr
loadaddr=200000
=> print oftaddr
oftaddr=0x300000
=> bootm $loadaddr - $oftaddr
## Booting image at 00200000 ...
   Image Name:	 Linux-2.6.17-dirty
   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
   Data Size:	 1029343 Bytes = 1005.2 kB
   Entry Point:	 00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Booting using flat device tree at 0x300000
Using MPC85xx ADS machine description
Memory CAM mapping: CAM0=256Mb, CAM1=256Mb, CAM2=0Mb residual: 0Mb
[snip]


More About U-Boot Image Types:
------------------------------

U-Boot supports the following image types:

   "Standalone Programs" are directly runnable in the environment
	provided by U-Boot; it is expected that (if they behave
	well) you can continue to work in U-Boot after return from
	the Standalone Program.
   "OS Kernel Images" are usually images of some Embedded OS which
	will take over control completely. Usually these programs
	will install their own set of exception handlers, device
	drivers, set up the MMU, etc. - this means, that you cannot
	expect to re-enter U-Boot except by resetting the CPU.
   "RAMDisk Images" are more or less just data blocks, and their
	parameters (address, size) are passed to an OS kernel that is
	being started.
   "Multi-File Images" contain several images, typically an OS
	(Linux) kernel image and one or more data images like
	RAMDisks. This construct is useful for instance when you want
	to boot over the network using BOOTP etc., where the boot
	server provides just a single image file, but you want to get
	for instance an OS kernel and a RAMDisk image.

	"Multi-File Images" start with a list of image sizes, each
	image size (in bytes) specified by an "uint32_t" in network
	byte order. This list is terminated by an "(uint32_t)0".
	Immediately after the terminating 0 follow the images, one by
	one, all aligned on "uint32_t" boundaries (size rounded up to
	a multiple of 4 bytes).

   "Firmware Images" are binary images containing firmware (like
	U-Boot or FPGA images) which usually will be programmed to
	flash memory.

   "Script files" are command sequences that will be executed by
	U-Boot's command interpreter; this feature is especially
	useful when you configure U-Boot to use a real shell (hush)
	as command interpreter.

Booting the Linux zImage:
-------------------------

On some platforms, it's possible to boot Linux zImage. This is done
using the "bootz" command. The syntax of "bootz" command is the same
as the syntax of "bootm" command.

Note, defining the CONFIG_SUPPORT_RAW_INITRD allows user to supply
kernel with raw initrd images. The syntax is slightly different, the
address of the initrd must be augmented by it's size, in the following
format: "<initrd addres>:<initrd size>".


Standalone HOWTO:
=================

One of the features of U-Boot is that you can dynamically load and
run "standalone" applications, which can use some resources of
U-Boot like console I/O functions or interrupt services.

Two simple examples are included with the sources:

"Hello World" Demo:
-------------------

'examples/hello_world.c' contains a small "Hello World" Demo
application; it is automatically compiled when you build U-Boot.
It's configured to run at address 0x00040004, so you can play with it
like that:

	=> loads
	## Ready for S-Record download ...
	~>examples/hello_world.srec
	1 2 3 4 5 6 7 8 9 10 11 ...
	[file transfer complete]
	[connected]
	## Start Addr = 0x00040004

	=> go 40004 Hello World! This is a test.
	## Starting application at 0x00040004 ...
	Hello World
	argc = 7
	argv[0] = "40004"
	argv[1] = "Hello"
	argv[2] = "World!"
	argv[3] = "This"
	argv[4] = "is"
	argv[5] = "a"
	argv[6] = "test."
	argv[7] = "<NULL>"
	Hit any key to exit ...

	## Application terminated, rc = 0x0

Another example, which demonstrates how to register a CPM interrupt
handler with the U-Boot code, can be found in 'examples/timer.c'.
Here, a CPM timer is set up to generate an interrupt every second.
The interrupt service routine is trivial, just printing a '.'
character, but this is just a demo program. The application can be
controlled by the following keys:

	? - print current values og the CPM Timer registers
	b - enable interrupts and start timer
	e - stop timer and disable interrupts
	q - quit application

	=> loads
	## Ready for S-Record download ...
	~>examples/timer.srec
	1 2 3 4 5 6 7 8 9 10 11 ...
	[file transfer complete]
	[connected]
	## Start Addr = 0x00040004

	=> go 40004
	## Starting application at 0x00040004 ...
	TIMERS=0xfff00980
	Using timer 1
	  tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0

Hit 'b':
	[q, b, e, ?] Set interval 1000000 us
	Enabling timer
Hit '?':
	[q, b, e, ?] ........
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
Hit 'e':
	[q, b, e, ?] ...Stopping timer
Hit 'q':
	[q, b, e, ?] ## Application terminated, rc = 0x0


Implementation Internals:
=========================

The following is not intended to be a complete description of every
implementation detail. However, it should help to understand the
inner workings of U-Boot and make it easier to port it to custom
hardware.


Initial Stack, Global Data:
---------------------------

The implementation of U-Boot is complicated by the fact that U-Boot
starts running out of ROM (flash memory), usually without access to
system RAM (because the memory controller is not initialized yet).
This means that we don't have writable Data or BSS segments, and BSS
is not initialized as zero. To be able to get a C environment working
at all, we have to allocate at least a minimal stack. Implementation
options for this are defined and restricted by the CPU used: Some CPU
models provide on-chip memory (like the IMMR area on MPC8xx and
MPC826x processors), on others (parts of) the data cache can be
locked as (mis-) used as memory, etc.

	Chris Hallinan posted a good summary of these issues to the

	Subject: RE: [U-Boot-Users] RE: More On Memory Bank x (nothingness)?
	From: "Chris Hallinan" <clh@net1plus.com>
	Date: Mon, 10 Feb 2003 16:43:46 -0500 (22:43 MET)
	...

	Correct me if I'm wrong, folks, but the way I understand it
	is this: Using DCACHE as initial RAM for Stack, etc, does not
	require any physical RAM backing up the cache. The cleverness
	is that the cache is being used as a temporary supply of
	necessary storage before the SDRAM controller is setup. It's
	beyond the scope of this list to explain the details, but you
	can see how this works by studying the cache architecture and
	operation in the architecture and processor-specific manuals.

	OCM is On Chip Memory, which I believe the 405GP has 4K. It
	is another option for the system designer to use as an
	initial stack/RAM area prior to SDRAM being available. Either
	option should work for you. Using CS 4 should be fine if your
	board designers haven't used it for something that would
	cause you grief during the initial boot! It is frequently not
	used.

	CFG_SYS_INIT_RAM_ADDR should be somewhere that won't interfere
	with your processor/board/system design. The default value
	you will find in any recent u-boot distribution in
	walnut.h should work for you. I'd set it to a value larger
	than your SDRAM module. If you have a 64MB SDRAM module, set
	it above 400_0000. Just make sure your board has no resources
	that are supposed to respond to that address! That code in
	start.S has been around a while and should work as is when
	you get the config right.

	-Chris Hallinan
	DS4.COM, Inc.

It is essential to remember this, since it has some impact on the C
code for the initialization procedures:

* Initialized global data (data segment) is read-only. Do not attempt
  to write it.

* Do not use any uninitialized global data (or implicitly initialized
  as zero data - BSS segment) at all - this is undefined, initiali-
  zation is performed later (when relocating to RAM).

* Stack space is very limited. Avoid big data buffers or things like
  that.

Having only the stack as writable memory limits means we cannot use
normal global data to share information between the code. But it
turned out that the implementation of U-Boot can be greatly
simplified by making a global data structure (gd_t) available to all
functions. We could pass a pointer to this data as argument to _all_
functions, but this would bloat the code. Instead we use a feature of
the GCC compiler (Global Register Variables) to share the data: we
place a pointer (gd) to the global data into a register which we
reserve for this purpose.

When choosing a register for such a purpose we are restricted by the
relevant  (E)ABI  specifications for the current architecture, and by
GCC's implementation.

For PowerPC, the following registers have specific use:
	R1:	stack pointer
	R2:	reserved for system use
	R3-R4:	parameter passing and return values
	R5-R10: parameter passing
	R13:	small data area pointer
	R30:	GOT pointer
	R31:	frame pointer

	(U-Boot also uses R12 as internal GOT pointer. r12
	is a volatile register so r12 needs to be reset when
	going back and forth between asm and C)
    ==> U-Boot will use R2 to hold a pointer to the global data

    Note: on PPC, we could use a static initializer (since the
    address of the global data structure is known at compile time),
    but it turned out that reserving a register results in somewhat
    smaller code - although the code savings are not that big (on
    average for all boards 752 bytes for the whole U-Boot image,
    624 text + 127 data).

On ARM, the following registers are used:

	R0:	function argument word/integer result
	R1-R3:	function argument word
	R9:	platform specific
	R10:	stack limit (used only if stack checking is enabled)
	R11:	argument (frame) pointer
	R12:	temporary workspace
	R13:	stack pointer
	R14:	link register
	R15:	program counter

    ==> U-Boot will use R9 to hold a pointer to the global data

    Note: on ARM, only R_ARM_RELATIVE relocations are supported.
On Nios II, the ABI is documented here:
	https://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf

    ==> U-Boot will use gp to hold a pointer to the global data

    Note: on Nios II, we give "-G0" option to gcc and don't use gp
    to access small data sections, so gp is free.

On RISC-V, the following registers are used:

	x0: hard-wired zero (zero)
	x1: return address (ra)
	x2:	stack pointer (sp)
	x3:	global pointer (gp)
	x4:	thread pointer (tp)
	x5:	link register (t0)
	x8:	frame pointer (fp)
	x10-x11:	arguments/return values (a0-1)
	x12-x17:	arguments (a2-7)
	x28-31:	 temporaries (t3-6)
	pc:	program counter (pc)

    ==> U-Boot will use gp to hold a pointer to the global data

Memory Management:
------------------

U-Boot runs in system state and uses physical addresses, i.e. the
MMU is not used either for address mapping nor for memory protection.

The available memory is mapped to fixed addresses using the memory
controller. In this process, a contiguous block is formed for each
memory type (Flash, SDRAM, SRAM), even when it consists of several
physical memory banks.

U-Boot is installed in the first 128 kB of the first Flash bank (on
TQM8xxL modules this is the range 0x40000000 ... 0x4001FFFF). After
booting and sizing and initializing DRAM, the code relocates itself
to the upper end of DRAM. Immediately below the U-Boot code some
memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN
configuration setting]. Below that, a structure with global Board
Info data is placed, followed by the stack (growing downward).

Additionally, some exception handler code is copied to the low 8 kB
of DRAM (0x00000000 ... 0x00001FFF).

So a typical memory configuration with 16 MB of DRAM could look like
this:

	0x0000 0000	Exception Vector code
	      :
	0x0000 1FFF
	0x0000 2000	Free for Application Use
	      :
	      :

	      :
	      :
	0x00FB FF20	Monitor Stack (Growing downward)
	0x00FB FFAC	Board Info Data and permanent copy of global data
	0x00FC 0000	Malloc Arena
	      :
	0x00FD FFFF
	0x00FE 0000	RAM Copy of Monitor Code
	...		eventually: LCD or video framebuffer
	...		eventually: pRAM (Protected RAM - unchanged by reset)
	0x00FF FFFF	[End of RAM]


System Initialization:
----------------------
Wolfgang Denk's avatar
Wolfgang Denk committed

In the reset configuration, U-Boot starts at the reset entry point
(on most PowerPC systems at address 0x00000100). Because of the reset
configuration for CS0# this is a mirror of the on board Flash memory.
To be able to re-map memory U-Boot then jumps to its link address.
To be able to implement the initialization code in C, a (small!)
initial stack is set up in the internal Dual Ported RAM (in case CPUs
which provide such a feature like), or in a locked part of the data
cache. After that, U-Boot initializes the CPU core, the caches and
the SIU.

Next, all (potentially) available memory banks are mapped using a
preliminary mapping. For example, we put them on 512 MB boundaries
(multiples of 0x20000000: SDRAM on 0x00000000 and 0x20000000, Flash
on 0x40000000 and 0x60000000, SRAM on 0x80000000). Then UPM A is
programmed for SDRAM access. Using the temporary configuration, a
simple memory test is run that determines the size of the SDRAM
banks.

When there is more than one SDRAM bank, and the banks are of
different size, the largest is mapped first. For equal size, the first
bank (CS2#) is mapped first. The first mapping is always for address
0x00000000, with any additional banks following immediately to create
contiguous memory starting from 0.

Then, the monitor installs itself at the upper end of the SDRAM area
and allocates memory for use by malloc() and for the global Board
Info data; also, the exception vector code is copied to the low RAM
pages, and the final stack is set up.

Only after this relocation will you have a "normal" C environment;
until that you are restricted in several ways, mostly because you are
running from ROM, and because the code will have to be relocated to a
new address in RAM.


Contributing
============
The U-Boot projects depends on contributions from the user community.
If you want to participate, please, have a look at the 'General'
section of https://docs.u-boot.org/en/latest/develop/index.html
where we describe coding standards and the patch submission process.