【问题标题】:Boot loader arguments passed to the Linux kernel via argument registers (MIPS 24KEc)通过参数寄存器 (MIPS 24KEc) 传递给 Linux 内核的引导加载程序参数
【发布时间】:2020-07-13 17:21:48
【问题描述】:

我正在尝试在包含 MIPS 24KEc 处理器的交换机上使用 custom bootloader 启动压缩内核 (vmlinuz)。这个引导加载程序不是我编写的,它存在于产品的 NOR 闪存中,源代码由供应商在其 GPL 存档中提供。

引导加载程序从闪存中的固定位置读取一个标头,其中包含:

  1. 标题魔法 (SPIM)
  2. 内核加载地址
  3. 要加载的数据长度
  4. 内核入口地址

然后,它将标头后面的 num_bytes 复制到内核加载地址并跳转到指定的入口地址。引导命令行和 initrd 被编译到内核映像中(通过 CONFIG_CMDLINE 和 CONFIG_INITRAMFS_SOURCE)。

未压缩的内核映像 (vmlinux) 正常启动。当我尝试启动压缩内核时,我没有来自解压缩器或内核的任何输出。

我注意到Linux kernel saves the argument registers 在清除 BSS 并跳转到解压器之前(来自 arch/mips/boot/compressed/head.S):

start:
    /* Save boot rom start args */
    move    s0, a0
    move    s1, a1
    move    s2, a2
    move    s3, a3

我是 MIPS 程序集的新手,但我知道上述移动语句正在将参数寄存器保存到已保存的寄存器中。保存的寄存器在内核解压后、跳转到内核入口点之前恢复:

    move    a0, s0
    move    a1, s1
    move    a2, s2
    move    a3, s3
    PTR_LI  k0, KERNEL_ENTRY

看了u-boot源码,想知道this call in boot_jump_linux是否对应上面提到的“boot rom start args”:

kernel(linux_argc, (ulong)linux_argv, (ulong)linux_env,
            linux_extra);

我找不到任何内核文档来解释内核期望引导 rom 在寄存器 a0、a1、a2 和 a3 中传递给它的参数。

【问题讨论】:

  • 是的,这似乎是正确的。请注意,它们被存储到 fw_arg0..3 中,然后平台代码访问它们,例如argc = fw_arg0;
  • 可能值得在像 QEMU 这样的模拟器中尝试相同的引导加载程序 + 内核,看看它是否在那里工作。您可以连接到 QEMU 作为 GDB 远程和单步/设置断点,以查看应该如何工作。但是,模拟机器可能具有与路由器不同的硬件设备,因此在内核中测试早期启动 asm 调试打印指令可能很难确定它们是否应该在真实硬件上工作。
  • @PeterCordes 我已经尝试在 qemu 中加载引导加载程序/内核,但不幸的是,它们都没有将任何内容打印到串行。不过,我还没有尝试过 qemu+gdb。我想我总是可以修改马耳他机器定义,使其具有与交换机 ASIC 相同地址的 uart 端口。
  • 试图在没有调试器的情况下在 asm 中查找问题就像试图构建一个蒙着眼睛的机器人。许多小规模/局部问题在盯着源头时很容易错过,但当您可以单步执行并观察寄存器值的变化时就非常明显了。尤其是在大范围内,只有一条信息是“不起作用”,这使得缩小搜索范围变得困难。与找到您陷入的循环相比,或者发生的故障可能是巨大的。所以是的,IMO 值得付出巨大的努力,让调试器甚至间接使用成为可能,并获得在模拟机器上工作的东西
  • 在真正的硬件(未压缩内核)上工作的东西是否也可以在你的 QEMU 客户机中工作?如果是这样,那么您就有了一个众所周知的良好起点。

标签: assembly linux-kernel mips


【解决方案1】:

您平台的函数prom_init_cmdline 应该实现从fw_arg0 读取引导参数(argc) 的数量以及从fw_arg1 读取引导参数(argv)。如果此函数丢失或为空,您必须定义它以接收来自引导加载程序的引导参数。

没有输出的问题原来是供应商内核无法从引导加载程序中读取参数(没有prom_init_cmdline),并且依赖于通过CONFIG_CMDLINE 将引导参数编译到内核中。

我没有从内核输出的原因是我没有用CONFIG_CMDLINE编译内核,因此它没有输出到uart。我patched the vendor kernel 接受引导加载程序在寄存器a1 中传递的引导参数,并在uart 上得到输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 2021-01-01
    • 2019-01-16
    • 1970-01-01
    • 2014-10-15
    • 2021-02-28
    相关资源
    最近更新 更多