From fbda160e9a26827768149dbbcec42581f4ebb0a8 Mon Sep 17 00:00:00 2001 From: ranchuan Date: Thu, 17 Oct 2024 16:14:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BB=A5=E4=B8=8B=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.自动判断bin文件是否需要解密 2.添加下载指定ram.bin的功能,支持命令行交互 3.去除手动指定上传还是下载的命令选项 --- bin/bin_to_hex.py | 26 ++++--- bin/bootram_kl1_build.bin | Bin 0 -> 45487 bytes bin/log.py | 12 ++- kunlun.py | 154 +++++++++++++++++++++++++++----------- 4 files changed, 140 insertions(+), 52 deletions(-) create mode 100644 bin/bootram_kl1_build.bin diff --git a/bin/bin_to_hex.py b/bin/bin_to_hex.py index 559c306..5ae87f8 100644 --- a/bin/bin_to_hex.py +++ b/bin/bin_to_hex.py @@ -214,6 +214,18 @@ def img_header_check(data:bytearray): return "V0" return "" +# 判断是不是加密了 +def pkt_encrypt_check(data:bytearray): + magic_data=data[12:16] + pat=magic_data[0] + for i in range(len(magic_data)): + magic_data[i]=magic_data[i]^pat + magic=(magic_data[0]<<24)|(magic_data[1]<<16)|(magic_data[2]<<8)|(magic_data[3]) + if (magic==_PKT_HEADER_MAGIC_NO): + if(pat!=0): + return True + return False + # 转化为hex文本 def bin_to_hex(bin:bytearray,f,oem_file=None): @@ -261,11 +273,11 @@ def bin_to_hex(bin:bytearray,f,oem_file=None): return kunlun -def bin_to_hex_file(bin_file_name:str,hex_file_name:str,enc=0): +def bin_to_hex_file(bin_file_name:str,hex_file_name:str): with open(bin_file_name,mode='rb') as f: bin=bytearray(f.read()) - if(enc): - myprint("start decrypt") + if(pkt_encrypt_check(bin)): + myprint("start decrypt:") pat=(bin[12]^0x00)&0xff myprint(f"decrypt image:{hex(pat)}({_PatternType.get(pat,'unknown')})") for index in range(len(bin)): @@ -291,7 +303,7 @@ def bin_file_decrypt(bin_file:str): with open(bin_file,mode='rb') as f: bin=bytearray(f.read()) # 自动判断是否需要解密 - if ((bin[12]==bin[13])and(bin[12]!=0x00)): + if (pkt_encrypt_check(bin)): pat=(bin[12]^0x00)&0xff myprint(f"decrypt image:{hex(pat)}({_PatternType.get(pat,'unknown')})") for index in range(len(bin)): @@ -313,8 +325,4 @@ def clear_tmp(): # bin_to_hex.py input_file if __name__ == "__main__": - if(len(sys.argv)>=3): - enc=1 - else: - enc=0 - bin_to_hex_file(sys.argv[1],"work/"+sys.argv[1]+".txt",enc) + bin_to_hex_file(sys.argv[1],"work/"+sys.argv[1]+".txt") diff --git a/bin/bootram_kl1_build.bin b/bin/bootram_kl1_build.bin new file mode 100644 index 0000000000000000000000000000000000000000..9b3f094f4f150ae7eb655f6c9a9cdeb4f619d85c GIT binary patch literal 45487 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 N+@}-Ea!yz2{~OhfP6+@2 literal 0 HcmV?d00001 diff --git a/bin/log.py b/bin/log.py index cc31776..1f52929 100644 --- a/bin/log.py +++ b/bin/log.py @@ -1,5 +1,5 @@ import time - +import sys # 同一个进程中所有调用这个文件的 .py 文件都使用这个变量 @@ -23,6 +23,16 @@ def myprint_dec(func): myprint=myprint_dec(print) +def mywrite(data:str): + if(_log_fp is not None): + txt=data.replace('\r','\n') + txt=txt.replace('\n\n','\n') + txt=txt.replace('\n\n','\n') + _log_fp.write(txt) + _log_fp.flush() + sys.stdout.write(data) + sys.stdout.flush() + def log_init(file_name:str): global _log_fp if _log_fp is None: diff --git a/kunlun.py b/kunlun.py index e460a2f..a48f465 100644 --- a/kunlun.py +++ b/kunlun.py @@ -10,11 +10,14 @@ import time import xmodem import os import binascii +import threading from bin.log import myprint from bin.log import log_init +from bin.log import mywrite from bin.bin_to_hex import bin_to_hex_file from bin.bin_to_hex import bin_file_decrypt from bin.bin_to_hex import clear_tmp +from bin.bin_to_hex import load_flash_info from bin.base import bin_path @@ -117,6 +120,46 @@ def print_device_str(data:bytearray): except Exception as e: myprint("DEVICE:",item) + + +_recv_thread=False +# 读取input +def read_input(s_port:serial.Serial): + global _recv_thread + def read(): + while True: + try: + d=input() + except KeyboardInterrupt: + break + if(d=='exit'): + break + try: + s_port.write(d.encode('utf-8')+b'\n') + except Exception: + break + read() + _recv_thread=False + +# 循环接收串口数据 +def recv_ser_data(s_port:serial.Serial): + global _recv_thread + def recv(s_port:serial.Serial): + global _recv_thread + while _recv_thread: + time.sleep(0.1) + bytes2read = s_port.in_waiting + if(bytes2read>0): + tmp = s_port.read(bytes2read) + try: + txt=tmp.decode('utf-8') + mywrite(txt) + except Exception as e: + pass + _recv_thread=True + t=threading.Thread(target=recv,args=(s_port,)) + t.start() + # 上传固件 def upload_bin(x_modem:xmodem.XMODEM, w_file): global time_stamp_end @@ -193,13 +236,13 @@ def upload_fun(): f.writelines(ser_read_data.decode('utf-8').split('\r\n')) # 显示image信息 ser.write(b"f s\n") - time.sleep(0.5) + time.sleep(1) ser_read_data=ser.read(4096) print_device_str(ser_read_data) with open(calc_flash_info_name(),mode='a+',encoding='utf-8') as f: f.writelines(ser_read_data.decode('utf-8').split('\r\n')) # 上传整个镜像 - ser.write(b"fw u d all\n") + ser.write(f"fw u d {get_upload_cfg(upload_key)}\n".encode("utf-8")) time.sleep(0.5) myprint(ser.read(4096).decode('utf-8')) upload_bin(modem,calc_upload_name()) @@ -224,6 +267,21 @@ def burn_fun(): print_device_str(ser_read_data) +# 配置要上传的镜像配置 +def get_upload_cfg(key:str): + if(key=='all'): + return key + info_list=load_flash_info(calc_flash_info_name()) + # print(info_list) + for item in info_list: + index=item["ImgType"].find(key.upper()) + if(index>=0): + return f"{item['Offset']} {item['Size']}" + myprint(f'Can not found key:{key}') + return "all" + + + def global_def(): global init_str @@ -235,78 +293,84 @@ def global_def(): global ser global time_stamp_start global time_stamp_end - global upload - global encrypt + global function_type + global upload_key init_str="WQKL" serial_com=sys.argv[1] b_rate=115200 nb_rate=1500000 - arg_num=len(sys.argv) - - if(arg_num==2): - if(sys.argv[1].endswith('.bin')): - iot_flash_file=sys.argv[1] - return - elif(arg_num==3): - if(sys.argv[1].endswith('.bin')): - iot_flash_file=sys.argv[1] - encrypt=1 - return - elif(arg_num==5): - if(sys.argv[3]=='upload'): - upload=True - elif(sys.argv[3]=='download'): - upload=False - iot_flash_file=sys.argv[4] - elif(arg_num==4): + def set_upload(): + global function_type if(sys.argv[3].endswith('.bin')): if(os.path.exists(sys.argv[3])): # 存在这个文件 是下载 - upload=False + function_type='download' else: # 不存在这个文件 是上传 - upload=True + function_type='upload' else: print("param err.") sys.exit(-1) - iot_flash_file=sys.argv[3] - if(upload): + if(arg_num==2): + if(sys.argv[1].endswith('.bin')): + function_type='convert' + elif(arg_num==3): + if(sys.argv[2].endswith('.bin')): + function_type='ram' + elif(arg_num==4): + set_upload() + upload_key="all" + elif(arg_num==5): + set_upload() + upload_key=sys.argv[4] + + if(function_type=='upload'): ram_file=f'bootram_{sys.argv[2]}.bin' - else: + iot_flash_file=sys.argv[3] + elif(function_type=='download'): ram_file=f'{sys.argv[2]}_ram_build.bin' + iot_flash_file=sys.argv[3] + elif(function_type=='ram'): + ram_file=sys.argv[2] + iot_flash_file=sys.argv[2] + return + elif(function_type=='convert'): + iot_flash_file=sys.argv[1] + return ram_file=os.path.join(bin_path(),ram_file) def print_help(): help=f''' - Automatically determine whether to upload or download:" - {sys.argv[0]} [com] [kl1/kl3] [upload.bin/download.bin] - Manually specify whether to upload or download: - {sys.argv[0]} [com] [kl1/kl3] [upload/download] [upload.bin/download.bin] - Convert bin file: - {sys.argv[0]} [file.bin] + 自动判断上传还是下载: + {sys.argv[0]} [com] [kl1/kl3] [upload.bin/download.bin] + 下载ram文件: + {sys.argv[0]} [com] [ram.bin] + 转换bin文件: + {sys.argv[0]} [file.bin] ''' print(help) # 如果不指定上传还是下载 脚本会根据输入文件是否存在来决定上传还是下载 -# kunlun.py [com] [kl1/kl3] [upload.bin/download.bin] -# kunlun.py [com] [kl1/kl3] [upload/download] [upload.bin/download.bin] +# kunlun.py [com] [kl1/kl3] [upload.bin/download.bin] +# kunlun.py [com] [ram.bin] # kunlun.py [file.bin] if __name__ == '__main__': - upload=None + function_type=None # 功能类型 "download" 下载,"upload" 上传,"ram" 下载ram,"convert"" 转换bin time_stamp_start, time_stamp_end = 0, 0 init_str, serial_com, b_rate, nb_rate, ram_file, iot_flash_file, ser = None, None, None, None, None, None, None - encrypt=0 + upload_key=None global_def() - if(iot_flash_file is None): + if(function_type is None): print("param err.") print_help() sys.exit(-1) log_init(calc_log_file_name()) - if(ram_file is None): - bin_to_hex_file(iot_flash_file,calc_hex_name(),encrypt) + if(function_type=='convert'): + bin_to_hex_file(iot_flash_file,calc_hex_name()) sys.exit(0) + try: ser = serial.Serial(port=serial_com, baudrate=b_rate, timeout=0.3) except Exception: @@ -318,9 +382,15 @@ if __name__ == '__main__': init_send(ser, init_str) burn_ram_bin(modem, ram_file) - if(upload): + if(function_type=='upload'): upload_fun() - else: + elif(function_type=='download'): iot_flash_file=bin_file_decrypt(iot_flash_file) burn_fun() clear_tmp() + elif(function_type=='ram'): + recv_ser_data(ser) + read_input(ser) + +# if __name__ == "__main__": +# read_input(None)