Linux内核初始化中未调用内置平台驱动程序__initcall

神秘麋

背景

我正在通过Yocto提出一些供应商提供的嵌入式硬件的Linux内核。我已将映像配置为通过具有initramfs且没有rootfs的fitImage进行引导(存在持久存储,但这完全供用户空间应用程序使用)。考虑一下PXE实时图像,您就不会遥不可及。

一切进展顺利,直到我的initramfs图片超过了〜128MB。在此之下,一切都会按预期启动,并且所有驱动程序均无问题地绑定。在此标记之上,内核仍会引导,但许多驱动程序(虽然不是全部)没有绑定。这是非常令人困惑的,因为所有驱动程序都是静态内置在内核中的(此平台上未使用任何模块)。不幸的是,这些模块之一运行平台监视程序,这会导致完全可预测的重启。

到目前为止,我已经验证了所有符号都存在于vmlinux映像中:

$ objdump -x vmlinux | grep mtk_wdt
0000000000000000 l    df *ABS*  0000000000000000 mtk_wdt.c
ffffff800880ac40 l     F .text  000000000000004c mtk_wdt_stop
ffffff800880ac90 l     F .text  0000000000000040 mtk_wdt_shutdown
ffffff80091de778 l     F .init.text     0000000000000020 mtk_wdt_driver_init
ffffff800880acd0 l     F .text  000000000000004c mtk_wdt_ping
ffffff800880ad20 l     F .text  0000000000000070 mtk_wdt_set_timeout
ffffff800880ad90 l     F .text  0000000000000074 mtk_wdt_start
ffffff800880ae08 l     F .text  0000000000000144 mtk_wdt_resume
ffffff800880af50 l     F .text  0000000000000120 mtk_wdt_suspend
ffffff800880b070 l     F .text  0000000000000080 mtk_wdt_remove
ffffff80088977a8 l     F .text  0000000000000210 mtk_wdt_isr
ffffff80091fe0a0 l     F .exit.text     000000000000001c mtk_wdt_driver_exit
ffffff800880b4f0 l     F .text  0000000000000310 mtk_wdt_probe
ffffff8008c2acd8 l     O .rodata        0000000000000028 mtk_wdt_info
ffffff8008c2ad00 l     O .rodata        0000000000000050 mtk_wdt_ops
ffffff8008c2ad98 l     O .rodata        00000000000000b8 mtk_wdt_pm_ops
ffffff8008c2ae50 l     O .rodata        0000000000000190 mtk_wdt_dt_ids
ffffff80093a3cb8 l     O .data  00000000000000b0 mtk_wdt_driver
ffffff800a199368 l     O .bss   0000000000000008 mtk_wdt1
ffffff8009285598 l     O .init.data     0000000000000008 __initcall_mtk_wdt_driver_init6

另外,我在fitImage程序集之前,fitImage程序集之后和解压缩到系统内存后(通过引导加载程序)中都有二进制内核(例如linux.bin),initramfs和设备树的sha256校验和。全部匹配。据我所知,构建的是打开包装并启动的东西。

此外,我已经启用了,initcall_debug并且在看到其他__initcall()时,毫无疑问,缺少了非绑定驱动程序。

我知道设备存在于设备树中并已正确配置。启动后,在看门狗启动之前,我获得了大约5秒钟的控制台访问权限。只有足够的时间来执行一两个命令。在“有效”映像(initramfs <〜128MB)和失败映像(initramfs>〜128MB)上,/sys/bus/platform/devices它们的内容相同,并且可以看到我的看门狗(除其他外):

$ ls -lha /sys/bus/platform/devices
...
lrwxrwxrwx 1 root root 0 Jan  1 00:00 10007000.watchdog -> ../../../devices/platform/10007000.watchdog

执行相同的测试,但进行比较/sys/bus/platform/devices显示未__initcall()缺失的驱动程序。

我检查了一些集体的其他东西:

  • 设备树在工作图像和损坏图像中都使用了相同的DTB。我还如上所述验证了设备树在内存中。不使用设备树覆盖。
  • 实际内存加载偏移量一切都应该存在,并且每个区域都有足够的空间。我可以在内存中移动内核,无论位置在哪里,问题仍然存在。
  • 记性不好此故障在多个单元上相同地发生。
  • 压缩不良无论内核/ initramfs压缩如何,问题都会显现。目前,我正在测试所有未压缩的东西,以最大程度地减少破损点。
  • 错误的签名我已经禁用签名验证(毕竟适用于fitImage分区图像);那里也没有骰子。
  • 尝试将initramfs直接捆绑到内核中没变化。现在,我将initramfs内置到fitImage中,但否则将单独加载和验证。
  • 错误的内核命令行参数我正在使用root=/dev/ram initrd=0x48000000,384M并且一直跟踪到init/initramfs.c完成拆包的位置。我能够验证传递的偏移量确实在正确的虚拟内存空间中,总和为384M。
  • 根据论坛帖子更新内核链接程序脚本我能够.initramfs通过objdump看到vmlinux中生成部分,但是问题仍然存在。

