BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
REALTEK_RTL8195AM.py
00001 """ 00002 Realtek Semiconductor Corp. 00003 00004 RTL8195A elf2bin script 00005 """ 00006 00007 import sys, array, struct, os, re, subprocess 00008 import hashlib 00009 import shutil 00010 import time 00011 import binascii 00012 00013 from tools.paths import TOOLS_BOOTLOADERS 00014 from tools.toolchains import TOOLCHAIN_PATHS 00015 00016 # Constant Variables 00017 TAG = 0x81950001 00018 VER = 0x81950001 00019 CAMPAIGN = binascii.hexlify('FFFFFFFFFFFFFFFF') 00020 00021 RAM2_HEADER = { 00022 'tag': 0, 00023 'ver': 0, 00024 'timestamp': 0, 00025 'size': 72, 00026 'hash': 'FF', 00027 'campaign': 'FF', 00028 'crc32': 0xFFFFFFFF, 00029 } 00030 00031 def format_number(number, width): 00032 # convert to string 00033 line = format(number, '0%dx' % (width)) 00034 if len(line) > width: 00035 print "[ERROR] 0x%s cannot fit in width %d" % (line, width) 00036 sys.exit(-1) 00037 # cut string to list & reverse 00038 line = [line[i:i+2] for i in range(0, len(line), 2)] 00039 line.reverse() 00040 return binascii.a2b_hex("".join(line)) 00041 00042 def format_string(string): 00043 return binascii.a2b_hex(string) 00044 00045 def write_number(value, width, output): 00046 output.write(format_number(value, width)) 00047 00048 def write_string(value, width, output): 00049 output.write(format_string(value)) 00050 00051 def append_image_file(image, output): 00052 input = open(image, "rb") 00053 output.write(input.read()) 00054 input.close() 00055 00056 def write_padding_bytes(output_name, size): 00057 current_size = os.stat(output_name).st_size 00058 padcount = size - current_size 00059 if padcount < 0: 00060 print "[ERROR] image is larger than expected size" 00061 sys.exit(-1) 00062 output = open(output_name, "ab") 00063 output.write('\377' * padcount) 00064 output.close() 00065 00066 def crc32_checksum(string): 00067 return binascii.crc32(string) & 0xFFFFFFFF 00068 00069 def sha256_checksum(filename, block_size=65536): 00070 sha256 = hashlib.sha256() 00071 with open(filename, 'rb') as f: 00072 for block in iter(lambda: f.read(block_size), b''): 00073 sha256.update(block) 00074 return sha256.hexdigest() 00075 00076 def epoch_timestamp(): 00077 epoch = int(time.time()) 00078 return epoch 00079 00080 def find_symbol(toolchain, mapfile, symbol): 00081 ret = None 00082 00083 HEX = '0x0{,8}(?P<addr>[0-9A-Fa-f]{8})' 00084 if toolchain == "GCC_ARM": 00085 SYM = re.compile(r'^\s+' + HEX + r'\s+' + symbol + '\r?$') 00086 elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]: 00087 SYM = re.compile(r'^\s+' + HEX + r'\s+0x[0-9A-Fa-f]{8}\s+Code.*\s+i\.' + symbol + r'\s+.*$') 00088 elif toolchain == "IAR": 00089 SYM = re.compile(r'^' + symbol + r'\s+' + HEX + '\s+.*$') 00090 00091 with open(mapfile, 'r') as infile: 00092 for line in infile: 00093 match = re.match(SYM, line) 00094 if match: 00095 ret = match.group("addr") 00096 00097 if not ret: 00098 print "[ERROR] cannot find the address of symbol " + symbol 00099 return 0 00100 00101 return int(ret,16) | 1 00102 00103 def parse_load_segment_gcc(image_elf): 00104 # Program Headers: 00105 # Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 00106 # LOAD 0x000034 0x10006000 0x10006000 0x026bc 0x026bc RW 0x8 00107 # LOAD 0x0026f0 0x30000000 0x30000000 0x06338 0x06338 RWE 0x4 00108 segment_list = [] 00109 cmd = os.path.join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-readelf') 00110 cmd = '"' + cmd + '"' + ' -l ' + image_elf 00111 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"): 00112 if not line.startswith(" LOAD"): 00113 continue 00114 segment = line.split() 00115 if len(segment) != 8: 00116 continue 00117 offset = int(segment[1][2:], 16) 00118 addr = int(segment[2][2:], 16) 00119 size = int(segment[4][2:], 16) 00120 if addr != 0 and size != 0: 00121 segment_list.append((offset, addr, size)) 00122 return segment_list 00123 00124 def parse_load_segment_armcc(image_elf): 00125 # ==================================== 00126 # 00127 # ** Program header #2 00128 # 00129 # Type : PT_LOAD (1) 00130 # File Offset : 52 (0x34) 00131 # Virtual Addr : 0x30000000 00132 # Physical Addr : 0x30000000 00133 # Size in file : 27260 bytes (0x6a7c) 00134 # Size in memory: 42168 bytes (0xa4b8) 00135 # Flags : PF_X + PF_W + PF_R + PF_ARM_ENTRY (0x80000007) 00136 # Alignment : 8 00137 # 00138 (offset, addr, size) = (0, 0, 0) 00139 segment_list = [] 00140 in_segment = False 00141 cmd = os.path.join(TOOLCHAIN_PATHS['ARM'], 'bin', 'fromelf') 00142 cmd = '"' + cmd + '"' + ' --text -v --only=none ' + image_elf 00143 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"): 00144 if line == "": 00145 pass 00146 elif line.startswith("** Program header"): 00147 in_segment = True 00148 elif in_segment == False: 00149 pass 00150 elif line.startswith("============"): 00151 if addr != 0 and size != 0: 00152 segment_list.append((offset, addr, size)) 00153 in_segment = False 00154 (offset, addr, size) = (0, 0, 0) 00155 elif line.startswith(" Type"): 00156 if not re.match(r'\s+Type\s+:\s+PT_LOAD\s.*$', line): 00157 in_segment = False 00158 elif line.startswith(" File Offset"): 00159 match = re.match(r'^\s+File Offset\s+:\s+(?P<offset>\d+).*$', line) 00160 if match: 00161 offset = int(match.group("offset")) 00162 elif line.startswith(" Virtual Addr"): 00163 match = re.match(r'^\s+Virtual Addr\s+:\s+0x(?P<addr>[0-9a-f]+).*$', line) 00164 if match: 00165 addr = int(match.group("addr"), 16) 00166 elif line.startswith(" Size in file"): 00167 match = re.match(r'^\s+Size in file\s+:.*\(0x(?P<size>[0-9a-f]+)\).*$', line) 00168 if match: 00169 size = int(match.group("size"), 16) 00170 return segment_list 00171 00172 00173 def parse_load_segment_iar(image_elf): 00174 # SEGMENTS: 00175 # 00176 # Type Offset Virtual Physical File Sz Mem Sz Flags Align 00177 # ---- ------ ------- -------- ------- ------ ----- ----- 00178 # 0: load 0x34 0x10006000 0x10006000 0x26bc 0x26bc 0x6 WR 0x8 00179 # 1: load 0x26f0 0x30000000 0x30000000 0x6338 0x6338 0x7 XWR 0x4 00180 # 00181 # SECTIONS: 00182 # 00183 # Name Type Addr Offset Size Aln Lnk Inf ESz Flags 00184 # ---- ---- ---- ------ ---- --- --- --- --- ----- 00185 # 1: .shstrtab strtab 0xfc4d8 0x60 0x4 00186 # 2: .strtab strtab 0xfc538 0xbb3f 0x4 00187 00188 segment_list = [] 00189 in_segment = False 00190 cmd = os.path.join(TOOLCHAIN_PATHS['IAR'], 'bin', 'ielfdumparm') 00191 cmd = '"' + cmd + '"' + ' ' + image_elf 00192 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"): 00193 if line.startswith(" SEGMENTS:"): 00194 in_segment = True 00195 elif in_segment == False: 00196 pass 00197 elif line.startswith(" SECTIONS:"): 00198 break 00199 elif re.match(r'^\s+\w+:\s+load\s+.*$', line): 00200 segment = line.split() 00201 offset = int(segment[2][2:], 16) 00202 addr = int(segment[3][2:], 16) 00203 size = int(segment[5][2:], 16) 00204 if addr != 0 and size != 0: 00205 segment_list.append((offset, addr, size)) 00206 return segment_list 00207 00208 def parse_load_segment(toolchain, image_elf): 00209 if toolchain == "GCC_ARM": 00210 return parse_load_segment_gcc(image_elf) 00211 elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]: 00212 return parse_load_segment_armcc(image_elf) 00213 elif toolchain == "IAR": 00214 return parse_load_segment_iar(image_elf) 00215 else: 00216 return [] 00217 00218 def create_payload(image_elf, ram2_bin, entry, segment): 00219 file_elf = open(image_elf, "rb") 00220 file_bin = open(ram2_bin, "wb") 00221 00222 write_number(int(entry), 8, file_bin) 00223 write_number(int(len(segment)), 8, file_bin) 00224 write_number(0xFFFFFFFF, 8, file_bin) 00225 write_number(0xFFFFFFFF, 8, file_bin) 00226 00227 for (offset, addr, size) in segment: 00228 file_elf.seek(offset) 00229 # write image header - size & addr 00230 write_number(addr, 8, file_bin) 00231 write_number(size, 8, file_bin) 00232 # write load segment 00233 file_bin.write(file_elf.read(size)) 00234 delta = size % 4 00235 if delta != 0: 00236 padding = 4 - delta 00237 write_number(0x0, padding * 2, file_bin) 00238 file_bin.close() 00239 file_elf.close() 00240 00241 def create_daplink(image_bin, ram1_bin, ram2_bin): 00242 00243 # remove target binary file/path 00244 if os.path.isfile(image_bin): 00245 os.remove(image_bin) 00246 else: 00247 shutil.rmtree(image_bin) 00248 00249 RAM2_HEADER['tag'] = format_number(TAG, 8) 00250 RAM2_HEADER['ver'] = format_number(VER, 8) 00251 RAM2_HEADER['timestamp'] = format_number(epoch_timestamp(), 16) 00252 RAM2_HEADER['size'] = format_number(os.stat(ram2_bin).st_size + 72, 8) 00253 RAM2_HEADER['hash'] = format_string(sha256_checksum(ram2_bin)) 00254 RAM2_HEADER['campaign'] = format_string(CAMPAIGN) 00255 00256 output = open(image_bin, "wb") 00257 append_image_file(ram1_bin, output) 00258 append_image_file(ram2_bin, output) 00259 00260 output.seek(0xb000) 00261 line = "" 00262 for key in ['tag', 'ver', 'timestamp', 'size', 'hash', 'campaign']: 00263 line += RAM2_HEADER[key] 00264 output.write(RAM2_HEADER[key]) 00265 00266 RAM2_HEADER['crc32'] = format_number(crc32_checksum(line), 8) 00267 00268 output.write(RAM2_HEADER['crc32']) 00269 output.close() 00270 00271 # ---------------------------- 00272 # main function 00273 # ---------------------------- 00274 def rtl8195a_elf2bin(t_self, image_elf, image_bin): 00275 00276 image_name = list(os.path.splitext(image_elf))[:-1] 00277 image_map = ".".join(image_name + ['map']) 00278 00279 ram1_bin = os.path.join(TOOLS_BOOTLOADERS, "REALTEK_RTL8195AM", "ram_1.bin") 00280 ram2_bin = ".".join(image_name) + '-payload.bin' 00281 00282 entry = find_symbol(t_self.name, image_map, "PLAT_Start") 00283 segment = parse_load_segment(t_self.name, image_elf) 00284 00285 create_payload(image_elf, ram2_bin, entry, segment) 00286 create_daplink(image_bin, ram1_bin, ram2_bin)
Generated on Tue Jul 12 2022 12:22:18 by
