为何UBoot的boot.scr脚本中setenv与tftp命令无法正常工作?
U-Boot脚本boot.scr执行失败,ipaddr未生效问题排查
手动输入可正常执行的U-Boot命令
setenv ipaddr 192.168.0.199 setenv serverip 192.168.0.198 tftp 0x10000000 rpi3bp/image.bin go 0x10000000
编译为boot.scr的脚本内容
echo ===== Saving RPi's IP Address ===== setenv ipaddr 192.168.0.199 echo ===== Saving Home TFTP server's IP Address ===== setenv serverip 192.168.0.198 echo ===== Loading file from Home TFTP server ===== tftp 0x10000000 rpi3bp/image.bin echo ===== Running image ===== go 0x10000000
执行boot.scr时的错误输出
... Found U-Boot script /boot.scr 359 bytes read in 2 ms (174.8 KiB/s) ## Executing script at 02400000 ===== Saving RPis IP Address ===== setenv ipaddr 192.168.0.199 echo ===== Saving Home TFTP servers IP Address ===== ===== Loading file from Home TFTP server ===== lan78xx_eth Waiting for PHY auto negotiation to complete........ done *** ERROR: `ipaddr' not set ===== Running image ===== ## Starting application at 0x10000000 ... "Synchronous Abort" handler, esr 0x02000000 elr: ffffffffd4d27000 lr : 0000000000088cc0 (reloc) elr: 0000000010000000 lr : 000000003b361cc0 x0 : 0000000000000001 x1 : 000000003af6a028 x2 : 000000003af6a028 x3 : 000000000000003f x4 : 000000003af60df0 x5 : 0000000000000000 x6 : 0000000000000000 x7 : 0000000000c0c0c0 x8 : 0000000000000010 x9 : 0000000000000008 x10: 00000000ffffffd0 x11: 0000000000000010 x12: 0000000000000000 x13: 0000000000000200 x14: 000000003b3cc640 x15: 0000000000000001 x16: 0000000010000000 x17: 0fac920a292163a0 x18: 000000003af54db0 x19: 000000003af6a028 x20: 0000000010000000 x21: 0000000000000002 x22: 000000003af6a020 x23: 0000000000000002 x24: 000000003b3e567c x25: 0000000000000000 x26: 0000000000000000 x27: 0000000000000000 x28: 000000003af6a080 x29: 000000003af52ed0 Code: aaaaaaaa aaaaaaaa aaaaaaaa a2aaaaaa (55555555)
补充说明
已通过十六进制转储确认boot.scr使用Unix换行符(基于macOS环境):
❯ hexdump -C boot.scr 00000000 27 05 19 56 fc 01 13 df 63 d4 67 63 00 00 01 27 |'..V�..�c�gc...'| 00000010 00 00 00 00 00 00 00 00 a6 de 91 ea 05 02 06 01 |........��.�....| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000040 00 00 01 1f 00 00 00 00 0a 65 63 68 6f 20 3d 3d |.........echo ==| 00000050 3d 3d 3d 20 53 61 76 69 6e 67 20 52 50 69 27 73 |=== Saving RPi's| 00000060 20 49 50 20 41 64 64 72 65 73 73 20 3d 3d 3d 3d | IP Address ====| 00000070 3d 0a 73 65 74 65 6e 76 20 69 70 61 64 64 72 20 |=.setenv ipaddr | 00000080 31 39 32 2e 31 36 38 2e 30 2e 31 39 39 0a 0a 65 |192.168.0.199..e| 00000090 63 68 6f 20 3d 3d 3d 3d 3d 20 53 61 76 69 6e 67 |cho ===== Saving| 000000a0 20 48 6f 6d 65 20 54 46 54 50 20 73 65 72 76 65 | Home TFTP serve| 000000b0 72 27 73 20 49 50 20 41 64 64 72 65 73 73 20 3d |r's IP Address =| 000000c0 3d 3d 3d 3d 0a 73 65 74 65 6e 76 20 73 65 72 76 |====.setenv serv| 000000d0 65 72 69 70 20 31 39 32 2e 31 36 38 2e 30 2e 31 |erip 192.168.0.1| 000000e0 39 38 0a 0a 65 63 68 6f 20 3d 3d 3d 3d 3d 20 4c |98..echo ===== L| 000000f0 6f 61 64 69 6e 67 20 66 69 6c 65 20 66 72 6f 6d |oading file from| 00000100 20 48 6f 6d 65 20 54 46 54 50 20 73 65 72 76 65 | Home TFTP serve| 00000110 72 20 3d 3d 3d 3d 3d 0a 74 66 74 70 20 30 78 31 |r =====.tftp 0x1| 00000120 30 30 30 30 30 30 30 20 72 70 69 33 62 70 2f 69 |0000000 rpi3bp/i| 00000130 6d 61 67 65 2e 62 69 6e 0a 0a 65 63 68 6f 20 3d |mage.bin..echo =| 00000140 3d 3d 3d 3d 20 52 75 6e 6e 69 6e 67 20 69 6d 61 |==== Running ima| 00000150 67 65 20 3d 3d 3d 3d 3d 0a 67 6f 20 30 78 31 30 |ge =====.go 0x10| 00000160 30 30 30 30 30 30 0a |000000.| 00000167
问题原因
从错误输出可见,setenv ipaddr 192.168.0.199被直接打印而非执行,说明这条命令未被U-Boot解析为有效命令。
问题根源是echo命令参数中的未转义单引号:脚本中echo ===== Saving RPi's IP Address =====和echo ===== Saving Home TFTP server's IP Address =====两行里的RPi's、server's包含单引号',U-Boot脚本解析器会将单引号视为字符串分界符,导致echo命令参数被错误截断,后续的setenv命令被当成echo的输出内容,完全没有执行。
手动输入命令时,U-Boot命令行的解析逻辑与脚本模式不同,换行符会明确分割命令,因此不会触发该问题。
修复方法
修改脚本中包含单引号的echo命令,有两种可行方式:
- 用双引号包裹整个echo内容,避免单引号被解析为分界符:
echo "===== Saving RPi's IP Address =====" setenv ipaddr 192.168.0.199 echo "===== Saving Home TFTP server's IP Address =====" setenv serverip 192.168.0.198
- 转义单引号,在单引号前添加反斜杠
\:
echo ===== Saving RPi\'s IP Address ===== setenv ipaddr 192.168.0.199 echo ===== Saving Home TFTP server\'s IP Address ===== setenv serverip 192.168.0.198
修改后重新用mkimage编译脚本为boot.scr即可正常执行。
关于boot.scr与手动命令的效果一致性
正常情况下,boot.scr的执行效果应当和手动输入命令完全一致,前提是脚本语法正确、无解析错误。出现差异的原因几乎都是脚本存在语法问题,或是U-Boot命令行解析与脚本解析的细微差异(如特殊字符处理),修正脚本语法后就能达到和手动输入相同的效果。
内容的提问来源于stack exchange,提问作者ptk
相关产品推荐
相关产品推荐

