112.龙芯2k1000-pmon(11)- gzrom-dtb.bin 文件的组成

最近又要折腾2k1000的设备了,研究了一下gzrom文件组成部分。

pmon的编译可以参考之前的文档,这里我就不详述了

源码:GitHub - zhaozhi0810/pmon-ls2k1000-2022

gzrom-dtb.bin的生成命令在Makefile.inc(zloader.ls2k-hj20004目录)中

截取出来如下:

[ -f gzrom.bin ] && cp gzrom.bin gzrom-dtb.bin && python ../tools/pmonenv.py -f gzrom-dtb.bin -d ${TARGET}.dtb -w  al=\(usb0,0\)/boot/vmlinuz al1=\(wd0,0\)/vmlinuz append="'console=ttyS0,115200 noinitrd root=/dev/sda2  rootfstype=ext4 rootwait rw'" FR=1  

  1. [ -f gzrom.bin ] && cp gzrom.bin gzrom-dtb.bin 存在gzrom.bin这个文件,复制这个文件为gzrom-dtb.bin,相当于重命名了。

     2. python ../tools/pmonenv.py   用这个脚本来处理。(1.把dtb合并起来,2.加入一些环境变量)

     3. gzrom-dtb.bin = gzrom.bin + dtb + env

     4. pmonenv.py 注意这个命令之后的几个选项,这里有-f -d -w

     5. pmonenv.py 可以看到源码,在tools目录中

一、加入env变量

1.1  从main函数入口。

if __name__ == '__main__':opt,argv=getopt.getopt(sys.argv[1:],'b:o:s:f:wd:')opt=dict(opt)foff = int(opt['-o'],0) if '-o' in opt  else 0x000ff000  fsz = int(opt['-s'],0) if '-s' in opt else 500  fname = opt['-f'] if '-f' in opt else 'gzrom.bin' d=readenv(fname,foff,fsz,argv)print(d) if '-w' in opt:  writeenv(fname,foff,fsz,d)   if '-b' in opt: writehexenv(fname, opt['-b'])if '-d' in opt: writedtb(fname, opt['-d'], foff)

1.1.1 分析一下foff,fsz,fname

实际没有-o 选项,所以foff = 0x000ff000    (十进制1044480)

实际没有-o 选项 ,所以fsz = 500

有-f 选项 fname = gzrom-dtb.bin

可以使用打印语句打印出来看看

1.1.2 gzrom-dtb.bin的文件大小正好等于foff + fsz;

打开gzrom-dtb.bin,果然是这个位置开始放置环境变量

1.2  继续往下,看到writeenv

def writeenv(fname,foff,fsz,d):# print("\nwriteenv start*******************")# print("7 d = ",d)   # 8a=b'\x00\x00'   for i in d.keys():   a += i+b'='+d[i]+b'\x00' # print("8 a = ",a)   # 9a=a.ljust(fsz,b'\x00')   b = struct.pack('!H',(-sum(struct.unpack('!'+str(len(a)//2)+'H',a)))&0xffff)# print("9 b = ",b)   # 10a=b+a[2:]# print("10 a = ",a)   # 11f=open(fname,'rb+')f.seek(foff,0)f.write(a)  f.close()

1.2.1 可以打开其中的注释,看到一些打印信息

打开 9,10,11 处的打印

('8 a = ', '\x00\x00FR=1\x00')

('8 a = ', '\x00\x00FR=1\x00al=(usb0,0)/boot/vmlinuz\x00')

('8 a = ', "\x00\x00FR=1\x00al=(usb0,0)/boot/vmlinuz\x00append='console=ttyS0,115200 noinitrd root=/dev/sda2  rootfstype=ext4 rootwait rw'\x00")

('8 a = ', "\x00\x00FR=1\x00al=(usb0,0)/boot/vmlinuz\x00append='console=ttyS0,115200 noinitrd root=/dev/sda2  rootfstype=ext4 rootwait rw'\x00al1=(wd0,0)/vmlinuz\x00")

('9 b = ', ')\x0e')    # 这个位置应该是0x290e 转为两个字节存放,0x29 正好对应一个右括号

