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