uboot引导linux的实验笔记

按各地址起作用的顺序,uboot引导linux内核启动涉及到以下地址:

  1. load address:
  2. entry point: 这两个地址是mkimage时指定的
  3. bootm address:bootm为uboot的一个命令,以此从address启动kernel
  4. kernel运行地址:在具体mach目录中的Makefile.boot中指定,为kernel启动后实际运行的物理地址
mkimage -n 'linux-3.2.1' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage

理论上因为mkimage要为zImage加上0x40字节的header,所以entry point = load address + 0x40

但由于uboot 的bootm对uImage处理不是简单的go操作,其对前三个地址都有比较判断,所以在实际的操作中,就分为两种不同的情况:

1. bootm地址和load address一样

  此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行。因此此时的entry point必须设置为load address + 0x40。如果kernel boot过程没有到uncompressing the kernel,就可能是这里设置不对。

boom address == load address == entry point - 0x40

具体细节可参看uboot代码common/cmd_bootm.c中bootm_load_os函数的实现:

        switch (comp) {
        case IH_COMP_NONE:
                if (load == blob_start || load == image_start) {
                        printf("   XIP %s ... ", type_name);
                        no_overlap = 1;
                } else {
                        printf("   Loading %s ... ", type_name);
                        memmove_wd((void *)load, (void *)image_start,
                                        image_len, CHUNKSZ);
                }
                *load_end = load + image_len;
                puts("OK\n");
                break;

2. bootm地址和load address不一样(但需要避免出现memory move时出现覆盖导致zImage被破坏的情况)

  此种情况下,bootm会把uImage header后的zImage move到load address(见上方代码),然后go到entry point开始执行。 由此知道此时的load address必须等于entry point。

boom address != load address == entry point

因此,在mkimage以及设置uboot boot command的时候需要注意到以上两种情况。

至于kernel的运行地址,其与前3个地址没有关系,除了要避免内存覆盖导致解压后kernel不完整的情况。

zImage的头部有地址无关的自解压程序,因此刚开始执行的时候,zImage所在的内存地址(entry point)不需要同编译kernel的地址相同。自解压程序会把kernel解压到编译时指定的物理地址,然后开始地址相关代码的执行。在开启MMU之前,kernel都是直接使用物理地址(可参看System.map)。

以上转自:uboot load address、entry point、 bootm address以及kernel运行地址的意义及联系 - schips - 博客园 (cnblogs.com)


以下对不同LOADADDR做了个实验:

LOADADDR=0x8000内核可以正常启动

## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux-5.10.0-xilinx
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    4455712 Bytes = 4.2 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image
   Loading Device Tree to 2fff9000, end 2ffffcc1 ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
......

LOADADDR=0x30008000加载内核镜像没有问题,但是fdt_check_header时挂掉

## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux-5.10.0-xilinx
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    4455712 Bytes = 4.2 MiB
   Load Address: 30008000
   Entry Point:  30008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image
   Loading Device Tree to 2fff9000, end 2ffffcc1 ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 5.10.0-xilinx (lrp@ubuntu) (arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4, GNU ld (Linaro_Binutils-2017.01) 2.24.0.20141017 Linaro 2014_11-3-git) #6 SMP PREEMPT Wed Nov 22 14:14:58 CST 2023
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
-- 1 -- fdt[0xbfff9000]
magic[0xedfe0dd0]
OF: fdt: Machine model: Xilinx ZC706 board
OF: fdt: Ignoring memory range 0x0 - 0x30000000
printk: bootconsole [earlycon0] enabled
Memory policy: Data cache writealloc
cma: Reserved 16 MiB at 0x3f000000
Zone ranges:
  Normal   [mem 0x0000000030000000-0x000000003fffffff]
  HighMem  empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000030000000-0x000000003fffffff]
