blob: f9d8f50f2c89c563134c918cbf5dd0a7f8b957f2 [file] [log] [blame]
David Burger7fd1dbe2020-03-26 09:26:55 -06001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2020 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""Transforms config from /config/proto/api proto format to platform JSON."""
7
8import argparse
9import json
10import pprint
C Shapiro90fda252020-04-17 14:34:57 -050011import os
David Burger7fd1dbe2020-03-26 09:26:55 -060012import sys
C Shapiro90fda252020-04-17 14:34:57 -050013import re
C Shapiro5bf23a72020-04-24 11:40:17 -050014import xml.etree.ElementTree as etree
C Shapiro9a3ac8c2020-04-25 07:49:21 -050015import xml.dom.minidom as minidom
David Burger7fd1dbe2020-03-26 09:26:55 -060016
Andrew Lamb319cc922020-06-15 10:45:46 -060017from typing import List
18
David Burger7fd1dbe2020-03-26 09:26:55 -060019from collections import namedtuple
20
Andrew Lambcd33f702020-06-11 10:45:16 -060021from google.protobuf import json_format
22
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070023from chromiumos.config.api import device_brand_pb2
David Burger92609a32020-04-23 10:38:50 -060024from chromiumos.config.api import topology_pb2
C Shapiro5bf23a72020-04-24 11:40:17 -050025from chromiumos.config.payload import config_bundle_pb2
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070026from chromiumos.config.api.software import brand_config_pb2
David Burger7fd1dbe2020-03-26 09:26:55 -060027
Andrew Lamb2413c982020-05-29 12:15:36 -060028Config = namedtuple('Config', [
29 'program', 'hw_design', 'odm', 'hw_design_config', 'device_brand',
30 'device_signer_config', 'oem', 'sw_config', 'brand_config', 'build_target'
31])
David Burger7fd1dbe2020-03-26 09:26:55 -060032
Andrew Lamb2413c982020-05-29 12:15:36 -060033ConfigFiles = namedtuple(
David Burger8ee9b4d2020-06-16 17:40:21 -060034 'ConfigFiles',
35 ['bluetooth', 'arc_hw_features', 'touch_fw', 'dptf_map', 'camera_map'])
36
37CAMERA_CONFIG_DEST_PATH_TEMPLATE = '/etc/camera/camera_config_{}.json'
38CAMERA_CONFIG_SOURCE_PATH_TEMPLATE = (
39 'sw_build_config/platform/chromeos-config/camera/camera_config_{}.json')
C Shapiro5bf23a72020-04-24 11:40:17 -050040
David Burger52c9d322020-06-09 07:16:18 -060041DPTF_PATH = 'sw_build_config/platform/chromeos-config/thermal'
42DPTF_FILE = 'dptf.dv'
C Shapiro2b6d5332020-05-06 17:51:35 -050043TOUCH_PATH = 'sw_build_config/platform/chromeos-config/touch'
Andrew Lamb6c42efc2020-06-16 10:40:43 -060044WALLPAPER_BASE_PATH = '/usr/share/chromeos-assets/wallpaper'
David Burger7fd1dbe2020-03-26 09:26:55 -060045
Andrew Lamb2413c982020-05-29 12:15:36 -060046
Andrew Lambcd33f702020-06-11 10:45:16 -060047def parse_args(argv):
David Burger7fd1dbe2020-03-26 09:26:55 -060048 """Parse the available arguments.
49
50 Invalid arguments or -h cause this function to print a message and exit.
51
52 Args:
53 argv: List of string arguments (excluding program name / argv[0])
54
55 Returns:
56 argparse.Namespace object containing the attributes.
57 """
58 parser = argparse.ArgumentParser(
59 description='Converts source proto config into platform JSON config.')
60 parser.add_argument(
61 '-c',
62 '--project_configs',
63 nargs='+',
64 type=str,
65 help='Space delimited list of source protobinary project config files.')
66 parser.add_argument(
67 '-p',
68 '--program_config',
69 type=str,
70 help='Path to the source program-level protobinary file')
71 parser.add_argument(
Andrew Lamb2413c982020-05-29 12:15:36 -060072 '-o', '--output', type=str, help='Output file that will be generated')
David Burger7fd1dbe2020-03-26 09:26:55 -060073 return parser.parse_args(argv)
74
75
David Burger8ee9b4d2020-06-16 17:40:21 -060076def _upsert(field, target, target_name):
77 """Updates or inserts `field` within `target`.
78
79 If `target_name` already exists within `target` an update is performed,
80 otherwise, an insert is performed.
81 """
Sam McNally9a873f72020-06-05 19:47:22 +100082 if field or field == 0:
David Burger8ee9b4d2020-06-16 17:40:21 -060083 if target_name in target:
84 target[target_name].update(field)
85 else:
86 target[target_name] = field
David Burger7fd1dbe2020-03-26 09:26:55 -060087
88
Andrew Lambcd33f702020-06-11 10:45:16 -060089def _build_arc(config, config_files):
90 if not config.build_target.arc:
91 return None
92
93 build_properties = {
94 'device': config.build_target.arc.device,
95 'first-api-level': config.build_target.arc.first_api_level,
96 'marketing-name': config.device_brand.brand_name,
97 'metrics-tag': config.hw_design.name.lower(),
98 'product': config.build_target.id.value,
99 }
100 if config.oem:
101 build_properties['oem'] = config.oem.name
102 result = {'build-properties': build_properties}
103 feature_id = _arc_hardware_feature_id(config.hw_design_config)
104 if feature_id in config_files.arc_hw_features:
105 result['hardware-features'] = config_files.arc_hw_features[feature_id]
106 topology = config.hw_design_config.hardware_topology
107 ppi = topology.screen.hardware_feature.screen.panel_properties.pixels_per_in
108 # Only set for high resolution displays
109 if ppi and ppi > 250:
110 result['scale'] = ppi
111 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600112
Andrew Lamb2413c982020-05-29 12:15:36 -0600113
Andrew Lamb319cc922020-06-15 10:45:46 -0600114def _build_ash_flags(config: Config) -> List[str]:
115 """Returns a list of Ash flags for config.
116
117 Ash is the window manager and system UI for ChromeOS, see
118 https://chromium.googlesource.com/chromium/src/+/refs/heads/master/ash/.
119 """
120 # A map from flag name -> value. Value may be None for boolean flags.
121 flags = {}
122
123 hw_features = config.hw_design_config.hardware_features
124 if hw_features.stylus.stylus == topology_pb2.HardwareFeatures.Stylus.INTERNAL:
Andrew Lamb2e641e22020-06-15 12:30:41 -0600125 flags['has-internal-stylus'] = None
Andrew Lamb319cc922020-06-15 10:45:46 -0600126
Andrew Lamb2e641e22020-06-15 12:30:41 -0600127 fp_loc = hw_features.fingerprint.location
128 if fp_loc and fp_loc != topology_pb2.HardwareFeatures.Fingerprint.NOT_PRESENT:
129 loc_name = topology_pb2.HardwareFeatures.Fingerprint.Location.Name(fp_loc)
130 flags['fingerprint-sensor-location'] = loc_name.lower().replace('_', '-')
131
Andrew Lamb6c42efc2020-06-16 10:40:43 -0600132 wallpaper = config.brand_config.wallpaper
133 # If a wallpaper is set, the 'default-wallpaper-is-oem' flag needs to be set.
134 # If a wallpaper is not set, the 'default_[large|small].jpg' wallpapers
135 # should still be set.
136 if wallpaper:
137 flags['default-wallpaper-is-oem'] = None
138 else:
139 wallpaper = 'default'
140
141 for size in ('small', 'large'):
142 flags[f'default-wallpaper-{size}'] = (
143 f'{WALLPAPER_BASE_PATH}/{wallpaper}_{size}.jpg')
144
145 # For each size, also install 'guest' and 'child' wallpapers.
146 for wallpaper_type in ('guest', 'child'):
147 flags[f'{wallpaper_type}-wallpaper-{size}'] = (
148 f'{WALLPAPER_BASE_PATH}/{wallpaper_type}_{size}.jpg')
149
Andrew Lamb72d41362020-06-17 09:19:02 -0600150 flags['arc-build-properties'] = json_format.MessageToDict(
151 config.build_target.arc)
152
Andrew Lamb90b168c2020-06-22 10:42:30 -0600153 power_button = hw_features.power_button
154 if power_button.edge:
155 flags['ash-power-button-position'] = json.dumps({
156 'edge':
157 topology_pb2.HardwareFeatures.Button.Edge.Name(power_button.edge
158 ).lower(),
159 # Starlark sometimes represents float literals strangely, e.g. changing
160 # 0.9 to 0.899999. Round to two digits here.
161 'position':
162 round(power_button.position, 2)
163 })
164
165 volume_button = hw_features.volume_button
166 if volume_button.edge:
167 flags['ash-side-volume-button-position'] = json.dumps({
168 'region':
169 topology_pb2.HardwareFeatures.Button.Region.Name(
170 volume_button.region).lower(),
171 'edge':
172 topology_pb2.HardwareFeatures.Button.Edge.Name(volume_button.edge
173 ).lower(),
174 })
175
Andrew Lamb2e641e22020-06-15 12:30:41 -0600176 return sorted([f'--{k}={v}' if v else f'--{k}' for k, v in flags.items()])
Andrew Lamb319cc922020-06-15 10:45:46 -0600177
178
179def _build_ui(config: Config) -> dict:
180 """Builds the 'ui' property from cros_config_schema."""
181 return {'extra-ash-flags': _build_ash_flags(config)}
182
183
Andrew Lambcd33f702020-06-11 10:45:16 -0600184def _build_bluetooth(config, bluetooth_files):
C Shapiro90fda252020-04-17 14:34:57 -0500185 bt_flags = config.sw_config.bluetooth_config.flags
186 # Convert to native map (from proto wrapper)
187 bt_flags_map = dict(bt_flags)
188 result = {}
189 if bt_flags_map:
190 result['flags'] = bt_flags_map
C Shapiro74da76e2020-05-04 13:02:20 -0500191 bt_comp = config.hw_design_config.hardware_features.bluetooth.component.usb
C Shapiro90fda252020-04-17 14:34:57 -0500192 if bt_comp.vendor_id:
Andrew Lambcd33f702020-06-11 10:45:16 -0600193 bt_id = _bluetooth_id(config.hw_design.name.lower(), bt_comp)
C Shapiro90fda252020-04-17 14:34:57 -0500194 if bt_id in bluetooth_files:
195 result['config'] = bluetooth_files[bt_id]
196 return result
197
David Burger7fd1dbe2020-03-26 09:26:55 -0600198
Andrew Lambcd33f702020-06-11 10:45:16 -0600199def _build_fingerprint(hw_topology):
200 if not hw_topology.HasField('fingerprint'):
201 return None
202
203 fp = hw_topology.fingerprint.hardware_feature.fingerprint
204 result = {}
205 if fp.location != topology_pb2.HardwareFeatures.Fingerprint.NOT_PRESENT:
206 location = fp.Location.DESCRIPTOR.values_by_number[fp.location].name
207 result['sensor-location'] = location.lower().replace('_', '-')
208 if fp.board:
209 result['board'] = fp.board
Tom Hughesdfc35402020-06-29 16:02:09 -0700210 if fp.ro_version:
211 result['ro-version'] = fp.ro_version
212
Andrew Lambcd33f702020-06-11 10:45:16 -0600213 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600214
215
Andrew Lambcd33f702020-06-11 10:45:16 -0600216def _fw_bcs_path(payload):
David Burger7fd1dbe2020-03-26 09:26:55 -0600217 if payload and payload.firmware_image_name:
Andrew Lamb2413c982020-05-29 12:15:36 -0600218 return 'bcs://%s.%d.%d.0.tbz2' % (payload.firmware_image_name,
219 payload.version.major,
220 payload.version.minor)
David Burger7fd1dbe2020-03-26 09:26:55 -0600221
Andrew Lambcd33f702020-06-11 10:45:16 -0600222 return None
David Burger7fd1dbe2020-03-26 09:26:55 -0600223
Andrew Lambcd33f702020-06-11 10:45:16 -0600224
225def _fw_build_target(payload):
David Burger7fd1dbe2020-03-26 09:26:55 -0600226 if payload:
227 return payload.build_target_name
228
Andrew Lambcd33f702020-06-11 10:45:16 -0600229 return None
David Burger7fd1dbe2020-03-26 09:26:55 -0600230
Andrew Lambcd33f702020-06-11 10:45:16 -0600231
232def _build_firmware(config):
David Burgerb70b6762020-05-21 12:14:59 -0600233 """Returns firmware config, or None if no build targets."""
Andrew Lamb3da156d2020-04-16 16:00:56 -0600234 fw_payload_config = config.sw_config.firmware
235 fw_build_config = config.sw_config.firmware_build_config
236 main_ro = fw_payload_config.main_ro_payload
237 main_rw = fw_payload_config.main_rw_payload
238 ec_ro = fw_payload_config.ec_ro_payload
239 pd_ro = fw_payload_config.pd_ro_payload
David Burger7fd1dbe2020-03-26 09:26:55 -0600240
241 build_targets = {}
Andrew Lamb3da156d2020-04-16 16:00:56 -0600242
David Burger8ee9b4d2020-06-16 17:40:21 -0600243 _upsert(fw_build_config.build_targets.depthcharge, build_targets,
244 'depthcharge')
245 _upsert(fw_build_config.build_targets.coreboot, build_targets, 'coreboot')
246 _upsert(fw_build_config.build_targets.ec, build_targets, 'ec')
247 _upsert(
Andrew Lambf8954ee2020-04-21 10:24:40 -0600248 list(fw_build_config.build_targets.ec_extras), build_targets, 'ec_extras')
David Burger8ee9b4d2020-06-16 17:40:21 -0600249 _upsert(fw_build_config.build_targets.libpayload, build_targets, 'libpayload')
David Burger7fd1dbe2020-03-26 09:26:55 -0600250
David Burgerb70b6762020-05-21 12:14:59 -0600251 if not build_targets:
252 return None
253
David Burger7fd1dbe2020-03-26 09:26:55 -0600254 result = {
255 'bcs-overlay': config.build_target.overlay_name,
256 'build-targets': build_targets,
David Burger7fd1dbe2020-03-26 09:26:55 -0600257 }
Andrew Lamb883fa042020-04-06 11:37:22 -0600258
David Burger8ee9b4d2020-06-16 17:40:21 -0600259 _upsert(main_ro.firmware_image_name.lower(), result, 'image-name')
Andrew Lamb883fa042020-04-06 11:37:22 -0600260
David Burger8ee9b4d2020-06-16 17:40:21 -0600261 _upsert(_fw_bcs_path(main_ro), result, 'main-ro-image')
262 _upsert(_fw_bcs_path(main_rw), result, 'main-rw-image')
263 _upsert(_fw_bcs_path(ec_ro), result, 'ec-ro-image')
264 _upsert(_fw_bcs_path(pd_ro), result, 'pd-ro-image')
David Burger7fd1dbe2020-03-26 09:26:55 -0600265
David Burger8ee9b4d2020-06-16 17:40:21 -0600266 _upsert(
Andrew Lambf39fbe82020-04-13 16:14:33 -0600267 config.hw_design_config.hardware_features.fw_config.value,
268 result,
269 'firmware-config',
270 )
271
David Burger7fd1dbe2020-03-26 09:26:55 -0600272 return result
273
274
Andrew Lambcd33f702020-06-11 10:45:16 -0600275def _build_fw_signing(config):
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500276 if config.sw_config.firmware and config.device_signer_config:
David Burger68e0d142020-05-15 17:29:33 -0600277 hw_design = config.hw_design.name.lower()
Sam McNally2fc807f2020-07-16 18:13:53 +1000278 brand_scan_config = config.brand_config.scan_config
279 if brand_scan_config and brand_scan_config.whitelabel_tag:
280 signature_id = '%s-%s' % (hw_design, brand_scan_config.whitelabel_tag)
281 else:
282 signature_id = hw_design
283
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500284 return {
285 'key-id': config.device_signer_config.key_id,
Sam McNally2fc807f2020-07-16 18:13:53 +1000286 'signature-id': signature_id,
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500287 }
288 return {}
David Burger7fd1dbe2020-03-26 09:26:55 -0600289
290
Andrew Lambcd33f702020-06-11 10:45:16 -0600291def _file(source, destination):
Andrew Lamb2413c982020-05-29 12:15:36 -0600292 return {'destination': destination, 'source': source}
David Burger7fd1dbe2020-03-26 09:26:55 -0600293
294
David Burger40dfe3a2020-06-18 17:09:13 -0600295def _file_v2(build_path, system_path):
296 return {'build-path': build_path, 'system-path': system_path}
297
298
Andrew Lambcd33f702020-06-11 10:45:16 -0600299def _build_audio(config):
David Burger178f3ef2020-06-26 12:11:57 -0600300 if not config.sw_config.audio_configs:
301 return {}
David Burger7fd1dbe2020-03-26 09:26:55 -0600302 alsa_path = '/usr/share/alsa/ucm'
303 cras_path = '/etc/cras'
304 project_name = config.hw_design.name.lower()
David Burger43250662020-05-07 11:21:50 -0600305 program_name = config.program.name.lower()
David Burger7fd1dbe2020-03-26 09:26:55 -0600306 files = []
David Burger178f3ef2020-06-26 12:11:57 -0600307 ucm_suffix = None
308 for audio in config.sw_config.audio_configs:
309 card = audio.card_name
310 card_with_suffix = audio.card_name
311 if audio.ucm_suffix:
312 # TODO: last ucm_suffix wins.
313 ucm_suffix = audio.ucm_suffix
314 card_with_suffix += '.' + audio.ucm_suffix
315 if audio.ucm_file:
316 files.append(
317 _file(audio.ucm_file,
318 '%s/%s/HiFi.conf' % (alsa_path, card_with_suffix)))
319 if audio.ucm_master_file:
320 files.append(
321 _file(
322 audio.ucm_master_file, '%s/%s/%s.conf' %
Andrew Lamb2413c982020-05-29 12:15:36 -0600323 (alsa_path, card_with_suffix, card_with_suffix)))
David Burger178f3ef2020-06-26 12:11:57 -0600324 if audio.card_config_file:
325 files.append(
326 _file(audio.card_config_file,
327 '%s/%s/%s' % (cras_path, project_name, card)))
328 if audio.dsp_file:
329 files.append(
330 _file(audio.dsp_file, '%s/%s/dsp.ini' % (cras_path, project_name)))
331 if audio.module_file:
332 files.append(
333 _file(audio.module_file,
334 '/etc/modprobe.d/alsa-%s.conf' % program_name))
335 if audio.board_file:
336 files.append(
337 _file(audio.board_file,
338 '%s/%s/board.ini' % (cras_path, project_name)))
David Burger599ff7b2020-04-06 16:29:31 -0600339
340 result = {
David Burger7fd1dbe2020-03-26 09:26:55 -0600341 'main': {
342 'cras-config-dir': project_name,
343 'files': files,
344 }
345 }
David Burger178f3ef2020-06-26 12:11:57 -0600346
347 if ucm_suffix:
348 result['main']['ucm-suffix'] = ucm_suffix
David Burger599ff7b2020-04-06 16:29:31 -0600349
350 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600351
352
Andrew Lambcd33f702020-06-11 10:45:16 -0600353def _build_camera(hw_topology):
David Burger8aa8fa32020-04-14 08:30:34 -0600354 if hw_topology.HasField('camera'):
355 camera = hw_topology.camera.hardware_feature.camera
356 result = {}
357 if camera.count.value:
358 result['count'] = camera.count.value
359 return result
360
Andrew Lambcd33f702020-06-11 10:45:16 -0600361 return None
David Burger8aa8fa32020-04-14 08:30:34 -0600362
Andrew Lambcd33f702020-06-11 10:45:16 -0600363
364def _build_identity(hw_scan_config, program, brand_scan_config=None):
David Burger7fd1dbe2020-03-26 09:26:55 -0600365 identity = {}
David Burger8ee9b4d2020-06-16 17:40:21 -0600366 _upsert(hw_scan_config.firmware_sku, identity, 'sku-id')
367 _upsert(hw_scan_config.smbios_name_match, identity, 'smbios-name-match')
Andrew Lamb7806ce92020-04-07 10:22:17 -0600368 # 'platform-name' is needed to support 'mosys platform name'. Clients should
369 # longer require platform name, but set it here for backwards compatibility.
David Burger8ee9b4d2020-06-16 17:40:21 -0600370 _upsert(program.name, identity, 'platform-name')
David Burger7fd1dbe2020-03-26 09:26:55 -0600371 # ARM architecture
David Burger8ee9b4d2020-06-16 17:40:21 -0600372 _upsert(hw_scan_config.device_tree_compatible_match, identity,
373 'device-tree-compatible-match')
David Burger7fd1dbe2020-03-26 09:26:55 -0600374
375 if brand_scan_config:
David Burger8ee9b4d2020-06-16 17:40:21 -0600376 _upsert(brand_scan_config.whitelabel_tag, identity, 'whitelabel-tag')
David Burger7fd1dbe2020-03-26 09:26:55 -0600377
378 return identity
379
380
Andrew Lambcd33f702020-06-11 10:45:16 -0600381def _lookup(id_value, id_map):
382 if not id_value.value:
383 return None
384
385 key = id_value.value
386 if key in id_map:
387 return id_map[id_value.value]
388 error = 'Failed to lookup %s with value: %s' % (
389 id_value.__class__.__name__.replace('Id', ''), key)
390 print(error)
391 print('Check the config contents provided:')
392 printer = pprint.PrettyPrinter(indent=4)
393 printer.pprint(id_map)
394 raise Exception(error)
David Burger7fd1dbe2020-03-26 09:26:55 -0600395
396
Andrew Lambcd33f702020-06-11 10:45:16 -0600397def _build_touch_file_config(config, project_name):
398 partners = {x.id.value: x for x in config.partners.value}
C Shapiro2b6d5332020-05-06 17:51:35 -0500399 files = []
400 for comp in config.components:
C Shapiro4813be62020-05-13 17:31:58 -0500401 touch = comp.touchscreen
402 # Everything is the same for Touch screen/pad, except different fields
403 if comp.HasField('touchpad'):
404 touch = comp.touchpad
405 if touch.product_id:
Andrew Lambcd33f702020-06-11 10:45:16 -0600406 vendor = _lookup(comp.manufacturer_id, partners)
C Shapiro2b6d5332020-05-06 17:51:35 -0500407 if not vendor:
Andrew Lamb2413c982020-05-29 12:15:36 -0600408 raise Exception("Manufacturer must be set for touch device %s" %
409 comp.id.value)
C Shapiro2b6d5332020-05-06 17:51:35 -0500410
C Shapiro4813be62020-05-13 17:31:58 -0500411 product_id = touch.product_id
412 fw_version = touch.fw_version
C Shapiro2b6d5332020-05-06 17:51:35 -0500413
C Shapiro2b6d5332020-05-06 17:51:35 -0500414 file_name = "%s_%s.bin" % (product_id, fw_version)
415 fw_file_path = os.path.join(TOUCH_PATH, vendor.name, file_name)
416
417 if not os.path.exists(fw_file_path):
Andrew Lamb2413c982020-05-29 12:15:36 -0600418 raise Exception("Touchscreen fw bin file doesn't exist at: %s" %
419 fw_file_path)
C Shapiro2b6d5332020-05-06 17:51:35 -0500420
C Shapiro303cece2020-07-22 07:15:21 -0500421 touch_vendor = vendor.touch_vendor
422 sym_link = touch_vendor.symlink_file_format.format(
423 vendor_name=vendor.name,
424 vendor_id=touch_vendor.vendor_id,
425 product_id=product_id,
426 fw_version=fw_version,
427 product_series=touch.product_series)
428
429 dest = "%s_%s" % (vendor.name, file_name)
430 if touch_vendor.destination_file_format:
431 dest = touch_vendor.destination_file_format.format(
432 vendor_name=vendor.name,
433 vendor_id=touch_vendor.vendor_id,
434 product_id=product_id,
435 fw_version=fw_version,
436 product_series=touch.product_series)
437
C Shapiro2b6d5332020-05-06 17:51:35 -0500438 files.append({
C Shapiro303cece2020-07-22 07:15:21 -0500439 "destination": os.path.join("/opt/google/touch/firmware", dest),
Andrew Lamb2413c982020-05-29 12:15:36 -0600440 "source":
441 os.path.join(project_name, fw_file_path),
442 "symlink":
443 os.path.join("/lib/firmware", sym_link),
C Shapiro2b6d5332020-05-06 17:51:35 -0500444 })
445
446 result = {}
David Burger8ee9b4d2020-06-16 17:40:21 -0600447 _upsert(files, result, 'files')
C Shapiro2b6d5332020-05-06 17:51:35 -0500448 return result
449
450
David Burger8ee9b4d2020-06-16 17:40:21 -0600451def _transform_build_configs(config,
452 config_files=ConfigFiles({}, {}, {}, {}, {})):
Andrew Lambcd33f702020-06-11 10:45:16 -0600453 # pylint: disable=too-many-locals,too-many-branches
454 partners = {x.id.value: x for x in config.partners.value}
455 programs = {x.id.value: x for x in config.programs.value}
David Burger7fd1dbe2020-03-26 09:26:55 -0600456 sw_configs = list(config.software_configs)
Andrew Lambcd33f702020-06-11 10:45:16 -0600457 brand_configs = {x.brand_id.value: x for x in config.brand_configs}
David Burger7fd1dbe2020-03-26 09:26:55 -0600458
C Shapiroa0b766c2020-03-31 08:35:28 -0500459 if len(config.build_targets) != 1:
460 # Artifact of sharing the config_bundle for analysis and transforms.
461 # Integrated analysis of multiple programs/projects it the only time
462 # having multiple build targets would be valid.
463 raise Exception('Single build_target required for transform')
464
David Burger7fd1dbe2020-03-26 09:26:55 -0600465 results = {}
466 for hw_design in config.designs.value:
467 if config.device_brands.value:
Andrew Lamb2413c982020-05-29 12:15:36 -0600468 device_brands = [
469 x for x in config.device_brands.value
470 if x.design_id.value == hw_design.id.value
471 ]
David Burger7fd1dbe2020-03-26 09:26:55 -0600472 else:
473 device_brands = [device_brand_pb2.DeviceBrand()]
474
475 for device_brand in device_brands:
476 # Brand config can be empty since platform JSON config allows it
477 brand_config = brand_config_pb2.BrandConfig()
478 if device_brand.id.value in brand_configs:
479 brand_config = brand_configs[device_brand.id.value]
480
481 for hw_design_config in hw_design.configs:
482 design_id = hw_design_config.id.value
Andrew Lamb2413c982020-05-29 12:15:36 -0600483 sw_config_matches = [
484 x for x in sw_configs if x.design_config_id.value == design_id
485 ]
David Burger7fd1dbe2020-03-26 09:26:55 -0600486 if len(sw_config_matches) == 1:
487 sw_config = sw_config_matches[0]
488 elif len(sw_config_matches) > 1:
489 raise Exception('Multiple software configs found for: %s' % design_id)
490 else:
491 raise Exception('Software config is required for: %s' % design_id)
492
Andrew Lambcd33f702020-06-11 10:45:16 -0600493 program = _lookup(hw_design.program_id, programs)
C Shapiroadefd7c2020-05-19 16:37:21 -0500494 signer_configs_by_design = {}
495 signer_configs_by_brand = {}
496 for signer_config in program.device_signer_configs:
497 design_id = signer_config.design_id.value
498 brand_id = signer_config.brand_id.value
499 if design_id:
500 signer_configs_by_design[design_id] = signer_config
501 elif brand_id:
502 signer_configs_by_brand[brand_id] = signer_config
503 else:
504 raise Exception('No ID found for signer config: %s' % signer_config)
505
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500506 device_signer_config = None
C Shapiroadefd7c2020-05-19 16:37:21 -0500507 if signer_configs_by_design or signer_configs_by_brand:
508 design_id = hw_design.id.value
509 brand_id = device_brand.id.value
510 if design_id in signer_configs_by_design:
511 device_signer_config = signer_configs_by_design[design_id]
512 elif brand_id in signer_configs_by_brand:
513 device_signer_config = signer_configs_by_brand[brand_id]
514 else:
515 # Assume that if signer configs are set, every config is setup
Andrew Lamb2413c982020-05-29 12:15:36 -0600516 raise Exception('Signer config missing for design: %s, brand: %s' %
517 (design_id, brand_id))
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500518
Andrew Lambcd33f702020-06-11 10:45:16 -0600519 transformed_config = _transform_build_config(
C Shapiro90fda252020-04-17 14:34:57 -0500520 Config(
521 program=program,
522 hw_design=hw_design,
Andrew Lambcd33f702020-06-11 10:45:16 -0600523 odm=_lookup(hw_design.odm_id, partners),
C Shapiro90fda252020-04-17 14:34:57 -0500524 hw_design_config=hw_design_config,
525 device_brand=device_brand,
526 device_signer_config=device_signer_config,
Andrew Lambcd33f702020-06-11 10:45:16 -0600527 oem=_lookup(device_brand.oem_id, partners),
C Shapiro90fda252020-04-17 14:34:57 -0500528 sw_config=sw_config,
529 brand_config=brand_config,
Andrew Lamb2413c982020-05-29 12:15:36 -0600530 build_target=config.build_targets[0]), config_files)
David Burger7fd1dbe2020-03-26 09:26:55 -0600531
Andrew Lamb2413c982020-05-29 12:15:36 -0600532 config_json = json.dumps(
533 transformed_config,
534 sort_keys=True,
535 indent=2,
536 separators=(',', ': '))
David Burger7fd1dbe2020-03-26 09:26:55 -0600537
538 if config_json not in results:
539 results[config_json] = transformed_config
540
541 return list(results.values())
542
543
Andrew Lambcd33f702020-06-11 10:45:16 -0600544def _transform_build_config(config, config_files):
David Burger7fd1dbe2020-03-26 09:26:55 -0600545 """Transforms Config instance into target platform JSON schema.
546
547 Args:
548 config: Config namedtuple
C Shapiro5bf23a72020-04-24 11:40:17 -0500549 config_files: Map to look up the generated config files.
David Burger7fd1dbe2020-03-26 09:26:55 -0600550
551 Returns:
552 Unique config payload based on the platform JSON schema.
553 """
554 result = {
Andrew Lamb2413c982020-05-29 12:15:36 -0600555 'identity':
Andrew Lambcd33f702020-06-11 10:45:16 -0600556 _build_identity(config.sw_config.id_scan_config, config.program,
557 config.brand_config.scan_config),
Andrew Lamb2413c982020-05-29 12:15:36 -0600558 'name':
559 config.hw_design.name.lower(),
David Burger7fd1dbe2020-03-26 09:26:55 -0600560 }
561
David Burger8ee9b4d2020-06-16 17:40:21 -0600562 _upsert(_build_arc(config, config_files), result, 'arc')
563 _upsert(_build_audio(config), result, 'audio')
564 _upsert(_build_bluetooth(config, config_files.bluetooth), result, 'bluetooth')
565 _upsert(config.device_brand.brand_code, result, 'brand-code')
566 _upsert(
Andrew Lambcd33f702020-06-11 10:45:16 -0600567 _build_camera(config.hw_design_config.hardware_topology), result,
568 'camera')
David Burger8ee9b4d2020-06-16 17:40:21 -0600569 _upsert(_build_firmware(config), result, 'firmware')
570 _upsert(_build_fw_signing(config), result, 'firmware-signing')
571 _upsert(
Andrew Lambcd33f702020-06-11 10:45:16 -0600572 _build_fingerprint(config.hw_design_config.hardware_topology), result,
Andrew Lamb2413c982020-05-29 12:15:36 -0600573 'fingerprint')
Andrew Lamb0d236ab2020-06-30 12:30:20 -0600574 _upsert(_build_ui(config), result, 'ui')
David Burger7fd1dbe2020-03-26 09:26:55 -0600575 power_prefs = config.sw_config.power_config.preferences
576 power_prefs_map = dict(
Andrew Lamb2413c982020-05-29 12:15:36 -0600577 (x.replace('_', '-'), power_prefs[x]) for x in power_prefs)
David Burger8ee9b4d2020-06-16 17:40:21 -0600578 _upsert(power_prefs_map, result, 'power')
579 if config_files.camera_map:
580 camera_file = config_files.camera_map.get(config.hw_design.name, {})
581 _upsert(camera_file, result, 'camera')
David Burger52c9d322020-06-09 07:16:18 -0600582 if config_files.dptf_map:
583 # Prefer design specific if found, if not fall back to project wide config
584 # mapped under the empty string.
585 if config_files.dptf_map.get(config.hw_design.name):
586 dptf_file = config_files.dptf_map[config.hw_design.name]
587 else:
588 dptf_file = config_files.dptf_map.get('')
David Burger8ee9b4d2020-06-16 17:40:21 -0600589 _upsert(dptf_file, result, 'thermal')
590 _upsert(config_files.touch_fw, result, 'touch')
David Burger7fd1dbe2020-03-26 09:26:55 -0600591
592 return result
593
594
Andrew Lambcd33f702020-06-11 10:45:16 -0600595def write_output(configs, output=None):
David Burger7fd1dbe2020-03-26 09:26:55 -0600596 """Writes a list of configs to platform JSON format.
597
598 Args:
599 configs: List of config dicts defined in cros_config_schema.yaml
600 output: Target file output (if None, prints to stdout)
601 """
Andrew Lamb2413c982020-05-29 12:15:36 -0600602 json_output = json.dumps({'chromeos': {
603 'configs': configs,
604 }},
605 sort_keys=True,
606 indent=2,
607 separators=(',', ': '))
David Burger7fd1dbe2020-03-26 09:26:55 -0600608 if output:
609 with open(output, 'w') as output_stream:
610 # Using print function adds proper trailing newline.
611 print(json_output, file=output_stream)
612 else:
613 print(json_output)
614
615
Andrew Lambcd33f702020-06-11 10:45:16 -0600616def _bluetooth_id(project_name, bt_comp):
Andrew Lamb2413c982020-05-29 12:15:36 -0600617 return '_'.join(
618 [project_name, bt_comp.vendor_id, bt_comp.product_id, bt_comp.bcd_device])
C Shapiro90fda252020-04-17 14:34:57 -0500619
620
Andrew Lambcd33f702020-06-11 10:45:16 -0600621def _feature(name, present):
C Shapiro5bf23a72020-04-24 11:40:17 -0500622 attrib = {'name': name}
623 if present:
624 return etree.Element('feature', attrib=attrib)
Andrew Lambcd33f702020-06-11 10:45:16 -0600625
626 return etree.Element('unavailable-feature', attrib=attrib)
C Shapiro5bf23a72020-04-24 11:40:17 -0500627
628
Andrew Lambcd33f702020-06-11 10:45:16 -0600629def _any_present(features):
Andrew Lamb2413c982020-05-29 12:15:36 -0600630 return topology_pb2.HardwareFeatures.PRESENT in features
C Shapiro5bf23a72020-04-24 11:40:17 -0500631
632
Andrew Lambcd33f702020-06-11 10:45:16 -0600633def _arc_hardware_feature_id(design_config):
C Shapiro5bf23a72020-04-24 11:40:17 -0500634 return design_config.id.value.lower().replace(':', '_')
635
636
Andrew Lambcd33f702020-06-11 10:45:16 -0600637def _write_arc_hardware_feature_file(output_dir, file_name, config_content):
David Burger77a1d312020-05-23 16:05:45 -0600638 output_dir += '/arc'
639 os.makedirs(output_dir, exist_ok=True)
640 output = '%s/%s' % (output_dir, file_name)
Andrew Lamb2413c982020-05-29 12:15:36 -0600641 file_content = minidom.parseString(config_content).toprettyxml(
642 indent=' ', encoding='utf-8')
C Shapiroea33cff2020-05-11 13:32:05 -0500643
644 with open(output, 'wb') as f:
645 f.write(file_content)
646
647
Andrew Lambcd33f702020-06-11 10:45:16 -0600648def _write_arc_hardware_feature_files(config, output_dir, build_root_dir):
C Shapiro5bf23a72020-04-24 11:40:17 -0500649 """Writes ARC hardware_feature.xml files for each config
650
651 Args:
652 config: Source ConfigBundle to process.
653 output_dir: Path to the generated output.
C Shapiro5c877992020-04-29 12:11:28 -0500654 build_root_path: Path to the config file from portage's perspective.
C Shapiro5bf23a72020-04-24 11:40:17 -0500655 Returns:
656 dict that maps the design_config_id onto the correct file.
657 """
Andrew Lambcd33f702020-06-11 10:45:16 -0600658 # pylint: disable=too-many-locals
C Shapiro5bf23a72020-04-24 11:40:17 -0500659 result = {}
C Shapiroea33cff2020-05-11 13:32:05 -0500660 configs_by_design = {}
C Shapiro5bf23a72020-04-24 11:40:17 -0500661 for hw_design in config.designs.value:
662 for design_config in hw_design.configs:
663 hw_features = design_config.hardware_features
Kazuhiro Inaba76d8bb52020-06-26 10:34:07 +0900664 any_camera = hw_features.camera.count.value > 0
Josie Nordrumadc27a72020-07-08 11:05:26 -0600665 multi_camera = hw_features.camera.count.value > 1
Andrew Lambcd33f702020-06-11 10:45:16 -0600666 touchscreen = _any_present([hw_features.screen.touch_support])
C Shapiro5bf23a72020-04-24 11:40:17 -0500667 acc = hw_features.accelerometer
668 gyro = hw_features.gyroscope
669 compass = hw_features.magnetometer
Andrew Lambcd33f702020-06-11 10:45:16 -0600670 light_sensor = hw_features.light_sensor
C Shapiro5bf23a72020-04-24 11:40:17 -0500671 root = etree.Element('permissions')
672 root.extend([
Andrew Lambcd33f702020-06-11 10:45:16 -0600673 _feature('android.hardware.camera', multi_camera),
674 _feature('android.hardware.camera.autofocus', multi_camera),
Kazuhiro Inaba76d8bb52020-06-26 10:34:07 +0900675 _feature('android.hardware.camera.any', any_camera),
676 _feature('android.hardware.camera.front', any_camera),
Andrew Lambcd33f702020-06-11 10:45:16 -0600677 _feature(
678 'android.hardware.sensor.accelerometer',
679 _any_present([acc.lid_accelerometer, acc.base_accelerometer])),
680 _feature('android.hardware.sensor.gyroscope',
681 _any_present([gyro.lid_gyroscope, gyro.base_gyroscope])),
682 _feature(
Andrew Lamb2413c982020-05-29 12:15:36 -0600683 'android.hardware.sensor.compass',
Andrew Lambcd33f702020-06-11 10:45:16 -0600684 _any_present(
685 [compass.lid_magnetometer, compass.base_magnetometer])),
686 _feature(
687 'android.hardware.sensor.light',
688 _any_present(
689 [light_sensor.lid_lightsensor,
690 light_sensor.base_lightsensor])),
691 _feature('android.hardware.touchscreen', touchscreen),
692 _feature('android.hardware.touchscreen.multitouch', touchscreen),
693 _feature('android.hardware.touchscreen.multitouch.distinct',
Andrew Lamb2413c982020-05-29 12:15:36 -0600694 touchscreen),
Andrew Lambcd33f702020-06-11 10:45:16 -0600695 _feature('android.hardware.touchscreen.multitouch.jazzhand',
Andrew Lamb2413c982020-05-29 12:15:36 -0600696 touchscreen),
C Shapiro5bf23a72020-04-24 11:40:17 -0500697 ])
698
C Shapiroea33cff2020-05-11 13:32:05 -0500699 design_name = hw_design.name.lower()
C Shapiro5bf23a72020-04-24 11:40:17 -0500700
C Shapiroea33cff2020-05-11 13:32:05 -0500701 # Constructs the following map:
702 # design_name -> config -> design_configs
703 # This allows any of the following file naming schemes:
704 # - All configs within a design share config (design_name prefix only)
705 # - Nobody shares (full design_name and config id prefix needed)
706 #
707 # Having shared configs when possible makes code reviews easier around
708 # the configs and makes debugging easier on the platform side.
709 config_content = etree.tostring(root)
710 arc_configs = configs_by_design.get(design_name, {})
711 design_configs = arc_configs.get(config_content, [])
712 design_configs.append(design_config)
713 arc_configs[config_content] = design_configs
714 configs_by_design[design_name] = arc_configs
C Shapiro9a3ac8c2020-04-25 07:49:21 -0500715
C Shapiroea33cff2020-05-11 13:32:05 -0500716 for design_name, unique_configs in configs_by_design.items():
717 for file_content, design_configs in unique_configs.items():
Andrew Lamb2413c982020-05-29 12:15:36 -0600718 file_name = 'hardware_features_%s.xml' % design_name
719 if len(unique_configs) == 1:
Andrew Lambcd33f702020-06-11 10:45:16 -0600720 _write_arc_hardware_feature_file(output_dir, file_name, file_content)
C Shapiro9a3ac8c2020-04-25 07:49:21 -0500721
Andrew Lamb2413c982020-05-29 12:15:36 -0600722 for design_config in design_configs:
Andrew Lambcd33f702020-06-11 10:45:16 -0600723 feature_id = _arc_hardware_feature_id(design_config)
Andrew Lamb2413c982020-05-29 12:15:36 -0600724 if len(unique_configs) > 1:
725 file_name = 'hardware_features_%s.xml' % feature_id
Andrew Lambcd33f702020-06-11 10:45:16 -0600726 _write_arc_hardware_feature_file(output_dir, file_name, file_content)
David Burger40dfe3a2020-06-18 17:09:13 -0600727 result[feature_id] = _file_v2('%s/arc/%s' % (build_root_dir, file_name),
728 '/etc/%s' % file_name)
C Shapiro5bf23a72020-04-24 11:40:17 -0500729 return result
730
731
Andrew Lambcd33f702020-06-11 10:45:16 -0600732def _write_bluetooth_config_files(config, output_dir, build_root_path):
C Shapiro90fda252020-04-17 14:34:57 -0500733 """Writes bluetooth conf files for every unique bluetooth chip.
734
735 Args:
736 config: Source ConfigBundle to process.
737 output_dir: Path to the generated output.
C Shapiro5c877992020-04-29 12:11:28 -0500738 build_root_path: Path to the config file from portage's perspective.
C Shapiro90fda252020-04-17 14:34:57 -0500739 Returns:
740 dict that maps the bluetooth component id onto the file config.
741 """
David Burger77a1d312020-05-23 16:05:45 -0600742 output_dir += '/bluetooth'
C Shapiro90fda252020-04-17 14:34:57 -0500743 result = {}
744 for hw_design in config.designs.value:
745 project_name = hw_design.name.lower()
746 for design_config in hw_design.configs:
C Shapiro74da76e2020-05-04 13:02:20 -0500747 bt_comp = design_config.hardware_features.bluetooth.component.usb
C Shapiro90fda252020-04-17 14:34:57 -0500748 if bt_comp.vendor_id:
Andrew Lambcd33f702020-06-11 10:45:16 -0600749 bt_id = _bluetooth_id(project_name, bt_comp)
David Burger40dfe3a2020-06-18 17:09:13 -0600750 result[bt_id] = _file_v2(
751 '%s/bluetooth/%s.conf' % (build_root_path, bt_id),
752 '/etc/bluetooth/%s/main.conf' % bt_id)
C Shapiro90fda252020-04-17 14:34:57 -0500753 bt_content = '''[General]
Andrew Lamb2413c982020-05-29 12:15:36 -0600754DeviceID = bluetooth:%s:%s:%s''' % (bt_comp.vendor_id, bt_comp.product_id,
C Shapiro90fda252020-04-17 14:34:57 -0500755 bt_comp.bcd_device)
756
David Burger77a1d312020-05-23 16:05:45 -0600757 os.makedirs(output_dir, exist_ok=True)
758 output = '%s/%s.conf' % (output_dir, bt_id)
C Shapiro90fda252020-04-17 14:34:57 -0500759 with open(output, 'w') as output_stream:
760 # Using print function adds proper trailing newline.
761 print(bt_content, file=output_stream)
762 return result
763
764
Andrew Lambcd33f702020-06-11 10:45:16 -0600765def _read_config(path):
David Burgerd4f32962020-05-02 12:07:40 -0600766 """Reads a ConfigBundle proto from a json pb file.
David Burgere6f76222020-04-27 11:08:01 -0600767
768 Args:
David Burgerd4f32962020-05-02 12:07:40 -0600769 path: Path to the file encoding the json pb proto.
David Burgere6f76222020-04-27 11:08:01 -0600770 """
771 config = config_bundle_pb2.ConfigBundle()
772 with open(path, 'r') as f:
773 return json_format.Parse(f.read(), config)
774
775
Andrew Lambcd33f702020-06-11 10:45:16 -0600776def _merge_configs(configs):
David Burger7fd1dbe2020-03-26 09:26:55 -0600777 result = config_bundle_pb2.ConfigBundle()
778 for config in configs:
779 result.MergeFrom(config)
780
781 return result
782
783
David Burger1ba78a22020-06-18 18:42:47 -0600784def _camera_map(configs, project_name):
David Burger8ee9b4d2020-06-16 17:40:21 -0600785 """Produces a camera config map for the given configs.
786
787 Produces a map that maps from the design name to the camera config for that
788 design.
789
790 Args:
791 configs: Source ConfigBundle to process.
David Burger1ba78a22020-06-18 18:42:47 -0600792 project_name: Name of project processing for.
David Burger8ee9b4d2020-06-16 17:40:21 -0600793
794 Returns:
795 map from design name to camera config.
796 """
797 result = {}
798 for design in configs.designs.value:
799 design_name = design.name
David Burger0d9e8462020-06-19 14:12:37 -0600800 config_path = CAMERA_CONFIG_SOURCE_PATH_TEMPLATE.format(design_name.lower())
David Burger8ee9b4d2020-06-16 17:40:21 -0600801 if os.path.exists(config_path):
David Burger0d9e8462020-06-19 14:12:37 -0600802 destination = CAMERA_CONFIG_DEST_PATH_TEMPLATE.format(design_name.lower())
David Burger8ee9b4d2020-06-16 17:40:21 -0600803 result[design_name] = {
David Burger1ba78a22020-06-18 18:42:47 -0600804 'config-path':
805 destination,
806 'config-file':
807 _file_v2(os.path.join(project_name, config_path), destination),
David Burger8ee9b4d2020-06-16 17:40:21 -0600808 }
809 return result
810
811
David Burger52c9d322020-06-09 07:16:18 -0600812def _dptf_map(configs, project_name):
813 """Produces a dptf map for the given configs.
814
815 Produces a map that maps from design name to the dptf file config for that
816 design. It looks for the dptf files at:
817 DPTF_PATH + DPTF_FILE
818 for a project wide config, that it maps under the empty string, and at:
819 DPTF_PATH + design_name + DPTF_FILE
820 for design specific configs that it maps under the design name.
821
822 Args:
823 configs: Source ConfigBundle to process.
824 project_name: Name of project processing for.
825
826 Returns:
David Burger8ee9b4d2020-06-16 17:40:21 -0600827 map from design name or empty string (project wide), to dptf config.
David Burger52c9d322020-06-09 07:16:18 -0600828 """
829 result = {}
David Burger52c9d322020-06-09 07:16:18 -0600830 # Looking at top level for project wide, and then for each design name
831 # for design specific.
832 dirs = [""] + [d.name for d in configs.designs.value]
833 for directory in dirs:
David Burgera2252762020-07-09 15:09:49 -0600834 design = directory.lower()
835 if os.path.exists(os.path.join(DPTF_PATH, design, DPTF_FILE)):
836 project_dptf_path = os.path.join(project_name, design, 'dptf.dv')
David Burger52c9d322020-06-09 07:16:18 -0600837 dptf_file = {
838 'dptf-dv':
839 project_dptf_path,
840 'files': [
841 _file(
David Burgera2252762020-07-09 15:09:49 -0600842 os.path.join(project_name, DPTF_PATH, design, DPTF_FILE),
David Burger52c9d322020-06-09 07:16:18 -0600843 os.path.join('/etc/dptf', project_dptf_path))
844 ]
845 }
846 result[directory] = dptf_file
847 return result
848
849
Andrew Lambcd33f702020-06-11 10:45:16 -0600850def Main(project_configs, program_config, output): # pylint: disable=invalid-name
David Burger7fd1dbe2020-03-26 09:26:55 -0600851 """Transforms source proto config into platform JSON.
852
853 Args:
854 project_configs: List of source project configs to transform.
855 program_config: Program config for the given set of projects.
856 output: Output file that will be generated by the transform.
857 """
Andrew Lambcd33f702020-06-11 10:45:16 -0600858 configs = _merge_configs([_read_config(program_config)] +
859 [_read_config(config) for config in project_configs])
C Shapiro5bf23a72020-04-24 11:40:17 -0500860 bluetooth_files = {}
861 arc_hw_feature_files = {}
C Shapiro2b6d5332020-05-06 17:51:35 -0500862 touch_fw = {}
David Burger52c9d322020-06-09 07:16:18 -0600863 dptf_map = {}
David Burger8ee9b4d2020-06-16 17:40:21 -0600864 camera_map = {}
C Shapiro5bf23a72020-04-24 11:40:17 -0500865 output_dir = os.path.dirname(output)
C Shapiro5c877992020-04-29 12:11:28 -0500866 build_root_dir = output_dir
C Shapiro5c877992020-04-29 12:11:28 -0500867 if 'sw_build_config' in output_dir:
868 full_path = os.path.realpath(output)
Andrew Lamb2413c982020-05-29 12:15:36 -0600869 project_name = re.match(r'.*/(\w*)/sw_build_config/.*',
870 full_path).groups(1)[0]
C Shapiro5c877992020-04-29 12:11:28 -0500871 # Projects don't know about each other until they are integrated into the
872 # build system. When this happens, the files need to be able to co-exist
873 # without any collisions. This prefixes the project name (which is how
874 # portage maps in the project), so project files co-exist and can be
875 # installed together.
876 # This is necessary to allow projects to share files at the program level
877 # without having portage file installation collisions.
878 build_root_dir = os.path.join(project_name, output_dir)
C Shapiro6830e6c2020-04-29 13:29:56 -0500879
David Burger1ba78a22020-06-18 18:42:47 -0600880 camera_map = _camera_map(configs, project_name)
David Burger52c9d322020-06-09 07:16:18 -0600881 dptf_map = _dptf_map(configs, project_name)
882
C Shapiro2b6d5332020-05-06 17:51:35 -0500883 if os.path.exists(TOUCH_PATH):
Andrew Lambcd33f702020-06-11 10:45:16 -0600884 touch_fw = _build_touch_file_config(configs, project_name)
885 bluetooth_files = _write_bluetooth_config_files(configs, output_dir,
886 build_root_dir)
887 arc_hw_feature_files = _write_arc_hardware_feature_files(
888 configs, output_dir, build_root_dir)
C Shapiro5bf23a72020-04-24 11:40:17 -0500889 config_files = ConfigFiles(
890 bluetooth=bluetooth_files,
891 arc_hw_features=arc_hw_feature_files,
C Shapiro2b6d5332020-05-06 17:51:35 -0500892 touch_fw=touch_fw,
David Burger8ee9b4d2020-06-16 17:40:21 -0600893 dptf_map=dptf_map,
894 camera_map=camera_map)
Andrew Lambcd33f702020-06-11 10:45:16 -0600895 write_output(_transform_build_configs(configs, config_files), output)
David Burger7fd1dbe2020-03-26 09:26:55 -0600896
897
898def main(argv=None):
899 """Main program which parses args and runs
900
901 Args:
902 argv: List of command line arguments, if None uses sys.argv.
903 """
904 if argv is None:
905 argv = sys.argv[1:]
Andrew Lambcd33f702020-06-11 10:45:16 -0600906 opts = parse_args(argv)
David Burger7fd1dbe2020-03-26 09:26:55 -0600907 Main(opts.project_configs, opts.program_config, opts.output)
908
909
910if __name__ == '__main__':
911 sys.exit(main(sys.argv[1:]))