Daniel Vizcaya / Mbed OS 04_RTOS_Embebidos
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers REALTEK_RTL8195AM.py Source File

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 import elftools
00013 
00014 from tools.paths import TOOLS_BOOTLOADERS
00015 from tools.toolchains import TOOLCHAIN_PATHS
00016 
00017 # Constant Variables
00018 TAG = 0x81950001
00019 VER = 0x81950001
00020 CAMPAIGN = binascii.hexlify('FFFFFFFFFFFFFFFF')
00021 
00022 RAM2_HEADER = {
00023     'tag': 0,
00024     'ver': 0,
00025     'timestamp': 0,
00026     'size': 72,
00027     'hash': 'FF',
00028     'campaign': 'FF',
00029     'crc32': 0xFFFFFFFF,
00030 }
00031 
00032 def format_number(number, width):
00033     # convert to string
00034     line = format(number, '0%dx' % (width))
00035     if len(line) > width:
00036         print "[ERROR] 0x%s cannot fit in width %d" % (line, width)
00037         sys.exit(-1)
00038     # cut string to list & reverse
00039     line = [line[i:i+2] for i in range(0, len(line), 2)]
00040     line.reverse()
00041     return binascii.a2b_hex("".join(line))
00042 
00043 def format_string(string):
00044     return binascii.a2b_hex(string)
00045 
00046 def write_number(value, width, output):
00047     output.write(format_number(value, width))
00048 
00049 def write_string(value, width, output):
00050     output.write(format_string(value))
00051 
00052 def append_image_file(image, output):
00053     input = open(image, "rb")
00054     output.write(input.read())
00055     input.close()
00056 
00057 def write_padding_bytes(output_name, size):
00058     current_size = os.stat(output_name).st_size
00059     padcount = size - current_size
00060     if padcount < 0:
00061         print "[ERROR] image is larger than expected size"
00062         sys.exit(-1)
00063     output = open(output_name, "ab")
00064     output.write('\377' * padcount)
00065     output.close()
00066 
00067 def crc32_checksum(string):
00068     return binascii.crc32(string) & 0xFFFFFFFF
00069 
00070 def sha256_checksum(filename, block_size=65536):
00071     sha256 = hashlib.sha256()
00072     with open(filename, 'rb') as f:
00073         for block in iter(lambda: f.read(block_size), b''):
00074             sha256.update(block)
00075     return sha256.hexdigest()
00076 
00077 def epoch_timestamp():
00078     epoch = int(time.time())
00079     return epoch
00080 
00081 def find_symbol(toolchain, mapfile, symbol):
00082     ret = None
00083 
00084     HEX = '0x0{,8}(?P<addr>[0-9A-Fa-f]{8})'
00085     if toolchain == "GCC_ARM":
00086         SYM = re.compile(r'^\s+' + HEX + r'\s+' + symbol + '\r?$')
00087     elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]:
00088         SYM = re.compile(r'^\s+' + HEX + r'\s+0x[0-9A-Fa-f]{8}\s+Code.*\s+i\.' + symbol + r'\s+.*$')
00089     elif toolchain == "IAR":
00090         SYM = re.compile(r'^' + symbol + r'\s+' + HEX + '\s+.*$')
00091 
00092     with open(mapfile, 'r') as infile:
00093         for line in infile:
00094             match = re.match(SYM, line)
00095             if match:
00096                 ret = match.group("addr")
00097 
00098     if not ret:
00099         print "[ERROR] cannot find the address of symbol " + symbol
00100         return 0
00101 
00102     return int(ret,16) | 1
00103 
00104 def _parse_load_segment_inner(image_elf):
00105     with open(image_elf, "rb") as fd:
00106         elffile = elftools.elf.elffile.ELFFile(fd)
00107         for segment in elffile.iter_segments():
00108             offset = segment['p_offset']
00109             addr = segment['p_vaddr']
00110             size = segment['p_filesz']
00111             if (addr != 0 and size != 0 and segment['p_type'] == 'PT_LOAD'):
00112                 yield offset, addr, size
00113 
00114 def parse_load_segment(toolchain, image_elf):
00115     return list(_parse_load_segment_inner(image_elf))
00116 
00117 def create_payload(image_elf, ram2_bin, entry, segment):
00118     file_elf = open(image_elf, "rb")
00119     file_bin = open(ram2_bin, "wb")
00120 
00121     write_number(int(entry), 8, file_bin)
00122     write_number(int(len(segment)), 8, file_bin)
00123     write_number(0xFFFFFFFF, 8, file_bin)
00124     write_number(0xFFFFFFFF, 8, file_bin)
00125 
00126     for (offset, addr, size) in segment:
00127         file_elf.seek(offset)
00128         # write image header - size & addr
00129         write_number(addr, 8, file_bin)
00130         write_number(size, 8, file_bin)
00131         # write load segment
00132         file_bin.write(file_elf.read(size))
00133         delta = size % 4
00134         if delta != 0:
00135             padding = 4 - delta
00136             write_number(0x0, padding * 2, file_bin)
00137     file_bin.close()
00138     file_elf.close()
00139 
00140 def create_daplink(image_bin, ram1_bin, ram2_bin):
00141 
00142     # remove target binary file/path
00143     if os.path.isfile(image_bin):
00144         os.remove(image_bin)
00145     else:
00146         shutil.rmtree(image_bin)
00147 
00148     RAM2_HEADER['tag'] = format_number(TAG, 8)
00149     RAM2_HEADER['ver'] = format_number(VER, 8)
00150     RAM2_HEADER['timestamp'] = format_number(epoch_timestamp(), 16)
00151     RAM2_HEADER['size'] = format_number(os.stat(ram2_bin).st_size + 72, 8)
00152     RAM2_HEADER['hash'] = format_string(sha256_checksum(ram2_bin))
00153     RAM2_HEADER['campaign'] = format_string(CAMPAIGN)
00154 
00155     output = open(image_bin, "wb")
00156     append_image_file(ram1_bin, output)
00157     append_image_file(ram2_bin, output)
00158 
00159     output.seek(0xb000)
00160     line = ""
00161     for key in ['tag', 'ver', 'timestamp', 'size', 'hash', 'campaign']:
00162         line += RAM2_HEADER[key]
00163         output.write(RAM2_HEADER[key])
00164 
00165     RAM2_HEADER['crc32'] = format_number(crc32_checksum(line), 8)
00166 
00167     output.write(RAM2_HEADER['crc32'])
00168     output.close()
00169 
00170 # ----------------------------
00171 #       main function
00172 # ----------------------------
00173 def rtl8195a_elf2bin(t_self, image_elf, image_bin):
00174 
00175     image_name = list(os.path.splitext(image_elf))[:-1]
00176     image_map = ".".join(image_name + ['map'])
00177 
00178     ram1_bin = os.path.join(TOOLS_BOOTLOADERS, "REALTEK_RTL8195AM", "ram_1.bin")
00179     ram2_bin = ".".join(image_name) + '-payload.bin'
00180 
00181     entry = find_symbol(t_self.name, image_map, "PLAT_Start")
00182     segment = parse_load_segment(t_self.name, image_elf)
00183 
00184     create_payload(image_elf, ram2_bin, entry, segment)
00185     create_daplink(image_bin, ram1_bin, ram2_bin)