代码之家  ›  专栏  ›  技术社区  ›  Atilla Filiz

当ARM Linux无法解压缩时,我如何找到它的入口点?

  •  6
  • Atilla Filiz  · 技术社区  · 12 年前

    我正试图在带有I.MX6的自定义板上通过U-boot引导Linux(CPU核心是ARM Cortex A9)

    我们似乎已经成功移植了Das U-Boot(2009.08)。但在最后一条U-Boot消息中引导Linux失败:“正在启动内核…”

    以下是我的相关环境:

    bootargs=console=ttymxc1,115200 vmalloc=400M root=/dev/mmcblk0p1 rootwait consoleblank=0 earlyprintk video=mxcfb0:dev=lcd,LCD-ORTUS,if=RGB24 video=mxcfb1:dev=hdmi,1280x720M@60,if=RGB24 calibration tsdev=tsc2004 fbmem=10M,28M
    bootcmd=ext2load mmc 0:1 10800000 /boot/uImage ; bootm 10800000
    

    引导输出为

    Loading file "/boot/uImage" from mmc device 0:1 (xxa1)  
    4043552 bytes read  
    ## Booting kernel from Legacy Image at 10800000 ...  
       Image Name:   Linux-3.0.35  
       Image Type:   ARM Linux Kernel Image (uncompressed)  
       Data Size:    4043488 Bytes =  3.9 MB  
       Load Address: 10008000  
       Entry Point:  10008000  
       Verifying Checksum ... OK  
       Loading Kernel Image ... OK  
    OK  
    
    Starting kernel ...  
    

    当我objdump内核时,在地址80008000,我看到的入口点是arch/arm/kernel/head.S,而不是arch/arm/boot/compressed/head.S

    我看到的是,内核甚至没有解压。我尝试添加一些寄存器操作代码以在压缩/头.S中发送GPIO信号,但没有响应。

    我的问题是,如何确保U-Boot调用的入口点正确?

    完全相同的内核二进制文件使用相同的U-Boot命令在Freescale的参考板上成功引导。

    编辑:我为U-Boot添加了一些跟踪。就在调用内核之前,指针theKernel是10008000,而不是10800000。这是否意味着U型脚跳错了位置?

    3 回复  |  直到 12 年前
        1
  •  7
  •   sawdust    12 年前

    我们似乎已经成功移植了Das U-Boot。

    有证据表明这是一个错误的假设。

    就在调用内核之前,指针theKernel是10008000,而不是10800000。

    您正在使用哪个版本的U-Boot?
    在U-Boot的2012.10和2013.04版本中,变量 theKernel 仅由诸如AVR32和MIPS之类的拱门的代码声明和使用。
    没有应该使用的ARM代码 内核 .

    u-boot-2012.10$ find . -print | xargs grep theKernel
    ./arch/avr32/lib/bootm.c:   void    (*theKernel)(int magic, void *tagtable);
    ./arch/avr32/lib/bootm.c:   theKernel = (void *)images->ep;
    ./arch/avr32/lib/bootm.c:          theKernel, params_start);
    ./arch/avr32/lib/bootm.c:   theKernel(ATAG_MAGIC, params_start);
    ./arch/microblaze/lib/bootm.c:  void    (*theKernel) (char *, ulong, ulong);
    ./arch/microblaze/lib/bootm.c:  theKernel = (void (*)(char *, ulong,    ulong))images->ep;
    ./arch/microblaze/lib/bootm.c:      (ulong) theKernel, rd_data_start, (ulong) of_flat_tree);
    ./arch/microblaze/lib/bootm.c:  theKernel (commandline, rd_data_start, (ulong) of_flat_tree);
    ./arch/mips/lib/bootm.c:    void (*theKernel) (int, char **, char **, int *);
    ./arch/mips/lib/bootm.c:    theKernel = (void (*)(int, char **, char **, int *))images->ep;
    ./arch/mips/lib/bootm.c:        (ulong) theKernel);
    ./arch/mips/lib/bootm.c:    theKernel(linux_argc, linux_argv, linux_env, 0);
    ./arch/mips/lib/bootm_qemu_mips.c:  void (*theKernel) (int, char **, char **, int *);
    ./arch/mips/lib/bootm_qemu_mips.c:  theKernel = (void (*)(int, char **, char **, int *))images->ep;
    ./arch/mips/lib/bootm_qemu_mips.c:      (ulong) theKernel);
    ./arch/mips/lib/bootm_qemu_mips.c:  theKernel(0, NULL, NULL, 0);
    ./arch/nds32/lib/bootm.c:   void    (*theKernel)(int zero, int arch, uint params);
    ./arch/nds32/lib/bootm.c:   theKernel = (void (*)(int, int, uint))images->ep;
    ./arch/nds32/lib/bootm.c:          (ulong)theKernel);
    ./arch/nds32/lib/bootm.c:   theKernel(0, machid, bd->bi_boot_params);
    u-boot-2012.10$
    


    请解释如何跟踪不应在ARM处理器上定义或分配的变量。

    U-Boot打印“Starting kernel…”之后的下一个输出应该是“Uncompressing Linux…”。
    对于Freescale拱门,此文本输出取决于 machine type number (又名 arch_id )通过U-Boot到内核。
    您需要验证 机器型号 在U-Boot中正确定义。

    您的U-Boot配置文件是什么样子的?

    我尝试添加一些寄存器操作代码以在压缩/头.S中发送GPIO信号,但没有响应。

    您是否对该代码进行了健全性检查,以确保它如您所期望的那样工作?
    您是否尝试过从U-Boot命令行执行GPIO操作?

    我的问题是,如何确保U-Boot调用的入口点正确?

    对于ARM拱门,它是跳转到 战利品 命令
    由于uImage加载地址和 战利品 指定相同的0x10800000地址,这应该是好的(假设U-Boot是为ARM正确配置和构建的)。

    就在调用内核之前,指针theKernel是10008000,而不是10800000。这是否意味着U型脚跳错了位置?

    对。
    如果你检查源代码(用于AVR32或MIPS),你会发现 内核 是从图像标题(特别是入口点值)中指定的。U-Boot会跳到这个位置。
    但真正的问题是,你的ARM Cortex A9不应该使用这个代码或这个变量。

    似乎U-Boot没有配置为正确的拱形和/或机器类型可能没有正确定义。

    修正 :

    正如OP所指出的,U-Boot的旧版本确实使用了变量 内核 即使对于ARM拱也是如此。

    U-Boot输出行:

       Loading Kernel Image ... OK  
    

    指示U-Boot已(成功)从 bootm 地址0x10800000(加上标头长度的偏移量0x40)到加载地址0x10008000。此内存移动操作由以下程序执行 bootm_load_os() 在里面 公共/cmd_bootm.c .

    因此,您报告的0x10008000值对于 内核 .
    没有迹象表明U-Boot跳到了错误的位置。

    如前所述,您应该验证是否正确定义了机器类型。该值将用于 __arch_decomp_setup() 在里面 arch/arm/plat-mxc/include/mach/uncompress.h 从而可以在内核引导之前的解压缩期间输出文本。

        2
  •  4
  •   tangrs    12 年前

    您似乎没有启动vmlinux内核文件,因此不必担心入口点。图像开头的解压缩代码将根据需要重新定位内核,并在完成后跳转到正确的入口点。你只需要跳到图像的开头,uBoot似乎做得很正确。

    我会打开内核调试,尤其是早期的printk和低级别调试选项,然后再次尝试引导。至少你可以看到它在哪里。

    编辑:正如所指出的,我的答案只适用于uBoot一开始就正确的情况。在这种情况下,有可能不是这样。也许你可以创建并尝试引导一个伪“内核”,它只需打开一些LED或将一些寄存器值输出到串行(特别是r0、r1和r2)。那么你至少可以检查和/或排除uBoot是罪魁祸首。

        3
  •  0
  •   Community Mohan Dere    8 年前

    U-Boot加载的文件实际上是的二进制映像吗 vmlinux 文件,而不是自解压 zImage / bzImage ? 这只是猜测,我不是这方面的专家。

    我最近在Unix Stack Exchange上问的这个问题可能会引起您的兴趣: https://unix.stackexchange.com/questions/197225/is-vmlinuz-and-bzimage-really-the-same