mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

UserRevisionLine numberNew contents of line
be_bryan 0:b74591d5ab33 1 """
be_bryan 0:b74591d5ab33 2 Realtek Semiconductor Corp.
be_bryan 0:b74591d5ab33 3
be_bryan 0:b74591d5ab33 4 RTL8195A elf2bin script
be_bryan 0:b74591d5ab33 5 """
be_bryan 0:b74591d5ab33 6
be_bryan 0:b74591d5ab33 7 import sys, array, struct, os, re, subprocess
be_bryan 0:b74591d5ab33 8 import hashlib
be_bryan 0:b74591d5ab33 9 import shutil
be_bryan 0:b74591d5ab33 10 import time
be_bryan 0:b74591d5ab33 11 import binascii
be_bryan 0:b74591d5ab33 12
be_bryan 0:b74591d5ab33 13 from tools.paths import TOOLS_BOOTLOADERS
be_bryan 0:b74591d5ab33 14 from tools.toolchains import TOOLCHAIN_PATHS
be_bryan 0:b74591d5ab33 15
be_bryan 0:b74591d5ab33 16 # Constant Variables
be_bryan 0:b74591d5ab33 17 TAG = 0x81950001
be_bryan 0:b74591d5ab33 18 VER = 0x81950001
be_bryan 0:b74591d5ab33 19 CAMPAIGN = binascii.hexlify('FFFFFFFFFFFFFFFF')
be_bryan 0:b74591d5ab33 20
be_bryan 0:b74591d5ab33 21 RAM2_HEADER = {
be_bryan 0:b74591d5ab33 22 'tag': 0,
be_bryan 0:b74591d5ab33 23 'ver': 0,
be_bryan 0:b74591d5ab33 24 'timestamp': 0,
be_bryan 0:b74591d5ab33 25 'size': 72,
be_bryan 0:b74591d5ab33 26 'hash': 'FF',
be_bryan 0:b74591d5ab33 27 'campaign': 'FF',
be_bryan 0:b74591d5ab33 28 'crc32': 0xFFFFFFFF,
be_bryan 0:b74591d5ab33 29 }
be_bryan 0:b74591d5ab33 30
be_bryan 0:b74591d5ab33 31 def format_number(number, width):
be_bryan 0:b74591d5ab33 32 # convert to string
be_bryan 0:b74591d5ab33 33 line = format(number, '0%dx' % (width))
be_bryan 0:b74591d5ab33 34 if len(line) > width:
be_bryan 0:b74591d5ab33 35 print "[ERROR] 0x%s cannot fit in width %d" % (line, width)
be_bryan 0:b74591d5ab33 36 sys.exit(-1)
be_bryan 0:b74591d5ab33 37 # cut string to list & reverse
be_bryan 0:b74591d5ab33 38 line = [line[i:i+2] for i in range(0, len(line), 2)]
be_bryan 0:b74591d5ab33 39 line.reverse()
be_bryan 0:b74591d5ab33 40 return binascii.a2b_hex("".join(line))
be_bryan 0:b74591d5ab33 41
be_bryan 0:b74591d5ab33 42 def format_string(string):
be_bryan 0:b74591d5ab33 43 return binascii.a2b_hex(string)
be_bryan 0:b74591d5ab33 44
be_bryan 0:b74591d5ab33 45 def write_number(value, width, output):
be_bryan 0:b74591d5ab33 46 output.write(format_number(value, width))
be_bryan 0:b74591d5ab33 47
be_bryan 0:b74591d5ab33 48 def write_string(value, width, output):
be_bryan 0:b74591d5ab33 49 output.write(format_string(value))
be_bryan 0:b74591d5ab33 50
be_bryan 0:b74591d5ab33 51 def append_image_file(image, output):
be_bryan 0:b74591d5ab33 52 input = open(image, "rb")
be_bryan 0:b74591d5ab33 53 output.write(input.read())
be_bryan 0:b74591d5ab33 54 input.close()
be_bryan 0:b74591d5ab33 55
be_bryan 0:b74591d5ab33 56 def write_padding_bytes(output_name, size):
be_bryan 0:b74591d5ab33 57 current_size = os.stat(output_name).st_size
be_bryan 0:b74591d5ab33 58 padcount = size - current_size
be_bryan 0:b74591d5ab33 59 if padcount < 0:
be_bryan 0:b74591d5ab33 60 print "[ERROR] image is larger than expected size"
be_bryan 0:b74591d5ab33 61 sys.exit(-1)
be_bryan 0:b74591d5ab33 62 output = open(output_name, "ab")
be_bryan 0:b74591d5ab33 63 output.write('\377' * padcount)
be_bryan 0:b74591d5ab33 64 output.close()
be_bryan 0:b74591d5ab33 65
be_bryan 0:b74591d5ab33 66 def crc32_checksum(string):
be_bryan 0:b74591d5ab33 67 return binascii.crc32(string) & 0xFFFFFFFF
be_bryan 0:b74591d5ab33 68
be_bryan 0:b74591d5ab33 69 def sha256_checksum(filename, block_size=65536):
be_bryan 0:b74591d5ab33 70 sha256 = hashlib.sha256()
be_bryan 0:b74591d5ab33 71 with open(filename, 'rb') as f:
be_bryan 0:b74591d5ab33 72 for block in iter(lambda: f.read(block_size), b''):
be_bryan 0:b74591d5ab33 73 sha256.update(block)
be_bryan 0:b74591d5ab33 74 return sha256.hexdigest()
be_bryan 0:b74591d5ab33 75
be_bryan 0:b74591d5ab33 76 def epoch_timestamp():
be_bryan 0:b74591d5ab33 77 epoch = int(time.time())
be_bryan 0:b74591d5ab33 78 return epoch
be_bryan 0:b74591d5ab33 79
be_bryan 0:b74591d5ab33 80 def find_symbol(toolchain, mapfile, symbol):
be_bryan 0:b74591d5ab33 81 ret = None
be_bryan 0:b74591d5ab33 82
be_bryan 0:b74591d5ab33 83 HEX = '0x0{,8}(?P<addr>[0-9A-Fa-f]{8})'
be_bryan 0:b74591d5ab33 84 if toolchain == "GCC_ARM":
be_bryan 0:b74591d5ab33 85 SYM = re.compile(r'^\s+' + HEX + r'\s+' + symbol + '\r?$')
be_bryan 0:b74591d5ab33 86 elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]:
be_bryan 0:b74591d5ab33 87 SYM = re.compile(r'^\s+' + HEX + r'\s+0x[0-9A-Fa-f]{8}\s+Code.*\s+i\.' + symbol + r'\s+.*$')
be_bryan 0:b74591d5ab33 88 elif toolchain == "IAR":
be_bryan 0:b74591d5ab33 89 SYM = re.compile(r'^' + symbol + r'\s+' + HEX + '\s+.*$')
be_bryan 0:b74591d5ab33 90
be_bryan 0:b74591d5ab33 91 with open(mapfile, 'r') as infile:
be_bryan 0:b74591d5ab33 92 for line in infile:
be_bryan 0:b74591d5ab33 93 match = re.match(SYM, line)
be_bryan 0:b74591d5ab33 94 if match:
be_bryan 0:b74591d5ab33 95 ret = match.group("addr")
be_bryan 0:b74591d5ab33 96
be_bryan 0:b74591d5ab33 97 if not ret:
be_bryan 0:b74591d5ab33 98 print "[ERROR] cannot find the address of symbol " + symbol
be_bryan 0:b74591d5ab33 99 return 0
be_bryan 0:b74591d5ab33 100
be_bryan 0:b74591d5ab33 101 return int(ret,16) | 1
be_bryan 0:b74591d5ab33 102
be_bryan 0:b74591d5ab33 103 def parse_load_segment_gcc(image_elf):
be_bryan 0:b74591d5ab33 104 # Program Headers:
be_bryan 0:b74591d5ab33 105 # Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
be_bryan 0:b74591d5ab33 106 # LOAD 0x000034 0x10006000 0x10006000 0x026bc 0x026bc RW 0x8
be_bryan 0:b74591d5ab33 107 # LOAD 0x0026f0 0x30000000 0x30000000 0x06338 0x06338 RWE 0x4
be_bryan 0:b74591d5ab33 108 segment_list = []
be_bryan 0:b74591d5ab33 109 cmd = os.path.join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-readelf')
be_bryan 0:b74591d5ab33 110 cmd = '"' + cmd + '"' + ' -l ' + image_elf
be_bryan 0:b74591d5ab33 111 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"):
be_bryan 0:b74591d5ab33 112 if not line.startswith(" LOAD"):
be_bryan 0:b74591d5ab33 113 continue
be_bryan 0:b74591d5ab33 114 segment = line.split()
be_bryan 0:b74591d5ab33 115 if len(segment) != 8:
be_bryan 0:b74591d5ab33 116 continue
be_bryan 0:b74591d5ab33 117 offset = int(segment[1][2:], 16)
be_bryan 0:b74591d5ab33 118 addr = int(segment[2][2:], 16)
be_bryan 0:b74591d5ab33 119 size = int(segment[4][2:], 16)
be_bryan 0:b74591d5ab33 120 if addr != 0 and size != 0:
be_bryan 0:b74591d5ab33 121 segment_list.append((offset, addr, size))
be_bryan 0:b74591d5ab33 122 return segment_list
be_bryan 0:b74591d5ab33 123
be_bryan 0:b74591d5ab33 124 def parse_load_segment_armcc(image_elf):
be_bryan 0:b74591d5ab33 125 # ====================================
be_bryan 0:b74591d5ab33 126 #
be_bryan 0:b74591d5ab33 127 # ** Program header #2
be_bryan 0:b74591d5ab33 128 #
be_bryan 0:b74591d5ab33 129 # Type : PT_LOAD (1)
be_bryan 0:b74591d5ab33 130 # File Offset : 52 (0x34)
be_bryan 0:b74591d5ab33 131 # Virtual Addr : 0x30000000
be_bryan 0:b74591d5ab33 132 # Physical Addr : 0x30000000
be_bryan 0:b74591d5ab33 133 # Size in file : 27260 bytes (0x6a7c)
be_bryan 0:b74591d5ab33 134 # Size in memory: 42168 bytes (0xa4b8)
be_bryan 0:b74591d5ab33 135 # Flags : PF_X + PF_W + PF_R + PF_ARM_ENTRY (0x80000007)
be_bryan 0:b74591d5ab33 136 # Alignment : 8
be_bryan 0:b74591d5ab33 137 #
be_bryan 0:b74591d5ab33 138 (offset, addr, size) = (0, 0, 0)
be_bryan 0:b74591d5ab33 139 segment_list = []
be_bryan 0:b74591d5ab33 140 in_segment = False
be_bryan 0:b74591d5ab33 141 cmd = os.path.join(TOOLCHAIN_PATHS['ARM'], 'bin', 'fromelf')
be_bryan 0:b74591d5ab33 142 cmd = '"' + cmd + '"' + ' --text -v --only=none ' + image_elf
be_bryan 0:b74591d5ab33 143 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"):
be_bryan 0:b74591d5ab33 144 if line == "":
be_bryan 0:b74591d5ab33 145 pass
be_bryan 0:b74591d5ab33 146 elif line.startswith("** Program header"):
be_bryan 0:b74591d5ab33 147 in_segment = True
be_bryan 0:b74591d5ab33 148 elif in_segment == False:
be_bryan 0:b74591d5ab33 149 pass
be_bryan 0:b74591d5ab33 150 elif line.startswith("============"):
be_bryan 0:b74591d5ab33 151 if addr != 0 and size != 0:
be_bryan 0:b74591d5ab33 152 segment_list.append((offset, addr, size))
be_bryan 0:b74591d5ab33 153 in_segment = False
be_bryan 0:b74591d5ab33 154 (offset, addr, size) = (0, 0, 0)
be_bryan 0:b74591d5ab33 155 elif line.startswith(" Type"):
be_bryan 0:b74591d5ab33 156 if not re.match(r'\s+Type\s+:\s+PT_LOAD\s.*$', line):
be_bryan 0:b74591d5ab33 157 in_segment = False
be_bryan 0:b74591d5ab33 158 elif line.startswith(" File Offset"):
be_bryan 0:b74591d5ab33 159 match = re.match(r'^\s+File Offset\s+:\s+(?P<offset>\d+).*$', line)
be_bryan 0:b74591d5ab33 160 if match:
be_bryan 0:b74591d5ab33 161 offset = int(match.group("offset"))
be_bryan 0:b74591d5ab33 162 elif line.startswith(" Virtual Addr"):
be_bryan 0:b74591d5ab33 163 match = re.match(r'^\s+Virtual Addr\s+:\s+0x(?P<addr>[0-9a-f]+).*$', line)
be_bryan 0:b74591d5ab33 164 if match:
be_bryan 0:b74591d5ab33 165 addr = int(match.group("addr"), 16)
be_bryan 0:b74591d5ab33 166 elif line.startswith(" Size in file"):
be_bryan 0:b74591d5ab33 167 match = re.match(r'^\s+Size in file\s+:.*\(0x(?P<size>[0-9a-f]+)\).*$', line)
be_bryan 0:b74591d5ab33 168 if match:
be_bryan 0:b74591d5ab33 169 size = int(match.group("size"), 16)
be_bryan 0:b74591d5ab33 170 return segment_list
be_bryan 0:b74591d5ab33 171
be_bryan 0:b74591d5ab33 172
be_bryan 0:b74591d5ab33 173 def parse_load_segment_iar(image_elf):
be_bryan 0:b74591d5ab33 174 # SEGMENTS:
be_bryan 0:b74591d5ab33 175 #
be_bryan 0:b74591d5ab33 176 # Type Offset Virtual Physical File Sz Mem Sz Flags Align
be_bryan 0:b74591d5ab33 177 # ---- ------ ------- -------- ------- ------ ----- -----
be_bryan 0:b74591d5ab33 178 # 0: load 0x34 0x10006000 0x10006000 0x26bc 0x26bc 0x6 WR 0x8
be_bryan 0:b74591d5ab33 179 # 1: load 0x26f0 0x30000000 0x30000000 0x6338 0x6338 0x7 XWR 0x4
be_bryan 0:b74591d5ab33 180 #
be_bryan 0:b74591d5ab33 181 # SECTIONS:
be_bryan 0:b74591d5ab33 182 #
be_bryan 0:b74591d5ab33 183 # Name Type Addr Offset Size Aln Lnk Inf ESz Flags
be_bryan 0:b74591d5ab33 184 # ---- ---- ---- ------ ---- --- --- --- --- -----
be_bryan 0:b74591d5ab33 185 # 1: .shstrtab strtab 0xfc4d8 0x60 0x4
be_bryan 0:b74591d5ab33 186 # 2: .strtab strtab 0xfc538 0xbb3f 0x4
be_bryan 0:b74591d5ab33 187
be_bryan 0:b74591d5ab33 188 segment_list = []
be_bryan 0:b74591d5ab33 189 in_segment = False
be_bryan 0:b74591d5ab33 190 cmd = os.path.join(TOOLCHAIN_PATHS['IAR'], 'bin', 'ielfdumparm')
be_bryan 0:b74591d5ab33 191 cmd = '"' + cmd + '"' + ' ' + image_elf
be_bryan 0:b74591d5ab33 192 for line in subprocess.check_output(cmd, shell=True, universal_newlines=True).split("\n"):
be_bryan 0:b74591d5ab33 193 if line.startswith(" SEGMENTS:"):
be_bryan 0:b74591d5ab33 194 in_segment = True
be_bryan 0:b74591d5ab33 195 elif in_segment == False:
be_bryan 0:b74591d5ab33 196 pass
be_bryan 0:b74591d5ab33 197 elif line.startswith(" SECTIONS:"):
be_bryan 0:b74591d5ab33 198 break
be_bryan 0:b74591d5ab33 199 elif re.match(r'^\s+\w+:\s+load\s+.*$', line):
be_bryan 0:b74591d5ab33 200 segment = line.split()
be_bryan 0:b74591d5ab33 201 offset = int(segment[2][2:], 16)
be_bryan 0:b74591d5ab33 202 addr = int(segment[3][2:], 16)
be_bryan 0:b74591d5ab33 203 size = int(segment[5][2:], 16)
be_bryan 0:b74591d5ab33 204 if addr != 0 and size != 0:
be_bryan 0:b74591d5ab33 205 segment_list.append((offset, addr, size))
be_bryan 0:b74591d5ab33 206 return segment_list
be_bryan 0:b74591d5ab33 207
be_bryan 0:b74591d5ab33 208 def parse_load_segment(toolchain, image_elf):
be_bryan 0:b74591d5ab33 209 if toolchain == "GCC_ARM":
be_bryan 0:b74591d5ab33 210 return parse_load_segment_gcc(image_elf)
be_bryan 0:b74591d5ab33 211 elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]:
be_bryan 0:b74591d5ab33 212 return parse_load_segment_armcc(image_elf)
be_bryan 0:b74591d5ab33 213 elif toolchain == "IAR":
be_bryan 0:b74591d5ab33 214 return parse_load_segment_iar(image_elf)
be_bryan 0:b74591d5ab33 215 else:
be_bryan 0:b74591d5ab33 216 return []
be_bryan 0:b74591d5ab33 217
be_bryan 0:b74591d5ab33 218 def create_payload(image_elf, ram2_bin, entry, segment):
be_bryan 0:b74591d5ab33 219 file_elf = open(image_elf, "rb")
be_bryan 0:b74591d5ab33 220 file_bin = open(ram2_bin, "wb")
be_bryan 0:b74591d5ab33 221
be_bryan 0:b74591d5ab33 222 write_number(int(entry), 8, file_bin)
be_bryan 0:b74591d5ab33 223 write_number(int(len(segment)), 8, file_bin)
be_bryan 0:b74591d5ab33 224 write_number(0xFFFFFFFF, 8, file_bin)
be_bryan 0:b74591d5ab33 225 write_number(0xFFFFFFFF, 8, file_bin)
be_bryan 0:b74591d5ab33 226
be_bryan 0:b74591d5ab33 227 for (offset, addr, size) in segment:
be_bryan 0:b74591d5ab33 228 file_elf.seek(offset)
be_bryan 0:b74591d5ab33 229 # write image header - size & addr
be_bryan 0:b74591d5ab33 230 write_number(addr, 8, file_bin)
be_bryan 0:b74591d5ab33 231 write_number(size, 8, file_bin)
be_bryan 0:b74591d5ab33 232 # write load segment
be_bryan 0:b74591d5ab33 233 file_bin.write(file_elf.read(size))
be_bryan 0:b74591d5ab33 234 delta = size % 4
be_bryan 0:b74591d5ab33 235 if delta != 0:
be_bryan 0:b74591d5ab33 236 padding = 4 - delta
be_bryan 0:b74591d5ab33 237 write_number(0x0, padding * 2, file_bin)
be_bryan 0:b74591d5ab33 238 file_bin.close()
be_bryan 0:b74591d5ab33 239 file_elf.close()
be_bryan 0:b74591d5ab33 240
be_bryan 0:b74591d5ab33 241 def create_daplink(image_bin, ram1_bin, ram2_bin):
be_bryan 0:b74591d5ab33 242
be_bryan 0:b74591d5ab33 243 # remove target binary file/path
be_bryan 0:b74591d5ab33 244 if os.path.isfile(image_bin):
be_bryan 0:b74591d5ab33 245 os.remove(image_bin)
be_bryan 0:b74591d5ab33 246 else:
be_bryan 0:b74591d5ab33 247 shutil.rmtree(image_bin)
be_bryan 0:b74591d5ab33 248
be_bryan 0:b74591d5ab33 249 RAM2_HEADER['tag'] = format_number(TAG, 8)
be_bryan 0:b74591d5ab33 250 RAM2_HEADER['ver'] = format_number(VER, 8)
be_bryan 0:b74591d5ab33 251 RAM2_HEADER['timestamp'] = format_number(epoch_timestamp(), 16)
be_bryan 0:b74591d5ab33 252 RAM2_HEADER['size'] = format_number(os.stat(ram2_bin).st_size + 72, 8)
be_bryan 0:b74591d5ab33 253 RAM2_HEADER['hash'] = format_string(sha256_checksum(ram2_bin))
be_bryan 0:b74591d5ab33 254 RAM2_HEADER['campaign'] = format_string(CAMPAIGN)
be_bryan 0:b74591d5ab33 255
be_bryan 0:b74591d5ab33 256 output = open(image_bin, "wb")
be_bryan 0:b74591d5ab33 257 append_image_file(ram1_bin, output)
be_bryan 0:b74591d5ab33 258
be_bryan 0:b74591d5ab33 259 line = ""
be_bryan 0:b74591d5ab33 260 for key in ['tag', 'ver', 'timestamp', 'size', 'hash', 'campaign']:
be_bryan 0:b74591d5ab33 261 line += RAM2_HEADER[key]
be_bryan 0:b74591d5ab33 262 output.write(RAM2_HEADER[key])
be_bryan 0:b74591d5ab33 263
be_bryan 0:b74591d5ab33 264 RAM2_HEADER['crc32'] = format_number(crc32_checksum(line), 8)
be_bryan 0:b74591d5ab33 265
be_bryan 0:b74591d5ab33 266 output.write(RAM2_HEADER['crc32'])
be_bryan 0:b74591d5ab33 267 append_image_file(ram2_bin, output)
be_bryan 0:b74591d5ab33 268 output.close()
be_bryan 0:b74591d5ab33 269
be_bryan 0:b74591d5ab33 270 # ----------------------------
be_bryan 0:b74591d5ab33 271 # main function
be_bryan 0:b74591d5ab33 272 # ----------------------------
be_bryan 0:b74591d5ab33 273 def rtl8195a_elf2bin(t_self, image_elf, image_bin):
be_bryan 0:b74591d5ab33 274
be_bryan 0:b74591d5ab33 275 image_name = os.path.splitext(image_elf)[0]
be_bryan 0:b74591d5ab33 276 image_map = image_name + '.map'
be_bryan 0:b74591d5ab33 277
be_bryan 0:b74591d5ab33 278 ram1_bin = os.path.join(TOOLS_BOOTLOADERS, "REALTEK_RTL8195AM", "ram_1.bin")
be_bryan 0:b74591d5ab33 279 ram2_bin = image_name + '-payload.bin'
be_bryan 0:b74591d5ab33 280
be_bryan 0:b74591d5ab33 281 entry = find_symbol(t_self.name, image_map, "PLAT_Start")
be_bryan 0:b74591d5ab33 282 segment = parse_load_segment(t_self.name, image_elf)
be_bryan 0:b74591d5ab33 283
be_bryan 0:b74591d5ab33 284 create_payload(image_elf, ram2_bin, entry, segment)
be_bryan 0:b74591d5ab33 285 create_daplink(image_bin, ram1_bin, ram2_bin)