|
21 | 21 | import shutil
|
22 | 22 | from argparse import ArgumentParser
|
23 | 23 |
|
24 |
| -ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) |
| 24 | +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), |
| 25 | + os.pardir, os.pardir)) |
25 | 26 | sys.path.insert(0, ROOT)
|
26 | 27 | from tools.targets import Target, TARGET_MAP, TARGET_NAMES
|
27 | 28 |
|
28 | 29 | MAKE_PY_LOCATTION = os.path.join(ROOT, 'tools', 'make.py')
|
29 | 30 | TEST_PY_LOCATTION = os.path.join(ROOT, 'tools', 'test.py')
|
30 |
| -MBED_PSA_TESTS = '*psa-spm*,*psa-crypto_access_control' |
31 | 31 | TFM_MBED_APP = os.path.join(ROOT, 'tools', 'psa', 'tfm', 'mbed_app.json')
|
| 32 | +MBED_PSA_TESTS = '*psa-spm*,*psa-crypto_access_control' |
32 | 33 | TFM_TESTS = {
|
33 | 34 | '*psa-spm_smoke': ['USE_PSA_TEST_PARTITIONS', 'USE_SMOKE_TESTS_PART1'],
|
34 | 35 | '*psa-spm_client': ['USE_PSA_TEST_PARTITIONS', 'USE_CLIENT_TESTS_PART1'],
|
35 |
| - '*psa-spm_server': ['USE_PSA_TEST_PARTITIONS', 'USE_SERVER_TESTS_PART1', 'USE_SERVER_TESTS_PART2'], |
36 |
| - '*psa-crypto_access_control': ['USE_PSA_TEST_PARTITIONS', 'USE_CRYPTO_ACL_TEST'] |
| 36 | + '*psa-spm_server': ['USE_PSA_TEST_PARTITIONS', 'USE_SERVER_TESTS_PART1', |
| 37 | + 'USE_SERVER_TESTS_PART2'], |
| 38 | + '*psa-crypto_access_control': ['USE_PSA_TEST_PARTITIONS', |
| 39 | + 'USE_CRYPTO_ACL_TEST'] |
37 | 40 | }
|
38 | 41 |
|
39 | 42 |
|
40 |
| -def _psa_backend(target_name): |
41 |
| - return 'TFM' if 'TFM' in Target.get_target(target_name).labels else 'MBED_SPM' |
| 43 | +def _psa_backend(target): |
| 44 | + """ |
| 45 | + Returns a target PSA backend. |
| 46 | +
|
| 47 | + :param target: Target name as in targets.json |
| 48 | + :return: PSA backend as string (TFM/MBED_SPM) |
| 49 | + """ |
| 50 | + return 'TFM' if 'TFM' in Target.get_target(target).labels else 'MBED_SPM' |
| 51 | + |
| 52 | + |
| 53 | +def _get_target_info(target): |
| 54 | + """ |
| 55 | + Creates a PSA target tuple with default toolchain and |
| 56 | + artifact delivery directory. |
| 57 | +
|
| 58 | + :param target: Target name. |
| 59 | + :return: tuple (target, toolchain, delivery directory). |
| 60 | + """ |
| 61 | + delivery_dir = os.path.join(ROOT, 'targets', |
| 62 | + TARGET_MAP[target].delivery_dir) |
| 63 | + |
| 64 | + if not os.path.exists(delivery_dir): |
| 65 | + raise Exception("{} does not have delivery_dir".format(target)) |
| 66 | + |
| 67 | + return tuple([TARGET_MAP[target].name, |
| 68 | + TARGET_MAP[target].default_toolchain, |
| 69 | + delivery_dir]) |
42 | 70 |
|
43 | 71 |
|
44 |
| -def get_mbed_official_psa_release(): |
| 72 | +def get_mbed_official_psa_release(target=None): |
| 73 | + """ |
| 74 | + Creates a list of PSA targets with default toolchain and |
| 75 | + artifact delivery directory. |
| 76 | +
|
| 77 | + :param target: Ask for specific target, None for all targets. |
| 78 | + :return: List of tuples (target, toolchain, delivery directory). |
| 79 | + """ |
45 | 80 | psa_targets_release_list = []
|
46 |
| - psa_secure_targets = [t for t in TARGET_NAMES if Target.get_target(t).is_PSA_secure_target] |
47 |
| - for t in psa_secure_targets: |
48 |
| - psa_targets_release_list.append( |
49 |
| - tuple( |
50 |
| - [ |
51 |
| - TARGET_MAP[t].name, |
52 |
| - TARGET_MAP[t].default_toolchain |
53 |
| - ] |
54 |
| - ) |
55 |
| - ) |
| 81 | + psa_secure_targets = [t for t in TARGET_NAMES if |
| 82 | + Target.get_target(t).is_PSA_secure_target] |
| 83 | + if target is not None: |
| 84 | + if target not in psa_secure_targets: |
| 85 | + raise Exception("{} is not a PSA secure target".format(target)) |
| 86 | + psa_targets_release_list.append(_get_target_info(target)) |
| 87 | + else: |
| 88 | + for t in psa_secure_targets: |
| 89 | + psa_targets_release_list.append(_get_target_info(target)) |
56 | 90 |
|
57 | 91 | return psa_targets_release_list
|
58 | 92 |
|
59 | 93 |
|
60 | 94 | def create_mbed_ignore(build_dir):
|
| 95 | + """ |
| 96 | + Creates a .mbedignore file in a given directory. |
| 97 | +
|
| 98 | + :param build_dir: Directory to create .mbedignore file. |
| 99 | + """ |
61 | 100 | with open(os.path.join(build_dir, '.mbedignore'), 'w') as f:
|
62 | 101 | f.write('*\n')
|
63 | 102 |
|
64 | 103 |
|
65 | 104 | def build_mbed_spm_platform(target, toolchain, profile='release'):
|
66 |
| - subprocess.call([ |
| 105 | + """ |
| 106 | + Builds Secure images for MBED-SPM target. |
| 107 | +
|
| 108 | + :param target: target to be built. |
| 109 | + :param toolchain: toolchain to be used. |
| 110 | + :param profile: build profile. |
| 111 | + """ |
| 112 | + subprocess.check_call([ |
67 | 113 | sys.executable, '-u', TEST_PY_LOCATTION,
|
68 | 114 | '--greentea',
|
69 | 115 | '--profile', profile,
|
70 | 116 | '-t', toolchain,
|
71 | 117 | '-m', target,
|
72 | 118 | '--source', ROOT,
|
73 | 119 | '--build', os.path.join(ROOT, 'BUILD', 'tests', target),
|
74 |
| - '--test-spec', os.path.join(ROOT, 'BUILD', 'tests', target, 'test_spec.json'), |
75 |
| - '--build-data', os.path.join(ROOT, 'BUILD', 'tests', target, 'build_data.json'), |
| 120 | + '--test-spec', os.path.join(ROOT, 'BUILD', 'tests', |
| 121 | + target, 'test_spec.json'), |
| 122 | + '--build-data', os.path.join(ROOT, 'BUILD', 'tests', |
| 123 | + target, 'build_data.json'), |
76 | 124 | '-n', MBED_PSA_TESTS
|
77 |
| - ]) |
| 125 | + ], stdout=subprocess.PIPE) |
78 | 126 |
|
79 |
| - subprocess.call([ |
| 127 | + subprocess.check_call([ |
80 | 128 | sys.executable, '-u', MAKE_PY_LOCATTION,
|
81 | 129 | '-t', toolchain,
|
82 | 130 | '-m', target,
|
83 | 131 | '--profile', profile,
|
84 | 132 | '--source', ROOT,
|
85 | 133 | '--build', os.path.join(ROOT, 'BUILD', target),
|
86 | 134 | '--artifact-name', 'psa_release_1.0'
|
87 |
| - ]) |
| 135 | + ], stdout=subprocess.PIPE) |
88 | 136 |
|
89 | 137 |
|
90 | 138 | def _tfm_test_defines(test):
|
| 139 | + """ |
| 140 | + Creates a define list to enable test partitions on TF-M. |
| 141 | +
|
| 142 | + :param test: Test name. |
| 143 | + :return: List of defines with a leading -D. |
| 144 | + """ |
91 | 145 | return ['-D{}'.format(define) for define in TFM_TESTS[test]]
|
92 | 146 |
|
93 | 147 |
|
94 | 148 | def build_tfm_platform(target, toolchain, profile='release'):
|
| 149 | + """ |
| 150 | + Builds Secure images for TF-M target. |
| 151 | +
|
| 152 | + :param target: target to be built. |
| 153 | + :param toolchain: toolchain to be used. |
| 154 | + :param profile: build profile. |
| 155 | + """ |
95 | 156 | for test in TFM_TESTS.keys():
|
96 |
| - subprocess.call([ |
| 157 | + subprocess.check_call([ |
97 | 158 | sys.executable, '-u', TEST_PY_LOCATTION,
|
98 | 159 | '--greentea',
|
99 | 160 | '--profile', profile,
|
100 | 161 | '-t', toolchain,
|
101 | 162 | '-m', target,
|
102 | 163 | '--source', ROOT,
|
103 | 164 | '--build', os.path.join(ROOT, 'BUILD', 'tests', target),
|
104 |
| - '--test-spec', os.path.join(ROOT, 'BUILD', 'tests', target, 'test_spec.json'), |
105 |
| - '--build-data', os.path.join(ROOT, 'BUILD', 'tests', target, 'build_data.json'), |
106 |
| - '--app-config', TFM_MBED_APP, '-n', test] + _tfm_test_defines(test)) |
107 |
| - |
108 |
| - subprocess.call([ |
| 165 | + '--test-spec', os.path.join(ROOT, 'BUILD', 'tests', |
| 166 | + target, 'test_spec.json'), |
| 167 | + '--build-data', os.path.join(ROOT, 'BUILD', 'tests', |
| 168 | + target, 'build_data.json'), |
| 169 | + '--app-config', TFM_MBED_APP, '-n', test] + _tfm_test_defines(test), |
| 170 | + stdout=subprocess.PIPE) |
| 171 | + |
| 172 | + subprocess.check_call([ |
109 | 173 | sys.executable, '-u', MAKE_PY_LOCATTION,
|
110 | 174 | '-t', toolchain,
|
111 | 175 | '-m', target,
|
112 | 176 | '--profile', profile,
|
113 | 177 | '--source', ROOT,
|
114 | 178 | '--build', os.path.join(ROOT, 'BUILD', target),
|
115 | 179 | '--app-config', TFM_MBED_APP
|
116 |
| - ]) |
117 |
| - |
118 |
| - |
119 |
| -def build_psa_platform(target, toolchain, debug=False): |
| 180 | + ], stdout=subprocess.PIPE) |
| 181 | + |
| 182 | + |
| 183 | +def commit_binaries(target, delivery_dir): |
| 184 | + """ |
| 185 | + Commits changes in secure binaries. |
| 186 | +
|
| 187 | + :param target: Target name. |
| 188 | + :param delivery_dir: Secure images should be moved to this folder |
| 189 | + by the build system. |
| 190 | + """ |
| 191 | + changes_made = subprocess.call([ |
| 192 | + 'git', |
| 193 | + '-C', ROOT, |
| 194 | + 'diff', '--exit-code', |
| 195 | + delivery_dir |
| 196 | + ], stdout=subprocess.PIPE) |
| 197 | + |
| 198 | + if changes_made: |
| 199 | + subprocess.check_call([ |
| 200 | + 'git', |
| 201 | + '-C', ROOT, |
| 202 | + 'add', os.path.relpath(delivery_dir, ROOT) |
| 203 | + ], stdout=subprocess.PIPE) |
| 204 | + |
| 205 | + commit_message = '-m\"Update secure binaries for {}\"'.format(target) |
| 206 | + subprocess.check_call([ |
| 207 | + 'git', |
| 208 | + '-C', ROOT, |
| 209 | + 'commit', |
| 210 | + commit_message |
| 211 | + ], stdout=subprocess.PIPE) |
| 212 | + |
| 213 | + |
| 214 | +def build_psa_platform(target, toolchain, delivery_dir, debug=False, |
| 215 | + git_commit=False): |
| 216 | + """ |
| 217 | + Calls the correct build function and commits if requested. |
| 218 | +
|
| 219 | + :param target: Target name. |
| 220 | + :param toolchain: Toolchain to be used. |
| 221 | + :param delivery_dir: Artifact directory, where images should be placed. |
| 222 | + :param debug: Build with debug profile. |
| 223 | + :param git_commit: Commit the changes. |
| 224 | + """ |
120 | 225 | profile = 'debug' if debug else 'release'
|
121 | 226 | if _psa_backend(target) is 'TFM':
|
122 | 227 | build_tfm_platform(target, toolchain, profile)
|
123 | 228 | else:
|
124 | 229 | build_mbed_spm_platform(target, toolchain, profile)
|
125 | 230 |
|
| 231 | + if git_commit: |
| 232 | + commit_binaries(target, delivery_dir) |
| 233 | + |
126 | 234 |
|
127 | 235 | def get_parser():
|
128 | 236 | parser = ArgumentParser()
|
129 | 237 | parser.add_argument("-m", "--mcu",
|
130 | 238 | help="build for the given MCU",
|
131 |
| - default='*', |
| 239 | + default=None, |
132 | 240 | metavar="MCU")
|
133 | 241 |
|
134 | 242 | parser.add_argument("-d", "--debug",
|
135 |
| - help="build for the given MCU", |
| 243 | + help="set build profile to debug", |
136 | 244 | action="store_true",
|
137 | 245 | default=False)
|
138 | 246 |
|
139 |
| - return parser |
140 |
| - |
141 |
| - |
142 |
| -def filter_target(mcu): |
143 |
| - def filter_func(t): |
144 |
| - return t[0] == mcu |
| 247 | + parser.add_argument("--commit", |
| 248 | + help="create a git commit for each platform", |
| 249 | + action="store_true", |
| 250 | + default=False) |
145 | 251 |
|
146 |
| - return filter_func |
| 252 | + return parser |
147 | 253 |
|
148 | 254 |
|
149 |
| -def main(): |
150 |
| - parser = get_parser() |
151 |
| - options = parser.parse_args() |
| 255 | +def prep_build_dir(): |
| 256 | + """ |
| 257 | + Creates a clean BUILD directory |
| 258 | + """ |
152 | 259 | build_dir = os.path.join(ROOT, 'BUILD')
|
153 | 260 | if os.path.exists(build_dir):
|
154 | 261 | shutil.rmtree(build_dir)
|
155 | 262 |
|
156 | 263 | os.makedirs(build_dir)
|
157 | 264 | create_mbed_ignore(build_dir)
|
158 |
| - target_filter_function = None |
159 |
| - psa_platforms_list = get_mbed_official_psa_release() |
160 | 265 |
|
161 |
| - if options.mcu is not '*': |
162 |
| - target_filter_function = filter_target(options.mcu) |
163 | 266 |
|
164 |
| - for target, toolchain in filter(target_filter_function, psa_platforms_list): |
165 |
| - build_psa_platform(target, toolchain, options.debug) |
| 267 | +def main(): |
| 268 | + parser = get_parser() |
| 269 | + options = parser.parse_args() |
| 270 | + prep_build_dir() |
| 271 | + psa_platforms_list = get_mbed_official_psa_release(options.mcu) |
| 272 | + |
| 273 | + for target, tc, directory in psa_platforms_list: |
| 274 | + build_psa_platform(target, tc, directory, options.debug, options.commit) |
166 | 275 |
|
167 | 276 |
|
168 | 277 | if __name__ == '__main__':
|
|
0 commit comments