背景
我正在通过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()缺失的驱动程序。
我检查了一些集体的其他东西:
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:
下面是所有内存和空间利用率的基本内存映射。如上所述,在注释中,我可以将内核,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影响的,这超出了我自己的范围,这是我自己的问题。
对于以后遇到此问题的任何人,下面列出了我上面特定问题的答案:
我无法弄清楚如何静态地执行此操作。就是说,我可以通过在in中添加printk()
s在运行时打印init函数的地址。然后可以将打印的地址与vmdlinux上objdump的输出进行比较(有关咒语,请参阅我的问题)。do_initcall_level
init/main.c
在这里可以找到有关initcall进程的非常有用且深入的描述。
请注意,您也可以打开initcall_debug
,这将打印每个功能名称。在我的情况下,我想要原始地址,这就是为什么我选择该printk()
方法。
其中大多数归结为您的.config。绝大多数的包含/排除是通过预处理器完成的。其他有用的项是设备的链接器脚本通用标头include/asm-generic/vmlinux.lds.h
和的平台链接器脚本arch/<arch>/*/*.lds
。
仍然不知道这一点。
不要惊慌
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句