RK3568 Android 12在parameter.txt添加buildtime参数防止重复刷机

一、场景描述

        因为做了上电检测U盘中升级包自动进行升级的功能,为了防止同一个版本的image重复刷机,需要在image文件中添加软件编译时间用来判断是否同一个版本,如果是则跳过升级,直接开机启动。所以决定在parameter.txt文件中添加多一个BUILD_TIME参数来实现。

二、添加BUILD_TIME参数到parameter.txt文件

1.parameter.txt文件生成解析

parameter.txt是在编译Android的时候从RebuildParameter.mk里面去执行重建的,下面是mk文件中具体的执行部分(其中“--build-time $(BUILDTIME) \” 这个是项目中自己新增加的参数 )

$(rebuild_parameter) : $(PRODUCT_PARAMETER_TEMPLATE) $(ROCKCHIP_PARAMETER_TOOLS)
	@echo "Building parameter.txt $@."
	$(ROCKCHIP_PARAMETER_TOOLS) --input $(PRODUCT_PARAMETER_TEMPLATE) \
	--start-offset 8192 \
	--firmware-version $(BOARD_PLATFORM_VERSION) \
	--machine-model $(PRODUCT_MODEL) \
	--manufacturer $(PRODUCT_MANUFACTURER) \
	--machine $(PRODUCT_DEVICE) \
    --build-time $(BUILDTIME) \
	--partition-list $(partition_list) \
	--output $(rebuild_parameter)

其中PRODUCT_PARAMETER_TEMPLATE是传入的模板文件,通过全文检索可以知道其对应的文件是device/rockchip/common/scripts/parameter_tools/parameter.in,其内容如下(其中“BUILD_TIME: ${_buildtime}”是项目中自己新加的参数):

FIRMWARE_VER: ${_firmware_version}
MACHINE_MODEL: ${_machine_model}
MACHINE_ID: ${_machine_id}
MANUFACTURER: ${_manufacturer}
MAGIC: ${_magic}
ATAG: ${_atag}
MACHINE: ${_machine}
CHECK_MASK: ${_check_mask}
PWR_HLD: ${_pwr_hld}
TYPE: ${_type}
BUILD_TIME: ${_buildtime}
CMDLINE:mtdparts=rk29xxnand:${_partition_list}

--machine-model $(PRODUCT_MODEL) 这个是传入重建工具的参数,其中PRODUCT_MODEL是获取的编译配置的宏,最终会赋值给parameter.in中的MACHINE_MODEL

ROCKCHIP_PARAMETER_TOOLS是调用的重建工具,在该工具中会调用parameter_generator.py脚本来真正执行参数的赋值和文件的生成(其中“build_time”相关代码是项目中自己新加的部分)。

def main(argv):
    ifile = 'parameter.in'
    type = 'GPT'
    start_offset = 16384
    firmware_version = ''
    machine_model = ''
    machine_id = '007'
    manufacturer = ''
    magic = '0x5041524B'
    atag = '0x00200800'
    machine = ''
    check_mask = '0x80'
    pwr_hld = '0,0,A,0,1'
    ofile = ''
    partition_list = ''
    build_time = ''
    try:
        opts, args = getopt.getopt(argv, "h", ["input=","start-offset=","firmware-version=","machine-model=","machine-id=","manufacturer=","magic=","atag=","machine=","check-mask=","pwr-hld=","build-time=","partition-list=","output="])
    except getopt.GetoptError:
        print (usage)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print (usage)
            sys.exit(2)
        elif opt == "--input":
            ifile = arg;
        elif opt == "--start-offset":
            start_offset = arg;
        elif opt == "--firmware-version":
            firmware_version = arg;
        elif opt == "--machine":
            machine = arg
        elif opt == "--machine-model":
            machine_model = arg;
        elif opt == "--machine-id":
            machine_id = arg;
        elif opt == "--manufacturer":
            manufacturer = arg;
        elif opt == "--magic":
            magic = arg;
        elif opt == "--atag":
            atag = arg;
        elif opt == "--check-mask":
            check_mask = arg;
        elif opt == "--pwr-hld":
            pwr_hld = arg;
        elif opt == "--partition-list":
            partition_list = arg;
        elif opt == "--output":
            ofile = arg;
        elif opt == "--build-time":
            build_time = arg;
        else:
            print (usage)
            sys.exit(2)

    if partition_list == '':
        print (usage)
        sys.exit(2)
    # append '_b' parts if '_a' is exists.
    list_partitions = partition_list.split(',')
    cur_part_start = int(start_offset)
    final_parts = ''
    for cur_part in list_partitions:
        pos_split = cur_part.find(':')
        cur_part_name = cur_part[:pos_split]
        pos_slotselect = cur_part.find('_a')

        cur_part_size = cur_part[1 + pos_split:]
        str_part, int_next_start_offset = generate_pt(cur_part_name, cur_part_size, cur_part_start)
        cur_part_start = int_next_start_offset
        final_parts += str_part + ","
        if pos_slotselect >= 0:
            slot_b_part_name = cur_part[:pos_slotselect] + '_b'
            str_part, int_next_start_offset = generate_pt(slot_b_part_name, cur_part_size, cur_part_start)
            cur_part_start = int_next_start_offset
            final_parts += str_part + ","

    partition_list = final_parts + generate_pt('userdata', '0', cur_part_start)

    file_parameter_in = open(ifile)
    template_parameter_in = file_parameter_in.read()
    template_in_t = Template(template_parameter_in)

    line = template_in_t.substitute(_firmware_version=firmware_version,_machine_model=machine_model,_machine_id=machine_id,_manufacturer=manufacturer,_magic=magic,_atag=atag,_machine=machine,_check_mask=check_mask,_pwr_hld=pwr_hld,_type=type,_buildtime=build_time,_partition_list=partition_list)

    if ofile != '':
        with open(ofile,"w") as f:
            f.write(line)
    else:
        print (line)

