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)   # 8
	a=b'\x00\x00'   
	for i in d.keys():   
		a += i+b'='+d[i]+b'\x00' 
		# print("8 a = ",a)   # 9
	a=a.ljust(fsz,b'\x00')   
	b = struct.pack('!H',(-sum(struct.unpack('!'+str(len(a)//2)+'H',a)))&0xffff)
	# print("9 b = ",b)   # 10
	a=b+a[2:]
	# print("10 a = ",a)   # 11
	f=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))  # 12
	f.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怎么解析这几个部分了,看源码吧)

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值