BA
/
BaBoRo_test2
Backup 1
mbed-os/tools/targets/__init__.py@0:02dd72d1d465, 2018-04-24 (annotated)
- Committer:
- borlanic
- Date:
- Tue Apr 24 11:45:18 2018 +0000
- Revision:
- 0:02dd72d1d465
BaBoRo_test2 - backup 1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
borlanic | 0:02dd72d1d465 | 1 | """ |
borlanic | 0:02dd72d1d465 | 2 | mbed SDK |
borlanic | 0:02dd72d1d465 | 3 | Copyright (c) 2011-2016 ARM Limited |
borlanic | 0:02dd72d1d465 | 4 | |
borlanic | 0:02dd72d1d465 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); |
borlanic | 0:02dd72d1d465 | 6 | you may not use this file except in compliance with the License. |
borlanic | 0:02dd72d1d465 | 7 | You may obtain a copy of the License at |
borlanic | 0:02dd72d1d465 | 8 | |
borlanic | 0:02dd72d1d465 | 9 | http://www.apache.org/licenses/LICENSE-2.0 |
borlanic | 0:02dd72d1d465 | 10 | |
borlanic | 0:02dd72d1d465 | 11 | Unless required by applicable law or agreed to in writing, software |
borlanic | 0:02dd72d1d465 | 12 | distributed under the License is distributed on an "AS IS" BASIS, |
borlanic | 0:02dd72d1d465 | 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
borlanic | 0:02dd72d1d465 | 14 | See the License for the specific language governing permissions and |
borlanic | 0:02dd72d1d465 | 15 | limitations under the License. |
borlanic | 0:02dd72d1d465 | 16 | """ |
borlanic | 0:02dd72d1d465 | 17 | from __future__ import print_function |
borlanic | 0:02dd72d1d465 | 18 | |
borlanic | 0:02dd72d1d465 | 19 | import os |
borlanic | 0:02dd72d1d465 | 20 | import binascii |
borlanic | 0:02dd72d1d465 | 21 | import struct |
borlanic | 0:02dd72d1d465 | 22 | import shutil |
borlanic | 0:02dd72d1d465 | 23 | import inspect |
borlanic | 0:02dd72d1d465 | 24 | import sys |
borlanic | 0:02dd72d1d465 | 25 | from copy import copy |
borlanic | 0:02dd72d1d465 | 26 | from inspect import getmro |
borlanic | 0:02dd72d1d465 | 27 | from collections import namedtuple, Mapping |
borlanic | 0:02dd72d1d465 | 28 | from tools.targets.LPC import patch |
borlanic | 0:02dd72d1d465 | 29 | from tools.paths import TOOLS_BOOTLOADERS |
borlanic | 0:02dd72d1d465 | 30 | from tools.utils import json_file_to_dict |
borlanic | 0:02dd72d1d465 | 31 | |
borlanic | 0:02dd72d1d465 | 32 | __all__ = ["target", "TARGETS", "TARGET_MAP", "TARGET_NAMES", "CORE_LABELS", |
borlanic | 0:02dd72d1d465 | 33 | "HookError", "generate_py_target", "Target", |
borlanic | 0:02dd72d1d465 | 34 | "CUMULATIVE_ATTRIBUTES", "get_resolution_order"] |
borlanic | 0:02dd72d1d465 | 35 | |
borlanic | 0:02dd72d1d465 | 36 | CORE_LABELS = { |
borlanic | 0:02dd72d1d465 | 37 | "Cortex-M0" : ["M0", "CORTEX_M", "LIKE_CORTEX_M0", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 38 | "Cortex-M0+": ["M0P", "CORTEX_M", "LIKE_CORTEX_M0", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 39 | "Cortex-M1" : ["M1", "CORTEX_M", "LIKE_CORTEX_M1", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 40 | "Cortex-M3" : ["M3", "CORTEX_M", "LIKE_CORTEX_M3", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 41 | "Cortex-M4" : ["M4", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M4", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 42 | "Cortex-M4F" : ["M4", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M4", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 43 | "Cortex-M7" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 44 | "Cortex-M7F" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 45 | "Cortex-M7FD" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 46 | "Cortex-A9" : ["A9", "CORTEX_A", "LIKE_CORTEX_A9", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 47 | "Cortex-M23": ["M23", "CORTEX_M", "LIKE_CORTEX_M23", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 48 | "Cortex-M23-NS": ["M23", "CORTEX_M", "LIKE_CORTEX_M23", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 49 | "Cortex-M33": ["M33", "CORTEX_M", "LIKE_CORTEX_M33", "CORTEX"], |
borlanic | 0:02dd72d1d465 | 50 | "Cortex-M33-NS": ["M33", "CORTEX_M", "LIKE_CORTEX_M33", "CORTEX"] |
borlanic | 0:02dd72d1d465 | 51 | } |
borlanic | 0:02dd72d1d465 | 52 | |
borlanic | 0:02dd72d1d465 | 53 | ################################################################################ |
borlanic | 0:02dd72d1d465 | 54 | # Generic Target class that reads and interprets the data in targets.json |
borlanic | 0:02dd72d1d465 | 55 | |
borlanic | 0:02dd72d1d465 | 56 | class HookError(Exception): |
borlanic | 0:02dd72d1d465 | 57 | """ A simple class that represents all the exceptions associated with |
borlanic | 0:02dd72d1d465 | 58 | hooking |
borlanic | 0:02dd72d1d465 | 59 | """ |
borlanic | 0:02dd72d1d465 | 60 | pass |
borlanic | 0:02dd72d1d465 | 61 | |
borlanic | 0:02dd72d1d465 | 62 | CACHES = {} |
borlanic | 0:02dd72d1d465 | 63 | def cached(func): |
borlanic | 0:02dd72d1d465 | 64 | """A simple decorator used for automatically caching data returned by a |
borlanic | 0:02dd72d1d465 | 65 | function |
borlanic | 0:02dd72d1d465 | 66 | """ |
borlanic | 0:02dd72d1d465 | 67 | def wrapper(*args, **kwargs): |
borlanic | 0:02dd72d1d465 | 68 | """The wrapped function itself""" |
borlanic | 0:02dd72d1d465 | 69 | if (func.__name__, args) not in CACHES: |
borlanic | 0:02dd72d1d465 | 70 | CACHES[(func.__name__, args)] = func(*args, **kwargs) |
borlanic | 0:02dd72d1d465 | 71 | return CACHES[(func.__name__, args)] |
borlanic | 0:02dd72d1d465 | 72 | return wrapper |
borlanic | 0:02dd72d1d465 | 73 | |
borlanic | 0:02dd72d1d465 | 74 | |
borlanic | 0:02dd72d1d465 | 75 | # Cumulative attributes can have values appended to them, so they |
borlanic | 0:02dd72d1d465 | 76 | # need to be computed differently than regular attributes |
borlanic | 0:02dd72d1d465 | 77 | CUMULATIVE_ATTRIBUTES = ['extra_labels', 'macros', 'device_has', 'features'] |
borlanic | 0:02dd72d1d465 | 78 | |
borlanic | 0:02dd72d1d465 | 79 | |
borlanic | 0:02dd72d1d465 | 80 | def get_resolution_order(json_data, target_name, order, level=0): |
borlanic | 0:02dd72d1d465 | 81 | """ Return the order in which target descriptions are searched for |
borlanic | 0:02dd72d1d465 | 82 | attributes. This mimics the Python 2.2 method resolution order, which |
borlanic | 0:02dd72d1d465 | 83 | is what the old targets.py module used. For more details, check |
borlanic | 0:02dd72d1d465 | 84 | http://makina-corpus.com/blog/metier/2014/python-tutorial-understanding-python-mro-class-search-path |
borlanic | 0:02dd72d1d465 | 85 | The resolution order contains (name, level) tuples, where "name" is the |
borlanic | 0:02dd72d1d465 | 86 | name of the class and "level" is the level in the inheritance hierarchy |
borlanic | 0:02dd72d1d465 | 87 | (the target itself is at level 0, its first parent at level 1, its |
borlanic | 0:02dd72d1d465 | 88 | parent's parent at level 2 and so on) |
borlanic | 0:02dd72d1d465 | 89 | """ |
borlanic | 0:02dd72d1d465 | 90 | # the resolution order can't contain duplicate target names |
borlanic | 0:02dd72d1d465 | 91 | if target_name not in [l[0] for l in order]: |
borlanic | 0:02dd72d1d465 | 92 | order.append((target_name, level)) |
borlanic | 0:02dd72d1d465 | 93 | parents = json_data[target_name].get("inherits", []) |
borlanic | 0:02dd72d1d465 | 94 | for par in parents: |
borlanic | 0:02dd72d1d465 | 95 | order = get_resolution_order(json_data, par, order, level + 1) |
borlanic | 0:02dd72d1d465 | 96 | return order |
borlanic | 0:02dd72d1d465 | 97 | |
borlanic | 0:02dd72d1d465 | 98 | |
borlanic | 0:02dd72d1d465 | 99 | def target(name, json_data): |
borlanic | 0:02dd72d1d465 | 100 | """Construct a target object""" |
borlanic | 0:02dd72d1d465 | 101 | resolution_order = get_resolution_order(json_data, name, []) |
borlanic | 0:02dd72d1d465 | 102 | resolution_order_names = [tgt for tgt, _ in resolution_order] |
borlanic | 0:02dd72d1d465 | 103 | return Target(name=name, |
borlanic | 0:02dd72d1d465 | 104 | json_data={key: value for key, value in json_data.items() |
borlanic | 0:02dd72d1d465 | 105 | if key in resolution_order_names}, |
borlanic | 0:02dd72d1d465 | 106 | resolution_order=resolution_order, |
borlanic | 0:02dd72d1d465 | 107 | resolution_order_names=resolution_order_names) |
borlanic | 0:02dd72d1d465 | 108 | |
borlanic | 0:02dd72d1d465 | 109 | def generate_py_target(new_targets, name): |
borlanic | 0:02dd72d1d465 | 110 | """Add one or more new target(s) represented as a Python dictionary |
borlanic | 0:02dd72d1d465 | 111 | in 'new_targets'. It is an error to add a target with a name that |
borlanic | 0:02dd72d1d465 | 112 | already exists. |
borlanic | 0:02dd72d1d465 | 113 | """ |
borlanic | 0:02dd72d1d465 | 114 | base_targets = Target.get_json_target_data() |
borlanic | 0:02dd72d1d465 | 115 | for new_target in new_targets.keys(): |
borlanic | 0:02dd72d1d465 | 116 | if new_target in base_targets: |
borlanic | 0:02dd72d1d465 | 117 | raise Exception("Attempt to add target '%s' that already exists" |
borlanic | 0:02dd72d1d465 | 118 | % new_target) |
borlanic | 0:02dd72d1d465 | 119 | total_data = {} |
borlanic | 0:02dd72d1d465 | 120 | total_data.update(new_targets) |
borlanic | 0:02dd72d1d465 | 121 | total_data.update(base_targets) |
borlanic | 0:02dd72d1d465 | 122 | return target(name, total_data) |
borlanic | 0:02dd72d1d465 | 123 | |
borlanic | 0:02dd72d1d465 | 124 | class Target(namedtuple("Target", "name json_data resolution_order resolution_order_names")): |
borlanic | 0:02dd72d1d465 | 125 | """An object to represent a Target (MCU/Board)""" |
borlanic | 0:02dd72d1d465 | 126 | |
borlanic | 0:02dd72d1d465 | 127 | # Default location of the 'targets.json' file |
borlanic | 0:02dd72d1d465 | 128 | __targets_json_location_default = os.path.join( |
borlanic | 0:02dd72d1d465 | 129 | os.path.dirname(os.path.abspath(__file__)), '..', '..', 'targets', 'targets.json') |
borlanic | 0:02dd72d1d465 | 130 | |
borlanic | 0:02dd72d1d465 | 131 | # Current/new location of the 'targets.json' file |
borlanic | 0:02dd72d1d465 | 132 | __targets_json_location = None |
borlanic | 0:02dd72d1d465 | 133 | |
borlanic | 0:02dd72d1d465 | 134 | # Extra custom targets files |
borlanic | 0:02dd72d1d465 | 135 | __extra_target_json_files = [] |
borlanic | 0:02dd72d1d465 | 136 | |
borlanic | 0:02dd72d1d465 | 137 | @staticmethod |
borlanic | 0:02dd72d1d465 | 138 | @cached |
borlanic | 0:02dd72d1d465 | 139 | def get_json_target_data(): |
borlanic | 0:02dd72d1d465 | 140 | """Load the description of JSON target data""" |
borlanic | 0:02dd72d1d465 | 141 | targets = json_file_to_dict(Target.__targets_json_location or |
borlanic | 0:02dd72d1d465 | 142 | Target.__targets_json_location_default) |
borlanic | 0:02dd72d1d465 | 143 | |
borlanic | 0:02dd72d1d465 | 144 | for extra_target in Target.__extra_target_json_files: |
borlanic | 0:02dd72d1d465 | 145 | for k, v in json_file_to_dict(extra_target).items(): |
borlanic | 0:02dd72d1d465 | 146 | if k in targets: |
borlanic | 0:02dd72d1d465 | 147 | print('WARNING: Custom target "%s" cannot replace existing ' |
borlanic | 0:02dd72d1d465 | 148 | 'target.' % k) |
borlanic | 0:02dd72d1d465 | 149 | else: |
borlanic | 0:02dd72d1d465 | 150 | targets[k] = v |
borlanic | 0:02dd72d1d465 | 151 | |
borlanic | 0:02dd72d1d465 | 152 | return targets |
borlanic | 0:02dd72d1d465 | 153 | |
borlanic | 0:02dd72d1d465 | 154 | @staticmethod |
borlanic | 0:02dd72d1d465 | 155 | def add_extra_targets(source_dir): |
borlanic | 0:02dd72d1d465 | 156 | extra_targets_file = os.path.join(source_dir, "custom_targets.json") |
borlanic | 0:02dd72d1d465 | 157 | if os.path.exists(extra_targets_file): |
borlanic | 0:02dd72d1d465 | 158 | Target.__extra_target_json_files.append(extra_targets_file) |
borlanic | 0:02dd72d1d465 | 159 | CACHES.clear() |
borlanic | 0:02dd72d1d465 | 160 | |
borlanic | 0:02dd72d1d465 | 161 | @staticmethod |
borlanic | 0:02dd72d1d465 | 162 | def set_targets_json_location(location=None): |
borlanic | 0:02dd72d1d465 | 163 | """Set the location of the targets.json file""" |
borlanic | 0:02dd72d1d465 | 164 | Target.__targets_json_location = (location or |
borlanic | 0:02dd72d1d465 | 165 | Target.__targets_json_location_default) |
borlanic | 0:02dd72d1d465 | 166 | Target.__extra_target_json_files = [] |
borlanic | 0:02dd72d1d465 | 167 | # Invalidate caches, since the location of the JSON file changed |
borlanic | 0:02dd72d1d465 | 168 | CACHES.clear() |
borlanic | 0:02dd72d1d465 | 169 | |
borlanic | 0:02dd72d1d465 | 170 | @staticmethod |
borlanic | 0:02dd72d1d465 | 171 | @cached |
borlanic | 0:02dd72d1d465 | 172 | def get_module_data(): |
borlanic | 0:02dd72d1d465 | 173 | """Get the members of this module using Python's "inspect" module""" |
borlanic | 0:02dd72d1d465 | 174 | return dict([(m[0], m[1]) for m in |
borlanic | 0:02dd72d1d465 | 175 | inspect.getmembers(sys.modules[__name__])]) |
borlanic | 0:02dd72d1d465 | 176 | |
borlanic | 0:02dd72d1d465 | 177 | @staticmethod |
borlanic | 0:02dd72d1d465 | 178 | def __add_paths_to_progen(data): |
borlanic | 0:02dd72d1d465 | 179 | """Modify the exporter specification ("progen") by changing all |
borlanic | 0:02dd72d1d465 | 180 | "template" keys to full paths |
borlanic | 0:02dd72d1d465 | 181 | """ |
borlanic | 0:02dd72d1d465 | 182 | out = {} |
borlanic | 0:02dd72d1d465 | 183 | for key, val in data.items(): |
borlanic | 0:02dd72d1d465 | 184 | if isinstance(val, dict): |
borlanic | 0:02dd72d1d465 | 185 | out[key] = Target.__add_paths_to_progen(val) |
borlanic | 0:02dd72d1d465 | 186 | elif key == "template": |
borlanic | 0:02dd72d1d465 | 187 | out[key] = [os.path.join(os.path.dirname(__file__), 'export', v) |
borlanic | 0:02dd72d1d465 | 188 | for v in val] |
borlanic | 0:02dd72d1d465 | 189 | else: |
borlanic | 0:02dd72d1d465 | 190 | out[key] = val |
borlanic | 0:02dd72d1d465 | 191 | return out |
borlanic | 0:02dd72d1d465 | 192 | |
borlanic | 0:02dd72d1d465 | 193 | def __getattr_cumulative(self, attrname): |
borlanic | 0:02dd72d1d465 | 194 | """Look for the attribute in the class and its parents, as defined by |
borlanic | 0:02dd72d1d465 | 195 | the resolution order |
borlanic | 0:02dd72d1d465 | 196 | """ |
borlanic | 0:02dd72d1d465 | 197 | tdata = self.json_data |
borlanic | 0:02dd72d1d465 | 198 | # For a cumulative attribute, figure out when it was defined the |
borlanic | 0:02dd72d1d465 | 199 | # last time (in attribute resolution order) then follow the "_add" |
borlanic | 0:02dd72d1d465 | 200 | # and "_remove" data fields |
borlanic | 0:02dd72d1d465 | 201 | for idx, tgt in enumerate(self.resolution_order): |
borlanic | 0:02dd72d1d465 | 202 | # the attribute was defined at this level in the resolution |
borlanic | 0:02dd72d1d465 | 203 | # order |
borlanic | 0:02dd72d1d465 | 204 | if attrname in tdata[tgt[0]]: |
borlanic | 0:02dd72d1d465 | 205 | def_idx = idx |
borlanic | 0:02dd72d1d465 | 206 | break |
borlanic | 0:02dd72d1d465 | 207 | else: |
borlanic | 0:02dd72d1d465 | 208 | raise AttributeError("Attribute '%s' not found in target '%s'" |
borlanic | 0:02dd72d1d465 | 209 | % (attrname, self.name)) |
borlanic | 0:02dd72d1d465 | 210 | # Get the starting value of the attribute |
borlanic | 0:02dd72d1d465 | 211 | starting_value = (tdata[self.resolution_order[def_idx][0]][attrname] |
borlanic | 0:02dd72d1d465 | 212 | or [])[:] |
borlanic | 0:02dd72d1d465 | 213 | # Traverse the resolution list in high inheritance to low |
borlanic | 0:02dd72d1d465 | 214 | # inheritance level, left to right order to figure out all the |
borlanic | 0:02dd72d1d465 | 215 | # other classes that change the definition by adding or removing |
borlanic | 0:02dd72d1d465 | 216 | # elements |
borlanic | 0:02dd72d1d465 | 217 | for idx in range(self.resolution_order[def_idx][1] - 1, -1, -1): |
borlanic | 0:02dd72d1d465 | 218 | same_level_targets = [tar[0] for tar in self.resolution_order |
borlanic | 0:02dd72d1d465 | 219 | if tar[1] == idx] |
borlanic | 0:02dd72d1d465 | 220 | for tar in same_level_targets: |
borlanic | 0:02dd72d1d465 | 221 | data = tdata[tar] |
borlanic | 0:02dd72d1d465 | 222 | # Do we have anything to add ? |
borlanic | 0:02dd72d1d465 | 223 | if (attrname + "_add") in data: |
borlanic | 0:02dd72d1d465 | 224 | starting_value.extend(data[attrname + "_add"]) |
borlanic | 0:02dd72d1d465 | 225 | # Do we have anything to remove ? |
borlanic | 0:02dd72d1d465 | 226 | if (attrname + "_remove") in data: |
borlanic | 0:02dd72d1d465 | 227 | # Macros can be defined either without a value (MACRO) |
borlanic | 0:02dd72d1d465 | 228 | # or with a value (MACRO=10). When removing, we specify |
borlanic | 0:02dd72d1d465 | 229 | # only the name of the macro, without the value. So we |
borlanic | 0:02dd72d1d465 | 230 | # need to create a mapping between the macro name and |
borlanic | 0:02dd72d1d465 | 231 | # its value. This will work for extra_labels and other |
borlanic | 0:02dd72d1d465 | 232 | # type of arrays as well, since they fall into the |
borlanic | 0:02dd72d1d465 | 233 | # "macros without a value" category (simple definitions |
borlanic | 0:02dd72d1d465 | 234 | # without a value). |
borlanic | 0:02dd72d1d465 | 235 | name_def_map = {} |
borlanic | 0:02dd72d1d465 | 236 | for crtv in starting_value: |
borlanic | 0:02dd72d1d465 | 237 | if crtv.find('=') != -1: |
borlanic | 0:02dd72d1d465 | 238 | temp = crtv.split('=') |
borlanic | 0:02dd72d1d465 | 239 | if len(temp) != 2: |
borlanic | 0:02dd72d1d465 | 240 | raise ValueError( |
borlanic | 0:02dd72d1d465 | 241 | "Invalid macro definition '%s'" % crtv) |
borlanic | 0:02dd72d1d465 | 242 | name_def_map[temp[0]] = crtv |
borlanic | 0:02dd72d1d465 | 243 | else: |
borlanic | 0:02dd72d1d465 | 244 | name_def_map[crtv] = crtv |
borlanic | 0:02dd72d1d465 | 245 | for element in data[attrname + "_remove"]: |
borlanic | 0:02dd72d1d465 | 246 | if element not in name_def_map: |
borlanic | 0:02dd72d1d465 | 247 | raise ValueError( |
borlanic | 0:02dd72d1d465 | 248 | ("Unable to remove '%s' in '%s.%s' since " |
borlanic | 0:02dd72d1d465 | 249 | % (element, self.name, attrname)) + |
borlanic | 0:02dd72d1d465 | 250 | "it doesn't exist") |
borlanic | 0:02dd72d1d465 | 251 | starting_value.remove(name_def_map[element]) |
borlanic | 0:02dd72d1d465 | 252 | return starting_value |
borlanic | 0:02dd72d1d465 | 253 | |
borlanic | 0:02dd72d1d465 | 254 | def __getattr_helper(self, attrname): |
borlanic | 0:02dd72d1d465 | 255 | """Compute the value of a given target attribute""" |
borlanic | 0:02dd72d1d465 | 256 | if attrname in CUMULATIVE_ATTRIBUTES: |
borlanic | 0:02dd72d1d465 | 257 | return self.__getattr_cumulative(attrname) |
borlanic | 0:02dd72d1d465 | 258 | else: |
borlanic | 0:02dd72d1d465 | 259 | tdata = self.json_data |
borlanic | 0:02dd72d1d465 | 260 | starting_value = None |
borlanic | 0:02dd72d1d465 | 261 | for tgt in self.resolution_order: |
borlanic | 0:02dd72d1d465 | 262 | data = tdata[tgt[0]] |
borlanic | 0:02dd72d1d465 | 263 | try: |
borlanic | 0:02dd72d1d465 | 264 | return data[attrname] |
borlanic | 0:02dd72d1d465 | 265 | except KeyError: |
borlanic | 0:02dd72d1d465 | 266 | pass |
borlanic | 0:02dd72d1d465 | 267 | else: # Attribute not found |
borlanic | 0:02dd72d1d465 | 268 | raise AttributeError( |
borlanic | 0:02dd72d1d465 | 269 | "Attribute '%s' not found in target '%s'" |
borlanic | 0:02dd72d1d465 | 270 | % (attrname, self.name)) |
borlanic | 0:02dd72d1d465 | 271 | |
borlanic | 0:02dd72d1d465 | 272 | def __getattr__(self, attrname): |
borlanic | 0:02dd72d1d465 | 273 | """ Return the value of an attribute. This function only computes the |
borlanic | 0:02dd72d1d465 | 274 | attribute's value once, then adds it to the instance attributes (in |
borlanic | 0:02dd72d1d465 | 275 | __dict__), so the next time it is returned directly |
borlanic | 0:02dd72d1d465 | 276 | """ |
borlanic | 0:02dd72d1d465 | 277 | result = self.__getattr_helper(attrname) |
borlanic | 0:02dd72d1d465 | 278 | self.__dict__[attrname] = result |
borlanic | 0:02dd72d1d465 | 279 | return result |
borlanic | 0:02dd72d1d465 | 280 | |
borlanic | 0:02dd72d1d465 | 281 | @staticmethod |
borlanic | 0:02dd72d1d465 | 282 | @cached |
borlanic | 0:02dd72d1d465 | 283 | def get_target(target_name): |
borlanic | 0:02dd72d1d465 | 284 | """ Return the target instance starting from the target name """ |
borlanic | 0:02dd72d1d465 | 285 | return target(target_name, Target.get_json_target_data()) |
borlanic | 0:02dd72d1d465 | 286 | |
borlanic | 0:02dd72d1d465 | 287 | |
borlanic | 0:02dd72d1d465 | 288 | @property |
borlanic | 0:02dd72d1d465 | 289 | def program_cycle_s(self): |
borlanic | 0:02dd72d1d465 | 290 | """Special override for program_cycle_s as it's default value depends |
borlanic | 0:02dd72d1d465 | 291 | upon is_disk_virtual |
borlanic | 0:02dd72d1d465 | 292 | """ |
borlanic | 0:02dd72d1d465 | 293 | try: |
borlanic | 0:02dd72d1d465 | 294 | return self.__getattr__("program_cycle_s") |
borlanic | 0:02dd72d1d465 | 295 | except AttributeError: |
borlanic | 0:02dd72d1d465 | 296 | return 4 if self.is_disk_virtual else 1.5 |
borlanic | 0:02dd72d1d465 | 297 | |
borlanic | 0:02dd72d1d465 | 298 | @property |
borlanic | 0:02dd72d1d465 | 299 | def labels(self): |
borlanic | 0:02dd72d1d465 | 300 | """Get all possible labels for this target""" |
borlanic | 0:02dd72d1d465 | 301 | names = copy(self.resolution_order_names) |
borlanic | 0:02dd72d1d465 | 302 | if "Target" in names: |
borlanic | 0:02dd72d1d465 | 303 | names.remove("Target") |
borlanic | 0:02dd72d1d465 | 304 | labels = (names + CORE_LABELS[self.core] + self.extra_labels) |
borlanic | 0:02dd72d1d465 | 305 | # Automatically define UVISOR_UNSUPPORTED if the target doesn't |
borlanic | 0:02dd72d1d465 | 306 | # specifically define UVISOR_SUPPORTED |
borlanic | 0:02dd72d1d465 | 307 | if "UVISOR_SUPPORTED" not in labels: |
borlanic | 0:02dd72d1d465 | 308 | labels.append("UVISOR_UNSUPPORTED") |
borlanic | 0:02dd72d1d465 | 309 | return labels |
borlanic | 0:02dd72d1d465 | 310 | |
borlanic | 0:02dd72d1d465 | 311 | def init_hooks(self, hook, toolchain): |
borlanic | 0:02dd72d1d465 | 312 | """Initialize the post-build hooks for a toolchain. For now, this |
borlanic | 0:02dd72d1d465 | 313 | function only allows "post binary" hooks (hooks that are executed |
borlanic | 0:02dd72d1d465 | 314 | after the binary image is extracted from the executable file) |
borlanic | 0:02dd72d1d465 | 315 | |
borlanic | 0:02dd72d1d465 | 316 | Positional Arguments: |
borlanic | 0:02dd72d1d465 | 317 | hook - the hook object to add post-binary-hooks to |
borlanic | 0:02dd72d1d465 | 318 | toolchain - the toolchain object for inspection |
borlanic | 0:02dd72d1d465 | 319 | """ |
borlanic | 0:02dd72d1d465 | 320 | |
borlanic | 0:02dd72d1d465 | 321 | # If there's no hook, simply return |
borlanic | 0:02dd72d1d465 | 322 | try: |
borlanic | 0:02dd72d1d465 | 323 | hook_data = self.post_binary_hook |
borlanic | 0:02dd72d1d465 | 324 | except AttributeError: |
borlanic | 0:02dd72d1d465 | 325 | return |
borlanic | 0:02dd72d1d465 | 326 | # A hook was found. The hook's name is in the format |
borlanic | 0:02dd72d1d465 | 327 | # "classname.functionname" |
borlanic | 0:02dd72d1d465 | 328 | temp = hook_data["function"].split(".") |
borlanic | 0:02dd72d1d465 | 329 | if len(temp) != 2: |
borlanic | 0:02dd72d1d465 | 330 | raise HookError( |
borlanic | 0:02dd72d1d465 | 331 | ("Invalid format for hook '%s' in target '%s'" |
borlanic | 0:02dd72d1d465 | 332 | % (hook_data["function"], self.name)) + |
borlanic | 0:02dd72d1d465 | 333 | " (must be 'class_name.function_name')") |
borlanic | 0:02dd72d1d465 | 334 | class_name, function_name = temp |
borlanic | 0:02dd72d1d465 | 335 | # "class_name" must refer to a class in this file, so check if the |
borlanic | 0:02dd72d1d465 | 336 | # class exists |
borlanic | 0:02dd72d1d465 | 337 | mdata = self.get_module_data() |
borlanic | 0:02dd72d1d465 | 338 | if class_name not in mdata or \ |
borlanic | 0:02dd72d1d465 | 339 | not inspect.isclass(mdata[class_name]): |
borlanic | 0:02dd72d1d465 | 340 | raise HookError( |
borlanic | 0:02dd72d1d465 | 341 | ("Class '%s' required by '%s' in target '%s'" |
borlanic | 0:02dd72d1d465 | 342 | % (class_name, hook_data["function"], self.name)) + |
borlanic | 0:02dd72d1d465 | 343 | " not found in targets.py") |
borlanic | 0:02dd72d1d465 | 344 | # "function_name" must refer to a static function inside class |
borlanic | 0:02dd72d1d465 | 345 | # "class_name" |
borlanic | 0:02dd72d1d465 | 346 | cls = mdata[class_name] |
borlanic | 0:02dd72d1d465 | 347 | if (not hasattr(cls, function_name)) or \ |
borlanic | 0:02dd72d1d465 | 348 | (not inspect.isfunction(getattr(cls, function_name))): |
borlanic | 0:02dd72d1d465 | 349 | raise HookError( |
borlanic | 0:02dd72d1d465 | 350 | ("Static function '%s' " % function_name) + |
borlanic | 0:02dd72d1d465 | 351 | ("required by '%s' " % hook_data["function"]) + |
borlanic | 0:02dd72d1d465 | 352 | ("in target '%s' " % self.name) + |
borlanic | 0:02dd72d1d465 | 353 | ("not found in class '%s'" % class_name)) |
borlanic | 0:02dd72d1d465 | 354 | # Check if the hook specification also has toolchain restrictions |
borlanic | 0:02dd72d1d465 | 355 | toolchain_restrictions = set(hook_data.get("toolchains", [])) |
borlanic | 0:02dd72d1d465 | 356 | toolchain_labels = set(c.__name__ for c in getmro(toolchain.__class__)) |
borlanic | 0:02dd72d1d465 | 357 | if toolchain_restrictions and \ |
borlanic | 0:02dd72d1d465 | 358 | not toolchain_labels.intersection(toolchain_restrictions): |
borlanic | 0:02dd72d1d465 | 359 | return |
borlanic | 0:02dd72d1d465 | 360 | # Finally, hook the requested function |
borlanic | 0:02dd72d1d465 | 361 | hook.hook_add_binary("post", getattr(cls, function_name)) |
borlanic | 0:02dd72d1d465 | 362 | |
borlanic | 0:02dd72d1d465 | 363 | ################################################################################ |
borlanic | 0:02dd72d1d465 | 364 | # Target specific code goes in this section |
borlanic | 0:02dd72d1d465 | 365 | # This code can be invoked from the target description using the |
borlanic | 0:02dd72d1d465 | 366 | # "post_binary_hook" key |
borlanic | 0:02dd72d1d465 | 367 | |
borlanic | 0:02dd72d1d465 | 368 | class LPCTargetCode(object): |
borlanic | 0:02dd72d1d465 | 369 | """General LPC Target patching code""" |
borlanic | 0:02dd72d1d465 | 370 | @staticmethod |
borlanic | 0:02dd72d1d465 | 371 | def lpc_patch(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 372 | """Patch an elf file""" |
borlanic | 0:02dd72d1d465 | 373 | t_self.debug("LPC Patch: %s" % os.path.split(binf)[1]) |
borlanic | 0:02dd72d1d465 | 374 | patch(binf) |
borlanic | 0:02dd72d1d465 | 375 | |
borlanic | 0:02dd72d1d465 | 376 | class LPC4088Code(object): |
borlanic | 0:02dd72d1d465 | 377 | """Code specific to the LPC4088""" |
borlanic | 0:02dd72d1d465 | 378 | @staticmethod |
borlanic | 0:02dd72d1d465 | 379 | def binary_hook(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 380 | """Hook to be run after an elf file is built""" |
borlanic | 0:02dd72d1d465 | 381 | if not os.path.isdir(binf): |
borlanic | 0:02dd72d1d465 | 382 | # Regular binary file, nothing to do |
borlanic | 0:02dd72d1d465 | 383 | LPCTargetCode.lpc_patch(t_self, resources, elf, binf) |
borlanic | 0:02dd72d1d465 | 384 | return |
borlanic | 0:02dd72d1d465 | 385 | outbin = open(binf + ".temp", "wb") |
borlanic | 0:02dd72d1d465 | 386 | partf = open(os.path.join(binf, "ER_IROM1"), "rb") |
borlanic | 0:02dd72d1d465 | 387 | # Pad the fist part (internal flash) with 0xFF to 512k |
borlanic | 0:02dd72d1d465 | 388 | data = partf.read() |
borlanic | 0:02dd72d1d465 | 389 | outbin.write(data) |
borlanic | 0:02dd72d1d465 | 390 | outbin.write('\xFF' * (512*1024 - len(data))) |
borlanic | 0:02dd72d1d465 | 391 | partf.close() |
borlanic | 0:02dd72d1d465 | 392 | # Read and append the second part (external flash) in chunks of fixed |
borlanic | 0:02dd72d1d465 | 393 | # size |
borlanic | 0:02dd72d1d465 | 394 | chunksize = 128 * 1024 |
borlanic | 0:02dd72d1d465 | 395 | partf = open(os.path.join(binf, "ER_IROM2"), "rb") |
borlanic | 0:02dd72d1d465 | 396 | while True: |
borlanic | 0:02dd72d1d465 | 397 | data = partf.read(chunksize) |
borlanic | 0:02dd72d1d465 | 398 | outbin.write(data) |
borlanic | 0:02dd72d1d465 | 399 | if len(data) < chunksize: |
borlanic | 0:02dd72d1d465 | 400 | break |
borlanic | 0:02dd72d1d465 | 401 | partf.close() |
borlanic | 0:02dd72d1d465 | 402 | outbin.close() |
borlanic | 0:02dd72d1d465 | 403 | # Remove the directory with the binary parts and rename the temporary |
borlanic | 0:02dd72d1d465 | 404 | # file to 'binf' |
borlanic | 0:02dd72d1d465 | 405 | shutil.rmtree(binf, True) |
borlanic | 0:02dd72d1d465 | 406 | os.rename(binf + '.temp', binf) |
borlanic | 0:02dd72d1d465 | 407 | t_self.debug("Generated custom binary file (internal flash + SPIFI)") |
borlanic | 0:02dd72d1d465 | 408 | LPCTargetCode.lpc_patch(t_self, resources, elf, binf) |
borlanic | 0:02dd72d1d465 | 409 | |
borlanic | 0:02dd72d1d465 | 410 | class TEENSY3_1Code(object): |
borlanic | 0:02dd72d1d465 | 411 | """Hooks for the TEENSY3.1""" |
borlanic | 0:02dd72d1d465 | 412 | @staticmethod |
borlanic | 0:02dd72d1d465 | 413 | def binary_hook(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 414 | """Hook that is run after elf is generated""" |
borlanic | 0:02dd72d1d465 | 415 | # This function is referenced by old versions of targets.json and should |
borlanic | 0:02dd72d1d465 | 416 | # be kept for backwards compatibility. |
borlanic | 0:02dd72d1d465 | 417 | pass |
borlanic | 0:02dd72d1d465 | 418 | |
borlanic | 0:02dd72d1d465 | 419 | class MTSCode(object): |
borlanic | 0:02dd72d1d465 | 420 | """Generic MTS code""" |
borlanic | 0:02dd72d1d465 | 421 | @staticmethod |
borlanic | 0:02dd72d1d465 | 422 | def _combine_bins_helper(target_name, binf): |
borlanic | 0:02dd72d1d465 | 423 | """combine bins with the bootloader for a particular target""" |
borlanic | 0:02dd72d1d465 | 424 | loader = os.path.join(TOOLS_BOOTLOADERS, target_name, "bootloader.bin") |
borlanic | 0:02dd72d1d465 | 425 | target = binf + ".tmp" |
borlanic | 0:02dd72d1d465 | 426 | if not os.path.exists(loader): |
borlanic | 0:02dd72d1d465 | 427 | print("Can't find bootloader binary: " + loader) |
borlanic | 0:02dd72d1d465 | 428 | return |
borlanic | 0:02dd72d1d465 | 429 | outbin = open(target, 'w+b') |
borlanic | 0:02dd72d1d465 | 430 | part = open(loader, 'rb') |
borlanic | 0:02dd72d1d465 | 431 | data = part.read() |
borlanic | 0:02dd72d1d465 | 432 | outbin.write(data) |
borlanic | 0:02dd72d1d465 | 433 | outbin.write('\xFF' * (64*1024 - len(data))) |
borlanic | 0:02dd72d1d465 | 434 | part.close() |
borlanic | 0:02dd72d1d465 | 435 | part = open(binf, 'rb') |
borlanic | 0:02dd72d1d465 | 436 | data = part.read() |
borlanic | 0:02dd72d1d465 | 437 | outbin.write(data) |
borlanic | 0:02dd72d1d465 | 438 | part.close() |
borlanic | 0:02dd72d1d465 | 439 | outbin.seek(0, 0) |
borlanic | 0:02dd72d1d465 | 440 | data = outbin.read() |
borlanic | 0:02dd72d1d465 | 441 | outbin.seek(0, 1) |
borlanic | 0:02dd72d1d465 | 442 | crc = struct.pack('<I', binascii.crc32(data) & 0xFFFFFFFF) |
borlanic | 0:02dd72d1d465 | 443 | outbin.write(crc) |
borlanic | 0:02dd72d1d465 | 444 | outbin.close() |
borlanic | 0:02dd72d1d465 | 445 | os.remove(binf) |
borlanic | 0:02dd72d1d465 | 446 | os.rename(target, binf) |
borlanic | 0:02dd72d1d465 | 447 | |
borlanic | 0:02dd72d1d465 | 448 | @staticmethod |
borlanic | 0:02dd72d1d465 | 449 | def combine_bins_mts_dot(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 450 | """A hook for the MTS MDOT""" |
borlanic | 0:02dd72d1d465 | 451 | MTSCode._combine_bins_helper("MTS_MDOT_F411RE", binf) |
borlanic | 0:02dd72d1d465 | 452 | |
borlanic | 0:02dd72d1d465 | 453 | @staticmethod |
borlanic | 0:02dd72d1d465 | 454 | def combine_bins_mts_dragonfly(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 455 | """A hoof for the MTS Dragonfly""" |
borlanic | 0:02dd72d1d465 | 456 | MTSCode._combine_bins_helper("MTS_DRAGONFLY_F411RE", binf) |
borlanic | 0:02dd72d1d465 | 457 | |
borlanic | 0:02dd72d1d465 | 458 | @staticmethod |
borlanic | 0:02dd72d1d465 | 459 | def combine_bins_mtb_mts_dragonfly(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 460 | """A hook for the MTB MTS Dragonfly""" |
borlanic | 0:02dd72d1d465 | 461 | MTSCode._combine_bins_helper("MTB_MTS_DRAGONFLY", binf) |
borlanic | 0:02dd72d1d465 | 462 | |
borlanic | 0:02dd72d1d465 | 463 | class MCU_NRF51Code(object): |
borlanic | 0:02dd72d1d465 | 464 | """NRF51 Hooks""" |
borlanic | 0:02dd72d1d465 | 465 | @staticmethod |
borlanic | 0:02dd72d1d465 | 466 | def binary_hook(t_self, resources, _, binf): |
borlanic | 0:02dd72d1d465 | 467 | """Hook that merges the soft device with the bin file""" |
borlanic | 0:02dd72d1d465 | 468 | # Scan to find the actual paths of soft device |
borlanic | 0:02dd72d1d465 | 469 | sdf = None |
borlanic | 0:02dd72d1d465 | 470 | for softdevice_and_offset_entry\ |
borlanic | 0:02dd72d1d465 | 471 | in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS: |
borlanic | 0:02dd72d1d465 | 472 | for hexf in resources.hex_files: |
borlanic | 0:02dd72d1d465 | 473 | if hexf.find(softdevice_and_offset_entry['name']) != -1: |
borlanic | 0:02dd72d1d465 | 474 | t_self.debug("SoftDevice file found %s." |
borlanic | 0:02dd72d1d465 | 475 | % softdevice_and_offset_entry['name']) |
borlanic | 0:02dd72d1d465 | 476 | sdf = hexf |
borlanic | 0:02dd72d1d465 | 477 | |
borlanic | 0:02dd72d1d465 | 478 | if sdf is not None: |
borlanic | 0:02dd72d1d465 | 479 | break |
borlanic | 0:02dd72d1d465 | 480 | if sdf is not None: |
borlanic | 0:02dd72d1d465 | 481 | break |
borlanic | 0:02dd72d1d465 | 482 | |
borlanic | 0:02dd72d1d465 | 483 | if sdf is None: |
borlanic | 0:02dd72d1d465 | 484 | t_self.debug("Hex file not found. Aborting.") |
borlanic | 0:02dd72d1d465 | 485 | return |
borlanic | 0:02dd72d1d465 | 486 | |
borlanic | 0:02dd72d1d465 | 487 | # Look for bootloader file that matches this soft device or bootloader |
borlanic | 0:02dd72d1d465 | 488 | # override image |
borlanic | 0:02dd72d1d465 | 489 | blf = None |
borlanic | 0:02dd72d1d465 | 490 | if t_self.target.MERGE_BOOTLOADER is True: |
borlanic | 0:02dd72d1d465 | 491 | for hexf in resources.hex_files: |
borlanic | 0:02dd72d1d465 | 492 | if hexf.find(t_self.target.OVERRIDE_BOOTLOADER_FILENAME) != -1: |
borlanic | 0:02dd72d1d465 | 493 | t_self.debug("Bootloader file found %s." |
borlanic | 0:02dd72d1d465 | 494 | % t_self.target.OVERRIDE_BOOTLOADER_FILENAME) |
borlanic | 0:02dd72d1d465 | 495 | blf = hexf |
borlanic | 0:02dd72d1d465 | 496 | break |
borlanic | 0:02dd72d1d465 | 497 | elif hexf.find(softdevice_and_offset_entry['boot']) != -1: |
borlanic | 0:02dd72d1d465 | 498 | t_self.debug("Bootloader file found %s." |
borlanic | 0:02dd72d1d465 | 499 | % softdevice_and_offset_entry['boot']) |
borlanic | 0:02dd72d1d465 | 500 | blf = hexf |
borlanic | 0:02dd72d1d465 | 501 | break |
borlanic | 0:02dd72d1d465 | 502 | |
borlanic | 0:02dd72d1d465 | 503 | # Merge user code with softdevice |
borlanic | 0:02dd72d1d465 | 504 | from intelhex import IntelHex |
borlanic | 0:02dd72d1d465 | 505 | binh = IntelHex() |
borlanic | 0:02dd72d1d465 | 506 | _, ext = os.path.splitext(binf) |
borlanic | 0:02dd72d1d465 | 507 | if ext == ".hex": |
borlanic | 0:02dd72d1d465 | 508 | binh.loadhex(binf) |
borlanic | 0:02dd72d1d465 | 509 | elif ext == ".bin": |
borlanic | 0:02dd72d1d465 | 510 | binh.loadbin(binf, softdevice_and_offset_entry['offset']) |
borlanic | 0:02dd72d1d465 | 511 | |
borlanic | 0:02dd72d1d465 | 512 | if t_self.target.MERGE_SOFT_DEVICE is True: |
borlanic | 0:02dd72d1d465 | 513 | t_self.debug("Merge SoftDevice file %s" |
borlanic | 0:02dd72d1d465 | 514 | % softdevice_and_offset_entry['name']) |
borlanic | 0:02dd72d1d465 | 515 | sdh = IntelHex(sdf) |
borlanic | 0:02dd72d1d465 | 516 | binh.merge(sdh) |
borlanic | 0:02dd72d1d465 | 517 | |
borlanic | 0:02dd72d1d465 | 518 | if t_self.target.MERGE_BOOTLOADER is True and blf is not None: |
borlanic | 0:02dd72d1d465 | 519 | t_self.debug("Merge BootLoader file %s" % blf) |
borlanic | 0:02dd72d1d465 | 520 | blh = IntelHex(blf) |
borlanic | 0:02dd72d1d465 | 521 | binh.merge(blh) |
borlanic | 0:02dd72d1d465 | 522 | |
borlanic | 0:02dd72d1d465 | 523 | with open(binf.replace(".bin", ".hex"), "w") as fileout: |
borlanic | 0:02dd72d1d465 | 524 | binh.write_hex_file(fileout, write_start_addr=False) |
borlanic | 0:02dd72d1d465 | 525 | |
borlanic | 0:02dd72d1d465 | 526 | class NCS36510TargetCode: |
borlanic | 0:02dd72d1d465 | 527 | @staticmethod |
borlanic | 0:02dd72d1d465 | 528 | def ncs36510_addfib(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 529 | from tools.targets.NCS import add_fib_at_start |
borlanic | 0:02dd72d1d465 | 530 | print("binf ", binf) |
borlanic | 0:02dd72d1d465 | 531 | add_fib_at_start(binf[:-4]) |
borlanic | 0:02dd72d1d465 | 532 | |
borlanic | 0:02dd72d1d465 | 533 | class RTL8195ACode: |
borlanic | 0:02dd72d1d465 | 534 | """RTL8195A Hooks""" |
borlanic | 0:02dd72d1d465 | 535 | @staticmethod |
borlanic | 0:02dd72d1d465 | 536 | def binary_hook(t_self, resources, elf, binf): |
borlanic | 0:02dd72d1d465 | 537 | from tools.targets.REALTEK_RTL8195AM import rtl8195a_elf2bin |
borlanic | 0:02dd72d1d465 | 538 | rtl8195a_elf2bin(t_self, elf, binf) |
borlanic | 0:02dd72d1d465 | 539 | ################################################################################ |
borlanic | 0:02dd72d1d465 | 540 | |
borlanic | 0:02dd72d1d465 | 541 | # Instantiate all public targets |
borlanic | 0:02dd72d1d465 | 542 | def update_target_data(): |
borlanic | 0:02dd72d1d465 | 543 | TARGETS[:] = [Target.get_target(tgt) for tgt, obj |
borlanic | 0:02dd72d1d465 | 544 | in Target.get_json_target_data().items() |
borlanic | 0:02dd72d1d465 | 545 | if obj.get("public", True)] |
borlanic | 0:02dd72d1d465 | 546 | # Map each target name to its unique instance |
borlanic | 0:02dd72d1d465 | 547 | TARGET_MAP.clear() |
borlanic | 0:02dd72d1d465 | 548 | TARGET_MAP.update(dict([(tgt.name, tgt) for tgt in TARGETS])) |
borlanic | 0:02dd72d1d465 | 549 | TARGET_NAMES[:] = TARGET_MAP.keys() |
borlanic | 0:02dd72d1d465 | 550 | |
borlanic | 0:02dd72d1d465 | 551 | TARGETS = [] |
borlanic | 0:02dd72d1d465 | 552 | TARGET_MAP = dict() |
borlanic | 0:02dd72d1d465 | 553 | TARGET_NAMES = [] |
borlanic | 0:02dd72d1d465 | 554 | |
borlanic | 0:02dd72d1d465 | 555 | update_target_data() |
borlanic | 0:02dd72d1d465 | 556 | |
borlanic | 0:02dd72d1d465 | 557 | # Some targets with different name have the same exporters |
borlanic | 0:02dd72d1d465 | 558 | EXPORT_MAP = {} |
borlanic | 0:02dd72d1d465 | 559 | |
borlanic | 0:02dd72d1d465 | 560 | # Detection APIs |
borlanic | 0:02dd72d1d465 | 561 | def get_target_detect_codes(): |
borlanic | 0:02dd72d1d465 | 562 | """ Returns dictionary mapping detect_code -> platform_name |
borlanic | 0:02dd72d1d465 | 563 | """ |
borlanic | 0:02dd72d1d465 | 564 | result = {} |
borlanic | 0:02dd72d1d465 | 565 | for tgt in TARGETS: |
borlanic | 0:02dd72d1d465 | 566 | for detect_code in tgt.detect_code: |
borlanic | 0:02dd72d1d465 | 567 | result[detect_code] = tgt.name |
borlanic | 0:02dd72d1d465 | 568 | return result |
borlanic | 0:02dd72d1d465 | 569 | |
borlanic | 0:02dd72d1d465 | 570 | def set_targets_json_location(location=None): |
borlanic | 0:02dd72d1d465 | 571 | """Sets the location of the JSON file that contains the targets""" |
borlanic | 0:02dd72d1d465 | 572 | # First instruct Target about the new location |
borlanic | 0:02dd72d1d465 | 573 | Target.set_targets_json_location(location) |
borlanic | 0:02dd72d1d465 | 574 | # Then re-initialize TARGETS, TARGET_MAP and TARGET_NAMES. The |
borlanic | 0:02dd72d1d465 | 575 | # re-initialization does not create new variables, it keeps the old ones |
borlanic | 0:02dd72d1d465 | 576 | # instead. This ensures compatibility with code that does |
borlanic | 0:02dd72d1d465 | 577 | # "from tools.targets import TARGET_NAMES" |
borlanic | 0:02dd72d1d465 | 578 | update_target_data() |
borlanic | 0:02dd72d1d465 | 579 |