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!
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.
check out include/configs folder. It contains all the board definitions
i.MX uboot include/configs
To port uboot to another port, base on a very similar board and modify from there.
Related
I'm trying to analyze and understand an embedded system that runs linux.
I'm pretty new to linux boot process, embedded linux etc, so I have to learn a lot but prefer learning by doing. So analyzing a system is the way I try to understand all this.
I already got some insight and learnt a lot in just looking at the bootmsg, checking some scripts and provided files (firmware) and trying to understand what's going on by just searching for answers here and elsewhere in the net. This might also be the reason for some wrong expressions I might use, I hope you can understand anyways. Atm I am not able to ask the creator of this system directly, so I hope you might help me out with some answers here.
So the System got a SOC (Marvell Armada-370 88F6707-A1) with some Flash (128 MiB - Hynix NAND (HY27U1G8F2BTR)) and DRAM (512 MB) and seems to load the bootload U-Boot from SPI flash (1MB).
As mentioned above as U-Boot is used as bootloader which then loads some Linux version 3.2.34. I think I already understand quite a bit of the general boot process here, but got some questions depending the provided bootargs.
Following is an excerpt of the printenv command (U-Boot environment)
image_name=uImage
mtdids=nand0=nand0
mtdparts=mtdparts=nand0:8m(kernel),6m(Initrd),-(rootfs)
select0=nand info
load0=nand read.e 0x02000000 0 360000
loadr0=nand read.e 0x04000000 800000 300000
boot=bootm 0x02000000 0x4000000
bootcmd=run beep select0 load0 loadr0 boot || run beep beep beep errled
bootargs=console=ttyS0,115200 root=ubi0:rootfs ubi.mtd=3,2048 initrd=0x12000000 rootfstype=ubifs
beep=beep
I see that they load the kernel and compressed ramdisk content into ram load0=nand read.e 0x02000000 0 360000 and loadr0=nand read.e 0x04000000 800000 300000. The kernel at start looks at 0x04000000 for the ramdisk_image and uncompresses to use the content for initial rootfs. Then the usual process with linuxrc / init begins... at the end the normal file system from nand (here rootfs partition of ubi device 0) is loaded as stated in kernel command line (root=ubi0:rootfs ubi.mtd=3,2048 rootfstype=ubifs). This is what I understood is happening here and might be pretty straight forward.
What I'm wondering now is the following bootargs part initrd=0x12000000. I don't quite get why they provide a different address here when we already let the kernel know about the real of the compressed ramdisk (as a second parameter of bootm).
I started the system with and without this parameter and it seems there are no differences.
As in my understanding of reading about that initrd= argument is that it seems to do the same as the second parameter that is already passed to bootm, it tells the kernel where to find an initrd to load the initial rootfs.
Could anyone explain why we here pass two different locations to an initrd to the kernel? Is this just some obsolete stuff that was forgotten to remove or is there a reason for?
Thanks in advance for your help.
I hope I haven't missed anything and the question wasn't already answered here somewhere, but I couldn't find anything.
edit-2:
Thanks to #sawdust in the comments I understood better what actually is going on here and saw the importance to add some more information to the question so an answer will be clearer to understand.
Here is a short excerpt of the bootmsg
> bootm 0x02000000 0x4000000
## Booting kernel from Legacy Image at 02000000 ...
Image Name: Linux-3.2.34
Created: 2013-08-15 4:18:54 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3464064 Bytes = 3.3 MB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 04000000 ...
Image Name:
Created: 2013-09-10 10:38:37 UTC
Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 3030739 Bytes = 2.9 MB
Load Address: 12000000
Entry Point: 12000000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
I also always missed some information in this part of bootm that might have already gave a hint on what's happening here. And might have in correlation to the presence of same address should have lead to the path of answer.
edit-1: Added some more information about the hardware
edit-2: Added bootmsg for more information
I am trying to run linux on an Arduino Yun board. The Arduino board contains an Atheros AR9331 chipset
On U-Boot These are the steps I am doing:
1- Download the kernel :
ar7240> tftp 0x80060000 openwrt-ar71xx-generic-uImage-lzma.bin;
Load address: 0x80060000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
######################
done
Bytes transferred = 1441863 (160047 hex)
2- Erase Flash in order to copy the kernel:
ar7240> erase 0x9fEa0000 +0x160047
Error: end address (0xa0000046) not in flash!
Bad address format
This is the problem It seems that 0x9fEa0000 +0x160047 exceeds the total size of the flash.
So my questions are:
1- How can I figure the total amount of memory reserved for the flash in Uboot (From wich address it starts and ends), I am thinking about changing 0x9fEa0000 by a fewer address but i'am afraid i can harm other things
This is the output of the help:
ar7240> help
? - alias for 'help'
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
cp - memory copy
erase - erase FLASH memory
help - print online help
md - memory display
mm - memory modify (auto-incrementing)
mtest - simple RAM test
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
progmac - Set ethernet MAC addresses
reset - Perform RESET of the CPU
run - run commands in an environment variable
setenv - set environment variables
tftpboot- boot image via network using TFTP protocol
version - print monitor version
2- Is there someone experienced with Atheros AR9331 chipset who can help me find the Flash mapping (From where it starts and ends) from the datasheet
You can determine the flash layout from the kernel boot command line. Either run the printenv command in u-boot or boot into the existing kernel and look through the boot log. You need to find something like the following:
(There are plenty of guides on the internet, I took this one from https://finninday.net/wiki/index.php/Arduino_yun, your board may or may not be the same).
linino> printenv
bootargs=console=ttyATH0,115200 board=linino-yun mem=64M rootfstype=squashfs,jffs2 noinitrd mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14656k(rootfs),1280k(kernel),64k(nvram),64k(art),15936k#0x50000(firmware)
bootcmd=bootm 0x9fea0000
This means there are the following partitions:
u-boot 0 to 256K (0x0 - 0x40000)
u-boot-env 256k to 320k (0x40000 - 0x50000)
rootfs (squashfs) 320k to 14976k (0x50000 - 0xea0000)
kernel 14976k to 16256k (0xea0000 - 0xfe0000)
nvram 16256k to 16320k (0xfe0000 - 0xff0000)
art 16320k to 16384k (0xff0000 - 0x1000000)
The rootfs partition is 14M, which is much larger than the rootfs image file (less than 8MB) so in theory you can move the kernel image at a lower address. For this you will need to modify the kernel boot line in the u-boot environment block (rootfs aand kernel partition sizes) and the bootcmd parameter so the u-boot know where the new kernel is located.
Flash is mapped to 0x9f000000 so the value in the bootcmd should be 0x9f000000 + the offset of the kernel in bytes.
What I am not sure about is if there is an overlay filesystem for any persistent changes to the flash. Can you boot into the existing system and post the output of df -h and cat /proc/mounts?
I have a couple of doubts about how the kernel is loaded into memory. Upon inspecting /proc/kallsyms I'm able to find the address of various symbols in the kernel.
$ cat /proc/kallsyms | head -n 10
00000000 t __vectors_start
80008240 T asm_do_IRQ
80008240 T _stext
80008240 T __exception_text_start
80008244 T do_undefinstr
80008408 T do_IPI
8000840c T do_DataAbort
800084a8 T do_PrefetchAbort
80008544 t gic_handle_irq
800085a0 T secondary_startup
Is there any way I can find the base address at which the kernel is loaded?
In userspace, suppose I use a libc with say the puts function at an offset of 0x200. When loaded into memory at say the address 0x8048000, I would be able to find the resolved puts at 0x8048000 + 0x200. Would the same hold for the kernel? i.e. is the kernel image loaded up into memory as 1 contiguous .text section?
for MIPS architecture
file Platform contain the field/variable "load-..." assigned with the location in physical address space.
example:
openwrt/build_dir/target-mips_mips32_musl-1.1.16/linux-brcm63xx_smp/linux-4.4.14/arch/mips/bcm63xx/Platform
#
# Broadcom BCM63XX boards
#
platform-$(CONFIG_BCM63XX) += bcm63xx/
cflags-$(CONFIG_BCM63XX) += \
-I$(srctree)/arch/mips/include/asm/mach-bcm63xx/
load-$(CONFIG_BCM63XX) := 0xffffffff80010000
for ARM architecture
file Makefile.boot contain the field/variable "zreladdr-y" assigned with the location in physical address space.
example:
openwrt/build_dir/target-mips_mips32_musl-1.1.16/linux-brcm63xx_smp/linux-4.4.14/arch/arm/mach-omap1/Makefile.boot
zreladdr-y += 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x10800000
for Microblaze architecture
file Makefile contain the field/variable "UIMAGE_LOADADDR" assigned with the location in physical address space (exported from Xilinx ISE).
example:
openwrt/build_dir/target-mips_mips32_musl-1.1.16/linux-brcm63xx_smp/linux-4.4.14/arch/microblaze/boot/Makefile
UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR)
Kernel is loaded at physical address of 1MiB which is mapped on PAGE_OFFSET + 0x00100000 (virtual address). usually 8MiB of virtual space is reserved for kernel image starting from PAGE_OFFSET + 0x00100000
As other answer states that Kernel base address is fixed for particular architecture. But due to many security issues kernel development community decided to make it random. It is called ASLR (Address Space Layout Randomization).
By reading your question (or because I am reading it in 2017), you may be trying to find offset used in ASLR (or KASLR for kernel).
KASLR offset = address of symbol loaded in memory - address of symbol present in binary.
As your question states you already know address of symbol in memory from /proc/kallsyms.
We can find address of symbol in binary using nm utility and vmlinux file.
nm vmlinux | grep do_IPI
This will print address of symbol do_IPI in vmlinux file. Subtracting these two address will provide you KASLR offset.
If you are using u-boot then at boot time bootloader usually print the kernel load address and entry point.
Erase Group Size: 512 Bytes
reading uImage
4670784 bytes read in 469 ms (9.5 MiB/s)
reading devicetree.dtb
20597 bytes read in 17 ms (1.2 MiB/s)
Booting Linux kernel with ramdisk and devicetree
## Booting kernel from Legacy Image at 02004000 ...
Image Name: Linux-4.9.0-xilinx
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4670720 Bytes = 4.5 MiB
Load Address: 10000000
Entry Point: 10000000
Verifying Checksum ... OK
## Flattened Device Tree blob at 04000000
Booting using the fdt blob at 0x4000000
Loading Kernel Image ... OK
Loading Device Tree to 1cb3d000, end 1cb45074 ... OK
Starting kernel ...
In the case of this ARM kernel the load address was at 0x80008000. Also, the kernel is loaded in a contiguous manner.
I am trying to read kernel image and calculate a checksum value of this image. Firstly, I used a smc instruction to trigger a exception, and in the exception handler, I tried to read the first bytes of the image. I don't really know what the address is, but from some documents, I know the kernel image is decompressed in address like 0x20008000, 0x30008000 or 0xC0008000(they call this ZRELADDR, i don't really know whether this is the right address...). So I tried to read the memory like this:
uint32_t test;
test = * (uint32_t *)0x30008000;
DMSG("test : %x\n",test);
But the system crashed with a data abort exception,
core data-abort at address 0x30008000
fsr 0x00000005 ttbr0 0x7df7006a ttbr1 0x7df7006a cidr 0x0
cpu #0 cpsr 0x200001b3
r0 0x00000090 r4 0x7df4bf51 r8 0x00000000 r12 0x00000000
r1 0x09010000 r5 0x806665e0 r9 0x00000000 sp 0x7df77f50
r2 0x0000000d r6 0x7f002000 r10 0x00000000 lr 0x7df273ff
r3 0x30008000 r7 0x7df77f60 r11 0x00000000 pc 0x7df052f0
ERR TEE-CORE:tee_pager_handle_fault:602: Unexpected page fault! Trap CPU
PANIC: tee_pager_handle_fault core/arch/arm/mm/tee_pager.c:603
I guess I am on the wrong way. Does anyone know how to read the kernel image in runtime environment?
Thanks for your help!
EDIT:Thanks for your reply. I am talking about secure kernel. I am trying to check the integrity of the kernel under TrustZone, and to insure the kernel haven't be compromised. So I guess a checksum like hash value may help me. Also, I am a novice who is trying to be familiar with the memory system of arm, so I tried to start with simple read some certain memory address. I have tried to read 0xc0000000 as Artless Noise said, but the same error occurs again. Again I tried to find "_test" and "stext" address in System.map, which is 0x80008000, and error occurs again.
The beginning of the RAM is usually mapped at 0xC0000000. This depends on CONFIG_PAGE_OFFSET:
- VMSPLIT_3G: 0xC0000000
- VMSPLIT_2G: 0x80000000
- VMSPLIT_1G: 0x40000000
Note that this is a virtual address if you have an MMU (usual case), the physical address will depend on your actual architecture (it may or may not be 0x00000000). The kernel is loaded a few pages after that, at an offset of 0x8000.
So, you can probably find the (uncompressed) kernel at 0xC0008000 but it may as well be located somewhere else.
You can also try to ioremap() offset 0x8000 of your RAM.
Can you give us a bit more information on the particular SoC you are working on?
If you are in secure mode and you believe that in secure mode it access physical address then from below these macro you can deduce the physical address.
The physical address at which kernel loads is PHYS_OFFSET + TEXT_OFFSET (text offset is 0x8000),
PHYS_OFFSET definition will be depend on the CONFIG_ARM_PATCH_PHYS_VIRT patch.
if CONFIG_ARM_PATCH_PHYS_VIRT is defined, then PHYS_OFFSET will be equal to __pv_phys_offset otherwise PHYS_OFFSET will be defined as CONFIG_PHYS_OFFSET in your kernel config file.
I am trying to get an original BeagleBoard (revC4) to boot a Angstrom OpenEmbedded image. Using instructions found here:
http://elinux.org/BeagleBoardAndOpenEmbeddedGit
and:
http://www.angstrom-distribution.org/building-angstrom
I have followed everything but the program freeze with message booting the kernel.
Output:
Texas Instruments X-Loader 1.4.2 (Feb 19 2009 - 12:01:24)
Reading boot sector
Loading u-boot.bin from mmc
U-Boot 2009.11 (Feb 23 2010 - 15:33:48)
OMAP3530-GP ES3.1, CPU-OPP2 L3-165MHz
OMAP3 Beagle board + LPDDR/NAND
I2C: ready
DRAM: 256 MB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Board revision C4
Die ID #40a8000400000000040365fa1301c014
Hit any key to stop autoboot: 0
mmc1 is available
reading boot.scr
** Unable to read "boot.scr" from mmc 0:1 **
reading uImage
4335440 bytes read
Booting from mmc ...
Booting kernel from Legacy Image at 82000000 ...
Image Name: Linux-3.2.28
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4335376 Bytes = 4.1 MB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
I have tried both ttyS2 and ttyO2 in the bootargs without difference and have also upgraded both the xLoader and uBoot.
My end goal is to run a rudimentary ROS (Robot Operating System) and the BeagleBoard.
Any help would truly be appreciated.
I don't know if you ever got past this, but as I have recently been trying to get a Beagleboard up and running again, I'll put an answer here for the sake of anyone else trying to get things working.
TLDR version: Use Angstrom v2013.6 and hold the user button as you boot (or zero out the NAND flash) for the easiest solution that just works. See below for more details.
First of all, the place you're stuck at here is due to the u-boot flashed into NAND being out-of-date for a recent version of Angstrom. Simple fix is to hold down the user button when booting, which will bypass NAND and boot straight from the SD card, which presumably has the version of u-boot you just built. You can then stop the boot and either zero out the NAND or flash the current MLO and u-boot into it.
After that, you'll run into some more issues if you're using an image based on systemd. The meta-ti layer controls the basic parameters for the 'beagleboard' configuration and has its virtual/kernel provider set to linux-mainline, which is also in the meta-ti layer. At some point there was a new recipe version added for it which builds a 3.14 kernel, but the kernel configuration isn't suitable for systemd and the system will hang shortly after booting.
The good news is that Angstrom v2013.06 predates the 3.14 kernel change in meta-ti, and I was able to get that running just fine. I am trying to get a more recent Angstrom working with the 3.2 kernel that works with v2013.6, but I haven't had any luck yet.