【问题标题】:How do we Load Linux Image to appropiate location in Memory我们如何将 Linux 映像加载到内存中的适当位置
【发布时间】:2013-03-09 07:48:52
【问题描述】:

我们正在尝试将 linux 映像加载到特定位置的 DRAM 中,DRAM 结束地址是 0x80000000,我们从引导日志中得知“mem 设备结束地址是 0x80000000”。我们正在将我们的图像加载到地址“0x5000000”,并且在图像中的 variuos 部分被加载到某个大于“0x80000000”的地址之前,再次从引导日志中获取示例

 loading section to address 0xc5000000 from file position 0x1000, size is 0x5ac13e

上面行中“从文件位置 0x1000”是什么意思。

加载的第一个部分是 .text 部分,下面是我们的部分标题的 vmlinux 图像转储

[Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al

[ 0]                     NULL            00000000 000000 000000 00      0   0  0

 [ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096

 [ 2]      .notes           NOTE            c55ac140 5ad140 000168 00  AX  0   0  4

 [ 3]    __ex_table        PROGBITS        c55ac2b0 5ad2b0 000fe0 00   A  0   0  4

 [ 4]   .rodata           PROGBITS        c55ae000 5af000 20a930 00   A  0   0 64

 [ 5]   __bug_table       PROGBITS        c57b8930 7b9930 0075fc 00   A  0   0  1

 [ 6]   .pci_fixup        PROGBITS        c57bff2c 7c0f2c 001a90 00   A  0   0  4

 [ 7]    .builtin_fw       PROGBITS        c57c19bc 7c29bc 0000cc 00   A  0   0  4

这是一个相当大的列表,所以没有发布完整的。但是我们可以在这里看到一件事。文本部分大于 DRAM 结束地址,所以图像不应该被正确加载,尽管我们在第一次加载后没有收到任何错误部分它继续加载其他部分,但在此消息之后它挂起。

    program load complete, entry point: 0x5000000, size: 0x92e7fc

我的问题是如何将这些不同的部分地址与我们的 DRAM 地址对齐, 是否可以在这里使用 objcopy 实用程序来更改这些不同部分的地址。

有没有办法在编译前设置这些段地址?? 第二件事可能是这个 Hang afer 程序加载完成的原因。

【问题讨论】:

  • 赏金固然好,但不一定能为您提供解决方案,因为该问题的信息量不够大,而且我们看不到您的代码。你基本上是在要求人们在黑暗中拍摄。
  • 是的,Alexey 你已经很好地回答了我的问题,我认为对这个问题有更多的看法是个好主意。我不希望人们解决我的问题,因为那样我就不会学习自我,只是想有几个好主意
  • 好点,其实。
  • @AmitSinghTomar:看看我的回答,Linux 内核在不同位置具有入口点和部分(程序头)是完全正常的(查看您自己的 Linux 的 vmlinux 文件)。重点是物理寻址与虚拟寻址。

标签: linux linux-kernel bootloader bootstrapping


【解决方案1】:

检查你的 arch/arm/mach-xxx/Makefile.boot (你使用 arm board 对吗?)

  zreladdr-y        += 0x80008000
params_phys-y       := 0x80000100
initrd_phys-y       := 0x80800000

这是来自 Ti omap3 芯片。

我认为你会需要同样的

【讨论】:

  • 感谢@liyaoshi 的回复,但我们在 x86 板上
  • 对不起这个答案,我犯了一个错误。我以为 0x80000000 是你板子的起始地址。
【解决方案2】:

你使用什么加载器? “图像”的形式是什么? U-boot 镜像,raw 一,vmlinux ELF 文件?我猜最后一个是根据节等的存在来判断的。从 ELF 文件中,您应该加载的不是节,而是所谓的程序头。例如,这是 OpenRISC linux 内核程序头文件列表(使用 readelf -l 获得):

Elf file type is EXEC (Executable file)
Entry point 0xc0000000
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x002000 0xc0000000 0x00000000 0x231728 0x232000 RWE 0x2000
  LOAD           0x234000 0xc0232000 0x00232000 0x17c78c 0x18bfcc RWE 0x2000

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata __ksymtab __ksymtab_gpl __ksymtab_strings __param __modver 
   01     .data __ex_table .head.text .init.text .init.data .bss 

查看VirtAddrPhysAddr 之间的区别(由于通常的Linux 内核映射而删除了c)。当然,应该使用物理地址进行加载。

内核为符号、节等使用虚拟地址的原因是,在启动过程中,当您快速进入 MMU 初始化的那一刻,虚拟地址是唯一有效的。

最后,关于更改这些地址。事实上,正如 Alexey 所指出的,链接描述文件是关键。您可以在arch/(your arch)/kernel/vmlinux.lds.S 中找到这些内容。但关键是 IMO 不是你的问题,问题可能出在加载程序或其选项上。

【讨论】:

    【解决方案3】:

    from file position 0x1000 意思是它所说的。你有它在转储:

    [Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al
    ...
    [ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096
    

    这是文件中.text 部分的起始位置,偏移量为0x1000

    但是我们可以在这里看到的一件事 .text 部分大于 DRAM 结束地址

    不,它不是更大(至少不是在更大的意义上),它的编译期望它会被加载到地址0xc5000000在记忆中。

    所以图像不应该被正确加载,尽管我们在加载第一部分后没有收到任何错误,它会继续加载其他部分

    图像可以在任何地方加载,它只是用于加载目的的数据。

    OTOH,如果loading section to address 0xc5000000 的意思是它所说的那样,由于您的 RAM 以 0x7fffffff 结尾,因此文件将被加载到任何地方。

    但在此消息之后它挂起。

    这是意料之中的。机器代码很少与位置无关,因此如果您将其加载到与应该加载​​的位置不同的位置,它将无法工作。或者如果它甚至没有被加载,那么你要执行什么?垃圾。

    有没有办法在编译前设置这些段地址??

    根据系统的不同,您可能有以下两个选项之一或两者兼有:

    • 以这样一种方式设置页面转换,即从 0xc5000000 和向上映射到从 0x5000000 和向上的整个程序的物理地址的虚拟地址
    • 找到您的编译器正在使用的链接器脚本,并将初始段地址从 0xc5000000 更改为 0x5000000,google 一下,查看编译器/链接器文档

    另外,入口点位于0x5000000 有点奇怪。并不是说这一定是错误的,只是这种情况很少发生。我会确保start 标签(或_start 或其他任何东西)确实收到与.text 部分开头相同的地址。如果由于某种原因不是这种情况,则链接器脚本或编译器/链接器命令行选项或加载程序有问题。

    【讨论】:

    • 感谢@Alexey 的友好回复。我想与您分享一些我在问题中遗漏的东西,我们通过更改内核的 .config 文件来更改入口点 0x5000000,因为无法'不将映像加载到默认地址 0x1000000。第二件事是我们之前已经将基于 QNX 的内核映像加载并执行到相同的 DRAM,现在我们可以将相同的地址用于已用于 QNX 映像的部分和入口点地址Linux 内核映像和您提出的另一点是入口点是 .text 部分的一部分。
    • 这是now can we use same addresses for sections and entry point address which have been used for QNX image here in for Linux kernel image 的问题吗?我不太明白你的意思。
    • 嗨 Alesxey 正如您在更改页面偏移值后建议的那样,在 2 GB 范围内获得了部分地址,并且在程序加载完成后,消息我们的图像没有挂起,但我们遇到了其他问题,很快它说程序加载完成,CPU 正在重置,而不是控制 Linux 内核映像,想听听你关于这件事的一两个字。
    • 我不知道。但我建议你先让一个小程序工作,然后再回到整个操作系统,也许,做增量“检查点”(例如在每个专业之前和之后在屏幕上或串行端口上打印一些东西进入内核初始化代码)。如果可能的话,也可以在带有调试器的模拟器中尝试一下。
    猜你喜欢
    • 2018-10-30
    • 2014-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 2016-08-02
    相关资源
    最近更新 更多