惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
T
Threatpost
Latest news
Latest news
N
News | PayPal Newsroom
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
T
Threat Research - Cisco Blogs
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Exploit Database - CXSecurity.com
NISL@THU
NISL@THU
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Securelist
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
AWS News Blog
AWS News Blog
GbyAI
GbyAI
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
美团技术团队
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
博客园 - 聂微东
V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
SecWiki News
SecWiki News
S
Secure Thoughts
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
腾讯CDC
H
Heimdal Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed

博客园 - midhillzhou

windows 11关闭防火墙 以使得 外部的开发板可以主动发起ping通电脑 uboot中调试景略以太网phy JL3111A2-NA windows上excel运行macro之后出现错误 在linux上移植sgdisk 在linux上移植phytool + 调试tja1103 以太网phy 使用gdb调试user程序 之 某个线程的调用栈 在uboot中修改tja 1103以太网phy from slave to master porting perf性能观测工具 porting 开源memtester uboot 2020版本下gpio命令的使用 + linux下的libgpiod lib库的移植使用 ubi文件系统的 制作 + 挂载 + 若干问题 i2c指令使用 + 仿照开源i2ctransfer实现的自己的i2ctransfer windows下outlook 撤回邮件 安装repo 使用lauterbach debug uboot之重定位 uboot中各种memory读写命令 uboot bootm代码详解图 Beyond Compare 进行二进制文档的比对时,怎么去对齐(转载) notepad++分析log小技巧 使用继电器控制开发板上下电 uboot debug小技巧
uboot nand flash dump 环境变量 + 制作环境变量分区 + 代码结构详解
midhillzhou · 2025-04-30 · via 博客园 - midhillzhou

第一部分,首先从外部感性的认识下env分区

1.1首先我们在uboot console里面执行saveenv,打印如下

UBOOT=>saveenv
Saving Environment to NAND... Erasing NAND...
Erasing at 0x400000 -- 100% complete.
Writing to NAND... OK
OK

1.2观察上述打印,我们可以知道uboot env分区是在nand flash 0x400000处

1.3使用命令dump出来看看内容是什么

 1.4解析dump出来的内容

env在uboot中的结构体如下,下面根据结构体来解析dump出来的内容

typedef struct environment_s {

    uint32_t    crc;        /* CRC32 over data bytes    */

#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT

    unsigned char   flags;      /* active/obsolete flags ENVF_REDUND_ */

#endif

    unsigned char   data[ENV_SIZE]; /* Environment data     */

} env_t;

dump出来的内容解析如下:

随便找了一个hex-》ascii的在线网站:https://www.rapidtables.com/convert/number/hex-to-ascii.html

第二部分,下面根据代码讲解下如何制作env分区

2.1首先准备好一个env.txt,其内容如下

2.2使用如下命令

uboot/u-boot-2020.04/tools/mkenvimage -s 0x20000 -r -p 0x00 -o env.bin env.txt

本小节参考如下两个链接,建议先看完这两个链接,再往下继续:

 https://bootlin.com/blog/mkenvimage-uboot-binary-env-generator/

https://source.denx.de/u-boot/u-boot/-/commit/a6337e6ffdea211e70dd8d6c638f6a5ec2295400

2.2.1 我们使用的工具是mkenvimage,其源代码已经被包含中uboot的源代码当中,编译uboot的同时就会编译出这个工具mkenvimage。如果没有被编译,生成这个tool,检查下如下路径的makefile。

2.2.2 -s 后面的0x20000表示env分区的大小,由代码的defconfig文件的如下宏决定

CONFIG_ENV_SIZE=0x20000,表示env的大小是0x20000,即128 kB,这里要注意的是 

128kB大小指的是 上述结构体的大小,并非mtd中env分区的大小

 这里再赘述下上述的结构体,一看便知什么意思

CONFIG_ENV_SIZE=0x20000       128kB
CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x480000

#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
# define ENV_HEADER_SIZE    (sizeof(uint32_t) + 1)
#else
# define ENV_HEADER_SIZE    (sizeof(uint32_t))
#endif

#define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)

typedef struct environment_s {

    uint32_t    crc;        /* CRC32 over data bytes    */

#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT

    unsigned char   flags;      /* active/obsolete flags ENVF_REDUND_ */

#endif

    unsigned char   data[ENV_SIZE]; /* Environment data     */

} env_t;

 

data[ENV_SIZE]中ENV_SIZE的值是(CONFIG_ENV_SIZE - ENV_HEADER_SIZE),说明这个结构就是128kB。
对于本项目,env_a和env_b的分区的大小是512kB, 即如下两个offset相减。

CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x480000

2.2.3 -r表示我使用的redundant env,即目前我有两个env,有两个env的话,生成的头是 crc32 + flags多了一个flags。

2.2.4 -p 0x00表示 data数组的后面用什么填充,因为这个结构体非常大,我们大概率是填不满的,此时用0x00填充而非0xff

在最后一个stdout环境变量之后我们开始用0x00来填充。

2.3.使用hexdump查看下header的crc值是否正确,是否有flag,以及内容是否正确。

 crc32值为 79 6c 88 58,和从nand flash的值是一样的

flag为01,具体值不用管,只要有这个byte就行

再看看altbootcmd和bautrate的值,也是对的,

2.4.下面只需要根据CONFIG_ENV_OFFSET和CONFIG_ENV_OFFSET_REDUND的值将这一个生成的env.bin写到两个env_a,env_b的开始处,就行了。自此大功告成。

CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_OFFSET_REDUND=0x480000

第三部分,下面讲解uboot启动过程中如何与env分区打交道

首先入口的函数调用顺序是initr_env -》 env_relocate -》env_load

注意下面开始最关键的代码分析

3.1 首先打印Loading Environment from,

3.2 调用函数指针drv->load(),这个值被填充的地方是在下图绿框里面结构定义,值为圆圈3,env_nand_load

3.3 进入env_nand_load以后,首先会从两个env_a, env_b的offset处开始读取

3.4 读取成功后进入env_import_redund(圆圈6),在这个函数里面会进行crc32值的计算(圆圈7)

3.5 如果失败,打印*** Warning - %s, " "using default environment (圆圈8和圆圈9)

3.6 如果成功,在返回后,会打印OK(圆圈10)

3.7 两种情况下crc错误 和 crc正确的串口打印log如下图