U-boot Script Bad Header CRC

Posted

技术标签:

【中文标题】U-boot Script Bad Header CRC【英文标题】: 【发布时间】:2021-11-09 03:17:03 【问题描述】:

我有一个“闪烁”脚本正在通过 sdp 从主机 PC 加载到 iMX6 上的 Uboot 中。该脚本已通过mkimage 运行,因此它具有图像标题。这是 mkimage 命令:

mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "U-Boot script" -d $files_dir$flash_txt $files_dir$flash_scr

我可以用binwalk解析标题:

$ binwalk -B flash.scr

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x315E128A, created: 2021-09-13 14:52:46, image size: 2406 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x7B909BAE, OS: Linux, CPU: ARM, image type: Script file, compression type: none, image name: "U-Boot script"

执行失败,uboot 提示“Bad Header CRC”。所以,我试图通过使用内置的 crc32 工具当场纠正 CRC,至少在设备上强制它工作。还是不行。

这是我正在尝试的 uboot 命令(在脚本已经在内存中的地址 0x10100000 之后):

# display the script bytes
md 0x10100000

# reset the crc
mw 0x10100004 0x0 1

# verify the change
md 0x10100000

# recalc the crc
crc32 0x10100000 64

# write the crc
#mw 0x10100004 <VALUE> 1

# example:
mw 0x10100004 0x3a833d99 1

# run the script
source 0x10100000

当我这样做时,我仍然收到可怕的“Bad Header CRC”错误!

我找到了许多来源,它们揭示/指示哪些字节包含“标头 CRC”。我看到多个消息来源说需要在尝试计算校验和之前“重置”校验和。这一切看起来都是有效的逻辑。我做错了什么?


更新

正确的uboot输入/结果

根据锯末的帮助

...
Bad header crc
CTRL+C - Operation aborted.
SDP ended
uboot# md 0x10100000
10100000: 56190527 229a2e76 f4f64161 66090000    '..Vv.."aA.....f
10100010: 00000000 00000000 0533a380 00060205    ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074    U-Boot script...
10100030: 00000000 00000000 00000000 00000000    ................
10100040: 5e090000 00000000 20766e65 61666564    ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574    ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865     size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41    ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f    tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239    hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f    .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337    e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65    0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074    ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f    E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f    _a_label "rootfs
uboot# mw 0x10100004 0x0 1
uboot# crc32 0x10100000 0x40 0x10100004
crc32 for 10100000 ... 1010003f ==> 94926f83
uboot# md 0x10100000                   
10100000: 56190527 836f9294 f4f64161 66090000    '..V..o.aA.....f
10100010: 00000000 00000000 0533a380 00060205    ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074    U-Boot script...
10100030: 00000000 00000000 00000000 00000000    ................
10100040: 5e090000 00000000 20766e65 61666564    ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574    ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865     size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41    ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f    tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239    hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f    .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337    e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65    0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074    ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f    E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f    _a_label "rootfs
uboot# source 0x10100000    
## Executing script at 10100000

... SUCCESS!!!!!

预上传 PC 补丁

运行 mkimage 后,我以这种方式修复了 CRC。我敢肯定,这可以用一种更优雅的方式编写——但至少证明它是有效的:

# The mkimage "header CRC" is invalid for some reason, so it needs to be corrected!

$files_dir=files/
$flash_scr=flash.scr
$flash_hdr=flash.hdr

chmod 644 $files_dir$flash_scr

# zero the current crc, and copy the 64 byte header to a separate file
printf '\x00\x00\x00\x00' | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc
head -c 64 $files_dir$flash_scr > $files_dir$flash_hdr

# calculate the correct crc
crc=$(crc32 $files_dir$flash_hdr)
b1=$(echo $crc | cut -c 1,2)
b2=$(echo $crc | cut -c 3,4)
b3=$(echo $crc | cut -c 5,6)
b4=$(echo $crc | cut -c 7,8)

# update the script, with the correct value
printf "\x$b1\x$b2\x$b3\x$b4" | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc

# clean up 
rm $files_dir$flash_hdr

mkimage 的根本缺陷

理想情况下,mkimage 会首先正确地完成它的工作。为什么它出现故障仍然是一个谜......

【问题讨论】:

阅读 U-Boot 手册以正确使用 mkimage 脚本(例如,没有操作系统规范)。使用imi 命令在加载到内存后(以及执行前)验证图像。 "When I do this ..." -- 显示实际的对话框,而不仅仅是你的总结。 【参考方案1】:

我做错了什么?

U-Boot 几乎总是假定命令参数为十六进制值,因此使用 0x... 前缀实际上是多余的。 AFAIK 无法输入十进制值。

# recalc the crc
crc32 0x10100000 64