2. build time参数添加

         在上一部分介绍parameter.txt的生成过程时已经顺带把添加的BUILD_TIME参数代码一起附上了,所以要添加新的参数只要在RebuildParameter.mk、parameter.in和parameter_generator.py 3个文件中添加相应的代码即可,最后生成的文件内容如下:

三、打包parameter.txt到update.img 

        这部分其实不需要改动,打包image的时候打包脚本会自动完成,不过为了让文章框架更完整,也就一起介绍一下吧。另外一个原因是在这里也踩过坑,希望能帮大家填坑,具体在第4节内容介绍。

       RK3568的编译流程是先编译u-boot,然后kernel,最后编译Android,这3个编译完后会在rockdev /product_model/目录下生成打包需要的img文件,例如boot.img、uboot.img、recovery.img、super.img等,最最后才调用打包脚本去生成update.img文件,下面是RK打包工具的输出信息,可以看到parameter.txt也是有被一起打包进去的 ,offset是0x73000

 四、解析update.img中的BUILD_TIME

        BUILD_TIME参数添加到update.img中之后,接下来就是要对其进行读取了。

        读取方式:因为parameter.txt是以文件的形式打包进update.img包中的,所以只要找到parameter.txt中的起始位置,然后在uboot中通过file_fat_read_at函数把parameter.txt的内容全部读取出来,然后通过字符串读取方式进行提取操作就行了。

 1.确定parameter.txt的offset

        确定了parameter.txt在update.img中的offset,读取的过程就算是完成一大半了。前面第3部分说到的坑,正是最重要的offset确定部分。从前面的图中可以看到,编译工具打印出的显示parameter.txt在打包的时候是被加载到offset为0x73000的位置的,但是实际读取的内容是空的,确认很多遍发现还是不对,无奈只能另寻其他方法。

       开始没有啥头绪,所以就想着看下update.img文件的内容,看能不能看出的端倪。于是把update.img用notepad++打开,发现里面有乱码也有正常的字符串,然后搜索BUILD_TIME,果然定位到了如下parameter.txt文件内容所在位置,开始有点眉目。

把上面这段内容拷贝出来,在notepad++中,通过插件——》Converter——》ASCII->HEX转换成16进制后,得到如下数据。可以看到PARM对应的16进制是5041524D,想起之前在recovery中看到的读取系统中paramter时有个TAG,正好是这个16进制数据,所以这个TAG的位置应该就是parameter.txt的offset

 

 原本想直接用notepad++把起始位置开始到parameter.txt的内容都拷贝出来转成十六进制数,然后通过左边的行号*16(每行是16个byte)来确认位置的,无奈内容太多,notepad++转换失败,所以直接自己写个简单的C程序去查找这个offset了。

下面是自己写的查找方法,有些地方写的不严谨,不过能满足需求了。最后获取到offset的值是936486,用16进制表示是0xE4A26

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include<fcntl.h>

#define READ_START   285000
#define TAG_START	0x50

void main(int argc, char* argv[])
{
	int fd = -1;
	int ret = -1;
	int n = -1;
    char ch;
	char tag[]={0x41, 0x52, 0x4D};
	char judge[4]={0};

	int count = READ_START;

	if (argc < 2) {
		printf("please input file name\n");
	}
    fd = open(argv[1], O_RDONLY);
	if (-1 == fd) {
		printf("open file faild,file=%s",argv[1]);
		return;
	}
	lseek(fd, READ_START, SEEK_SET);
	while((n = read(fd, &ch,1)))
	{
		if (n<0)
		{
			printf("read error\n");
			exit(1);
		}
		count += 1;
		if ( ch == TAG_START){
			n = read(fd, &judge, 3);
			if (n == 3) {
				count += 3;
				if (!strncmp(judge,tag,3)) {
					printf("find offset = %d\n", count-4);
					break;
				}
			}

		}
	}
	close(fd);
}

2.读取BUILD_TIME内容

        确定parameter.txt的offset后,接着就是读取内容了,可通过uboot的file_fat_read_at(path, PARAMATER_OFFSET, buf, MAX_LOADER_PARAM);把parameter.txt的所有内容读出来,MAX_LOADER_PARAM的值设置的比parameter.txt的内容大就可以了。

        buf是一个字符串缓冲器,把所有内容读出来后存储到buf后,再对buf进行字符串查找就可以获取到BUILD_TIME的值了。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值