""" mbed REALTEK_RTL8195AM elf2bin script Copyright (c) 2011-2016 Realtek Semiconductor Corp. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. LIBRARIES BUILD """ import sys, array, struct, os, re, subprocess import hashlib from tools.paths import TOOLS_BOOTLOADERS from datetime import datetime # Constant Variables RAM2_RSVD = 0x3131373835393138 RAM3_RSVD = 0xFFFFFFFFFFFFFFFF IMG2_OFFSET = 0x10006000 #default def write_fixed_width_string(value, width, output): # cut string to list & reverse line = [value[i:i+2] for i in range(0, len(value), 2)] output.write("".join([chr(long(b, 16)) for b in line])) def write_fixed_width_value(value, width, output): # convert to string line = format(value, '0%dx' % (width)) if len(line) > width: print "[ERROR] value 0x%s cannot fit width %d" % (line, width) sys.exit(-1) # cut string to list & reverse line = [line[i:i+2] for i in range(0, len(line), 2)] line.reverse() # convert to write buffer output.write("".join([chr(long(b, 16)) for b in line])) def append_image_file(image, output): try: input = open(image, "rb") output.write(input.read()) except Exception: return input.close() def prepend(image, image_prepend, toolchain, info): if info['size'] == 0: return output = open(image_prepend, "wb") write_fixed_width_value(info['size'], 8, output) write_fixed_width_value(info['addr'], 8, output) if info['img'] == 2 : write_fixed_width_value(RAM2_RSVD, 16, output) elif info['img'] == 3 : write_fixed_width_value(RAM3_RSVD, 16, output) if os.path.isfile(image): with open(image, "rb") as input: if toolchain == "IAR": input.seek(info['addr']) elif info['img'] == 3: #toolchain is not IAR input.seek(info['addr']-IMG2_OFFSET) output.write(input.read(info['size'])) else: image = os.path.join(image, info['name']) with open(image, "rb") as input: output.write(input.read(info['size'])) output.close() def _parse_section(toolchain, elf, section): info = {'addr':None, 'size':0}; if toolchain not in ["GCC_ARM", "ARM_STD", "ARM", "ARM_MICRO", "IAR"]: print "[ERROR] unsupported toolchain " + toolchain sys.exit(-1) mapfile = elf.rsplit(".", 1)[0] + ".map" with open(mapfile, 'r') as infile: # Search area to parse for line in infile: if toolchain == "GCC_ARM": # .image2.table 0x[00000000]30000000 0x18 # 0x[00000000]30000000 __image2_start__ = . # 0x[00000000]30000000 __image2_entry_func__ = . match = re.match(r'^' + section + \ r'\s+0x0{,8}(?P[0-9A-Fa-f]{8})\s+0x(?P[0-9A-Fa-f]+).*$', line) elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]: # Memory Map of the image # Load Region LR_DRAM (Base: 0x30000000, Size: 0x00006a74, Max: 0x00200000, ABSOLUTE) # Execution Region IMAGE2_TABLE (Base: 0x30000000, Size: 0x00000018, Max: 0xffffffff, ABSOLUTE, FIXED) # Base Addr Size Type Attr Idx E Section Name Object # 0x30000000 0x00000004 Data RO 5257 .image2.ram.data rtl8195a_init.o match = re.match(r'^.*Region\s+' + section + \ r'\s+\(Base: 0x(?P[0-9A-Fa-f]{8}),\s+Size: 0x(?P[0-9A-Fa-f]+), .*\)$', line) elif toolchain == "IAR": # Section Kind Address Size Object # ------- ---- ------- ---- ------ # "A3": 0x8470 # IMAGE2 0x10006000 0x5d18 # .ram_image2.text 0x10006000 0x5bbc # .rodata const 0x10006000 0x14 retarget.o [17] match = re.match(r'^\s+' + section + \ r'\s+0x(?P[0-9A-Fa-f]{8})\s+0x(?P[0-9A-Fa-f]+)\s+.*$', line) if match: info['addr'] = int(match.group("addr"), 16) try: info['size'] = int(match.group("size"), 16) except IndexError: print "[WARNING] cannot find the size of section " + section return info print "[ERROR] cannot find the address of section " + section return info def parse_section(toolchain, elf, sections, img): img_info = {'name':"", 'addr':None, 'size':0, 'img':img} for section in sections: section_info = _parse_section(toolchain, elf, section) if img_info['addr'] is None or img_info['addr'] > section_info['addr']: img_info['addr'] = section_info['addr'] img_info['name'] = section img_info['size'] = img_info['size'] + section_info['size'] return img_info # ---------------------------- # main function # ---------------------------- def rtl8195a_elf2bin(toolchain, image_elf, image_bin): if toolchain == "GCC_ARM": img2_sections = [".image2.table", ".text", ".data"] img3_sections = [".sdr_all"] elif toolchain in ["ARM_STD", "ARM", "ARM_MICRO"]: img2_sections = [".image2.table", ".text", ".data"] img3_sections = ["_DRAM_CODE"] elif toolchain == "IAR": img2_sections = ["IMAGE2"] img3_sections = ["SDRAM"] else: print("[error] unsupported toolchain") + toolchain return image2_info = {'addr':None, 'size':0, 'img':2} image3_info = {'addr':None, 'size':0, 'img':3} image_name = os.path.splitext(image_elf)[0] img1_prepend_bin = os.path.join(TOOLS_BOOTLOADERS, "REALTEK_RTL8195AM", "ram_1_prepend.bin") img2_prepend_bin = image_name + '-ram_2_prepend.bin' img3_prepend_bin = image_name + '-ram_3_prepend.bin' old_bin = image_name + '.bin' img_info = parse_section(toolchain, image_elf, img2_sections, 2) prepend(old_bin, img2_prepend_bin, toolchain, img_info) img_info = parse_section(toolchain, image_elf, img3_sections, 3) prepend(old_bin, img3_prepend_bin, toolchain, img_info) #delete original binary if os.path.isfile(image_bin): os.remove(image_bin) else: for i in os.listdir(image_bin): os.remove(os.path.join(image_bin, i)) os.removedirs(image_bin) # write output file output = open(image_bin, "wb") append_image_file(img1_prepend_bin, output) append_image_file(img2_prepend_bin, output) append_image_file(img3_prepend_bin, output) output.close() # post built done