Newer
Older
"initrd" images to be used are no longer part of one big Linux image;
instead, kernel and "initrd" are separate images. This implementation
serves several purposes:
- the same features can be used for other OS or standalone
applications (for instance: using compressed images to reduce the
Flash memory footprint)
- it becomes much easier to port new Linux kernel versions because
lots of low-level, hardware dependent stuff are done by U-Boot
- the same Linux kernel image can now be used with different "initrd"
images; of course this also means that different kernel images can
be run with the same "initrd". This makes testing easier (you don't
have to build a new "zImage.initrd" Linux image when you just
change a file in your "initrd"). Also, a field-upgrade of the
software is easier now.
Porting Linux to U-Boot based systems:
---------------------------------------
U-Boot cannot save you from doing all the necessary modifications to
configure the Linux device drivers for use with your target hardware
(no, we don't intend to provide a full virtual machine interface to
Linux :-).
But now you can ignore ALL boot loader code (in arch/powerpc/mbxboot).
Just make sure your machine specific header file (for instance
include/asm-ppc/tqm8xx.h) includes the same definition of the Board
Information structure as we define in include/asm-<arch>/u-boot.h,
and make sure that your definition of IMAP_ADDR uses the same value
as your U-Boot configuration in CONFIG_SYS_IMMR.
Note that U-Boot now has a driver model, a unified model for drivers.
If you are adding a new driver, plumb it into driver model. If there
is no uclass available, you are encouraged to create one. See
doc/driver-model.
Configuring the Linux kernel:
-----------------------------
No specific requirements for U-Boot. Make sure you have some root
device (initial ramdisk, NFS) for your target system.
Building a Linux Image:
-----------------------
With U-Boot, "normal" build targets like "zImage" or "bzImage" are
not used. If you use recent kernel source, a new build target
"uImage" will exist which automatically builds an image usable by
U-Boot. Most older kernels also have support for a "pImage" target,
which was introduced for our predecessor project PPCBoot and uses a
100% compatible format.
Example:
make TQM850L_defconfig
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
make oldconfig
make dep
make uImage
The "uImage" build target uses a special tool (in 'tools/mkimage') to
encapsulate a compressed Linux kernel image with header information,
CRC32 checksum etc. for use with U-Boot. This is what we are doing:
* build a standard "vmlinux" kernel image (in ELF binary format):
* convert the kernel into a raw binary image:
${CROSS_COMPILE}-objcopy -O binary \
-R .note -R .comment \
-S vmlinux linux.bin
* compress the binary image:
gzip -9 linux.bin
* package compressed binary image for U-Boot:
mkimage -A ppc -O linux -T kernel -C gzip \
-a 0 -e 0 -n "Linux Kernel Image" \
-d linux.bin.gz uImage
The "mkimage" tool can also be used to create ramdisk images for use
with U-Boot, either separated from the Linux kernel image, or
combined into one file. "mkimage" encapsulates the images with a 64
byte header containing information about target architecture,
operating system, image type, compression method, entry points, time
stamp, CRC32 checksums, etc.
"mkimage" can be called in two ways: to verify existing images and
print the header information, or to build new images.
In the first form (with "-l" option) mkimage lists the information
contained in the header of an existing U-Boot image; this includes
checksum verification:
tools/mkimage -l image
-l ==> list image header information
The second form (with "-d" option) is used to build a U-Boot image
from a "data file" which is used as image payload:
tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
-n name -d data_file image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
Right now, all Linux kernels for PowerPC systems use the same load
address (0x00000000), but the entry point address depends on the
kernel version:
- 2.2.x kernels have the entry point at 0x0000000C,
- 2.3.x and later kernels have the entry point at 0x00000000.
So a typical call to build a U-Boot image would read:
-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
> -A ppc -O linux -T kernel -C gzip -a 0 -e 0 \
> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz \
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
> examples/uImage.TQM850L
Image Name: 2.4.4 kernel for TQM850L
Created: Wed Jul 19 02:34:59 2000
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
Load Address: 0x00000000
Entry Point: 0x00000000
To verify the contents of the image (or check for corruption):
-> tools/mkimage -l examples/uImage.TQM850L
Image Name: 2.4.4 kernel for TQM850L
Created: Wed Jul 19 02:34:59 2000
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
Load Address: 0x00000000
Entry Point: 0x00000000
NOTE: for embedded systems where boot time is critical you can trade
speed for memory and install an UNCOMPRESSED image instead: this
needs more space in Flash, but boots much faster since it does not
need to be uncompressed:
-> gunzip /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz
-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
> -A ppc -O linux -T kernel -C none -a 0 -e 0 \
> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux \
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
> examples/uImage.TQM850L-uncompressed
Image Name: 2.4.4 kernel for TQM850L
Created: Wed Jul 19 02:34:59 2000
Image Type: PowerPC Linux Kernel Image (uncompressed)
Data Size: 792160 Bytes = 773.59 kB = 0.76 MB
Load Address: 0x00000000
Entry Point: 0x00000000
Similar you can build U-Boot images from a 'ramdisk.image.gz' file
when your kernel is intended to use an initial ramdisk:
-> tools/mkimage -n 'Simple Ramdisk Image' \
> -A ppc -O linux -T ramdisk -C gzip \
> -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
Image Name: Simple Ramdisk Image
Created: Wed Jan 12 14:01:50 2000
Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
Data Size: 566530 Bytes = 553.25 kB = 0.54 MB
Load Address: 0x00000000
Entry Point: 0x00000000
The "dumpimage" tool can be used to disassemble or list the contents of images
built by mkimage. See dumpimage's help output (-h) for details.
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
Installing a Linux Image:
-------------------------
To downloading a U-Boot image over the serial (console) interface,
you must convert the image to S-Record format:
objcopy -I binary -O srec examples/image examples/image.srec
The 'objcopy' does not understand the information in the U-Boot
image header, so the resulting S-Record file will be relative to
address 0x00000000. To load it to a given address, you need to
specify the target address as 'offset' parameter with the 'loads'
command.
Example: install the image to address 0x40100000 (which on the
TQM8xxL is in the first Flash bank):
=> erase 40100000 401FFFFF
.......... done
Erased 8 sectors
=> loads 40100000
## Ready for S-Record download ...
~>examples/image.srec
1 2 3 4 5 6 7 8 9 10 11 12 13 ...
...
15989 15990 15991 15992
[file transfer complete]
[connected]
## Start Addr = 0x00000000
You can check the success of the download using the 'iminfo' command;
this includes a checksum verification so you can be sure no data
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
corruption happened:
=> imi 40100000
## 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
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
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
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#
Matthew McClintock
committed
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
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
Matthew McClintock
committed
Load Address: 00000000
Matthew McClintock
committed
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]
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
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>".
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
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
Minicom warning:
================
Over time, many people have reported problems when trying to use the
"minicom" terminal emulation program for serial download. I (wd)
consider minicom to be broken, and recommend not to use it. Under
Unix, I recommend to use C-Kermit for general purpose use (and
especially for kermit binary protocol download ("loadb" command), and
use "cu" for S-Record download ("loads" command). See
https://www.denx.de/wiki/view/DULG/SystemSetup#Section_4.3.
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
Nevertheless, if you absolutely want to use it try adding this
configuration to your "File transfer protocols" section:
Name Program Name U/D FullScr IO-Red. Multi
X kermit /usr/bin/kermit -i -l %l -s Y U Y N N
Y kermit /usr/bin/kermit -i -l %l -r N D Y N N
NetBSD Notes:
=============
Starting at version 0.9.2, U-Boot supports NetBSD both as host
(build U-Boot) and target system (boots NetBSD/mpc8xx).
Building requires a cross environment; it is known to work on
NetBSD/i386 with the cross-powerpc-netbsd-1.3 package (you will also
need gmake since the Makefiles are not compatible with BSD make).
Note that the cross-powerpc package does not install include files;
attempting to build U-Boot will fail because <machine/ansi.h> is
missing. This file has to be installed and patched manually:
# cd /usr/pkg/cross/powerpc-netbsd/include
# mkdir powerpc
# ln -s powerpc machine
# cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h
# ${EDIT} powerpc/ansi.h ## must remove __va_list, _BSD_VA_LIST
Native builds *don't* work due to incompatibilities between native
and U-Boot include files.
Booting assumes that (the first part of) the image booted is a
stage-2 loader which in turn loads and then invokes the kernel
proper. Loader sources will eventually appear in the NetBSD source
tree (probably in sys/arc/mpc8xx/stand/u-boot_stage2/); in the
meantime, see ftp://ftp.denx.de/pub/u-boot/ppcboot_stage2.tar.gz
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
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
U-Boot mailing list:
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.
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
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
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:
----------------------
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.
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
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.
U-Boot Porting Guide:
----------------------
[Based on messages by Jerry Van Baren in the U-Boot-Users mailing
list, October 2002]
int main(int argc, char *argv[])
signal(SIGALRM, no_more_time);
alarm(PROJECT_DEADLINE - toSec (3 * WEEK));
if (available_money > available_manpower) {
Pay consultant to port U-Boot;
Download latest U-Boot source;
Subscribe to u-boot mailing list;
if (clueless)
email("Hi, I am new to U-Boot, how do I get started?");
while (learning) {
Read the README file in the top level directory;
Read https://www.denx.de/wiki/bin/view/DULG/Manual;
/* find . -name "*.[chS]" | xargs grep -i <keyword> */
if (available_money > toLocalCurrency ($2500))
Buy a BDI3000;
else
Add a lot of aggravation and time;
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
if (a similar board exists) { /* hopefully... */
cp -a board/<similar> board/<myboard>
cp include/configs/<similar>.h include/configs/<myboard>.h
} else {
Create your own board support subdirectory;
Create your own board include/configs/<myboard>.h file;
}
Edit new board/<myboard> files
Edit new include/configs/<myboard>.h
while (!accepted) {
while (!running) {
do {
Add / modify source code;
} until (compiles);
Debug;
if (clueless)
email("Hi, I am having problems...");
}
Send patch file to the U-Boot email list;
if (reasonable critiques)
Incorporate improvements from email list code review;
else
Defend code as written;
}
return 0;
}
void no_more_time (int sig)
{
hire_a_guru();
}
Coding Standards:
-----------------
All contributions to U-Boot should conform to the Linux kernel
coding style; see the kernel coding style guide at
https://www.kernel.org/doc/html/latest/process/coding-style.html, and the
script "scripts/Lindent" in your Linux kernel source directory.
Source files originating from a different project (for example the
MTD subsystem) are generally exempt from these guidelines and are not
reformatted to ease subsequent migration to newer versions of those
sources.
Please note that U-Boot is implemented in C (and to some small parts in
Assembler); no C++ is used, so please do not use C++ style comments (//)
in your code.
Please also stick to the following formatting rules:
- remove any trailing white space
- use TAB characters for indentation and vertical alignment, not spaces
- make sure NOT to use DOS '\r\n' line feeds
- do not add more than 2 consecutive empty lines to source files
- do not add trailing empty lines to source files
Submissions which do not conform to the standards may be returned
with a request to reformat the changes.
Submitting Patches:
-------------------
Since the number of patches for U-Boot is growing, we need to
establish some rules. Submissions which do not conform to these rules
may be rejected, even when they contain important and valuable stuff.
Please see https://www.denx.de/wiki/U-Boot/Patches for details.
Patches shall be sent to the u-boot mailing list <u-boot@lists.denx.de>;
see https://lists.denx.de/listinfo/u-boot
When you send a patch, please include the following information with
it:
* For bug fixes: a description of the bug and how your patch fixes
this bug. Please try to include a way of demonstrating that the
patch actually fixes something.
* For new features: a description of the feature and your
implementation.
* For major contributions, add a MAINTAINERS file with your
information and associated file and directory references.
* When you add support for a new board, don't forget to add a
maintainer e-mail address to the boards.cfg file, too.
* If your patch adds new configuration options, don't forget to
document these in the README file.
* The patch itself. If you are using git (which is *strongly*
recommended) you can easily generate the patch using the
"git format-patch". If you then use "git send-email" to send it to
the U-Boot mailing list, you will avoid most of the common problems
with some other mail clients.
If you cannot use git, use "diff -purN OLD NEW". If your version of
diff does not support these options, then get the latest version of
GNU diff.
The current directory when running this command shall be the parent
directory of the U-Boot source tree (i. e. please make sure that
your patch includes sufficient directory information for the
affected files).
We prefer patches as plain text. MIME attachments are discouraged,
and compressed attachments must not be used.
* If one logical set of modifications affects or creates several
files, all these changes shall be submitted in a SINGLE patch file.
* Changesets that contain different, unrelated modifications shall be
submitted as SEPARATE patches, one patch per changeset.
* Before sending the patch, run the buildman script on your patched
source tree and make sure that no errors or warnings are reported
for any of the boards.
* Keep your modifications to the necessary minimum: A patch
containing several unrelated changes or arbitrary reformats will be
returned with a request to re-formatting / split it.
* If you modify existing code, make sure that your new code does not
add to the memory footprint of the code ;-) Small is beautiful!
When adding new features, these should compile conditionally only
(using #ifdef), and the resulting code with the new feature
disabled must not need more memory than the old code without your
modification.
* Remember that there is a size limit of 100 kB per message on the
u-boot mailing list. Bigger patches will be moderated. If they are
reasonable and not too big, they will be acknowledged. But patches
bigger than the size limit should be avoided.