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