Initmem setup node 0 [mem 0x0000000030000000-0x000000003fffffff]
-- 1 -- fdt[0xbfff9000]
8<--- cut here ---
Unable to handle kernel paging request at virtual address bfff9000
pgd = (ptrval)
[bfff9000] *pgd=3eff1811, *pte=00000000, *ppte=00000000
Internal error: Oops - BUG: 7 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 0 PID: 0 Comm: swapper Not tainted 5.10.0-xilinx #6
Hardware name: Xilinx Zynq Platform
PC is at fdt_check_header+0x14/0x1b8
LR is at fdt_check_header+0x14/0x1b8
pc : [<c0344a3c>]    lr : [<c0344a3c>]    psr: 600000d3
sp : c0a01ee8  ip : fffffdff  fp : c0870c10
r10: c0a01f48  r9 : ceffff00  r8 : 00000000
r7 : bfff9000  r6 : c0a5a920  r5 : c0a0838c  r4 : bfff9000
r3 : 00000000  r2 : 00000000  r1 : 00000000  r0 : 00000017
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32  ISA ARM  Segment none
Control: 18c5387d  Table: 3000404a  DAC: 00000051
Process swapper (pid: 0, stack limit = 0x(ptrval))
Stack: (0xc0a01ee8 to 0xc0a02000)
1ee0:                   c09244dc c0a0838c c0a5a920 bfff9000 00000000 c059a8e8
1f00: c09244dc c0a0838c c0a3f1c0 c0a06f40 c0a01f50 ceffff00 c0a01f48 c0925588
1f20: 00000000 ffffffff c092fd3c c09041c8 00000000 c0a01f48 c0a01f4c 00000000
1f40: 00000000 c0a03cc8 30000000 40000000 ffffffff ffffffff c0a03cc8 c0a03cc0
1f60: 2fff9000 413fc090 18c5387d c0155f4c c0a01f94 00000000 00000000 c0900330
1f80: 00000051 c0a03cc8 c0a03cc0 2fff9000 413fc090 18c5387d 00000000 c090095c
1fa0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
1fc0: 00000000 c0932a38 00000000 00000000 00000000 c0900330 00000051 10c0387d
1fe0: 00000000 2fff9000 413fc090 18c5387d 00000000 00000000 00000000 00000000
[<c0344a3c>] (fdt_check_header) from [<c059a8e8>] (__unflatten_device_tree+0x1c/0xf8)
[<c059a8e8>] (__unflatten_device_tree) from [<c0925588>] (unflatten_device_tree+0x24/0x40)
[<c0925588>] (unflatten_device_tree) from [<c09041c8>] (setup_arch+0x7d0/0xa84)
[<c09041c8>] (setup_arch) from [<c090095c>] (start_kernel+0x50/0x56c)
[<c090095c>] (start_kernel) from [<00000000>] (0x0)
Code: e1a01000 e1a04000 e59f0198 eb0eb126 (e5941000)
random: get_random_bytes called from init_oops_id+0x20/0x40 with crng_init=0
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Attempted to kill the idle task!
---[ end Kernel panic - not syncing: Attempted to kill the idle task! ]---

LOADADDR=0x80008000加载内核镜像直接挂了

## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux-5.10.0-xilinx
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    4455712 Bytes = 4.2 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image

启动信息里有这么两行:(不确定有没有影响)

Zone ranges:
  Normal   [mem 0x0000000000000000-0x000000002fffffff]
  HighMem  [mem 0x0000000030000000-0x000000003fffffff]
ZONE_NORMAL标记了可直接映射到内存段的普通内存域. 这是在所有体系结构上保证会存在的唯一内存区域, 但无法保证该地址范围对应了实际的物理地址. 例如, 如果AMD64系统只有两2G内存, 那么所有的内存都属于ZONE_DMA32范围, 而ZONE_NORMAL则为空
ZONE_HIGHMEM标记了超出内核虚拟地址空间的物理内存段, 因此这段地址不能被内核直接映射

结论:对于1G内存,当LOADADDR在0-0x2FFFFFFF之间时,可以正常启动,大于0x30000000的内存会有问题。

  • 35
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值