- Understanding Linux load address for U-Boot process
- Ivo Slanina
- People also ask
- 2 Answers
- Jagdish
- what’s the difference between ‘load mmc’ and ‘load addr’?
- 1 Answer 1
- Building kernel uImage using LOADADDR
- 2 Answers 2
- Understanding Linux load address for U-Boot process
- why is load address of kernel, ramdisk important in booting?
Understanding Linux load address for U-Boot process
I’m trying to understand embedded Linux principles and can’t figure out addresses at u-boot output.
For example, I have UDOO board based on i.MX6 quad processor and I got following output from U-Boot:
U-Boot 2013.10-rc3 (Jan 20 2014 - 13:33:34) CPU: Freescale i.MX6Q rev1.2 at 792 MHz Reset cause: POR Board: UDOO DRAM: 1 GiB MMC: FSL_SDHC: 0 No panel detected: default to LDB-WVGA Display: LDB-WVGA (800x480) In: serial Out: serial Err: serial Net: using phy at 6 FEC [PRIME] Warning: FEC MAC addresses don't match: Address in SROM is 00:c0:08:88:a5:e6 Address in environment is 00:c0:08:88:9c:ce Hit any key to stop autoboot: 0 Booting from mmc . 4788388 bytes read in 303 ms (15.1 MiB/s) ## Booting kernel from Legacy Image at 12000000 . Image Name: Linux-3.0.35 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4788324 Bytes = 4.6 MiB Load Address: 10008000 Entry Point: 10008000 Verifying Checksum . OK Loading Kernel Image . OK Starting kernel .
I don’t understand the value of Load address 0x10008000. According to documentation for this particular processor, at address zone 0x10000000 — 0xffffffff is mapped main memory. But what is 0x8000 offset? I can’t figure out reason for this value.
I also don’t understand address 0x12000000, where the kernel image is loaded from. Is there mapped memory region for SD card?
Please, can you give me some explanation for these addresses or even better, some references to resources about this topic. My goal is to learn how to port u-boot and Linux kernel to another boards.
asked Jan 25 ’15 00:01
Ivo Slanina
People also ask
The load command is used to read a file from a filesystem into memory. The number of transferred bytes is saved in the environment variable filesize. The load address is saved in the environment variable fileaddr. interface for accessing the block device (mmc, sata, scsi, usb, ….)
You can pass the u-boot parameters by command «setenv bootargs » from u-boot terminal. After boot the kernel you can read it by «cat /proc/cmdline». The official images for i. MX6/7 support device tree and bootargs in default for all new kernels.
U-Boot boots an operating system by reading the kernel and any other required data (e.g. device tree and ramdisk image) into memory, and then executing the kernel with the appropriate arguments. U-Boot’s commands are actually generalized commands which can be used to read or write any arbitrary data.
Load Address is RAM location where the kernel binary image is to be copied. Entry Point is the Location of the copied binary to be executed by uboot to boot kernel. Your RAM is mapped at 80000000 and kernel LOAD ADDRESS is 80008000.
2 Answers
If you check the environment variables of the u-boot, you will find that kernel image is copied from boot device to the RAM location(Here, 12000000 ) through command like fatload .
Now, This is not the LOADADDRESS . You give LOADADDRESS to command line while compiling the kernel, This address is mostly at 32K offset from start of the RAM in Physical address space of the processor.
Your RAM is mapped at 10000000 and kernel LOADADDRESS is 10008000 (32K offset). bootm command uncompress the kernel image from 12000000 to 10008000 address and then calls the kernel entry point .
Jagdish
check out include/configs folder. It contains all the board definitions
To port uboot to another port, base on a very similar board and modify from there.
what’s the difference between ‘load mmc’ and ‘load addr’?
And it stuck. what’s the difference between the 42000000 and the 70008000? Should the two be the same?
Do you really think answers to your questions are going to solve the real issue of «it stuck»? Why not provide the details of your board, the typical boot sequence, and what’s different that it is now failing? FWIW your uImage loaded at 0x42000000 seems to be unable to decompress (assuming that there’s a zImage within that uImage, which is typical for an ARM kernel).
1 Answer 1
Booting kernel from Legacy Image at 42000000 .
- This first address is the one where u-boot will look for the (probably compressed) linux kernel image.
Entry Point: 70008000 — linux kernel entry point address
- Once the linux image has been decompressed and copied to the load address location, the entry point is the address where to start executing the kernel image, that in this case is exactly the start of the memory area where the kernel has been copied.
You can find further detail @ below link:
This is what really confused me: the uImage is on the file system, why u-boot trying to find it on some where in the memory? 42000000 is a memory address, right?
«This first address is the one where u-boot will look for the (probably compressed) linux kernel image.» — U-Boot isn’t «looking» for anything. That output line «## Booting kernel from Legacy Image at 42000000 . « is the direct consequence of a bootm 0x42000000 command. In other words you (or the bootcmd environment variable) explicitly told U-Boot that it should boot the uImage at that specific memory address.
Building kernel uImage using LOADADDR
Can you please help to understand what is the use of this? Can I change the LOADADDR, is there any restriction on the length of the LOADADDR?
2 Answers 2
(I’m assuming that you’re using ARM based on the mention of U-Boot and the value of LOADADDR.)
Can you please help to understand what is the use of this?
LOADADDR specifies the address where the kernel image will be located by the linker. (This is true for a few architectures (e.g. Blackfin), but not for ARM.
LOADADDR specifies the address where the kernel image will be located by U-Boot and is stored in the U-Boot header by the mkimage utility. Typically the load address (for placement in memory) is also the start address (for execution). Note that the uImage file is typically just the (self-extracting, compressed) zImage file with the U-Boot wrapper.
Yes, but according to (Vincent Sanders’) Booting ARM Linux that would be contrary to ARM convention:
- Despite the ability to place zImage anywhere within memory, convention has it that it is loaded at the base of physical RAM plus an offset of 0x8000 (32K). This leaves space for the parameter block usually placed at offset 0x100, zero page exception vectors and page tables. This convention is very common.
(The uImage mentioned in your question is probably just a zImage with the U-Boot wrapper, so the quotation does apply.)
is there any restriction on the length of the LOADADDR?
The «length«? If you’re using a 32-bit processor, then the length of this address would be 32 bits.
arch/arm/boot/Makefile only uses LOADADDR for building the uImage from the zImage.
From (Russel King’s) Booting ARM Linux the constraints on this LOADADDR are:
The kernel should be placed in the first 128MiB of RAM. It is recommended that it is loaded above 32MiB in order to avoid the need to relocate prior to decompression, which will make the boot process slightly faster.
When booting a raw (non-zImage) kernel the constraints are tighter. In this case the kernel must be loaded at an offset into system equal to TEXT_OFFSET — PAGE_OFFSET.
The expected locations for the Device Tree or ATAGs or an initramfs can add more constraints on this LOADADDR.
Understanding Linux load address for U-Boot process
I’m trying to understand embedded Linux principles and can’t figure out addresses at u-boot output. For example, I have UDOO board based on i.MX6 quad processor and I got following output from U-Boot:
U-Boot 2013.10-rc3 (Jan 20 2014 - 13:33:34) CPU: Freescale i.MX6Q rev1.2 at 792 MHz Reset cause: POR Board: UDOO DRAM: 1 GiB MMC: FSL_SDHC: 0 No panel detected: default to LDB-WVGA Display: LDB-WVGA (800x480) In: serial Out: serial Err: serial Net: using phy at 6 FEC [PRIME] Warning: FEC MAC addresses don't match: Address in SROM is 00:c0:08:88:a5:e6 Address in environment is 00:c0:08:88:9c:ce Hit any key to stop autoboot: 0 Booting from mmc . 4788388 bytes read in 303 ms (15.1 MiB/s) ## Booting kernel from Legacy Image at 12000000 . Image Name: Linux-3.0.35 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4788324 Bytes = 4.6 MiB Load Address: 10008000 Entry Point: 10008000 Verifying Checksum . OK Loading Kernel Image . OK Starting kernel .
I don’t understand the value of Load address 0x10008000. According to documentation for this particular processor, at address zone 0x10000000 — 0xffffffff is mapped main memory. But what is 0x8000 offset? I can’t figure out reason for this value. I also don’t understand address 0x12000000, where the kernel image is loaded from. Is there mapped memory region for SD card? Please, can you give me some explanation for these addresses or even better, some references to resources about this topic. My goal is to learn how to port u-boot and Linux kernel to another boards. Thank you!
The kernel boot requirements are documented in Documentation/arm/Booting. I can’t remember offhand precisely why TEXT_OFFSET is a thing, but it is.
Typical is start of RAM + 0x8000 as ‘ATAGS’ are stored at the lowest address. Download the iMX6 reference manual from Freescale and all of the addresses will be in one of the first few chapters.
«I also don’t understand address 0x12000000, where the kernel image is loaded from.» — U-Boot uses the variable loadaddr to store this value. It’s a somewhat arbitrary value in upper memory, but still well below where U-Boot is executing. This address is where the kernel uImage or zImage file is temporarily stored in main memory when read from nonvolatile memory (e.g. NAND or SDcard) or loaded from the network. This loadaddr for the uImage or zImage must be different from the actual kernel’s «load address» of 0x10008000 to allow for decompression of the kernel image.
«Is there mapped memory region for SD card?» — No. There would be a command to read the SDcard (such as fatload mmc 0:1 0x12000000 uImage ), and its only output is its result of «4788388 bytes read in 303 ms (15.1 MiB/s)». You need to get the output of the printenv command to fully reveal & understand how autoboot works on your board. The salient environment variable is bootcmd.
@sawdust «of 0x10008000 to allow for decompression of the kernel image» not in this case since the image is uncompressed. The kernel will perform at least two things when u-boot transfers control to it. 1) uncompress itself if needed, and 2) relocate itself. In the case of the OP, when u-boot transfers control to the kernel, no uncompression is performed BUT the relocation is performed. The kernel relocates/copies itself to the start of RAM (HW address).
why is load address of kernel, ramdisk important in booting?
I am dealing with android boot.img which is a combination of compressed kernel, ramdisk, and dtb. I see from the serial console log from uboot about the booting process and here’s the part that triggers my curiosity
CPU: Freescale i.MX6Q rev1.2 at 792 MHz CPU: Temperature 27 C Reset cause: POR Board: MX6-SabreSD I2C: ready DRAM: 1 GiB PMIC: PFUZE100 MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2 No panel detected: default to Hannstar-XGA Display: Hannstar-XGA (1024x768) In: serial Out: serial Err: serial check_and_clean: reg 0, flag_set 0 Fastboot: Normal flash target is MMC:1 Net: FEC [PRIME] Normal Boot Hit any key to stop autoboot: 3 2 1 0 boota mmc1 kernel @ 14008000 (7272352) ramdisk @ 15000000 (869937) fdt @ 14f00000 (44072) ## Booting Android Image at 0x12000000 . Kernel load addr 0x14008000 size 7102 KiB Kernel command line: console=ttymxc0,115200 init=/init video=mxcfb0:dev=hdmi,1920x1080M@60,bpp=32 video=mxcfb1:off video=mxcfb:off video=mxcfb3:off vmalloc=256M androidboot.console=ttymxc0 consolebalank=0 androidboot.hardware=freescale cma=384M ## Flattened Device Tree blob at 14f00000 Booting using the fdt blob at 0x14f00000 Loading Kernel Image . OK Using Device Tree in place at 14f00000, end 14f0dc27 switch to ldo_bypass mode! Starting kernel .
The kernel’s address is 14008000, ramdisk 15000000, fdt 14f00000. I have found out that these values are saved in the boot.img header and when I manually mess with this values, the image will not boot even though the actual contents are not modified. Why is this address so critical? Why does it have to be these values? why not other values? One of my own guess is: these load address values are hardcoded inside the kernel so if I change it in the boot.img header it will cause side-effects. To elaborate my own theory, loading the kernel to the ‘modified’ load addr won’t be a problem. But when actually executing the lines, it will cause severe problems because these codes are fixed to work with the proper ‘load addr’. Is my theory wrong? If so, I’d be grateful if you could correct me.