#!/usr/bin/env python3 # # Build Actions NVRAM config binary file # # Copyright (c) 2017 Actions Semiconductor Co., Ltd # # SPDX-License-Identifier: Apache-2.0 # import os import sys import struct import array import argparse import zlib import configparser from ctypes import *; BINARY_BLOCK_SIZE_ALIGN = 512 class BOOT_PARAMETERS(Structure): # import from ctypes _pack_ = 1 _fields_ = [ ("magic", c_uint32), ("uart_baudrate", c_uint32), ("uart_id", c_uint8), ("uart_mfp", c_uint8), ("jtag_groud", c_uint8), ("psram_mfp", c_uint8), ("adfu_txrx", c_uint8), ("adfu_gpio", c_uint8), ("reserved", c_uint8 * 14), ("checksum", c_uint32), ] # 32 bytes SIZEOF_BOOT_PARAMETERS_VERSION = 0x20 BOOT_PARAMETERS_MAGIC = 0x52415042 #'BPAR' BOOT_PARAMETERS_OFFSET = 0x30 def c_struct_crc(c_struct, length): crc_buf = (c_byte * length)() memmove(addressof(crc_buf), addressof(c_struct), length) return zlib.crc32(crc_buf, 0) & 0xffffffff def generate_boot_parameters(boot_name, boot_ini_name, out_ini_bin): if os.path.exists(boot_ini_name): boot_param = BOOT_PARAMETERS() memset(addressof(boot_param), 0, SIZEOF_BOOT_PARAMETERS_VERSION) boot_param.magic = BOOT_PARAMETERS_MAGIC configer = configparser.ConfigParser() configer.read(boot_ini_name) uart_baudrate = configer.get("serial config", "uart_baudrate") if uart_baudrate != None: boot_param.uart_baudrate = int(uart_baudrate, 0) print('uart id %s' %(uart_baudrate)) uart_id = configer.get("serial config", "uart_id") if uart_id != None: boot_param.uart_id = int(uart_id, 0) print('uart id %s' %(uart_id)) uart_mfp = configer.get("serial config", "uart_mfp") if uart_mfp != None: boot_param.uart_mfp = int(uart_mfp, 0) print('uart id %s' %(uart_mfp)) jtag_groud = configer.get("jtag config", "jtag_groud") if jtag_groud != None: boot_param.jtag_groud = int(jtag_groud, 0) print('jtag groud %s' %(jtag_groud)) psram_mfp = configer.get("psram_config", "psram_mfp") if psram_mfp != None: boot_param.psram_mfp = int(psram_mfp, 0) print('psram mfp %s' %(psram_mfp)) if configer.has_option("adfu config", "adfu_txrx") : adfu_txrx = configer.get("adfu config", "adfu_txrx") boot_param.adfu_txrx = int(adfu_txrx, 0) print('adfu_txrx %s' %(adfu_txrx)) if configer.has_option("adfu config", "adfu_gpio") : adfu_gpio = configer.get("adfu config", "adfu_gpio") boot_param.adfu_gpio = int(adfu_gpio, 0) print('adfu_gpio %s' %(adfu_gpio)) boot_param.checksum = c_struct_crc(boot_param, SIZEOF_BOOT_PARAMETERS_VERSION - 4) if out_ini_bin is None : with open(boot_name, 'rb+') as f: f.seek(BOOT_PARAMETERS_OFFSET, 0) f.write(boot_param) f.close() else : with open(out_ini_bin, 'wb+') as f: f.write(boot_param) f.close() def boot_padding(filename, align = BINARY_BLOCK_SIZE_ALIGN): fsize = os.path.getsize(filename) if fsize % align: padding_size = align - (fsize % align) print('fsize %d, padding_size %d' %(fsize, padding_size)) with open(filename, 'rb+') as f: f.seek(fsize, 0) buf = (c_byte * padding_size)(); f.write(buf) f.close() def boot_append_nand_id_table(filename, id_table_name): if not os.path.exists(id_table_name): return None fsize = os.path.getsize(filename) id_table_size = os.path.getsize(id_table_name) if id_table_size != 0: print('padding nand id table size %d' %(id_table_size)) with open(id_table_name, 'rb') as f: read_buf = f.read() f.close() with open(filename, 'rb+') as f: f.seek(fsize, 0) f.write(read_buf) f.close() def boot_calc_checksum(data): s = sum(array.array('H',data)) s = s & 0xffff return s def lark_boot_post_build(boot_name, boot_ini_name, nand_id_name): boot_len = os.path.getsize(boot_name) print('lark boot loader origin length %d.' %boot_len) generate_boot_parameters(boot_name, boot_ini_name, None) boot_append_nand_id_table(boot_name, nand_id_name) boot_padding(boot_name) boot_len_new = os.path.getsize(boot_name) print('boot loader new length %d.' %boot_len_new) with open(boot_name, 'rb+') as f: f.seek(0, 0) data = f.read(32) h_magic0,h_magic1,h_load_addr,h_name,h_version, \ h_header_size,h_header_chksm,h_data_chksm,\ h_body_size,h_tail_size \ = struct.unpack('III4sHHHHII',data) if(h_magic0 != 0x48544341 or h_magic1 != 0x41435448): print('boot loader header check fail.') return h_body_size = boot_len_new - h_header_size f.seek(0x18, 0) f.write(struct.pack(' h_tlv_size): # print('tlv_tol_size %d > header tlv size %d'%(tlv_tol_size, h_tlv_size)) # sys.exit(1) return tlv_tol_size return 0 def image_calc_checksum(data): s = sum(array.array('I',data)) s = s & 0xffffffff return s def image_add_cksum(filename, tlv_size): with open(filename, 'rb+') as f: f.seek(0, 0) data = f.read(48) h_magic0,h_magic1,h_load_addr,h_name,h_run_addr,h_img_size,h_img_chksum, h_hdr_chksum, \ h_header_size,h_ptlv_size,h_tlv_size,h_version,h_flags \ = struct.unpack('III8sIIIIHHHHI',data) if(h_magic0 != 0x48544341 or h_magic1 != 0x41435448): print('magic header check fail.') sys.exit(1) print('img header_size %d, img size=%d, ptlv_size=%d' %(h_header_size,h_img_size, h_ptlv_size)) f.seek(h_header_size, 0) data = f.read(h_img_size) checksum = image_calc_checksum(data) checksum = 0xffffffff - checksum f.seek(0x1c, 0) f.write(struct.pack('