鉴于以上所有内容,我唯一不知道如何验证的是从vmlinux到linux.bin的跳转。这是通过Yocto通过objcopy完成的,如下所示:

[ -n "${vmlinux_path}" ] && ${OBJCOPY} -O binary -R .note -R .comment -S "${vmlinux_path}" linux.bin

问题

  1. 如何验证给定的符号包含在最终的linux.bin中?
  2. 哪些机制会在构建时影响给定符号的包含或排除?
  3. initramfs大小会影响内核构建和运行时的哪些部分?
  4. 还有其他工具/技术/部落智慧可以帮助调试这种情况吗?

编辑1

下面是所有内存和空间利用率的基本内存映射。如上所述,在注释中,我可以将内核,DTB和initramfs重定位到(几乎)任意位置,但是问题仍然存在。

0x40000000 - 0x40001000 = Bootloader arg area (Fixed usage)
0x40080000 - 0x41EDFFFF = Kernel (~12MB / 29.5MB used)
0x41E00000 - 0x42FF5FFF = Trampoline (96 bytes / ~6MB used)
0x42FF6000 - 0x42FFFFFF = ATF BL3-1 (Fixed usage)
0x43000000 - 0x43FFFFFF = Trusted OS (~476K / 16M used)
0x44000000 - 0x44FFFFFF = DTB (~77.3K / 16M used)
0x45000000 - 0x47FFFFFF = Trusted OS memory (dynamic)
0x48000000 - 0x5FFFFFFF = Initramfs (~129MB / 384MB used)
0x60000000 - MEM END    = Free
神秘麋

因此,像大多数内核问题一样,真正的问题不在我想的地方。事实证明,此问题是由挂在内核中的init列表中较早的其他驱动程序之一引起的,从而阻止了看门狗驱动程序被注册。这是如何被initramfs影响的,这超出了我自己的范围,这是我自己的问题。

对于以后遇到此问题的任何人,下面列出了我上面特定问题的答案:

  1. 如何验证给定的符号包含在最终的linux.bin中?

我无法弄清楚如何静态地执行此操作。就是说,我可以通过在in中添加printk()s在运行时打印init函数的地址然后可以将打印的地址与vmdlinux上objdump的输出进行比较(有关咒语,请参阅我的问题)。do_initcall_levelinit/main.c

这里可以找到有关initcall进程的非常有用且深入的描述

请注意,您也可以打开initcall_debug,这将打印每个功能名称。在我的情况下,我想要原始地址,这就是为什么我选择该printk()方法。

  1. 哪些机制会在构建时影响给定符号的包含或排除?

其中大多数归结为您的.config。绝大多数的包含/排除是通过预处理器完成的。其他有用的项是设备的链接器脚本通用标头include/asm-generic/vmlinux.lds.h和的平台链接器脚本arch/<arch>/*/*.lds

  1. initramfs大小会影响内核构建和运行时的哪些部分?

仍然不知道这一点。

  1. 还有其他工具/技术/部落智慧可以帮助调试这种情况吗?

不要惊慌

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何获取在Linux内核启动期间已初始化/探测的所有模块/驱动程序的详细信息?

如何获得静态内置在Linux内核中的活动驱动程序的列表?

内核中内置了哪些设备驱动程序?

RethinkDB node.js驱动程序未正确初始化全局连接变量

无法初始化Chrome硒驱动程序

(502)错误的Gateway PhantomJS驱动程序初始化

为什么不能单独初始化struct成员字段?(在USB设备驱动程序中)

SimpleGA 或DifferentialEvolution 驱动程序中的设计变量是如何初始化的?

Linux内核:从驱动程序中删除输入处理程序

module init函数除了在linux设备驱动程序中进行打印外什么都不做,该驱动程序是否在设备树解析期间初始化?

Linux内核中的WS2812设备驱动程序

Linux内核中的USB鼠标使用哪些驱动程序?

ARM Linux内核驱动程序中的关键时序

如何将现有的内核驱动程序初始化为PCI内存映射?

在 Linux i2c 驱动程序中进行特定于芯片的初始化的正确功能是什么

linux内核驱动程序调试日志

如何阻止内核内置的驱动程序,即不是模块的驱动程序

在arc平台上的linux wifi驱动程序上未对齐的地址访问崩溃

Virtualbox 内核驱动程序错误:未安装内核驱动程序 (rc=-1908)

黄瓜Appium - 在何处存放鱼钩如果@Before初始化驱动程序

如何初始化驱动程序以避免NullPointerException错误

使用MongoDB的Java驱动程序无法初始化类com.mongodb.connection.MongoQueryAnalyzer

RAID驱动程序:无法初始化SCSI主机0

NVIDIA Docker - 初始化错误:nvml 错误:驱动程序未加载

Gremlin驱动程序在初始化带有多个端点的ConnectionPool时阻止

如何解决“无法初始化日志记录驱动程序”(ECS)

在每次使用C#/ Selenium进行测试之前,需要驱动程序进行初始化

扩展初始化驱动程序的 BaseClass 时出现 NullPointerException

Debian 11 蓝牙 sap 驱动程序初始化失败