因此,当您将 crc32 命令中的标头长度指定为 64 时,您指定了错误的(标头)长度 0x64 或十进制 100。 查看 U-Boot 命令响应确认您的错误:

=> crc32 0x10100000 64                                                          
CRC32 for 10100000 ... 10100063 ==> 9988c6ca

从 0x10100000 到 0x10100063 的地址范围是 100 个字节的跨度。


附录(有修订)

当您安装计算值时,您可能会引入字节序(字节顺序)问题。

# write the crc
#mw 0x10100004 <VALUE> 1

计算出的 CRC32 值可能需要在 mw 命令中以反向字节顺序(假设 i.MX6 为 little-endian 模式)指定。


例如,mkimage 命令在第二个单词中安装一个原始标头 CRC32 值 d8bc0e3a 3a0ebcd8(按小端顺序):

=> md 20000000                                                                  
20000000: 56190527 3a0ebcd8 a0284161 1f000000    '..V...:aA(.....               
20000010: ...

=> imi 20000000                                                                 
                                                                                
## Checking Image at 20000000 ...                                               
   Legacy image found                                                           
   Image Name:   U-Boot script                                                  
   Image Type:   PowerPC Linux Script (uncompressed)                            
   Data Size:    ...                                            

在将第二个字归零后,CRC32 命令产生(相同的)值(如预期的那样)(但作为 4 字节字符串而不是整数):

=> crc32 20000000 40                                                            
crc32 for 20000000 ... 2000003f ==> d8bc0e3a                                    

如果您使用mw 命令按字面意思安装此值,则字节顺序不是 32 位字值所要求的。

=> mw 20000004 d8bc0e3a                                                         
=> md 20000000                                                                  
20000000: 56190527 d8bc0e3a a0284161 1f000000    '..V:...aA(.....               
20000010: ...

=> imi 20000000                                                                 
                                                                        
## Checking Image at 20000000 ...                                               
   Legacy image found                                                           
   Bad Header Checksum                                                          
=> 

mw 命令将要写入的值视为 byte string 而不是整数值 整数值,因此 不执行字节重新排序(即使这是little-endian CPU) 需要对 CRC32 值进行字节重新排序。


附录 2

对以上关于 U-Boot 命令在 little-endian 模式下显示结果的轻微修正。

md 命令正在显示字值,假设存储的值是小端模式。 要查看内存中的真实字节顺序,请使用md.b 命令。

=> md 20000000 4                                                                
20000000: 56190527 3a0ebcd8 a0284161 1f000000    '..V...:aA(.....               

=> md.b 20000000 10                                                             
20000000: 27 05 19 56 d8 bc 0e 3a 61 41 28 a0 00 00 00 1f    '..V...:aA(.....   
=>

因此,mkimage 命令会在第二个字(以小端顺序)中安装原始标头 CRC32 值 3a0ebcd8

CRC32 命令将 4 字节值生成为字节字符串(即已经按 little-endian 顺序)。

mw 命令知道这是一个 little-endian CPU,并且确实将要写入的值视为整数值。 由于 CRC32 结果是 byte string(而不是整数值),因此必须使用 mw 命令对这些字节重新排序以便输入。 明白了吗?


避免这种字节序混淆的一种可能方法是使用 CRC32 命令的自动写入功能。 将标头 CRC 的地址附加到您的 crc32 命令中,计算的值将以正确的顺序为您存储,例如

crc32 0x10100000 0x40 0x10100004

仍然想知道为什么您一开始就没有使用 mkimage 的良好 CRC32,以及为什么必须求助于这个 hack。

【讨论】:

噢!不错的收获。我将长度更改为 0x40。 我还删除了 mkimage 中的操作系统规范。 但是唉...结果是一样的! 有人告诉我他们认为 USB 传输搞砸了数据,但我比较了我的 PC 和设备上的前 64 个字节,它们是相同的(减去字节序)。不过,在任一设备上运行 crc32 都会产生相同的结果。我还深入研究了 uboot 源代码的 C 端,相对于产生错误命令的原因,此过程中的所有内容似乎都是有效的。 哦。这是一个很好的笔记!我绝对想知道是否需要修复与翻转字节序相关的问题(正如我之前暗示的那样)。我试试看!

以上是关于U-boot Script Bad Header CRC的主要内容,如果未能解决你的问题,请参考以下文章

JZ2440 linux-3.4.2内核启动报错:Verifying Checksum ... Bad Data CRC

mvn项目运行报错invalid LOC header (bad signature)

nginx 400 bad request怎么解决

invalid LOC header (bad signature)-Maven异常

电脑蓝屏出现,BAD -POOL-HEADER

maven 错误 invalid CEN header (bad signature)