从二进制/十六进制转储中找出 U-Boot 环境位置的过程

从二进制/十六进制转储中找出 U-Boot 环境位置的过程

长话短说:

我有一个启用了 u-boot(版本 1.6.1)的板,我已使用 dd 将包含环境变量的分区转储到二进制文件,现在很难找到如何将找到的 ascii 值的位置转换为 OFFSET和 fw_env.config 的 SIZE 参数。 (任何其他查找和尝试数字的方法也都失败了)。

我希望在这里找到已经在任何类型的系统上完成此操作的人,他可以告诉我要添加或减去或移动什么,因为第一个 ascii 参数地址的简单复制粘贴不起作用。

完整历史(在 TLDR 上扩展的最相关信息;在“最相关”标题之后,长序言是“先前努力的证明”和完整性):


我面临着一个艰巨的问题,经过整个周末的搜索和尝试,我还没有找到解决方案。

我“继承”了一个基于三星ARM的Linux嵌入式系统,它运行U-boot-1.6.1的修改版本。我已经接受了修复一些错误的任务,其中一个错误要求我将环境变量更新为u-boot。

有问题的系统是 EmbedSky 板,具体来说是 TQ2440,这没有什么帮助,因为它不是一种非常知名的类型,在我看来来自中国/香港。

我已经成功编译了fw_printenv/fw_setenv使用像这样的指南并获得了已使用的 u-boot 的源文件。

具体来说,为了将来的参考,经过一番摸索和刺激,从基于 PC 的构建环境中对该工具的完整调用,结果是(在 u-boot 根文件夹内):
make env ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- HOSTCC=arm-none-linux-gnueabi-gcc
最后一个令牌似乎是一个错误,或者至少在 2012 年仍然存在一些争议,但它是必需的,因为 makefile 是为 env 工具的 HOSTCC 进行编译的。我不知道 2014/2015 版本中是否仍然如此,因为修改 EmbedSky 2015 版本的尝试发生了非常非常错误(各种缺失的东西),所以我放弃了。

现在,我的问题是,在 EmbedSky.h 中出现以下定义(没有找到任何 CONFIG_,只有 CFG_):

#define CFG_ENV_SIZE    0x020000
#define CFG_ENV_OFFSET  0x1F0000

虽然 /proc/mtd 显示 mtd0 名为“uboot”,mtd1 名为“kernel”,mtd2 名为“root”,但不存在其他 mtd 扇区。
其中带有“uboot”的 mtd0 很0x40000长,块大小为0x20000,擦除大小为 ,0x20000因此不适合0x1F0000偏移量。

确实匹配的一件事是 mtd0“uboot”设备位于 NAND 闪存中,并且 EmbedSky.h 文件中的所有配置参数均适用于 NAND 闪存。

当然,作为一个顽固的小工人我尝试设置我的 fw_env.config 文件所有三个 mtd 分区上已知数字的每个组合。在任何带有偏移量的组合上调用 fw_printenv0x1F0000都会产生诸如“无效指令”之类的错误,而我在下面尝试的任何内容都只会给出“CRC 错误:使用默认环境”。
(我确实注意到上面的链接仍然包含 HOSTCC= 指令:-))

这里的每个组合都意味着:OFFSET=0x00000;偏移量=0x1F0000;中途偏移,向内偏移1个0x20000大小的扇区,向内偏移2个扇区,大小分别为0x01000、0x02000; 0x04000; 0x04200; 0x10000 和 0x20000 并跨越 1、2 或 3 个扇区。所以不是真的每一个,但特别是对于大小,这些是我在我找到的教程以及头文件中遇到的所有数字。

此时,我认为我拥有的资源可能实际上并不是董事会中的内容,因为这符合项目的其余部分。所以我寻找其他方法。

今晚凌晨 3 点左右,我确实看到了一篇博客文章,其中谈到“转储包含 u-boot env 的 mtd”,然后通过查看 Primary 和冗余块”。我刚刚重新搜索了谷歌,因为在我混乱的午夜状态下,我在添加书签之前关闭了页面,但我似乎无法重新找到该博客。

最相关的:

因此,我满怀希望地跑去sudo dd if=/dev/mtd0 of=/home/ActiveMtd0.bin bs=128k count=2将信息放入我的 /proc/mtd 列表中。结果:复制了 256kbyte。

这给了我一个二进制文件,你瞧,它包含纯 ascii 格式的 u-boot 环境变量。欢呼!但是,唉,这整个“显而易见”似乎让我失望了。首先,这个转储只包含一个块,而不是冗余块,所以这个技巧就消失了。其次,看起来块的起始位置0x367F8(可能是 CRC 的 4 个字节,后跟第一个 ascii 参数)在我想象的任何体系结构中都远离方便的单元边界。它以零填充运行超过 488 个字节,env 后面的第一个非零字节位于 处0x369B8,这也不是一个好地方。两个点都与 8 字节对齐,因此至少是这样。这是否相关,我只能猜测。

乐观地我确实在配置文件中尝试了 OFFSET = 0x367F8on mtd0 ,大小为0x01C0(= 488 十进制),但这也给出了无效指令,可能是因为块大小,超出了 mtd0 的边界,或者类似的原因,但是这比我对内部 u-boot fw_printenv 过程的了解要详细得多。然后我还尝试了 OFFSET =0x367FC和 SIZE =0x01BC将其设置在第一个变量的第一个字符处,跳过我认为可能是 CRC 的内容,但这也失败了。需要注意的是,env 中的 ascii 值远小于 488 字节,大约后半部分是 0 填充,不知道这是否与该过程相关。

我现在完全被难住了。

有谁可以告诉我二进制 mtd0 转储中的一般“从中减去 12 个字节”或“从这一点除以 4”吗?我非常喜欢使用 fw_printenv 和 fw_setenv,因为它需要对现场数百个设备进行自动化,这比直接从脚本文件干预 NAND 闪存更安全。

即使它是“你尝试过的地址之一应该是正确的”,因为现在我只觉得我在黑暗中用看似随机的数字进行拍摄,尽管其中大多数背后都有一些原因。

相关内容