Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 #!/usr/bin/env python
Pawel Zarembski 0:01f31e923fe2 2 """
Pawel Zarembski 0:01f31e923fe2 3 mbed
Pawel Zarembski 0:01f31e923fe2 4 Copyright (c) 2017-2019 ARM Limited
Pawel Zarembski 0:01f31e923fe2 5
Pawel Zarembski 0:01f31e923fe2 6 Licensed under the Apache License, Version 2.0 (the "License");
Pawel Zarembski 0:01f31e923fe2 7 you may not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 8 You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 9
Pawel Zarembski 0:01f31e923fe2 10 http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 11
Pawel Zarembski 0:01f31e923fe2 12 Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 13 distributed under the License is distributed on an "AS IS" BASIS,
Pawel Zarembski 0:01f31e923fe2 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 15 See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 16 limitations under the License.
Pawel Zarembski 0:01f31e923fe2 17 """
Pawel Zarembski 0:01f31e923fe2 18
Pawel Zarembski 0:01f31e923fe2 19 from __future__ import print_function
Pawel Zarembski 0:01f31e923fe2 20 import os
Pawel Zarembski 0:01f31e923fe2 21 import struct
Pawel Zarembski 0:01f31e923fe2 22 import binascii
Pawel Zarembski 0:01f31e923fe2 23 import argparse
Pawel Zarembski 0:01f31e923fe2 24 import logging
Pawel Zarembski 0:01f31e923fe2 25 from six.moves import StringIO
Pawel Zarembski 0:01f31e923fe2 26 import jinja2
Pawel Zarembski 0:01f31e923fe2 27 from collections import namedtuple
Pawel Zarembski 0:01f31e923fe2 28 from itertools import count
Pawel Zarembski 0:01f31e923fe2 29
Pawel Zarembski 0:01f31e923fe2 30 from elftools.common.py3compat import bytes2str
Pawel Zarembski 0:01f31e923fe2 31 from elftools.elf.elffile import ELFFile
Pawel Zarembski 0:01f31e923fe2 32 from elftools.elf.sections import SymbolTableSection
Pawel Zarembski 0:01f31e923fe2 33
Pawel Zarembski 0:01f31e923fe2 34 logger = logging.getLogger(__name__)
Pawel Zarembski 0:01f31e923fe2 35 logger.addHandler(logging.NullHandler())
Pawel Zarembski 0:01f31e923fe2 36
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 def main():
Pawel Zarembski 0:01f31e923fe2 39 parser = argparse.ArgumentParser(description="Algo Extracter")
Pawel Zarembski 0:01f31e923fe2 40 parser.add_argument("input", help="File to extract flash algo from")
Pawel Zarembski 0:01f31e923fe2 41 parser.add_argument("template", default="py_blob.tmpl",
Pawel Zarembski 0:01f31e923fe2 42 help="Template to use")
Pawel Zarembski 0:01f31e923fe2 43 parser.add_argument("output", help="Output file")
Pawel Zarembski 0:01f31e923fe2 44 args = parser.parse_args()
Pawel Zarembski 0:01f31e923fe2 45
Pawel Zarembski 0:01f31e923fe2 46 with open(args.input, "rb") as file_handle:
Pawel Zarembski 0:01f31e923fe2 47 data = file_handle.read()
Pawel Zarembski 0:01f31e923fe2 48 algo = PackFlashAlgo(data)
Pawel Zarembski 0:01f31e923fe2 49 algo.process_template(args.template, args.output)
Pawel Zarembski 0:01f31e923fe2 50
Pawel Zarembski 0:01f31e923fe2 51
Pawel Zarembski 0:01f31e923fe2 52 class PackFlashAlgo(object):
Pawel Zarembski 0:01f31e923fe2 53 """
Pawel Zarembski 0:01f31e923fe2 54 Class to wrap a flash algo
Pawel Zarembski 0:01f31e923fe2 55
Pawel Zarembski 0:01f31e923fe2 56 This class is intended to provide easy access to the information
Pawel Zarembski 0:01f31e923fe2 57 provided by a flash algorithm, such as symbols and the flash
Pawel Zarembski 0:01f31e923fe2 58 algorithm itself.
Pawel Zarembski 0:01f31e923fe2 59 """
Pawel Zarembski 0:01f31e923fe2 60
Pawel Zarembski 0:01f31e923fe2 61 REQUIRED_SYMBOLS = set([
Pawel Zarembski 0:01f31e923fe2 62 "Init",
Pawel Zarembski 0:01f31e923fe2 63 "UnInit",
Pawel Zarembski 0:01f31e923fe2 64 "EraseSector",
Pawel Zarembski 0:01f31e923fe2 65 "ProgramPage",
Pawel Zarembski 0:01f31e923fe2 66 ])
Pawel Zarembski 0:01f31e923fe2 67
Pawel Zarembski 0:01f31e923fe2 68 EXTRA_SYMBOLS = set([
Pawel Zarembski 0:01f31e923fe2 69 "BlankCheck",
Pawel Zarembski 0:01f31e923fe2 70 "EraseChip",
Pawel Zarembski 0:01f31e923fe2 71 "Verify",
Pawel Zarembski 0:01f31e923fe2 72 ])
Pawel Zarembski 0:01f31e923fe2 73
Pawel Zarembski 0:01f31e923fe2 74 def __init__(self, data):
Pawel Zarembski 0:01f31e923fe2 75 """Construct a PackFlashAlgorithm from an ElfFileSimple"""
Pawel Zarembski 0:01f31e923fe2 76 self.elf = ElfFileSimple(data)
Pawel Zarembski 0:01f31e923fe2 77 self.flash_info = PackFlashInfo(self.elf)
Pawel Zarembski 0:01f31e923fe2 78
Pawel Zarembski 0:01f31e923fe2 79 self.flash_start = self.flash_info.start
Pawel Zarembski 0:01f31e923fe2 80 self.flash_size = self.flash_info.size
Pawel Zarembski 0:01f31e923fe2 81 self.page_size = self.flash_info.page_size
Pawel Zarembski 0:01f31e923fe2 82 self.sector_sizes = self.flash_info.sector_info_list
Pawel Zarembski 0:01f31e923fe2 83
Pawel Zarembski 0:01f31e923fe2 84 symbols = {}
Pawel Zarembski 0:01f31e923fe2 85 symbols.update(_extract_symbols(self.elf, self.REQUIRED_SYMBOLS))
Pawel Zarembski 0:01f31e923fe2 86 symbols.update(_extract_symbols(self.elf, self.EXTRA_SYMBOLS,
Pawel Zarembski 0:01f31e923fe2 87 default=0xFFFFFFFF))
Pawel Zarembski 0:01f31e923fe2 88 self.symbols = symbols
Pawel Zarembski 0:01f31e923fe2 89
Pawel Zarembski 0:01f31e923fe2 90 sections_to_find = (
Pawel Zarembski 0:01f31e923fe2 91 ("PrgCode", "SHT_PROGBITS"),
Pawel Zarembski 0:01f31e923fe2 92 ("PrgData", "SHT_PROGBITS"),
Pawel Zarembski 0:01f31e923fe2 93 ("PrgData", "SHT_NOBITS"),
Pawel Zarembski 0:01f31e923fe2 94 )
Pawel Zarembski 0:01f31e923fe2 95
Pawel Zarembski 0:01f31e923fe2 96 ro_rw_zi = _find_sections(self.elf, sections_to_find)
Pawel Zarembski 0:01f31e923fe2 97 ro_rw_zi = _algo_fill_zi_if_missing(ro_rw_zi)
Pawel Zarembski 0:01f31e923fe2 98 error_msg = _algo_check_for_section_problems(ro_rw_zi)
Pawel Zarembski 0:01f31e923fe2 99 if error_msg is not None:
Pawel Zarembski 0:01f31e923fe2 100 raise Exception(error_msg)
Pawel Zarembski 0:01f31e923fe2 101
Pawel Zarembski 0:01f31e923fe2 102 sect_ro, sect_rw, sect_zi = ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 103 self.ro_start = sect_ro["sh_addr"]
Pawel Zarembski 0:01f31e923fe2 104 self.ro_size = sect_ro["sh_size"]
Pawel Zarembski 0:01f31e923fe2 105 self.rw_start = sect_rw["sh_addr"]
Pawel Zarembski 0:01f31e923fe2 106 self.rw_size = sect_rw["sh_size"]
Pawel Zarembski 0:01f31e923fe2 107 self.zi_start = sect_zi["sh_addr"]
Pawel Zarembski 0:01f31e923fe2 108 self.zi_size = sect_zi["sh_size"]
Pawel Zarembski 0:01f31e923fe2 109
Pawel Zarembski 0:01f31e923fe2 110 self.algo_data = _create_algo_bin(ro_rw_zi)
Pawel Zarembski 0:01f31e923fe2 111
Pawel Zarembski 0:01f31e923fe2 112 def format_algo_data(self, spaces, group_size, fmt):
Pawel Zarembski 0:01f31e923fe2 113 """"
Pawel Zarembski 0:01f31e923fe2 114 Return a string representing algo_data suitable for use in a template
Pawel Zarembski 0:01f31e923fe2 115
Pawel Zarembski 0:01f31e923fe2 116 The string is intended for use in a template.
Pawel Zarembski 0:01f31e923fe2 117
Pawel Zarembski 0:01f31e923fe2 118 :param spaces: The number of leading spaces for each line
Pawel Zarembski 0:01f31e923fe2 119 :param group_size: number of elements per line (element type
Pawel Zarembski 0:01f31e923fe2 120 depends of format)
Pawel Zarembski 0:01f31e923fe2 121 :param fmt: - format to create - can be either "hex" or "c"
Pawel Zarembski 0:01f31e923fe2 122 """
Pawel Zarembski 0:01f31e923fe2 123 padding = " " * spaces
Pawel Zarembski 0:01f31e923fe2 124 if fmt == "hex":
Pawel Zarembski 0:01f31e923fe2 125 blob = binascii.b2a_hex(self.algo_data)
Pawel Zarembski 0:01f31e923fe2 126 line_list = []
Pawel Zarembski 0:01f31e923fe2 127 for i in xrange(0, len(blob), group_size):
Pawel Zarembski 0:01f31e923fe2 128 line_list.append('"' + blob[i:i + group_size] + '"')
Pawel Zarembski 0:01f31e923fe2 129 return ("\n" + padding).join(line_list)
Pawel Zarembski 0:01f31e923fe2 130 elif fmt == "c":
Pawel Zarembski 0:01f31e923fe2 131 blob = self.algo_data[:]
Pawel Zarembski 0:01f31e923fe2 132 pad_size = 0 if len(blob) % 4 == 0 else 4 - len(blob) % 4
Pawel Zarembski 0:01f31e923fe2 133 blob = blob + "\x00" * pad_size
Pawel Zarembski 0:01f31e923fe2 134 integer_list = struct.unpack("<" + "L" * (len(blob) / 4), blob)
Pawel Zarembski 0:01f31e923fe2 135 line_list = []
Pawel Zarembski 0:01f31e923fe2 136 for pos in range(0, len(integer_list), group_size):
Pawel Zarembski 0:01f31e923fe2 137 group = ["0x%08x" % value for value in
Pawel Zarembski 0:01f31e923fe2 138 integer_list[pos:pos + group_size]]
Pawel Zarembski 0:01f31e923fe2 139 line_list.append(", ".join(group))
Pawel Zarembski 0:01f31e923fe2 140 return (",\n" + padding).join(line_list)
Pawel Zarembski 0:01f31e923fe2 141 else:
Pawel Zarembski 0:01f31e923fe2 142 raise Exception("Unsupported format %s" % fmt)
Pawel Zarembski 0:01f31e923fe2 143
Pawel Zarembski 0:01f31e923fe2 144 def process_template(self, template_path, output_path, data_dict=None):
Pawel Zarembski 0:01f31e923fe2 145 """
Pawel Zarembski 0:01f31e923fe2 146 Generate output from the supplied template
Pawel Zarembski 0:01f31e923fe2 147
Pawel Zarembski 0:01f31e923fe2 148 All the public methods and fields of this class can be accessed from
Pawel Zarembski 0:01f31e923fe2 149 the template via "algo".
Pawel Zarembski 0:01f31e923fe2 150
Pawel Zarembski 0:01f31e923fe2 151 :param template_path: Relative or absolute file path to the template
Pawel Zarembski 0:01f31e923fe2 152 :param output_path: Relative or absolute file path to create
Pawel Zarembski 0:01f31e923fe2 153 :param data_dict: Additional data to use when generating
Pawel Zarembski 0:01f31e923fe2 154 """
Pawel Zarembski 0:01f31e923fe2 155 if data_dict is None:
Pawel Zarembski 0:01f31e923fe2 156 data_dict = {}
Pawel Zarembski 0:01f31e923fe2 157 else:
Pawel Zarembski 0:01f31e923fe2 158 assert isinstance(data_dict, dict)
Pawel Zarembski 0:01f31e923fe2 159 data_dict = dict(data_dict)
Pawel Zarembski 0:01f31e923fe2 160 assert "algo" not in data_dict, "algo already set by user data"
Pawel Zarembski 0:01f31e923fe2 161 data_dict["algo"] = self
Pawel Zarembski 0:01f31e923fe2 162
Pawel Zarembski 0:01f31e923fe2 163 with open(template_path) as file_handle:
Pawel Zarembski 0:01f31e923fe2 164 template_text = file_handle.read()
Pawel Zarembski 0:01f31e923fe2 165
Pawel Zarembski 0:01f31e923fe2 166 template = jinja2.Template(template_text)
Pawel Zarembski 0:01f31e923fe2 167 target_text = template.render(data_dict)
Pawel Zarembski 0:01f31e923fe2 168
Pawel Zarembski 0:01f31e923fe2 169 with open(output_path, "wb") as file_handle:
Pawel Zarembski 0:01f31e923fe2 170 file_handle.write(target_text)
Pawel Zarembski 0:01f31e923fe2 171
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 def _extract_symbols(simple_elf, symbols, default=None):
Pawel Zarembski 0:01f31e923fe2 174 """Fill 'symbols' field with required flash algo symbols"""
Pawel Zarembski 0:01f31e923fe2 175 to_ret = {}
Pawel Zarembski 0:01f31e923fe2 176 for symbol in symbols:
Pawel Zarembski 0:01f31e923fe2 177 if symbol not in simple_elf.symbols:
Pawel Zarembski 0:01f31e923fe2 178 if default is not None:
Pawel Zarembski 0:01f31e923fe2 179 to_ret[symbol] = default
Pawel Zarembski 0:01f31e923fe2 180 continue
Pawel Zarembski 0:01f31e923fe2 181 raise Exception("Missing symbol %s" % symbol)
Pawel Zarembski 0:01f31e923fe2 182 to_ret[symbol] = simple_elf.symbols[symbol].value
Pawel Zarembski 0:01f31e923fe2 183 return to_ret
Pawel Zarembski 0:01f31e923fe2 184
Pawel Zarembski 0:01f31e923fe2 185
Pawel Zarembski 0:01f31e923fe2 186 def _find_sections(elf, name_type_pairs):
Pawel Zarembski 0:01f31e923fe2 187 """Return a list of sections the same length and order of the input list"""
Pawel Zarembski 0:01f31e923fe2 188 sections = [None] * len(name_type_pairs)
Pawel Zarembski 0:01f31e923fe2 189 for section in elf.iter_sections():
Pawel Zarembski 0:01f31e923fe2 190 section_name = bytes2str(section.name)
Pawel Zarembski 0:01f31e923fe2 191 section_type = section["sh_type"]
Pawel Zarembski 0:01f31e923fe2 192 for i, name_and_type in enumerate(name_type_pairs):
Pawel Zarembski 0:01f31e923fe2 193 if name_and_type != (section_name, section_type):
Pawel Zarembski 0:01f31e923fe2 194 continue
Pawel Zarembski 0:01f31e923fe2 195 if sections[i] is not None:
Pawel Zarembski 0:01f31e923fe2 196 raise Exception("Elf contains duplicate section %s attr %s" %
Pawel Zarembski 0:01f31e923fe2 197 (section_name, section_type))
Pawel Zarembski 0:01f31e923fe2 198 sections[i] = section
Pawel Zarembski 0:01f31e923fe2 199 return sections
Pawel Zarembski 0:01f31e923fe2 200
Pawel Zarembski 0:01f31e923fe2 201
Pawel Zarembski 0:01f31e923fe2 202 def _algo_fill_zi_if_missing(ro_rw_zi):
Pawel Zarembski 0:01f31e923fe2 203 """Create an empty zi section if it is missing"""
Pawel Zarembski 0:01f31e923fe2 204 s_ro, s_rw, s_zi = ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 205 if s_rw is None:
Pawel Zarembski 0:01f31e923fe2 206 return ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 207 if s_zi is not None:
Pawel Zarembski 0:01f31e923fe2 208 return ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 209 s_zi = {
Pawel Zarembski 0:01f31e923fe2 210 "sh_addr": s_rw["sh_addr"] + s_rw["sh_size"],
Pawel Zarembski 0:01f31e923fe2 211 "sh_size": 0
Pawel Zarembski 0:01f31e923fe2 212 }
Pawel Zarembski 0:01f31e923fe2 213 return s_ro, s_rw, s_zi
Pawel Zarembski 0:01f31e923fe2 214
Pawel Zarembski 0:01f31e923fe2 215
Pawel Zarembski 0:01f31e923fe2 216 def _algo_check_for_section_problems(ro_rw_zi):
Pawel Zarembski 0:01f31e923fe2 217 """Return a string describing any errors with the layout or None if good"""
Pawel Zarembski 0:01f31e923fe2 218 s_ro, s_rw, s_zi = ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 219 if s_ro is None:
Pawel Zarembski 0:01f31e923fe2 220 return "RO section is missing"
Pawel Zarembski 0:01f31e923fe2 221 if s_rw is None:
Pawel Zarembski 0:01f31e923fe2 222 return "RW section is missing"
Pawel Zarembski 0:01f31e923fe2 223 if s_zi is None:
Pawel Zarembski 0:01f31e923fe2 224 return "ZI section is missing"
Pawel Zarembski 0:01f31e923fe2 225 if s_ro["sh_addr"] != 0:
Pawel Zarembski 0:01f31e923fe2 226 return "RO section does not start at address 0"
Pawel Zarembski 0:01f31e923fe2 227 if s_ro["sh_addr"] + s_ro["sh_size"] != s_rw["sh_addr"]:
Pawel Zarembski 0:01f31e923fe2 228 return "RW section does not follow RO section"
Pawel Zarembski 0:01f31e923fe2 229 if s_rw["sh_addr"] + s_rw["sh_size"] != s_zi["sh_addr"]:
Pawel Zarembski 0:01f31e923fe2 230 return "ZI section does not follow RW section"
Pawel Zarembski 0:01f31e923fe2 231 return None
Pawel Zarembski 0:01f31e923fe2 232
Pawel Zarembski 0:01f31e923fe2 233
Pawel Zarembski 0:01f31e923fe2 234 def _create_algo_bin(ro_rw_zi):
Pawel Zarembski 0:01f31e923fe2 235 """Create a binary blob of the flash algo which can execute from ram"""
Pawel Zarembski 0:01f31e923fe2 236 sect_ro, sect_rw, sect_zi = ro_rw_zi
Pawel Zarembski 0:01f31e923fe2 237 algo_size = sect_ro["sh_size"] + sect_rw["sh_size"] + sect_zi["sh_size"]
Pawel Zarembski 0:01f31e923fe2 238 algo_data = bytearray(algo_size)
Pawel Zarembski 0:01f31e923fe2 239 for section in (sect_ro, sect_rw):
Pawel Zarembski 0:01f31e923fe2 240 start = section["sh_addr"]
Pawel Zarembski 0:01f31e923fe2 241 size = section["sh_size"]
Pawel Zarembski 0:01f31e923fe2 242 data = section.data()
Pawel Zarembski 0:01f31e923fe2 243 assert len(data) == size
Pawel Zarembski 0:01f31e923fe2 244 algo_data[start:start + size] = data
Pawel Zarembski 0:01f31e923fe2 245 return algo_data
Pawel Zarembski 0:01f31e923fe2 246
Pawel Zarembski 0:01f31e923fe2 247
Pawel Zarembski 0:01f31e923fe2 248 class PackFlashInfo(object):
Pawel Zarembski 0:01f31e923fe2 249 """Wrapper class for the non-executable information in an FLM file"""
Pawel Zarembski 0:01f31e923fe2 250
Pawel Zarembski 0:01f31e923fe2 251 FLASH_DEVICE_STRUCT = "<H128sHLLLLBxxxLL"
Pawel Zarembski 0:01f31e923fe2 252 FLASH_SECTORS_STRUCT = "<LL"
Pawel Zarembski 0:01f31e923fe2 253 FLASH_SECTORS_STRUCT_SIZE = struct.calcsize(FLASH_SECTORS_STRUCT)
Pawel Zarembski 0:01f31e923fe2 254 SECTOR_END = 0xFFFFFFFF
Pawel Zarembski 0:01f31e923fe2 255
Pawel Zarembski 0:01f31e923fe2 256 def __init__(self, elf_simple):
Pawel Zarembski 0:01f31e923fe2 257 dev_info = elf_simple.symbols["FlashDevice"]
Pawel Zarembski 0:01f31e923fe2 258 info_start = dev_info.value
Pawel Zarembski 0:01f31e923fe2 259 info_size = struct.calcsize(self.FLASH_DEVICE_STRUCT)
Pawel Zarembski 0:01f31e923fe2 260 data = elf_simple.read(info_start, info_size)
Pawel Zarembski 0:01f31e923fe2 261 values = struct.unpack(self.FLASH_DEVICE_STRUCT, data)
Pawel Zarembski 0:01f31e923fe2 262
Pawel Zarembski 0:01f31e923fe2 263 self.version = values[0]
Pawel Zarembski 0:01f31e923fe2 264 self.name = values[1].strip("\x00")
Pawel Zarembski 0:01f31e923fe2 265 self.type = values[2]
Pawel Zarembski 0:01f31e923fe2 266 self.start = values[3]
Pawel Zarembski 0:01f31e923fe2 267 self.size = values[4]
Pawel Zarembski 0:01f31e923fe2 268 self.page_size = values[5]
Pawel Zarembski 0:01f31e923fe2 269 self.value_empty = values[7]
Pawel Zarembski 0:01f31e923fe2 270 self.prog_timeout_ms = values[8]
Pawel Zarembski 0:01f31e923fe2 271 self.erase_timeout_ms = values[9]
Pawel Zarembski 0:01f31e923fe2 272
Pawel Zarembski 0:01f31e923fe2 273 sector_gen = self._sector_and_sz_itr(elf_simple,
Pawel Zarembski 0:01f31e923fe2 274 info_start + info_size)
Pawel Zarembski 0:01f31e923fe2 275 self.sector_info_list = list(sector_gen)
Pawel Zarembski 0:01f31e923fe2 276
Pawel Zarembski 0:01f31e923fe2 277 def __str__(self):
Pawel Zarembski 0:01f31e923fe2 278 desc = ""
Pawel Zarembski 0:01f31e923fe2 279 desc += "Flash Device:" + os.linesep
Pawel Zarembski 0:01f31e923fe2 280 desc += " name=%s" % self.name + os.linesep
Pawel Zarembski 0:01f31e923fe2 281 desc += " version=0x%x" % self.version + os.linesep
Pawel Zarembski 0:01f31e923fe2 282 desc += " type=%i" % self.type + os.linesep
Pawel Zarembski 0:01f31e923fe2 283 desc += " start=0x%x" % self.start + os.linesep
Pawel Zarembski 0:01f31e923fe2 284 desc += " size=0x%x" % self.size + os.linesep
Pawel Zarembski 0:01f31e923fe2 285 desc += " page_size=0x%x" % self.page_size + os.linesep
Pawel Zarembski 0:01f31e923fe2 286 desc += " value_empty=0x%x" % self.value_empty + os.linesep
Pawel Zarembski 0:01f31e923fe2 287 desc += " prog_timeout_ms=%i" % self.prog_timeout_ms + os.linesep
Pawel Zarembski 0:01f31e923fe2 288 desc += " erase_timeout_ms=%i" % self.erase_timeout_ms + os.linesep
Pawel Zarembski 0:01f31e923fe2 289 desc += " sectors:" + os.linesep
Pawel Zarembski 0:01f31e923fe2 290 for sector_start, sector_size in self.sector_info_list:
Pawel Zarembski 0:01f31e923fe2 291 desc += (" start=0x%x, size=0x%x" %
Pawel Zarembski 0:01f31e923fe2 292 (sector_start, sector_size) + os.linesep)
Pawel Zarembski 0:01f31e923fe2 293 return desc
Pawel Zarembski 0:01f31e923fe2 294
Pawel Zarembski 0:01f31e923fe2 295 def _sector_and_sz_itr(self, elf_simple, data_start):
Pawel Zarembski 0:01f31e923fe2 296 """Iterator which returns starting address and sector size"""
Pawel Zarembski 0:01f31e923fe2 297 for entry_start in count(data_start, self.FLASH_SECTORS_STRUCT_SIZE):
Pawel Zarembski 0:01f31e923fe2 298 data = elf_simple.read(entry_start, self.FLASH_SECTORS_STRUCT_SIZE)
Pawel Zarembski 0:01f31e923fe2 299 size, start = struct.unpack(self.FLASH_SECTORS_STRUCT, data)
Pawel Zarembski 0:01f31e923fe2 300 start_and_size = start, size
Pawel Zarembski 0:01f31e923fe2 301 if start_and_size == (self.SECTOR_END, self.SECTOR_END):
Pawel Zarembski 0:01f31e923fe2 302 return
Pawel Zarembski 0:01f31e923fe2 303 yield start_and_size
Pawel Zarembski 0:01f31e923fe2 304
Pawel Zarembski 0:01f31e923fe2 305
Pawel Zarembski 0:01f31e923fe2 306 SymbolSimple = namedtuple("SymbolSimple", "name, value, size")
Pawel Zarembski 0:01f31e923fe2 307
Pawel Zarembski 0:01f31e923fe2 308
Pawel Zarembski 0:01f31e923fe2 309 class ElfFileSimple(ELFFile):
Pawel Zarembski 0:01f31e923fe2 310 """Wrapper for elf object which allows easy access to symbols and rom"""
Pawel Zarembski 0:01f31e923fe2 311
Pawel Zarembski 0:01f31e923fe2 312 def __init__(self, data):
Pawel Zarembski 0:01f31e923fe2 313 """Construct a ElfFileSimple from bytes or a bytearray"""
Pawel Zarembski 0:01f31e923fe2 314 super(ElfFileSimple, self).__init__(StringIO.StringIO(data))
Pawel Zarembski 0:01f31e923fe2 315 self.symbols = self._read_symbol_table()
Pawel Zarembski 0:01f31e923fe2 316
Pawel Zarembski 0:01f31e923fe2 317 def _read_symbol_table(self):
Pawel Zarembski 0:01f31e923fe2 318 """Read the symbol table into the field "symbols" for easy use"""
Pawel Zarembski 0:01f31e923fe2 319 section = self.get_section_by_name(b".symtab")
Pawel Zarembski 0:01f31e923fe2 320 if not section:
Pawel Zarembski 0:01f31e923fe2 321 raise Exception("Missing symbol table")
Pawel Zarembski 0:01f31e923fe2 322
Pawel Zarembski 0:01f31e923fe2 323 if not isinstance(section, SymbolTableSection):
Pawel Zarembski 0:01f31e923fe2 324 raise Exception("Invalid symbol table section")
Pawel Zarembski 0:01f31e923fe2 325
Pawel Zarembski 0:01f31e923fe2 326 symbols = {}
Pawel Zarembski 0:01f31e923fe2 327 for symbol in section.iter_symbols():
Pawel Zarembski 0:01f31e923fe2 328 name_str = bytes2str(symbol.name)
Pawel Zarembski 0:01f31e923fe2 329 if name_str in symbols:
Pawel Zarembski 0:01f31e923fe2 330 logging.debug("Duplicate symbol %s", name_str)
Pawel Zarembski 0:01f31e923fe2 331 symbols[name_str] = SymbolSimple(name_str, symbol["st_value"],
Pawel Zarembski 0:01f31e923fe2 332 symbol["st_size"])
Pawel Zarembski 0:01f31e923fe2 333 return symbols
Pawel Zarembski 0:01f31e923fe2 334
Pawel Zarembski 0:01f31e923fe2 335 def read(self, addr, size):
Pawel Zarembski 0:01f31e923fe2 336 """Read program data from the elf file
Pawel Zarembski 0:01f31e923fe2 337
Pawel Zarembski 0:01f31e923fe2 338 :param addr: physical address (load address) to read from
Pawel Zarembski 0:01f31e923fe2 339 :param size: number of bytes to read
Pawel Zarembski 0:01f31e923fe2 340 :return: Requested data or None if address is unmapped
Pawel Zarembski 0:01f31e923fe2 341 """
Pawel Zarembski 0:01f31e923fe2 342 for segment in self.iter_segments():
Pawel Zarembski 0:01f31e923fe2 343 seg_addr = segment["p_paddr"]
Pawel Zarembski 0:01f31e923fe2 344 seg_size = min(segment["p_memsz"], segment["p_filesz"])
Pawel Zarembski 0:01f31e923fe2 345 if addr >= seg_addr + seg_size:
Pawel Zarembski 0:01f31e923fe2 346 continue
Pawel Zarembski 0:01f31e923fe2 347 if addr + size <= seg_addr:
Pawel Zarembski 0:01f31e923fe2 348 continue
Pawel Zarembski 0:01f31e923fe2 349 # There is at least some overlap
Pawel Zarembski 0:01f31e923fe2 350
Pawel Zarembski 0:01f31e923fe2 351 if addr >= seg_addr and addr + size <= seg_addr + seg_size:
Pawel Zarembski 0:01f31e923fe2 352 # Region is fully contained
Pawel Zarembski 0:01f31e923fe2 353 data = segment.data()
Pawel Zarembski 0:01f31e923fe2 354 start = addr - seg_addr
Pawel Zarembski 0:01f31e923fe2 355 return data[start:start + size]
Pawel Zarembski 0:01f31e923fe2 356
Pawel Zarembski 0:01f31e923fe2 357
Pawel Zarembski 0:01f31e923fe2 358 if __name__ == '__main__':
Pawel Zarembski 0:01f31e923fe2 359 main()