('10 a = ', ")\x0eFR=1\x00al=(usb0,0)/boot/vmlinuz\x00append='console=ttyS0,115200 noinitrd root=/dev/sda2  rootfstype=ext4 rootwait rw'\x00al1=(wd0,0)/vmlinuz\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

1.2.2 简要分析

通过加入打印信息,做出如下解析

1.2.2.1 struct.unpack('!'+str(len(a)//2)+'H',a)   //这个!指的是大端模式,H表示unsigned short类型

这里的意思是把两个字节按大端的形式,组合,得到一个250个数的数组,类型为unsigned short

(0, 18002, 15665, 97, 27709, 10357, 29538, 12332, 12329, 12130, 28527, 29743, 30317, 27753, 28277, 31232, 24944, 28773, 28260, 15655, 25455, 28275, 28524, 25917, 29812, 31059, 12332, 12593, 13618, 12336, 8302, 28521, 28265, 29810, 25632, 29295, 28532, 15663, 25701, 30255, 29540, 24882, 8224, 29295, 28532, 26227, 29817, 28773, 15717, 30836, 13344, 29295, 28532, 30561, 26996, 8306, 30503, 97, 27697, 15656, 30564, 12332, 12329, 12150, 28012, 26990, 30074, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

注意18002  十六进制  0x4652  跟上面的截图(0xff002)能对上。其他就不看了

1.2.2.2 Sum   把他们加起来,按照unsigned short的类型,总共250个数  加起来等于1496818

1.2.2.3 - 把得到的校验和取负数,  等于-1496818

1.2.2.4 &0xffff 只取负数的最低16位    等于0x290e

 1.2.2.5 struct.pack('!H',…) 再用大端模式,打包unsigned short类型

0x290e,按大端解析为字节,data[0]=0x29,data[1]=0x0e   ,这个就是校验和!!!!写在最开始的两个字节,跟上面的截图(0xff000)能对上

1.2.2.6 尾部没有校验和,检验和在最开始的两个字节。校验的方法参考前面的描述

1.2.2.7 a=a.ljust(fsz,b'\x00') 对数据字节数进行补全,不足的位置补0.

二、加入dtb文件

2.1 明白env的加入之后,dtb 就比较简单了,

def writedtb(fname,dtb,foff):# print("\n writedtb start----------------------")f=open(dtb,'rb')a=f.read();# print("a.len= ",len(a))  # 12f.close()a=a.ljust(0x4000-8,'\x00')# print("a = ",a)b = struct.pack('I',(-sum(struct.unpack(''+str(len(a)//4)+'I',a)))&0xffffffff)a=b+a+b# print("a.len= ",len(a))  # 13# print("a = ",a)f=open(fname,'rb+')f.seek(foff-0x4000,0)f.write(a)f.close()

首先dtb能够保存的大小是0x4000-8个字节   (16K-8个字节),字节不足的地方填充0

文件偏移 0x000ff000 - 0x4000  = 0xfb000

前4个字节是校验和

 最末尾也是校验和(4个字节)

2.2 校验和的计算

经过上面的折腾,校验和计算比较简单了吧,小端的4个字节(unsigned int类型)组合,加起来,然后取负数,然后取低4个字节,即校验和了。

三、思考

最后,看到bin文件中env 和dtb 都是自己独立检验和,并且没有整体校验!!

3.1  env写的位置是ff000 后面的500字节,这个位置能否改动呢?

3.2  dtb写的位置是fb000 ,大小是0x4000(16k),这个位置能否改动呢?

3.3  能否只修改flash中的某个部分呢?这就提供了可行性。

(回答上面问题,就要看pmon怎么解析这几个部分了,看源码吧)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/501072.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux信号【产生-保存-处理】

目录 前言: 1、进程信号基本概念 1.1、什么是信号? 1.2、信号的作用 2、键盘键入 2.1、ctrlc 终止前台进程 2.1.1、signal 注册执行动作 3、系统调用 3.1、kill 函数 3.2、模拟实现 myKill 3.3、raise 函数 3.4、abort 函数 4、软件条件信号…

模拟算法题练习(二)(DNA序列修正、无尽的石头)

(一、DNA序列修正) 问题描述 在生物学中,DNA序列的相似性常被用来研究物种间的亲缘关系。现在我们有两条 DNA序列,每条序列由 A、C、G、T 四种字符组成,长度相同。但是现在我们记录的 DNA序列存在错误,为了…

QT之液晶电子时钟

根据qt的<QLDNumber>做了一个qt液晶电子时钟. 结果 实时显示当前时间,左键可以拖动时钟在屏幕的位置,右键点击关闭显示. 实现过程 新建一个class文件,让这个文件的父类是QLCDNumber 相关功能变量定义和函数实现 .c文件代码 这里需要注意的一点是event->button是获取的…

【cpp】深蓝学院 c++课程 基于课后作业的学习复习汇总 其1 1-6节

写在前面 N年前上来深蓝学院cpp的课&#xff0c;老师是大牛但却有讲的特别细致&#xff0c;感觉对于入门的我有很大帮助。当时作为初学者有很多不理解的地方&#xff0c;现在工作了几年回头去看理解深刻了一些&#xff0c;将会在学习行业算法的时候&#xff0c;复习一下课程内…

【详识JAVA语言】猜数字游戏

游戏规则: 系统自动生成一个随机整数(1-100), 然后由用户输入一个猜测的数字. 如果输入的数字比该随机数小, 提示 "低 了", 如果输入的数字比该随机数大, 提示 "高了" , 如果输入的数字和随机数相等, 则提示 "猜对了" . 参考代码 import java.…

当你的游览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么

当你的游览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么 1.负责域名解析的 DNS 服务 DNS&#xff08;Domain Name System&#xff09;服务是和 HTTP 协议一样位于应用层的 协议。它提供域名到 IP 地址之间的解析服务。 计算机既可以被赋予 IP 地址&#xf…

Ubuntu系统使用Docker搭建Jupyter Notebook并实现无公网ip远程连接

文章目录 1. 选择与拉取镜像2. 创建容器3. 访问Jupyter工作台4. 远程访问Jupyter工作台4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定二级子域名地址远程访问 本文主要介绍如何在Ubuntu系统中使用Docker本地部署Jupyter Notebook&#xff0c;并结合cpolar内网穿透…

【前端素材】推荐优质后台管理系统DAdmin平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理网站、应用程序或系统的管理界面&#xff0c;通常由管理员和工作人员使用。它提供了访问和控制网站或应用程序后台功能的工具和界面&#xff0c;使其能够管理用户、内容、数据和其他各种功能。 2、功能需求 后台管理系…

Python:关于数据服务中的Web API的设计

搭建类似joinquant、tushare类似的私有数据服务应用&#xff0c;有以下一些点需要注意&#xff1a; 需要说明的是&#xff0c;这里讨论的是web api前后端&#xff0c;当然还有其它方案&#xff0c;thrift&#xff0c;grpc等。因为要考虑到一鱼两吃&#xff0c;本文只探讨web ap…

利用Quartz实现复杂的任务调度

第一章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;任务调度&#xff0c;简而言之&#xff0c;就是按照预定计划自动执行任务的过程。不管是数据库备份、报表生成还是发送定时邮件&#xff0c;它们都需要一个可靠的任务调度系统来保证按时完成。 那么&#xff0…

用node或者vscode开启一个简单的本地server服务器,加载html网页

使用Live Server 想要加载本地html页面可以快速能让它在你本地浏览器中打开&#xff0c;可以有好多种方式&#xff0c;如果你有使用vscode&#xff0c;可以安装一个插件&#xff1a;Live Server&#xff0c;然后直接在vscode中直接右键就可以开启这个服务&#xff1a; 安装好之…

几个原创文章自动生成软件推荐

在数字化时代&#xff0c;原创文章的重要性越来越被重视&#xff0c;但是频繁的写作工作却也耗费大量时间和精力。原创文章自动生成软件能够帮助大家快速生成各种类型的原创文章&#xff0c;节省时间和精力。本文将介绍6款不同的原创文章自动生成软件&#xff0c;并介绍一款知名…