Clone of official tools
targets/REALTEK_RTL8195AM.py@47:21ae3e5a7128, 2021-02-04 (annotated)
- Committer:
- Anders Blomdell
- Date:
- Thu Feb 04 17:17:13 2021 +0100
- Revision:
- 47:21ae3e5a7128
- Parent:
- 43:2a7da56ebd24
Add a few normpath calls
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
The Other Jimmy |
36:96847d42f010 | 1 | """ |
theotherjimmy |
40:7d3fa6b99b2b | 2 | Realtek Semiconductor Corp. |
The Other Jimmy |
36:96847d42f010 | 3 | |
theotherjimmy |
40:7d3fa6b99b2b | 4 | RTL8195A elf2bin script |
The Other Jimmy |
36:96847d42f010 | 5 | """ |
The Other Jimmy |
36:96847d42f010 | 6 | |
The Other Jimmy |
36:96847d42f010 | 7 | import sys, array, struct, os, re, subprocess |
The Other Jimmy |
36:96847d42f010 | 8 | import hashlib |
theotherjimmy |
40:7d3fa6b99b2b | 9 | import shutil |
theotherjimmy |
43:2a7da56ebd24 | 10 | import time |
theotherjimmy |
43:2a7da56ebd24 | 11 | import binascii |
theotherjimmy |
43:2a7da56ebd24 | 12 | import elftools |
The Other Jimmy |
36:96847d42f010 | 13 | |
The Other Jimmy |
36:96847d42f010 | 14 | from tools.paths import TOOLS_BOOTLOADERS |
theotherjimmy |
41:2a77626a4c21 | 15 | from tools.toolchains import TOOLCHAIN_PATHS |
The Other Jimmy |
36:96847d42f010 | 16 | |
The Other Jimmy |
36:96847d42f010 | 17 | # Constant Variables |
theotherjimmy |
43:2a7da56ebd24 | 18 | TAG = 0x81950001 |
theotherjimmy |
43:2a7da56ebd24 | 19 | VER = 0x81950001 |
theotherjimmy |
43:2a7da56ebd24 | 20 | CAMPAIGN = binascii.hexlify('FFFFFFFFFFFFFFFF') |
The Other Jimmy |
36:96847d42f010 | 21 | |
theotherjimmy |
43:2a7da56ebd24 | 22 | RAM2_HEADER = { |
theotherjimmy |
43:2a7da56ebd24 | 23 | 'tag': 0, |
theotherjimmy |
43:2a7da56ebd24 | 24 | 'ver': 0, |
theotherjimmy |
43:2a7da56ebd24 | 25 | 'timestamp': 0, |
theotherjimmy |
43:2a7da56ebd24 | 26 | 'size': 72, |
theotherjimmy |
43:2a7da56ebd24 | 27 | 'hash': 'FF', |
theotherjimmy |
43:2a7da56ebd24 | 28 | 'campaign': 'FF', |
theotherjimmy |
43:2a7da56ebd24 | 29 | 'crc32': 0xFFFFFFFF, |
theotherjimmy |
43:2a7da56ebd24 | 30 | } |
The Other Jimmy |
36:96847d42f010 | 31 | |
theotherjimmy |
43:2a7da56ebd24 | 32 | def format_number(number, width): |
theotherjimmy |
43:2a7da56ebd24 | 33 | # convert to string |
theotherjimmy |
43:2a7da56ebd24 | 34 | line = format(number, '0%dx' % (width)) |
theotherjimmy |
43:2a7da56ebd24 | 35 | if len(line) > width: |
theotherjimmy |
43:2a7da56ebd24 | 36 | print "[ERROR] 0x%s cannot fit in width %d" % (line, width) |
theotherjimmy |
43:2a7da56ebd24 | 37 | sys.exit(-1) |
theotherjimmy |
43:2a7da56ebd24 | 38 | # cut string to list & reverse |
theotherjimmy |
43:2a7da56ebd24 | 39 | line = [line[i:i+2] for i in range(0, len(line), 2)] |
theotherjimmy |
43:2a7da56ebd24 | 40 | line.reverse() |
theotherjimmy |
43:2a7da56ebd24 | 41 | return binascii.a2b_hex("".join(line)) |
theotherjimmy |
43:2a7da56ebd24 | 42 | |
theotherjimmy |
43:2a7da56ebd24 | 43 | def format_string(string): |
theotherjimmy |
43:2a7da56ebd24 | 44 | return binascii.a2b_hex(string) |
theotherjimmy |
43:2a7da56ebd24 | 45 | |
theotherjimmy |
43:2a7da56ebd24 | 46 | def write_number(value, width, output): |
theotherjimmy |
43:2a7da56ebd24 | 47 | output.write(format_number(value, width)) |
theotherjimmy |
43:2a7da56ebd24 | 48 | |
theotherjimmy |
43:2a7da56ebd24 | 49 | def write_string(value, width, output): |
theotherjimmy |
43:2a7da56ebd24 | 50 | output.write(format_string(value)) |
The Other Jimmy |
36:96847d42f010 | 51 | |
The Other Jimmy |
36:96847d42f010 | 52 | def append_image_file(image, output): |
The Other Jimmy |
36:96847d42f010 | 53 | input = open(image, "rb") |
The Other Jimmy |
36:96847d42f010 | 54 | output.write(input.read()) |
The Other Jimmy |
36:96847d42f010 | 55 | input.close() |
The Other Jimmy |
36:96847d42f010 | 56 | |
theotherjimmy |
40:7d3fa6b99b2b | 57 | def write_padding_bytes(output_name, size): |
theotherjimmy |
40:7d3fa6b99b2b | 58 | current_size = os.stat(output_name).st_size |
theotherjimmy |
40:7d3fa6b99b2b | 59 | padcount = size - current_size |
theotherjimmy |
40:7d3fa6b99b2b | 60 | if padcount < 0: |
theotherjimmy |
40:7d3fa6b99b2b | 61 | print "[ERROR] image is larger than expected size" |
theotherjimmy |
40:7d3fa6b99b2b | 62 | sys.exit(-1) |
theotherjimmy |
40:7d3fa6b99b2b | 63 | output = open(output_name, "ab") |
theotherjimmy |
40:7d3fa6b99b2b | 64 | output.write('\377' * padcount) |
The Other Jimmy |
36:96847d42f010 | 65 | output.close() |
The Other Jimmy |
36:96847d42f010 | 66 | |
theotherjimmy |
43:2a7da56ebd24 | 67 | def crc32_checksum(string): |
theotherjimmy |
43:2a7da56ebd24 | 68 | return binascii.crc32(string) & 0xFFFFFFFF |
theotherjimmy |
43:2a7da56ebd24 | 69 | |
theotherjimmy |
40:7d3fa6b99b2b | 70 | def sha256_checksum(filename, block_size=65536): |
theotherjimmy |
40:7d3fa6b99b2b | 71 | sha256 = hashlib.sha256() |
theotherjimmy |
40:7d3fa6b99b2b | 72 | with open(filename, 'rb') as f: |
theotherjimmy |
40:7d3fa6b99b2b | 73 | for block in iter(lambda: f.read(block_size), b''): |
theotherjimmy |
40:7d3fa6b99b2b | 74 | sha256.update(block) |
theotherjimmy |
40:7d3fa6b99b2b | 75 | return sha256.hexdigest() |
The Other Jimmy |
36:96847d42f010 | 76 | |
theotherjimmy |
43:2a7da56ebd24 | 77 | def epoch_timestamp(): |
theotherjimmy |
43:2a7da56ebd24 | 78 | epoch = int(time.time()) |
theotherjimmy |
43:2a7da56ebd24 | 79 | return epoch |
theotherjimmy |
40:7d3fa6b99b2b | 80 | |
theotherjimmy |
40:7d3fa6b99b2b | 81 | def find_symbol(toolchain, mapfile, symbol): |
theotherjimmy |
40:7d3fa6b99b2b | 82 | ret = None |
theotherjimmy |
40:7d3fa6b99b2b | 83 | |
theotherjimmy |
40:7d3fa6b99b2b | 84 | HEX = '0x0{,8}(?P<addr>[0-9A-Fa-f]{8})' |
The Other Jimmy |
36:96847d42f010 | 85 | if toolchain == "GCC_ARM": |
theotherjimmy |
40:7d3fa6b99b2b | 86 | SYM = re.compile(r'^\s+' + HEX + r'\s+' + symbol + '\r?$') |
The Other Jimmy |
36:96847d42f010 | 87 | elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]: |
theotherjimmy |
40:7d3fa6b99b2b | 88 | SYM = re.compile(r'^\s+' + HEX + r'\s+0x[0-9A-Fa-f]{8}\s+Code.*\s+i\.' + symbol + r'\s+.*$') |
The Other Jimmy |
36:96847d42f010 | 89 | elif toolchain == "IAR": |
theotherjimmy |
40:7d3fa6b99b2b | 90 | SYM = re.compile(r'^' + symbol + r'\s+' + HEX + '\s+.*$') |
theotherjimmy |
40:7d3fa6b99b2b | 91 | |
theotherjimmy |
40:7d3fa6b99b2b | 92 | with open(mapfile, 'r') as infile: |
theotherjimmy |
40:7d3fa6b99b2b | 93 | for line in infile: |
theotherjimmy |
40:7d3fa6b99b2b | 94 | match = re.match(SYM, line) |
theotherjimmy |
40:7d3fa6b99b2b | 95 | if match: |
theotherjimmy |
40:7d3fa6b99b2b | 96 | ret = match.group("addr") |
theotherjimmy |
40:7d3fa6b99b2b | 97 | |
theotherjimmy |
40:7d3fa6b99b2b | 98 | if not ret: |
theotherjimmy |
40:7d3fa6b99b2b | 99 | print "[ERROR] cannot find the address of symbol " + symbol |
theotherjimmy |
40:7d3fa6b99b2b | 100 | return 0 |
theotherjimmy |
40:7d3fa6b99b2b | 101 | |
theotherjimmy |
40:7d3fa6b99b2b | 102 | return int(ret,16) | 1 |
theotherjimmy |
40:7d3fa6b99b2b | 103 | |
theotherjimmy |
43:2a7da56ebd24 | 104 | def _parse_load_segment_inner(image_elf): |
theotherjimmy |
43:2a7da56ebd24 | 105 | with open(image_elf, "rb") as fd: |
theotherjimmy |
43:2a7da56ebd24 | 106 | elffile = elftools.elf.elffile.ELFFile(fd) |
theotherjimmy |
43:2a7da56ebd24 | 107 | for segment in elffile.iter_segments(): |
theotherjimmy |
43:2a7da56ebd24 | 108 | offset = segment['p_offset'] |
theotherjimmy |
43:2a7da56ebd24 | 109 | addr = segment['p_vaddr'] |
theotherjimmy |
43:2a7da56ebd24 | 110 | size = segment['p_filesz'] |
theotherjimmy |
43:2a7da56ebd24 | 111 | if (addr != 0 and size != 0 and segment['p_type'] == 'PT_LOAD'): |
theotherjimmy |
43:2a7da56ebd24 | 112 | yield offset, addr, size |
theotherjimmy |
40:7d3fa6b99b2b | 113 | |
theotherjimmy |
40:7d3fa6b99b2b | 114 | def parse_load_segment(toolchain, image_elf): |
theotherjimmy |
43:2a7da56ebd24 | 115 | return list(_parse_load_segment_inner(image_elf)) |
theotherjimmy |
43:2a7da56ebd24 | 116 | |
theotherjimmy |
43:2a7da56ebd24 | 117 | def create_payload(image_elf, ram2_bin, entry, segment): |
theotherjimmy |
43:2a7da56ebd24 | 118 | file_elf = open(image_elf, "rb") |
theotherjimmy |
43:2a7da56ebd24 | 119 | file_bin = open(ram2_bin, "wb") |
theotherjimmy |
40:7d3fa6b99b2b | 120 | |
theotherjimmy |
43:2a7da56ebd24 | 121 | write_number(int(entry), 8, file_bin) |
theotherjimmy |
43:2a7da56ebd24 | 122 | write_number(int(len(segment)), 8, file_bin) |
theotherjimmy |
43:2a7da56ebd24 | 123 | write_number(0xFFFFFFFF, 8, file_bin) |
theotherjimmy |
43:2a7da56ebd24 | 124 | write_number(0xFFFFFFFF, 8, file_bin) |
theotherjimmy |
43:2a7da56ebd24 | 125 | |
theotherjimmy |
40:7d3fa6b99b2b | 126 | for (offset, addr, size) in segment: |
theotherjimmy |
40:7d3fa6b99b2b | 127 | file_elf.seek(offset) |
theotherjimmy |
40:7d3fa6b99b2b | 128 | # write image header - size & addr |
theotherjimmy |
43:2a7da56ebd24 | 129 | write_number(addr, 8, file_bin) |
theotherjimmy |
43:2a7da56ebd24 | 130 | write_number(size, 8, file_bin) |
theotherjimmy |
40:7d3fa6b99b2b | 131 | # write load segment |
theotherjimmy |
40:7d3fa6b99b2b | 132 | file_bin.write(file_elf.read(size)) |
theotherjimmy |
40:7d3fa6b99b2b | 133 | delta = size % 4 |
theotherjimmy |
40:7d3fa6b99b2b | 134 | if delta != 0: |
theotherjimmy |
40:7d3fa6b99b2b | 135 | padding = 4 - delta |
theotherjimmy |
43:2a7da56ebd24 | 136 | write_number(0x0, padding * 2, file_bin) |
theotherjimmy |
40:7d3fa6b99b2b | 137 | file_bin.close() |
theotherjimmy |
40:7d3fa6b99b2b | 138 | file_elf.close() |
theotherjimmy |
40:7d3fa6b99b2b | 139 | |
theotherjimmy |
43:2a7da56ebd24 | 140 | def create_daplink(image_bin, ram1_bin, ram2_bin): |
theotherjimmy |
43:2a7da56ebd24 | 141 | |
theotherjimmy |
40:7d3fa6b99b2b | 142 | # remove target binary file/path |
theotherjimmy |
40:7d3fa6b99b2b | 143 | if os.path.isfile(image_bin): |
theotherjimmy |
40:7d3fa6b99b2b | 144 | os.remove(image_bin) |
theotherjimmy |
40:7d3fa6b99b2b | 145 | else: |
theotherjimmy |
40:7d3fa6b99b2b | 146 | shutil.rmtree(image_bin) |
theotherjimmy |
40:7d3fa6b99b2b | 147 | |
theotherjimmy |
43:2a7da56ebd24 | 148 | RAM2_HEADER['tag'] = format_number(TAG, 8) |
theotherjimmy |
43:2a7da56ebd24 | 149 | RAM2_HEADER['ver'] = format_number(VER, 8) |
theotherjimmy |
43:2a7da56ebd24 | 150 | RAM2_HEADER['timestamp'] = format_number(epoch_timestamp(), 16) |
theotherjimmy |
43:2a7da56ebd24 | 151 | RAM2_HEADER['size'] = format_number(os.stat(ram2_bin).st_size + 72, 8) |
theotherjimmy |
43:2a7da56ebd24 | 152 | RAM2_HEADER['hash'] = format_string(sha256_checksum(ram2_bin)) |
theotherjimmy |
43:2a7da56ebd24 | 153 | RAM2_HEADER['campaign'] = format_string(CAMPAIGN) |
The Other Jimmy |
36:96847d42f010 | 154 | |
The Other Jimmy |
36:96847d42f010 | 155 | output = open(image_bin, "wb") |
theotherjimmy |
40:7d3fa6b99b2b | 156 | append_image_file(ram1_bin, output) |
theotherjimmy |
40:7d3fa6b99b2b | 157 | append_image_file(ram2_bin, output) |
theotherjimmy |
43:2a7da56ebd24 | 158 | |
theotherjimmy |
43:2a7da56ebd24 | 159 | output.seek(0xb000) |
theotherjimmy |
43:2a7da56ebd24 | 160 | line = "" |
theotherjimmy |
43:2a7da56ebd24 | 161 | for key in ['tag', 'ver', 'timestamp', 'size', 'hash', 'campaign']: |
theotherjimmy |
43:2a7da56ebd24 | 162 | line += RAM2_HEADER[key] |
theotherjimmy |
43:2a7da56ebd24 | 163 | output.write(RAM2_HEADER[key]) |
theotherjimmy |
43:2a7da56ebd24 | 164 | |
theotherjimmy |
43:2a7da56ebd24 | 165 | RAM2_HEADER['crc32'] = format_number(crc32_checksum(line), 8) |
theotherjimmy |
43:2a7da56ebd24 | 166 | |
theotherjimmy |
43:2a7da56ebd24 | 167 | output.write(RAM2_HEADER['crc32']) |
The Other Jimmy |
36:96847d42f010 | 168 | output.close() |
theotherjimmy |
43:2a7da56ebd24 | 169 | |
theotherjimmy |
43:2a7da56ebd24 | 170 | # ---------------------------- |
theotherjimmy |
43:2a7da56ebd24 | 171 | # main function |
theotherjimmy |
43:2a7da56ebd24 | 172 | # ---------------------------- |
theotherjimmy |
43:2a7da56ebd24 | 173 | def rtl8195a_elf2bin(t_self, image_elf, image_bin): |
theotherjimmy |
43:2a7da56ebd24 | 174 | |
theotherjimmy |
43:2a7da56ebd24 | 175 | image_name = list(os.path.splitext(image_elf))[:-1] |
theotherjimmy |
43:2a7da56ebd24 | 176 | image_map = ".".join(image_name + ['map']) |
theotherjimmy |
43:2a7da56ebd24 | 177 | |
theotherjimmy |
43:2a7da56ebd24 | 178 | ram1_bin = os.path.join(TOOLS_BOOTLOADERS, "REALTEK_RTL8195AM", "ram_1.bin") |
theotherjimmy |
43:2a7da56ebd24 | 179 | ram2_bin = ".".join(image_name) + '-payload.bin' |
theotherjimmy |
43:2a7da56ebd24 | 180 | |
theotherjimmy |
43:2a7da56ebd24 | 181 | entry = find_symbol(t_self.name, image_map, "PLAT_Start") |
theotherjimmy |
43:2a7da56ebd24 | 182 | segment = parse_load_segment(t_self.name, image_elf) |
theotherjimmy |
43:2a7da56ebd24 | 183 | |
theotherjimmy |
43:2a7da56ebd24 | 184 | create_payload(image_elf, ram2_bin, entry, segment) |
theotherjimmy |
43:2a7da56ebd24 | 185 | create_daplink(image_bin, ram1_bin, ram2_bin) |