blob: 039c9bf7458c8b37e30010b80698f882d1b9e79f [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
Ren-Pei Zengce869dd2020-08-18 01:29:37 +08008# pylint: disable=too-many-lines
9
David Burger7fd1dbe2020-03-26 09:26:55 -060010import argparse
11import json
12import pprint
C Shapiro90fda252020-04-17 14:34:57 -050013import os
David Burger7fd1dbe2020-03-26 09:26:55 -060014import sys
C Shapiro90fda252020-04-17 14:34:57 -050015import re
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
Ren-Pei Zengacf03be2020-11-11 13:56:51 +080022from lxml import etree
Andrew Lambcd33f702020-06-11 10:45:16 -060023
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070024from chromiumos.config.api import device_brand_pb2
David Burger92609a32020-04-23 10:38:50 -060025from chromiumos.config.api import topology_pb2
C Shapiro5bf23a72020-04-24 11:40:17 -050026from chromiumos.config.payload import config_bundle_pb2
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070027from chromiumos.config.api.software import brand_config_pb2
David Burger7fd1dbe2020-03-26 09:26:55 -060028
Andrew Lamb2413c982020-05-29 12:15:36 -060029Config = namedtuple('Config', [
30 'program', 'hw_design', 'odm', 'hw_design_config', 'device_brand',
C Shapirod5545f12020-11-30 16:37:04 -060031 'device_signer_config', 'oem', 'sw_config', 'brand_config'
Andrew Lamb2413c982020-05-29 12:15:36 -060032])
David Burger7fd1dbe2020-03-26 09:26:55 -060033
Ren-Pei Zengacf03be2020-11-11 13:56:51 +080034ConfigFiles = namedtuple('ConfigFiles', [
35 'arc_hw_features', 'arc_media_profiles', 'touch_fw', 'dptf_map',
36 'camera_map', 'wifi_sar_map'
37])
David Burger8ee9b4d2020-06-16 17:40:21 -060038
39CAMERA_CONFIG_DEST_PATH_TEMPLATE = '/etc/camera/camera_config_{}.json'
40CAMERA_CONFIG_SOURCE_PATH_TEMPLATE = (
41 'sw_build_config/platform/chromeos-config/camera/camera_config_{}.json')
C Shapiro5bf23a72020-04-24 11:40:17 -050042
David Burger52c9d322020-06-09 07:16:18 -060043DPTF_PATH = 'sw_build_config/platform/chromeos-config/thermal'
44DPTF_FILE = 'dptf.dv'
David Burger2f0d9522020-07-30 10:52:28 -060045
C Shapiro2b6d5332020-05-06 17:51:35 -050046TOUCH_PATH = 'sw_build_config/platform/chromeos-config/touch'
Andrew Lamb6c42efc2020-06-16 10:40:43 -060047WALLPAPER_BASE_PATH = '/usr/share/chromeos-assets/wallpaper'
David Burger7fd1dbe2020-03-26 09:26:55 -060048
Ren-Pei Zengacf03be2020-11-11 13:56:51 +080049XML_DECLARATION = b'<?xml version="1.0" encoding="utf-8"?>\n'
50
Andrew Lamb2413c982020-05-29 12:15:36 -060051
Andrew Lambcd33f702020-06-11 10:45:16 -060052def parse_args(argv):
David Burger7fd1dbe2020-03-26 09:26:55 -060053 """Parse the available arguments.
54
55 Invalid arguments or -h cause this function to print a message and exit.
56
57 Args:
58 argv: List of string arguments (excluding program name / argv[0])
59
60 Returns:
61 argparse.Namespace object containing the attributes.
62 """
63 parser = argparse.ArgumentParser(
64 description='Converts source proto config into platform JSON config.')
65 parser.add_argument(
66 '-c',
67 '--project_configs',
68 nargs='+',
69 type=str,
70 help='Space delimited list of source protobinary project config files.')
71 parser.add_argument(
72 '-p',
73 '--program_config',
74 type=str,
75 help='Path to the source program-level protobinary file')
76 parser.add_argument(
Andrew Lamb2413c982020-05-29 12:15:36 -060077 '-o', '--output', type=str, help='Output file that will be generated')
David Burger7fd1dbe2020-03-26 09:26:55 -060078 return parser.parse_args(argv)
79
80
David Burger8ee9b4d2020-06-16 17:40:21 -060081def _upsert(field, target, target_name):
82 """Updates or inserts `field` within `target`.
83
84 If `target_name` already exists within `target` an update is performed,
85 otherwise, an insert is performed.
86 """
Sam McNally9a873f72020-06-05 19:47:22 +100087 if field or field == 0:
David Burger8ee9b4d2020-06-16 17:40:21 -060088 if target_name in target:
89 target[target_name].update(field)
90 else:
91 target[target_name] = field
David Burger7fd1dbe2020-03-26 09:26:55 -060092
93
Andrew Lambcd33f702020-06-11 10:45:16 -060094def _build_arc(config, config_files):
Andrew Lambcd33f702020-06-11 10:45:16 -060095 build_properties = {
C Shapirod5545f12020-11-30 16:37:04 -060096 # TODO(chromium:1126527) - Push this into the overlay itself.
97 # This isn't/can't be device specific and shouldn't be configured as such.
98 'device': "%s_cheets" % config.program.name.lower(),
99 'first-api-level': '28',
Andrew Lambcd33f702020-06-11 10:45:16 -0600100 'marketing-name': config.device_brand.brand_name,
101 'metrics-tag': config.hw_design.name.lower(),
C Shapirod5545f12020-11-30 16:37:04 -0600102 'product': config.program.name.lower(),
Andrew Lambcd33f702020-06-11 10:45:16 -0600103 }
104 if config.oem:
105 build_properties['oem'] = config.oem.name
106 result = {'build-properties': build_properties}
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800107 config_id = _get_formatted_config_id(config.hw_design_config)
108 if config_id in config_files.arc_hw_features:
109 result['hardware-features'] = config_files.arc_hw_features[config_id]
Ren-Pei Zengacf03be2020-11-11 13:56:51 +0800110 if config_id in config_files.arc_media_profiles:
111 result['media-profiles'] = config_files.arc_media_profiles[config_id]
Andrew Lambcd33f702020-06-11 10:45:16 -0600112 topology = config.hw_design_config.hardware_topology
113 ppi = topology.screen.hardware_feature.screen.panel_properties.pixels_per_in
114 # Only set for high resolution displays
115 if ppi and ppi > 250:
116 result['scale'] = ppi
David Burger2f0d9522020-07-30 10:52:28 -0600117
Andrew Lambcd33f702020-06-11 10:45:16 -0600118 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600119
Andrew Lamb2413c982020-05-29 12:15:36 -0600120
Andrew Lamb319cc922020-06-15 10:45:46 -0600121def _build_ash_flags(config: Config) -> List[str]:
122 """Returns a list of Ash flags for config.
123
124 Ash is the window manager and system UI for ChromeOS, see
125 https://chromium.googlesource.com/chromium/src/+/refs/heads/master/ash/.
126 """
127 # A map from flag name -> value. Value may be None for boolean flags.
128 flags = {}
129
130 hw_features = config.hw_design_config.hardware_features
131 if hw_features.stylus.stylus == topology_pb2.HardwareFeatures.Stylus.INTERNAL:
Andrew Lamb2e641e22020-06-15 12:30:41 -0600132 flags['has-internal-stylus'] = None
Andrew Lamb319cc922020-06-15 10:45:46 -0600133
Andrew Lamb2e641e22020-06-15 12:30:41 -0600134 fp_loc = hw_features.fingerprint.location
135 if fp_loc and fp_loc != topology_pb2.HardwareFeatures.Fingerprint.NOT_PRESENT:
136 loc_name = topology_pb2.HardwareFeatures.Fingerprint.Location.Name(fp_loc)
137 flags['fingerprint-sensor-location'] = loc_name.lower().replace('_', '-')
138
Andrew Lamb6c42efc2020-06-16 10:40:43 -0600139 wallpaper = config.brand_config.wallpaper
140 # If a wallpaper is set, the 'default-wallpaper-is-oem' flag needs to be set.
141 # If a wallpaper is not set, the 'default_[large|small].jpg' wallpapers
142 # should still be set.
143 if wallpaper:
144 flags['default-wallpaper-is-oem'] = None
145 else:
146 wallpaper = 'default'
147
148 for size in ('small', 'large'):
149 flags[f'default-wallpaper-{size}'] = (
150 f'{WALLPAPER_BASE_PATH}/{wallpaper}_{size}.jpg')
151
152 # For each size, also install 'guest' and 'child' wallpapers.
153 for wallpaper_type in ('guest', 'child'):
154 flags[f'{wallpaper_type}-wallpaper-{size}'] = (
155 f'{WALLPAPER_BASE_PATH}/{wallpaper_type}_{size}.jpg')
156
C Shapiro2e97aad2020-11-16 11:58:10 -0600157 regulatory_label = config.brand_config.regulatory_label
158 if regulatory_label:
159 flags['regulatory-label-dir'] = (regulatory_label)
160
C Shapirod5545f12020-11-30 16:37:04 -0600161 flags['arc-build-properties'] = {
162 'device': "%s_cheets" % config.program.name.lower(),
163 'firstApiLevel': '28',
164 }
Andrew Lamb72d41362020-06-17 09:19:02 -0600165
Andrew Lamb90b168c2020-06-22 10:42:30 -0600166 power_button = hw_features.power_button
167 if power_button.edge:
168 flags['ash-power-button-position'] = json.dumps({
169 'edge':
170 topology_pb2.HardwareFeatures.Button.Edge.Name(power_button.edge
171 ).lower(),
172 # Starlark sometimes represents float literals strangely, e.g. changing
173 # 0.9 to 0.899999. Round to two digits here.
174 'position':
175 round(power_button.position, 2)
176 })
177
178 volume_button = hw_features.volume_button
179 if volume_button.edge:
180 flags['ash-side-volume-button-position'] = json.dumps({
181 'region':
182 topology_pb2.HardwareFeatures.Button.Region.Name(
183 volume_button.region).lower(),
184 'edge':
185 topology_pb2.HardwareFeatures.Button.Edge.Name(volume_button.edge
186 ).lower(),
187 })
188
Nikolai Artemievda87d992020-12-04 15:09:00 +1100189 form_factor = hw_features.form_factor.form_factor
190 lid_accel = hw_features.accelerometer.lid_accelerometer
191 if (form_factor == topology_pb2.HardwareFeatures.FormFactor.CHROMEBASE and
192 lid_accel == topology_pb2.HardwareFeatures.PRESENT):
193 flags['force-in-tablet-physical-state'] = None
194
Andrew Lamb2e641e22020-06-15 12:30:41 -0600195 return sorted([f'--{k}={v}' if v else f'--{k}' for k, v in flags.items()])
Andrew Lamb319cc922020-06-15 10:45:46 -0600196
197
198def _build_ui(config: Config) -> dict:
199 """Builds the 'ui' property from cros_config_schema."""
200 return {'extra-ash-flags': _build_ash_flags(config)}
201
202
David Burger07af5242020-08-11 11:08:25 -0600203def _build_bluetooth(config):
C Shapiro90fda252020-04-17 14:34:57 -0500204 bt_flags = config.sw_config.bluetooth_config.flags
205 # Convert to native map (from proto wrapper)
206 bt_flags_map = dict(bt_flags)
207 result = {}
208 if bt_flags_map:
209 result['flags'] = bt_flags_map
C Shapiro90fda252020-04-17 14:34:57 -0500210 return result
211
David Burger7fd1dbe2020-03-26 09:26:55 -0600212
David Burgerceeb68a2020-09-03 11:31:10 -0600213def _build_ath10k_config(ath10k_config):
214 """Builds the wifi configuration for the ath10k driver.
215
216 Args:
217 ath10k_config: Ath10kConfig config.
218
219 Returns:
220 wifi configuration for the ath10k driver.
221 """
David Burgerec753912020-08-10 12:59:11 -0600222 result = {}
David Burgerec753912020-08-10 12:59:11 -0600223
David Burgerceeb68a2020-09-03 11:31:10 -0600224 def power_chain(power):
225 return {
226 'limit-2g': power.limit_2g,
227 'limit-5g': power.limit_5g,
228 }
David Burgerec753912020-08-10 12:59:11 -0600229
David Burgerceeb68a2020-09-03 11:31:10 -0600230 result['tablet-mode-power-table-ath10k'] = power_chain(
231 ath10k_config.tablet_mode_power_table)
232 result['non-tablet-mode-power-table-ath10k'] = power_chain(
233 ath10k_config.non_tablet_mode_power_table)
David Burgerec753912020-08-10 12:59:11 -0600234 return result
235
236
David Burgerceeb68a2020-09-03 11:31:10 -0600237def _build_rtw88_config(rtw88_config):
238 """Builds the wifi configuration for the rtw88 driver.
239
240 Args:
241 rtw88_config: Rtw88Config config.
242
243 Returns:
244 wifi configuration for the rtw88 driver.
245 """
246 result = {}
247
248 def power_chain(power):
249 return {
250 'limit-2g': power.limit_2g,
251 'limit-5g-1': power.limit_5g_1,
252 'limit-5g-3': power.limit_5g_3,
253 'limit-5g-4': power.limit_5g_4,
254 }
255
256 result['tablet-mode-power-table-rtw'] = power_chain(
257 rtw88_config.tablet_mode_power_table)
258 result['non-tablet-mode-power-table-rtw'] = power_chain(
259 rtw88_config.non_tablet_mode_power_table)
260
261 def offsets(offset):
262 return {
263 'offset-2g': offset.offset_2g,
264 'offset-5g': offset.offset_5g,
265 }
266
267 result['geo-offsets-fcc'] = offsets(rtw88_config.offset_fcc)
268 result['geo-offsets-eu'] = offsets(rtw88_config.offset_eu)
269 result['geo-offsets-rest-of-world'] = offsets(rtw88_config.offset_other)
270 return result
271
272
273def _build_intel_config(config, config_files):
274 """Builds the wifi configuration for the intel driver.
275
276 Args:
277 config: Config namedtuple
278 config_files: Map to look up the generated config files.
279
280 Returns:
281 wifi configuration for the intel driver.
282 """
283 design_name = config.hw_design.name.lower()
284 return config_files.wifi_sar_map.get(design_name)
285
286
287def _build_wifi(config, config_files):
288 """Builds the wifi configuration.
289
290 Args:
291 config: Config namedtuple
292 config_files: Map to look up the generated config files.
293
294 Returns:
295 wifi configuration.
296 """
297 config_field = config.sw_config.wifi_config.WhichOneof('wifi_config')
298 if config_field == 'ath10k_config':
299 return _build_ath10k_config(config.sw_config.wifi_config.ath10k_config)
300 if config_field == 'rtw88_config':
301 return _build_rtw88_config(config.sw_config.wifi_config.rtw88_config)
302 if config_field == 'intel_config':
303 return _build_intel_config(config, config_files)
304 return {}
305
306
Andrew Lambcd33f702020-06-11 10:45:16 -0600307def _build_fingerprint(hw_topology):
308 if not hw_topology.HasField('fingerprint'):
309 return None
310
311 fp = hw_topology.fingerprint.hardware_feature.fingerprint
312 result = {}
313 if fp.location != topology_pb2.HardwareFeatures.Fingerprint.NOT_PRESENT:
314 location = fp.Location.DESCRIPTOR.values_by_number[fp.location].name
315 result['sensor-location'] = location.lower().replace('_', '-')
316 if fp.board:
317 result['board'] = fp.board
Tom Hughesdfc35402020-06-29 16:02:09 -0700318 if fp.ro_version:
319 result['ro-version'] = fp.ro_version
320
Andrew Lambcd33f702020-06-11 10:45:16 -0600321 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600322
323
Trent Beginf067ccb2020-08-12 12:33:53 -0600324def _build_hardware_properties(hw_topology):
325 if not hw_topology.HasField('form_factor'):
326 return None
327
328 form_factor = hw_topology.form_factor.hardware_feature.form_factor.form_factor
329 result = {}
330 if form_factor in [
331 topology_pb2.HardwareFeatures.FormFactor.CHROMEBIT,
332 topology_pb2.HardwareFeatures.FormFactor.CHROMEBASE,
333 topology_pb2.HardwareFeatures.FormFactor.CHROMEBOX
334 ]:
335 result['psu-type'] = "AC_only"
336 else:
337 result['psu-type'] = "battery"
338
339 result['has-backlight'] = form_factor not in [
340 topology_pb2.HardwareFeatures.FormFactor.CHROMEBIT,
341 topology_pb2.HardwareFeatures.FormFactor.CHROMEBOX
342 ]
343
Nikolai Artemiev1be27ef2021-01-11 17:32:17 +1100344 form_factor_names = {
345 topology_pb2.HardwareFeatures.FormFactor.CHROMEBASE: "CHROMEBASE",
346 }
347 if form_factor in form_factor_names:
348 result['form-factor'] = form_factor_names[form_factor]
349
Trent Beginf067ccb2020-08-12 12:33:53 -0600350 return result
351
352
Andrew Lambcd33f702020-06-11 10:45:16 -0600353def _fw_bcs_path(payload):
David Burger7fd1dbe2020-03-26 09:26:55 -0600354 if payload and payload.firmware_image_name:
YH Lin873742a2021-03-02 07:02:31 -0800355 return 'bcs://%s.%d.%d.%d.tbz2' % (
356 payload.firmware_image_name, payload.version.major,
357 payload.version.minor, payload.version.patch)
David Burger7fd1dbe2020-03-26 09:26:55 -0600358
Andrew Lambcd33f702020-06-11 10:45:16 -0600359 return None
David Burger7fd1dbe2020-03-26 09:26:55 -0600360
Andrew Lambcd33f702020-06-11 10:45:16 -0600361
362def _fw_build_target(payload):
David Burger7fd1dbe2020-03-26 09:26:55 -0600363 if payload:
364 return payload.build_target_name
365
Andrew Lambcd33f702020-06-11 10:45:16 -0600366 return None
David Burger7fd1dbe2020-03-26 09:26:55 -0600367
Andrew Lambcd33f702020-06-11 10:45:16 -0600368
369def _build_firmware(config):
David Burgerb70b6762020-05-21 12:14:59 -0600370 """Returns firmware config, or None if no build targets."""
Andrew Lamb3da156d2020-04-16 16:00:56 -0600371 fw_payload_config = config.sw_config.firmware
372 fw_build_config = config.sw_config.firmware_build_config
373 main_ro = fw_payload_config.main_ro_payload
374 main_rw = fw_payload_config.main_rw_payload
375 ec_ro = fw_payload_config.ec_ro_payload
376 pd_ro = fw_payload_config.pd_ro_payload
David Burger7fd1dbe2020-03-26 09:26:55 -0600377
378 build_targets = {}
Andrew Lamb3da156d2020-04-16 16:00:56 -0600379
David Burger8ee9b4d2020-06-16 17:40:21 -0600380 _upsert(fw_build_config.build_targets.depthcharge, build_targets,
381 'depthcharge')
382 _upsert(fw_build_config.build_targets.coreboot, build_targets, 'coreboot')
383 _upsert(fw_build_config.build_targets.ec, build_targets, 'ec')
384 _upsert(
Andrew Lambf8954ee2020-04-21 10:24:40 -0600385 list(fw_build_config.build_targets.ec_extras), build_targets, 'ec_extras')
David Burger8ee9b4d2020-06-16 17:40:21 -0600386 _upsert(fw_build_config.build_targets.libpayload, build_targets, 'libpayload')
David Burger7fd1dbe2020-03-26 09:26:55 -0600387
David Burgerb70b6762020-05-21 12:14:59 -0600388 if not build_targets:
389 return None
390
David Burger7fd1dbe2020-03-26 09:26:55 -0600391 result = {
C Shapirod5545f12020-11-30 16:37:04 -0600392 'bcs-overlay': 'overlay-%s-private' % config.program.name.lower(),
David Burger7fd1dbe2020-03-26 09:26:55 -0600393 'build-targets': build_targets,
David Burger7fd1dbe2020-03-26 09:26:55 -0600394 }
Andrew Lamb883fa042020-04-06 11:37:22 -0600395
David Burger8ee9b4d2020-06-16 17:40:21 -0600396 _upsert(main_ro.firmware_image_name.lower(), result, 'image-name')
Andrew Lamb883fa042020-04-06 11:37:22 -0600397
David Burger8ee9b4d2020-06-16 17:40:21 -0600398 _upsert(_fw_bcs_path(main_ro), result, 'main-ro-image')
399 _upsert(_fw_bcs_path(main_rw), result, 'main-rw-image')
400 _upsert(_fw_bcs_path(ec_ro), result, 'ec-ro-image')
401 _upsert(_fw_bcs_path(pd_ro), result, 'pd-ro-image')
David Burger7fd1dbe2020-03-26 09:26:55 -0600402
David Burger8ee9b4d2020-06-16 17:40:21 -0600403 _upsert(
Andrew Lambf39fbe82020-04-13 16:14:33 -0600404 config.hw_design_config.hardware_features.fw_config.value,
405 result,
406 'firmware-config',
407 )
408
David Burger7fd1dbe2020-03-26 09:26:55 -0600409 return result
410
411
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000412def _build_fw_signing(config, whitelabel):
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500413 if config.sw_config.firmware and config.device_signer_config:
David Burger68e0d142020-05-15 17:29:33 -0600414 hw_design = config.hw_design.name.lower()
Sam McNally2fc807f2020-07-16 18:13:53 +1000415 brand_scan_config = config.brand_config.scan_config
416 if brand_scan_config and brand_scan_config.whitelabel_tag:
417 signature_id = '%s-%s' % (hw_design, brand_scan_config.whitelabel_tag)
418 else:
419 signature_id = hw_design
420
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000421 result = {
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500422 'key-id': config.device_signer_config.key_id,
Sam McNally2fc807f2020-07-16 18:13:53 +1000423 'signature-id': signature_id,
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500424 }
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000425 if whitelabel:
426 result['sig-id-in-customization-id'] = True
427 return result
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500428 return {}
David Burger7fd1dbe2020-03-26 09:26:55 -0600429
430
Andrew Lambcd33f702020-06-11 10:45:16 -0600431def _file(source, destination):
Andrew Lamb2413c982020-05-29 12:15:36 -0600432 return {'destination': destination, 'source': source}
David Burger7fd1dbe2020-03-26 09:26:55 -0600433
434
David Burger40dfe3a2020-06-18 17:09:13 -0600435def _file_v2(build_path, system_path):
436 return {'build-path': build_path, 'system-path': system_path}
437
438
Andrew Lambcd33f702020-06-11 10:45:16 -0600439def _build_audio(config):
David Burger178f3ef2020-06-26 12:11:57 -0600440 if not config.sw_config.audio_configs:
441 return {}
David Burger7fd1dbe2020-03-26 09:26:55 -0600442 alsa_path = '/usr/share/alsa/ucm'
443 cras_path = '/etc/cras'
Judy Hsiao1ae95122020-12-23 15:39:50 +0800444 sound_card_init_path = '/etc/sound_card_init'
David Burger7fd1dbe2020-03-26 09:26:55 -0600445 project_name = config.hw_design.name.lower()
David Burger43250662020-05-07 11:21:50 -0600446 program_name = config.program.name.lower()
David Burger7fd1dbe2020-03-26 09:26:55 -0600447 files = []
David Burger178f3ef2020-06-26 12:11:57 -0600448 ucm_suffix = None
449 for audio in config.sw_config.audio_configs:
450 card = audio.card_name
451 card_with_suffix = audio.card_name
452 if audio.ucm_suffix:
453 # TODO: last ucm_suffix wins.
454 ucm_suffix = audio.ucm_suffix
455 card_with_suffix += '.' + audio.ucm_suffix
456 if audio.ucm_file:
457 files.append(
458 _file(audio.ucm_file,
459 '%s/%s/HiFi.conf' % (alsa_path, card_with_suffix)))
460 if audio.ucm_master_file:
461 files.append(
462 _file(
463 audio.ucm_master_file, '%s/%s/%s.conf' %
Andrew Lamb2413c982020-05-29 12:15:36 -0600464 (alsa_path, card_with_suffix, card_with_suffix)))
David Burger178f3ef2020-06-26 12:11:57 -0600465 if audio.card_config_file:
466 files.append(
467 _file(audio.card_config_file,
468 '%s/%s/%s' % (cras_path, project_name, card)))
469 if audio.dsp_file:
470 files.append(
471 _file(audio.dsp_file, '%s/%s/dsp.ini' % (cras_path, project_name)))
472 if audio.module_file:
473 files.append(
474 _file(audio.module_file,
475 '/etc/modprobe.d/alsa-%s.conf' % program_name))
476 if audio.board_file:
477 files.append(
478 _file(audio.board_file,
479 '%s/%s/board.ini' % (cras_path, project_name)))
Judy Hsiao1ae95122020-12-23 15:39:50 +0800480 if audio.sound_card_init_file:
481 files.append(
482 _file(audio.sound_card_init_file,
483 '%s/%s.yaml' % (sound_card_init_path, audio.card_id)))
David Burger599ff7b2020-04-06 16:29:31 -0600484
485 result = {
David Burger7fd1dbe2020-03-26 09:26:55 -0600486 'main': {
487 'cras-config-dir': project_name,
488 'files': files,
489 }
490 }
David Burger178f3ef2020-06-26 12:11:57 -0600491
492 if ucm_suffix:
493 result['main']['ucm-suffix'] = ucm_suffix
David Burger599ff7b2020-04-06 16:29:31 -0600494
495 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600496
497
Andrew Lambcd33f702020-06-11 10:45:16 -0600498def _build_camera(hw_topology):
Ren-Pei Zeng573d6332020-11-12 14:55:22 +0800499 camera_pb = topology_pb2.HardwareFeatures.Camera
500 camera = hw_topology.camera.hardware_feature.camera
501 result = {'count': len(camera.devices)}
502 if camera.devices:
503 result['devices'] = []
504 for device in camera.devices:
505 interface = {
506 camera_pb.INTERFACE_USB: 'usb',
507 camera_pb.INTERFACE_MIPI: 'mipi',
508 }[device.interface]
509 facing = {
510 camera_pb.FACING_FRONT: 'front',
511 camera_pb.FACING_BACK: 'back',
512 }[device.facing]
513 orientation = {
514 camera_pb.ORIENTATION_0: 0,
515 camera_pb.ORIENTATION_90: 90,
516 camera_pb.ORIENTATION_180: 180,
517 camera_pb.ORIENTATION_270: 270,
518 }[device.orientation]
519 flags = {
520 'support-1080p':
521 bool(device.flags & camera_pb.FLAGS_SUPPORT_1080P),
522 'support-autofocus':
523 bool(device.flags & camera_pb.FLAGS_SUPPORT_AUTOFOCUS),
524 }
Ricardo Ribaldab9b17b32021-01-13 17:10:20 +0100525 dev = {
Ren-Pei Zeng573d6332020-11-12 14:55:22 +0800526 'interface': interface,
527 'facing': facing,
528 'orientation': orientation,
529 'flags': flags,
530 'ids': list(device.ids),
Ricardo Ribaldab9b17b32021-01-13 17:10:20 +0100531 }
532 if device.privacy_switch != topology_pb2.HardwareFeatures.PRESENT_UNKNOWN:
533 dev['has-privacy-switch'] = device.privacy_switch == topology_pb2.HardwareFeatures.PRESENT
534 result['devices'].append(dev)
Ren-Pei Zeng573d6332020-11-12 14:55:22 +0800535 return result
David Burger8aa8fa32020-04-14 08:30:34 -0600536
Andrew Lambcd33f702020-06-11 10:45:16 -0600537
538def _build_identity(hw_scan_config, program, brand_scan_config=None):
David Burger7fd1dbe2020-03-26 09:26:55 -0600539 identity = {}
David Burger8ee9b4d2020-06-16 17:40:21 -0600540 _upsert(hw_scan_config.firmware_sku, identity, 'sku-id')
541 _upsert(hw_scan_config.smbios_name_match, identity, 'smbios-name-match')
Andrew Lamb7806ce92020-04-07 10:22:17 -0600542 # 'platform-name' is needed to support 'mosys platform name'. Clients should
Sean McAllister0b757772020-11-13 12:22:36 -0700543 # no longer require platform name, but set it here for backwards compatibility.
544 if program.mosys_platform_name:
545 _upsert(program.mosys_platform_name, identity, 'platform-name')
546 else:
547 _upsert(program.name, identity, 'platform-name')
548
David Burger7fd1dbe2020-03-26 09:26:55 -0600549 # ARM architecture
David Burger8ee9b4d2020-06-16 17:40:21 -0600550 _upsert(hw_scan_config.device_tree_compatible_match, identity,
551 'device-tree-compatible-match')
David Burger7fd1dbe2020-03-26 09:26:55 -0600552
553 if brand_scan_config:
David Burger8ee9b4d2020-06-16 17:40:21 -0600554 _upsert(brand_scan_config.whitelabel_tag, identity, 'whitelabel-tag')
David Burger7fd1dbe2020-03-26 09:26:55 -0600555
556 return identity
557
558
Andrew Lambcd33f702020-06-11 10:45:16 -0600559def _lookup(id_value, id_map):
560 if not id_value.value:
561 return None
562
563 key = id_value.value
564 if key in id_map:
565 return id_map[id_value.value]
566 error = 'Failed to lookup %s with value: %s' % (
567 id_value.__class__.__name__.replace('Id', ''), key)
568 print(error)
569 print('Check the config contents provided:')
570 printer = pprint.PrettyPrinter(indent=4)
571 printer.pprint(id_map)
572 raise Exception(error)
David Burger7fd1dbe2020-03-26 09:26:55 -0600573
574
Andrew Lambcd33f702020-06-11 10:45:16 -0600575def _build_touch_file_config(config, project_name):
Sean McAllistereaf10b72020-08-03 13:41:06 -0600576 partners = {x.id.value: x for x in config.partner_list}
C Shapiro2b6d5332020-05-06 17:51:35 -0500577 files = []
578 for comp in config.components:
C Shapiro4813be62020-05-13 17:31:58 -0500579 touch = comp.touchscreen
580 # Everything is the same for Touch screen/pad, except different fields
581 if comp.HasField('touchpad'):
582 touch = comp.touchpad
583 if touch.product_id:
Andrew Lambcd33f702020-06-11 10:45:16 -0600584 vendor = _lookup(comp.manufacturer_id, partners)
C Shapiro2b6d5332020-05-06 17:51:35 -0500585 if not vendor:
Andrew Lamb2413c982020-05-29 12:15:36 -0600586 raise Exception("Manufacturer must be set for touch device %s" %
587 comp.id.value)
C Shapiro2b6d5332020-05-06 17:51:35 -0500588
C Shapiro4813be62020-05-13 17:31:58 -0500589 product_id = touch.product_id
590 fw_version = touch.fw_version
C Shapiro2b6d5332020-05-06 17:51:35 -0500591
C Shapiro2b6d5332020-05-06 17:51:35 -0500592 file_name = "%s_%s.bin" % (product_id, fw_version)
593 fw_file_path = os.path.join(TOUCH_PATH, vendor.name, file_name)
594
595 if not os.path.exists(fw_file_path):
Andrew Lamb2413c982020-05-29 12:15:36 -0600596 raise Exception("Touchscreen fw bin file doesn't exist at: %s" %
597 fw_file_path)
C Shapiro2b6d5332020-05-06 17:51:35 -0500598
C Shapiro303cece2020-07-22 07:15:21 -0500599 touch_vendor = vendor.touch_vendor
600 sym_link = touch_vendor.symlink_file_format.format(
601 vendor_name=vendor.name,
602 vendor_id=touch_vendor.vendor_id,
603 product_id=product_id,
604 fw_version=fw_version,
605 product_series=touch.product_series)
606
607 dest = "%s_%s" % (vendor.name, file_name)
608 if touch_vendor.destination_file_format:
609 dest = touch_vendor.destination_file_format.format(
610 vendor_name=vendor.name,
611 vendor_id=touch_vendor.vendor_id,
612 product_id=product_id,
613 fw_version=fw_version,
614 product_series=touch.product_series)
615
C Shapiro2b6d5332020-05-06 17:51:35 -0500616 files.append({
C Shapiro303cece2020-07-22 07:15:21 -0500617 "destination": os.path.join("/opt/google/touch/firmware", dest),
YH Lin9160fc52020-07-22 16:35:28 -0700618 "source": os.path.join(project_name, fw_file_path),
619 "symlink": os.path.join("/lib/firmware", sym_link),
C Shapiro2b6d5332020-05-06 17:51:35 -0500620 })
621
622 result = {}
David Burger8ee9b4d2020-06-16 17:40:21 -0600623 _upsert(files, result, 'files')
C Shapiro2b6d5332020-05-06 17:51:35 -0500624 return result
625
626
Vincent Palatin2ef6bd62021-01-04 14:47:31 +0000627def _build_modem(config):
628 """Returns the cellular modem configuration, or None if absent."""
629 hw_features = config.hw_design_config.hardware_features
630 lte_support = _any_present([hw_features.lte.present])
631 if not lte_support:
632 return None
633 return {'firmware-variant': config.hw_design.name.lower()}
634
635
David Burgerceeb68a2020-09-03 11:31:10 -0600636def _sw_config(sw_configs, design_config_id):
637 """Returns the correct software config for `design_config_id`.
638
639 Returns the correct software config match for `design_config_id`. If no such
640 config or multiple such configs are found an exception is raised.
641 """
642 sw_config_matches = [
643 x for x in sw_configs if x.design_config_id.value == design_config_id
644 ]
645 if len(sw_config_matches) == 1:
646 return sw_config_matches[0]
647 if len(sw_config_matches) > 1:
648 raise ValueError('Multiple software configs found for: %s' %
649 design_config_id)
650 raise ValueError('Software config is required for: %s' % design_config_id)
651
652
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000653def _is_whitelabel(brand_configs, device_brands):
654 for device_brand in device_brands:
655 if device_brand.id.value in brand_configs:
656 brand_scan_config = brand_configs[device_brand.id.value].scan_config
657 if brand_scan_config and brand_scan_config.whitelabel_tag:
658 return True
659 return False
660
661
David Burgerceeb68a2020-09-03 11:31:10 -0600662def _transform_build_configs(config,
Ren-Pei Zengacf03be2020-11-11 13:56:51 +0800663 config_files=ConfigFiles({}, {}, {}, {}, {}, {})):
Andrew Lambcd33f702020-06-11 10:45:16 -0600664 # pylint: disable=too-many-locals,too-many-branches
Sean McAllistereaf10b72020-08-03 13:41:06 -0600665 partners = {x.id.value: x for x in config.partner_list}
Sean McAllisterf38d1e92020-08-03 13:57:53 -0600666 programs = {x.id.value: x for x in config.program_list}
David Burger7fd1dbe2020-03-26 09:26:55 -0600667 sw_configs = list(config.software_configs)
Andrew Lambcd33f702020-06-11 10:45:16 -0600668 brand_configs = {x.brand_id.value: x for x in config.brand_configs}
David Burger7fd1dbe2020-03-26 09:26:55 -0600669
670 results = {}
Sean McAllisterf66887b2020-08-03 14:00:51 -0600671 for hw_design in config.design_list:
Sean McAllister6cbb0ec2020-08-03 14:03:37 -0600672 if config.device_brand_list:
Andrew Lamb2413c982020-05-29 12:15:36 -0600673 device_brands = [
Sean McAllister6cbb0ec2020-08-03 14:03:37 -0600674 x for x in config.device_brand_list
Andrew Lamb2413c982020-05-29 12:15:36 -0600675 if x.design_id.value == hw_design.id.value
676 ]
David Burger7fd1dbe2020-03-26 09:26:55 -0600677 else:
678 device_brands = [device_brand_pb2.DeviceBrand()]
679
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000680 whitelabel = _is_whitelabel(brand_configs, device_brands)
681
David Burger7fd1dbe2020-03-26 09:26:55 -0600682 for device_brand in device_brands:
683 # Brand config can be empty since platform JSON config allows it
684 brand_config = brand_config_pb2.BrandConfig()
685 if device_brand.id.value in brand_configs:
686 brand_config = brand_configs[device_brand.id.value]
687
688 for hw_design_config in hw_design.configs:
David Burgerceeb68a2020-09-03 11:31:10 -0600689 sw_config = _sw_config(sw_configs, hw_design_config.id.value)
Andrew Lambcd33f702020-06-11 10:45:16 -0600690 program = _lookup(hw_design.program_id, programs)
C Shapiroadefd7c2020-05-19 16:37:21 -0500691 signer_configs_by_design = {}
692 signer_configs_by_brand = {}
693 for signer_config in program.device_signer_configs:
694 design_id = signer_config.design_id.value
695 brand_id = signer_config.brand_id.value
696 if design_id:
697 signer_configs_by_design[design_id] = signer_config
698 elif brand_id:
699 signer_configs_by_brand[brand_id] = signer_config
700 else:
701 raise Exception('No ID found for signer config: %s' % signer_config)
702
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500703 device_signer_config = None
C Shapiroadefd7c2020-05-19 16:37:21 -0500704 if signer_configs_by_design or signer_configs_by_brand:
705 design_id = hw_design.id.value
706 brand_id = device_brand.id.value
707 if design_id in signer_configs_by_design:
708 device_signer_config = signer_configs_by_design[design_id]
709 elif brand_id in signer_configs_by_brand:
710 device_signer_config = signer_configs_by_brand[brand_id]
711 else:
712 # Assume that if signer configs are set, every config is setup
Andrew Lamb2413c982020-05-29 12:15:36 -0600713 raise Exception('Signer config missing for design: %s, brand: %s' %
714 (design_id, brand_id))
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500715
Andrew Lambcd33f702020-06-11 10:45:16 -0600716 transformed_config = _transform_build_config(
C Shapiro90fda252020-04-17 14:34:57 -0500717 Config(
718 program=program,
719 hw_design=hw_design,
Andrew Lambcd33f702020-06-11 10:45:16 -0600720 odm=_lookup(hw_design.odm_id, partners),
C Shapiro90fda252020-04-17 14:34:57 -0500721 hw_design_config=hw_design_config,
722 device_brand=device_brand,
723 device_signer_config=device_signer_config,
Andrew Lambcd33f702020-06-11 10:45:16 -0600724 oem=_lookup(device_brand.oem_id, partners),
C Shapiro90fda252020-04-17 14:34:57 -0500725 sw_config=sw_config,
C Shapirod5545f12020-11-30 16:37:04 -0600726 brand_config=brand_config), config_files, whitelabel)
David Burger7fd1dbe2020-03-26 09:26:55 -0600727
Andrew Lamb2413c982020-05-29 12:15:36 -0600728 config_json = json.dumps(
729 transformed_config,
730 sort_keys=True,
731 indent=2,
732 separators=(',', ': '))
David Burger7fd1dbe2020-03-26 09:26:55 -0600733
734 if config_json not in results:
735 results[config_json] = transformed_config
736
737 return list(results.values())
738
739
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000740def _transform_build_config(config, config_files, whitelabel):
David Burger7fd1dbe2020-03-26 09:26:55 -0600741 """Transforms Config instance into target platform JSON schema.
742
743 Args:
744 config: Config namedtuple
C Shapiro5bf23a72020-04-24 11:40:17 -0500745 config_files: Map to look up the generated config files.
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000746 whitelabel: Whether the config is for a whitelabel design
David Burger7fd1dbe2020-03-26 09:26:55 -0600747
748 Returns:
749 Unique config payload based on the platform JSON schema.
750 """
751 result = {
Andrew Lamb2413c982020-05-29 12:15:36 -0600752 'identity':
Andrew Lambcd33f702020-06-11 10:45:16 -0600753 _build_identity(config.sw_config.id_scan_config, config.program,
754 config.brand_config.scan_config),
Andrew Lamb2413c982020-05-29 12:15:36 -0600755 'name':
756 config.hw_design.name.lower(),
David Burger7fd1dbe2020-03-26 09:26:55 -0600757 }
758
David Burger8ee9b4d2020-06-16 17:40:21 -0600759 _upsert(_build_arc(config, config_files), result, 'arc')
760 _upsert(_build_audio(config), result, 'audio')
David Burger07af5242020-08-11 11:08:25 -0600761 _upsert(_build_bluetooth(config), result, 'bluetooth')
David Burgerceeb68a2020-09-03 11:31:10 -0600762 _upsert(_build_wifi(config, config_files), result, 'wifi')
Andrew Lambca279902020-08-06 10:13:42 -0600763 _upsert(config.brand_config.wallpaper, result, 'wallpaper')
C Shapiro2e97aad2020-11-16 11:58:10 -0600764 _upsert(config.brand_config.regulatory_label, result, 'regulatory-label')
David Burger8ee9b4d2020-06-16 17:40:21 -0600765 _upsert(config.device_brand.brand_code, result, 'brand-code')
766 _upsert(
Andrew Lambcd33f702020-06-11 10:45:16 -0600767 _build_camera(config.hw_design_config.hardware_topology), result,
768 'camera')
David Burger8ee9b4d2020-06-16 17:40:21 -0600769 _upsert(_build_firmware(config), result, 'firmware')
Sam McNallyfd14e4b2020-09-12 10:26:35 +1000770 _upsert(_build_fw_signing(config, whitelabel), result, 'firmware-signing')
David Burger8ee9b4d2020-06-16 17:40:21 -0600771 _upsert(
Andrew Lambcd33f702020-06-11 10:45:16 -0600772 _build_fingerprint(config.hw_design_config.hardware_topology), result,
Andrew Lamb2413c982020-05-29 12:15:36 -0600773 'fingerprint')
Andrew Lamb0d236ab2020-06-30 12:30:20 -0600774 _upsert(_build_ui(config), result, 'ui')
David Burger7fd1dbe2020-03-26 09:26:55 -0600775 power_prefs = config.sw_config.power_config.preferences
776 power_prefs_map = dict(
Andrew Lamb2413c982020-05-29 12:15:36 -0600777 (x.replace('_', '-'), power_prefs[x]) for x in power_prefs)
David Burger8ee9b4d2020-06-16 17:40:21 -0600778 _upsert(power_prefs_map, result, 'power')
779 if config_files.camera_map:
780 camera_file = config_files.camera_map.get(config.hw_design.name, {})
781 _upsert(camera_file, result, 'camera')
David Burger52c9d322020-06-09 07:16:18 -0600782 if config_files.dptf_map:
783 # Prefer design specific if found, if not fall back to project wide config
784 # mapped under the empty string.
785 if config_files.dptf_map.get(config.hw_design.name):
786 dptf_file = config_files.dptf_map[config.hw_design.name]
787 else:
788 dptf_file = config_files.dptf_map.get('')
David Burger8ee9b4d2020-06-16 17:40:21 -0600789 _upsert(dptf_file, result, 'thermal')
790 _upsert(config_files.touch_fw, result, 'touch')
Trent Beginf067ccb2020-08-12 12:33:53 -0600791 _upsert(
792 _build_hardware_properties(config.hw_design_config.hardware_topology),
793 result, 'hardware-properties')
Vincent Palatin2ef6bd62021-01-04 14:47:31 +0000794 _upsert(_build_modem(config), result, 'modem')
David Burger7fd1dbe2020-03-26 09:26:55 -0600795
796 return result
797
798
Andrew Lambcd33f702020-06-11 10:45:16 -0600799def write_output(configs, output=None):
David Burger7fd1dbe2020-03-26 09:26:55 -0600800 """Writes a list of configs to platform JSON format.
801
802 Args:
803 configs: List of config dicts defined in cros_config_schema.yaml
804 output: Target file output (if None, prints to stdout)
805 """
Andrew Lamb2413c982020-05-29 12:15:36 -0600806 json_output = json.dumps({'chromeos': {
807 'configs': configs,
808 }},
809 sort_keys=True,
810 indent=2,
811 separators=(',', ': '))
David Burger7fd1dbe2020-03-26 09:26:55 -0600812 if output:
813 with open(output, 'w') as output_stream:
814 # Using print function adds proper trailing newline.
815 print(json_output, file=output_stream)
816 else:
817 print(json_output)
818
819
Andrew Lambcd33f702020-06-11 10:45:16 -0600820def _feature(name, present):
C Shapiro5bf23a72020-04-24 11:40:17 -0500821 attrib = {'name': name}
822 if present:
823 return etree.Element('feature', attrib=attrib)
Andrew Lambcd33f702020-06-11 10:45:16 -0600824
825 return etree.Element('unavailable-feature', attrib=attrib)
C Shapiro5bf23a72020-04-24 11:40:17 -0500826
827
Andrew Lambcd33f702020-06-11 10:45:16 -0600828def _any_present(features):
Andrew Lamb2413c982020-05-29 12:15:36 -0600829 return topology_pb2.HardwareFeatures.PRESENT in features
C Shapiro5bf23a72020-04-24 11:40:17 -0500830
831
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800832def _get_formatted_config_id(design_config):
C Shapiro5bf23a72020-04-24 11:40:17 -0500833 return design_config.id.value.lower().replace(':', '_')
834
835
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800836def _write_file(output_dir, file_name, file_content):
David Burger77a1d312020-05-23 16:05:45 -0600837 os.makedirs(output_dir, exist_ok=True)
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800838 output = '{}/{}'.format(output_dir, file_name)
C Shapiroea33cff2020-05-11 13:32:05 -0500839 with open(output, 'wb') as f:
840 f.write(file_content)
841
842
Ren-Pei Zengf22b5382020-09-02 13:31:22 +0800843def _get_arc_camera_features(camera):
844 """Gets camera related features for ARC hardware_features.xml from camera
845 topology. Check
846 https://developer.android.com/reference/android/content/pm/PackageManager#FEATURE_CAMERA
847 and CTS android.app.cts.SystemFeaturesTest#testCameraFeatures for the correct
848 settings.
849
850 Args:
851 camera: A HardwareFeatures.Camera proto message.
852 Returns:
853 list of camera related ARC features as XML elements.
854 """
855 camera_pb = topology_pb2.HardwareFeatures.Camera
856
Ren-Pei Zeng9b5682d2020-10-14 17:37:30 +0800857 count = len(camera.devices)
858 has_front_camera = any(
859 (d.facing == camera_pb.FACING_FRONT for d in camera.devices))
860 has_back_camera = any(
861 (d.facing == camera_pb.FACING_BACK for d in camera.devices))
862 has_autofocus_back_camera = any((d.facing == camera_pb.FACING_BACK and
863 d.flags & camera_pb.FLAGS_SUPPORT_AUTOFOCUS
864 for d in camera.devices))
865 # Assumes MIPI cameras support FULL-level.
866 # TODO(kamesan): Setting this in project configs when there's an exception.
867 has_level_full_camera = any(
868 (d.interface == camera_pb.INTERFACE_MIPI for d in camera.devices))
Ren-Pei Zengf22b5382020-09-02 13:31:22 +0800869
Ren-Pei Zengf22b5382020-09-02 13:31:22 +0800870 return [
871 _feature('android.hardware.camera', has_back_camera),
872 _feature('android.hardware.camera.any', count > 0),
873 _feature('android.hardware.camera.autofocus', has_autofocus_back_camera),
874 _feature('android.hardware.camera.capability.manual_post_processing',
875 has_level_full_camera),
876 _feature('android.hardware.camera.capability.manual_sensor',
877 has_level_full_camera),
878 _feature('android.hardware.camera.front', has_front_camera),
879 _feature('android.hardware.camera.level.full', has_level_full_camera),
880 ]
881
882
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800883def _generate_arc_hardware_features(hw_features):
884 """Generates ARC hardware_features.xml file content.
C Shapiro5bf23a72020-04-24 11:40:17 -0500885
886 Args:
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800887 hw_features: HardwareFeatures proto message.
C Shapiro5bf23a72020-04-24 11:40:17 -0500888 Returns:
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800889 bytes of the hardware_features.xml content.
C Shapiro5bf23a72020-04-24 11:40:17 -0500890 """
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +0800891 touchscreen = _any_present([hw_features.screen.touch_support])
892 acc = hw_features.accelerometer
893 gyro = hw_features.gyroscope
894 compass = hw_features.magnetometer
895 light_sensor = hw_features.light_sensor
896 root = etree.Element('permissions')
897 root.extend(
898 _get_arc_camera_features(hw_features.camera) + [
899 _feature(
900 'android.hardware.sensor.accelerometer',
901 _any_present([acc.lid_accelerometer, acc.base_accelerometer])),
902 _feature('android.hardware.sensor.gyroscope',
903 _any_present([gyro.lid_gyroscope, gyro.base_gyroscope])),
904 _feature(
905 'android.hardware.sensor.compass',
906 _any_present(
907 [compass.lid_magnetometer, compass.base_magnetometer])),
908 _feature(
909 'android.hardware.sensor.light',
910 _any_present([
911 light_sensor.lid_lightsensor, light_sensor.base_lightsensor
912 ])),
913 _feature('android.hardware.touchscreen', touchscreen),
914 _feature('android.hardware.touchscreen.multitouch', touchscreen),
915 _feature('android.hardware.touchscreen.multitouch.distinct',
916 touchscreen),
917 _feature('android.hardware.touchscreen.multitouch.jazzhand',
918 touchscreen),
919 ])
Ren-Pei Zengacf03be2020-11-11 13:56:51 +0800920 return XML_DECLARATION + etree.tostring(root, pretty_print=True)
921
922
923def _generate_arc_media_profiles(hw_features, sw_config):
924 """Generates ARC media_profiles.xml file content.
925
926 Args:
927 hw_features: HardwareFeatures proto message.
928 sw_config: SoftwareConfig proto message.
929 Returns:
930 bytes of the media_profiles.xml content, or None if |sw_config| disables the
Ren-Pei Zengb55e4312020-11-18 17:03:01 +0800931 generation or there's no camera.
Ren-Pei Zengacf03be2020-11-11 13:56:51 +0800932 """
933
934 def _gen_camcorder_profiles(camera_id, resolutions):
935 elem = etree.Element(
936 'CamcorderProfiles', attrib={'cameraId': str(camera_id)})
937 for width, height in resolutions:
938 elem.extend([
939 _gen_encoder_profile(width, height, False),
940 _gen_encoder_profile(width, height, True),
941 ])
942 elem.extend([
943 etree.Element('ImageEncoding', attrib={'quality': '90'}),
944 etree.Element('ImageEncoding', attrib={'quality': '80'}),
945 etree.Element('ImageEncoding', attrib={'quality': '70'}),
946 etree.Element('ImageDecoding', attrib={'memCap': '20000000'}),
947 ])
948 return elem
949
950 def _gen_encoder_profile(width, height, timelapse):
951 elem = etree.Element(
952 'EncoderProfile',
953 attrib={
954 'quality': ('timelapse' if timelapse else '') + str(height) + 'p',
955 'fileFormat': 'mp4',
956 'duration': '60',
957 })
958 elem.append(
959 etree.Element(
960 'Video',
961 attrib={
962 'codec': 'h264',
963 'bitRate': '8000000',
964 'width': str(width),
965 'height': str(height),
966 'frameRate': '30',
967 }))
968 elem.append(
969 etree.Element(
970 'Audio',
971 attrib={
972 'codec': 'aac',
973 'bitRate': '96000',
974 'sampleRate': '44100',
975 'channels': '1',
976 }))
977 return elem
978
979 def _gen_video_encoder_cap(name, min_bit_rate, max_bit_rate):
980 return etree.Element(
981 'VideoEncoderCap',
982 attrib={
983 'name': name,
984 'enabled': 'true',
985 'minBitRate': str(min_bit_rate),
986 'maxBitRate': str(max_bit_rate),
987 'minFrameWidth': '320',
988 'maxFrameWidth': '1920',
989 'minFrameHeight': '240',
990 'maxFrameHeight': '1080',
991 'minFrameRate': '15',
992 'maxFrameRate': '30',
993 })
994
995 def _gen_audio_encoder_cap(name, min_bit_rate, max_bit_rate, min_sample_rate,
996 max_sample_rate):
997 return etree.Element(
998 'AudioEncoderCap',
999 attrib={
1000 'name': name,
1001 'enabled': 'true',
1002 'minBitRate': str(min_bit_rate),
1003 'maxBitRate': str(max_bit_rate),
1004 'minSampleRate': str(min_sample_rate),
1005 'maxSampleRate': str(max_sample_rate),
1006 'minChannels': '1',
1007 'maxChannels': '1',
1008 })
1009
1010 camera_config = sw_config.camera_config
1011 if not camera_config.generate_media_profiles:
1012 return None
1013
1014 camera_pb = topology_pb2.HardwareFeatures.Camera
1015 root = etree.Element('MediaSettings')
1016 camera_id = 0
1017 for facing in [camera_pb.FACING_BACK, camera_pb.FACING_FRONT]:
1018 camera_device = next(
1019 (d for d in hw_features.camera.devices if d.facing == facing), None)
1020 if camera_device is None:
1021 continue
1022 if camera_config.camcorder_resolutions:
1023 resolutions = [
1024 (r.width, r.height) for r in camera_config.camcorder_resolutions
1025 ]
1026 else:
1027 resolutions = [(1280, 720)]
1028 if camera_device.flags & camera_pb.FLAGS_SUPPORT_1080P:
1029 resolutions.append((1920, 1080))
1030 root.append(_gen_camcorder_profiles(camera_id, resolutions))
1031 camera_id += 1
Ren-Pei Zengb55e4312020-11-18 17:03:01 +08001032 # media_profiles.xml should have at least one CamcorderProfiles.
1033 if camera_id == 0:
1034 return None
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001035
1036 root.extend([
1037 etree.Element('EncoderOutputFileFormat', attrib={'name': '3gp'}),
1038 etree.Element('EncoderOutputFileFormat', attrib={'name': 'mp4'}),
1039 _gen_video_encoder_cap('h264', 64000, 17000000),
1040 _gen_video_encoder_cap('h263', 64000, 1000000),
1041 _gen_video_encoder_cap('m4v', 64000, 2000000),
1042 _gen_audio_encoder_cap('aac', 758, 288000, 8000, 48000),
1043 _gen_audio_encoder_cap('heaac', 8000, 64000, 16000, 48000),
1044 _gen_audio_encoder_cap('aaceld', 16000, 192000, 16000, 48000),
1045 _gen_audio_encoder_cap('amrwb', 6600, 23050, 16000, 16000),
1046 _gen_audio_encoder_cap('amrnb', 5525, 12200, 8000, 8000),
1047 etree.Element(
1048 'VideoDecoderCap', attrib={
1049 'name': 'wmv',
1050 'enabled': 'false'
1051 }),
1052 etree.Element(
1053 'AudioDecoderCap', attrib={
1054 'name': 'wma',
1055 'enabled': 'false'
1056 }),
1057 ])
Ren-Pei Zeng21708cc2020-11-17 11:14:07 +08001058
1059 dtd_path = os.path.dirname(__file__)
1060 dtd = etree.DTD(os.path.join(dtd_path, 'media_profiles.dtd'))
1061 if not dtd.validate(root):
1062 raise etree.DTDValidateError(
1063 'Invalid media_profiles.xml generated:\n{}'.format(dtd.error_log))
1064
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001065 return XML_DECLARATION + etree.tostring(root, pretty_print=True)
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001066
1067
1068def _write_files_by_design_config(configs, output_dir, build_dir, system_dir,
1069 file_name_template, generate_file_content):
1070 """Writes generated files for each design config.
1071
1072 Args:
1073 configs: Source ConfigBundle to process.
1074 output_dir: Path to the generated output.
1075 build_dir: Path to the config file from portage's perspective.
1076 system_dir: Path to the config file in the target device.
1077 file_name_template: Template string of the config file name including one
1078 format()-style replacement field for the config id, e.g. 'config_{}.xml'.
1079 generate_file_content: Function to generate config file content from
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001080 HardwareFeatures and SoftwareConfig proto.
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001081 Returns:
1082 dict that maps the formatted config id to the correct file.
1083 """
1084 # pylint: disable=too-many-arguments,too-many-locals
C Shapiro5bf23a72020-04-24 11:40:17 -05001085 result = {}
C Shapiroea33cff2020-05-11 13:32:05 -05001086 configs_by_design = {}
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001087 for hw_design in configs.design_list:
C Shapiro5bf23a72020-04-24 11:40:17 -05001088 for design_config in hw_design.configs:
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001089 sw_config = _sw_config(configs.software_configs, design_config.id.value)
1090 config_content = generate_file_content(design_config.hardware_features,
1091 sw_config)
1092 if not config_content:
1093 continue
C Shapiroea33cff2020-05-11 13:32:05 -05001094 design_name = hw_design.name.lower()
C Shapiro5bf23a72020-04-24 11:40:17 -05001095
C Shapiroea33cff2020-05-11 13:32:05 -05001096 # Constructs the following map:
1097 # design_name -> config -> design_configs
1098 # This allows any of the following file naming schemes:
1099 # - All configs within a design share config (design_name prefix only)
1100 # - Nobody shares (full design_name and config id prefix needed)
1101 #
1102 # Having shared configs when possible makes code reviews easier around
1103 # the configs and makes debugging easier on the platform side.
C Shapiroea33cff2020-05-11 13:32:05 -05001104 arc_configs = configs_by_design.get(design_name, {})
1105 design_configs = arc_configs.get(config_content, [])
1106 design_configs.append(design_config)
1107 arc_configs[config_content] = design_configs
1108 configs_by_design[design_name] = arc_configs
C Shapiro9a3ac8c2020-04-25 07:49:21 -05001109
C Shapiroea33cff2020-05-11 13:32:05 -05001110 for design_name, unique_configs in configs_by_design.items():
1111 for file_content, design_configs in unique_configs.items():
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001112 file_name = file_name_template.format(design_name)
Andrew Lamb2413c982020-05-29 12:15:36 -06001113 if len(unique_configs) == 1:
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001114 _write_file(output_dir, file_name, file_content)
C Shapiro9a3ac8c2020-04-25 07:49:21 -05001115
Andrew Lamb2413c982020-05-29 12:15:36 -06001116 for design_config in design_configs:
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001117 config_id = _get_formatted_config_id(design_config)
Andrew Lamb2413c982020-05-29 12:15:36 -06001118 if len(unique_configs) > 1:
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001119 file_name = file_name_template.format(config_id)
1120 _write_file(output_dir, file_name, file_content)
1121 result[config_id] = _file_v2('{}/{}'.format(build_dir, file_name),
1122 '{}/{}'.format(system_dir, file_name))
C Shapiro5bf23a72020-04-24 11:40:17 -05001123 return result
1124
1125
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001126def _write_arc_hardware_feature_files(configs, output_root_dir, build_root_dir):
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001127 return _write_files_by_design_config(
1128 configs, output_root_dir + '/arc', build_root_dir + '/arc', '/etc',
1129 'hardware_features_{}.xml',
1130 lambda hw_features, _: _generate_arc_hardware_features(hw_features))
1131
1132
1133def _write_arc_media_profile_files(configs, output_root_dir, build_root_dir):
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001134 return _write_files_by_design_config(configs, output_root_dir + '/arc',
1135 build_root_dir + '/arc', '/etc',
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001136 'media_profiles_{}.xml',
1137 _generate_arc_media_profiles)
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001138
1139
Andrew Lambcd33f702020-06-11 10:45:16 -06001140def _read_config(path):
David Burgerd4f32962020-05-02 12:07:40 -06001141 """Reads a ConfigBundle proto from a json pb file.
David Burgere6f76222020-04-27 11:08:01 -06001142
1143 Args:
David Burgerd4f32962020-05-02 12:07:40 -06001144 path: Path to the file encoding the json pb proto.
David Burgere6f76222020-04-27 11:08:01 -06001145 """
1146 config = config_bundle_pb2.ConfigBundle()
1147 with open(path, 'r') as f:
1148 return json_format.Parse(f.read(), config)
1149
1150
Andrew Lambcd33f702020-06-11 10:45:16 -06001151def _merge_configs(configs):
David Burger7fd1dbe2020-03-26 09:26:55 -06001152 result = config_bundle_pb2.ConfigBundle()
1153 for config in configs:
1154 result.MergeFrom(config)
1155
1156 return result
1157
1158
David Burger1ba78a22020-06-18 18:42:47 -06001159def _camera_map(configs, project_name):
David Burger8ee9b4d2020-06-16 17:40:21 -06001160 """Produces a camera config map for the given configs.
1161
1162 Produces a map that maps from the design name to the camera config for that
1163 design.
1164
1165 Args:
1166 configs: Source ConfigBundle to process.
David Burger1ba78a22020-06-18 18:42:47 -06001167 project_name: Name of project processing for.
David Burger8ee9b4d2020-06-16 17:40:21 -06001168
1169 Returns:
1170 map from design name to camera config.
1171 """
1172 result = {}
Sean McAllisterf66887b2020-08-03 14:00:51 -06001173 for design in configs.design_list:
David Burger8ee9b4d2020-06-16 17:40:21 -06001174 design_name = design.name
David Burger0d9e8462020-06-19 14:12:37 -06001175 config_path = CAMERA_CONFIG_SOURCE_PATH_TEMPLATE.format(design_name.lower())
David Burger8ee9b4d2020-06-16 17:40:21 -06001176 if os.path.exists(config_path):
David Burger0d9e8462020-06-19 14:12:37 -06001177 destination = CAMERA_CONFIG_DEST_PATH_TEMPLATE.format(design_name.lower())
David Burger8ee9b4d2020-06-16 17:40:21 -06001178 result[design_name] = {
David Burger1ba78a22020-06-18 18:42:47 -06001179 'config-file':
1180 _file_v2(os.path.join(project_name, config_path), destination),
David Burger8ee9b4d2020-06-16 17:40:21 -06001181 }
1182 return result
1183
1184
David Burger52c9d322020-06-09 07:16:18 -06001185def _dptf_map(configs, project_name):
1186 """Produces a dptf map for the given configs.
1187
1188 Produces a map that maps from design name to the dptf file config for that
1189 design. It looks for the dptf files at:
David Burger2f0d9522020-07-30 10:52:28 -06001190 DPTF_PATH + '/' + DPTF_FILE
David Burger52c9d322020-06-09 07:16:18 -06001191 for a project wide config, that it maps under the empty string, and at:
David Burger2f0d9522020-07-30 10:52:28 -06001192 DPTF_PATH + '/' + design_name + '/' + DPTF_FILE
David Burger52c9d322020-06-09 07:16:18 -06001193 for design specific configs that it maps under the design name.
1194
1195 Args:
1196 configs: Source ConfigBundle to process.
1197 project_name: Name of project processing for.
1198
1199 Returns:
David Burger8ee9b4d2020-06-16 17:40:21 -06001200 map from design name or empty string (project wide), to dptf config.
David Burger52c9d322020-06-09 07:16:18 -06001201 """
1202 result = {}
David Burger52c9d322020-06-09 07:16:18 -06001203 # Looking at top level for project wide, and then for each design name
1204 # for design specific.
Sean McAllisterf66887b2020-08-03 14:00:51 -06001205 dirs = [""] + [d.name for d in configs.design_list]
David Burger52c9d322020-06-09 07:16:18 -06001206 for directory in dirs:
David Burgera2252762020-07-09 15:09:49 -06001207 design = directory.lower()
1208 if os.path.exists(os.path.join(DPTF_PATH, design, DPTF_FILE)):
David Burger2f0d9522020-07-30 10:52:28 -06001209 project_dptf_path = os.path.join(project_name, design, DPTF_FILE)
David Burger52c9d322020-06-09 07:16:18 -06001210 dptf_file = {
1211 'dptf-dv':
1212 project_dptf_path,
1213 'files': [
1214 _file(
David Burgera2252762020-07-09 15:09:49 -06001215 os.path.join(project_name, DPTF_PATH, design, DPTF_FILE),
David Burger52c9d322020-06-09 07:16:18 -06001216 os.path.join('/etc/dptf', project_dptf_path))
1217 ]
1218 }
1219 result[directory] = dptf_file
1220 return result
1221
1222
David Burgerceeb68a2020-09-03 11:31:10 -06001223def _wifi_sar_map(configs, project_name, output_dir, build_root_dir):
1224 """Constructs a map from design name to wifi sar config for that design.
1225
1226 Constructs a map from design name to the wifi sar config for that design.
1227 In the process a wifi sar hex file is generated that the config points at.
1228 This mapping is only made for the intel wifi where the generated file is
1229 provided when building coreboot.
1230
1231 Args:
1232 configs: Source ConfigBundle to process.
1233 project_name: Name of project processing for.
1234 output_dir: Path to the generated output.
Ren-Pei Zengc6ba15c2020-10-17 00:51:25 +08001235 build_root_dir: Path to the config file from portage's perspective.
David Burgerceeb68a2020-09-03 11:31:10 -06001236
1237 Returns:
1238 dict that maps the design name onto the wifi config for that design.
1239 """
1240 # pylint: disable=too-many-locals
1241 result = {}
1242 programs = {p.id.value: p for p in configs.program_list}
1243 sw_configs = list(configs.software_configs)
1244 for hw_design in configs.design_list:
1245 for hw_design_config in hw_design.configs:
1246 sw_config = _sw_config(sw_configs, hw_design_config.id.value)
1247 if sw_config.wifi_config.HasField('intel_config'):
1248 sar_file_content = _create_intel_sar_file_content(
1249 sw_config.wifi_config.intel_config)
1250 design_name = hw_design.name.lower()
1251 program = _lookup(hw_design.program_id, programs)
1252 wifi_sar_id = _extract_fw_config_value(hw_design_config, program,
1253 'Intel wifi sar id')
1254 output_path = os.path.join(output_dir, 'wifi')
1255 os.makedirs(output_path, exist_ok=True)
1256 filename = 'wifi_sar_{}.hex'.format(wifi_sar_id)
1257 output_path = os.path.join(output_path, filename)
1258 build_path = os.path.join(build_root_dir, 'wifi', filename)
1259 if os.path.exists(output_path):
1260 with open(output_path, 'r') as f:
1261 if f.read() != sar_file_content:
1262 raise Exception(
1263 'Project {} has conflicting wifi sar file content under '
1264 'wifi sar id {}.'.format(project_name, wifi_sar_id))
1265 else:
1266 with open(output_path, 'w') as f:
1267 f.write(sar_file_content)
1268 system_path = '/firmware/cbfs-rw-raw/{}/{}'.format(
1269 project_name, filename)
David Burger89e7cae2020-09-15 17:04:12 -06001270 result[design_name] = {'sar-file': _file_v2(build_path, system_path)}
David Burgerceeb68a2020-09-03 11:31:10 -06001271 return result
1272
1273
1274def _extract_fw_config_value(hw_design_config, program, name):
1275 """Extracts the firwmare config value with the given name.
1276
1277 Args:
1278 hw_design_config: Design extracting value from.
1279 program: Program the `hw_design_config` belongs to.
1280 name: Name of firmware config segment to extract.
1281
1282 Returns: the extracted value or raises a ValueError if no firmware
1283 configuration segment with `name` is found.
1284 """
1285 fw_config = hw_design_config.hardware_features.fw_config.value
1286 for fcs in program.firmware_configuration_segments:
1287 if fcs.name == name:
1288 value = fw_config & fcs.mask
1289 lsb_bit_set = (~fcs.mask + 1) & fcs.mask
1290 return value // lsb_bit_set
1291 raise ValueError(
1292 'No firmware configuration segment with name {} found'.format(name))
1293
1294
1295def _create_intel_sar_file_content(intel_config):
1296 """Creates and returns the intel sar file content for the given config.
1297
1298 Creates and returns the sar file content that is used with intel drivers
1299 only.
1300
1301 Args:
1302 intel_config: IntelConfig config.
1303
1304 Returns:
1305 sar file content for the given config, see:
1306 https://chromeos.google.com/partner/dlm/docs/connectivity/wifidyntxpower.html
1307 """
1308
1309 def to_hex(val):
1310 if val > 255 or val < 0:
1311 raise Exception('Sar file value %s out of range' % val)
1312 return '{0:0{1}X}'.format(val, 2)
1313
1314 def power_table(tpc):
1315 return (to_hex(tpc.limit_2g) + to_hex(tpc.limit_5g_1) +
1316 to_hex(tpc.limit_5g_2) + to_hex(tpc.limit_5g_3) +
1317 to_hex(tpc.limit_5g_4))
1318
1319 def wgds_value(wgds):
1320 return to_hex(wgds)
1321
1322 def offset_table(offsets):
1323 return (to_hex(offsets.max_2g) + to_hex(offsets.offset_2g_a) +
1324 to_hex(offsets.offset_2g_b) + to_hex(offsets.max_5g) +
1325 to_hex(offsets.offset_5g_a) + to_hex(offsets.offset_5g_b))
1326
1327 # See https://chromeos.google.com/partner/dlm/docs/connectivity/wifidyntxpower.html
1328 return (power_table(intel_config.tablet_mode_power_table_a) +
1329 power_table(intel_config.tablet_mode_power_table_b) +
1330 power_table(intel_config.non_tablet_mode_power_table_a) +
1331 power_table(intel_config.non_tablet_mode_power_table_b) +
1332 '00000000000000000000' + '00000000000000000000' +
1333 wgds_value(intel_config.wgds_version) +
1334 offset_table(intel_config.offset_fcc) +
1335 offset_table(intel_config.offset_eu) +
1336 offset_table(intel_config.offset_other))
1337
1338
Andrew Lambcd33f702020-06-11 10:45:16 -06001339def Main(project_configs, program_config, output): # pylint: disable=invalid-name
David Burger7fd1dbe2020-03-26 09:26:55 -06001340 """Transforms source proto config into platform JSON.
1341
1342 Args:
1343 project_configs: List of source project configs to transform.
1344 program_config: Program config for the given set of projects.
1345 output: Output file that will be generated by the transform.
1346 """
Andrew Lambcd33f702020-06-11 10:45:16 -06001347 configs = _merge_configs([_read_config(program_config)] +
1348 [_read_config(config) for config in project_configs])
C Shapiro2b6d5332020-05-06 17:51:35 -05001349 touch_fw = {}
David Burger8ee9b4d2020-06-16 17:40:21 -06001350 camera_map = {}
David Burgerceeb68a2020-09-03 11:31:10 -06001351 dptf_map = {}
1352 wifi_sar_map = {}
C Shapiro5bf23a72020-04-24 11:40:17 -05001353 output_dir = os.path.dirname(output)
C Shapiro5c877992020-04-29 12:11:28 -05001354 build_root_dir = output_dir
C Shapiro5c877992020-04-29 12:11:28 -05001355 if 'sw_build_config' in output_dir:
1356 full_path = os.path.realpath(output)
Andrew Lamb6b607732020-08-24 15:52:46 -06001357 project_name = re.match(r'.*/(\w*)/(public_)?sw_build_config/.*',
Andrew Lamb2413c982020-05-29 12:15:36 -06001358 full_path).groups(1)[0]
C Shapiro5c877992020-04-29 12:11:28 -05001359 # Projects don't know about each other until they are integrated into the
1360 # build system. When this happens, the files need to be able to co-exist
1361 # without any collisions. This prefixes the project name (which is how
1362 # portage maps in the project), so project files co-exist and can be
1363 # installed together.
1364 # This is necessary to allow projects to share files at the program level
1365 # without having portage file installation collisions.
1366 build_root_dir = os.path.join(project_name, output_dir)
C Shapiro6830e6c2020-04-29 13:29:56 -05001367
David Burger1ba78a22020-06-18 18:42:47 -06001368 camera_map = _camera_map(configs, project_name)
David Burger52c9d322020-06-09 07:16:18 -06001369 dptf_map = _dptf_map(configs, project_name)
David Burgerceeb68a2020-09-03 11:31:10 -06001370 wifi_sar_map = _wifi_sar_map(configs, project_name, output_dir,
1371 build_root_dir)
David Burger52c9d322020-06-09 07:16:18 -06001372
C Shapiro2b6d5332020-05-06 17:51:35 -05001373 if os.path.exists(TOUCH_PATH):
Andrew Lambcd33f702020-06-11 10:45:16 -06001374 touch_fw = _build_touch_file_config(configs, project_name)
Andrew Lambcd33f702020-06-11 10:45:16 -06001375 arc_hw_feature_files = _write_arc_hardware_feature_files(
1376 configs, output_dir, build_root_dir)
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001377 arc_media_profile_files = _write_arc_media_profile_files(
1378 configs, output_dir, build_root_dir)
C Shapiro5bf23a72020-04-24 11:40:17 -05001379 config_files = ConfigFiles(
C Shapiro5bf23a72020-04-24 11:40:17 -05001380 arc_hw_features=arc_hw_feature_files,
Ren-Pei Zengacf03be2020-11-11 13:56:51 +08001381 arc_media_profiles=arc_media_profile_files,
C Shapiro2b6d5332020-05-06 17:51:35 -05001382 touch_fw=touch_fw,
David Burger8ee9b4d2020-06-16 17:40:21 -06001383 dptf_map=dptf_map,
David Burgerceeb68a2020-09-03 11:31:10 -06001384 camera_map=camera_map,
1385 wifi_sar_map=wifi_sar_map)
Andrew Lambcd33f702020-06-11 10:45:16 -06001386 write_output(_transform_build_configs(configs, config_files), output)
David Burger7fd1dbe2020-03-26 09:26:55 -06001387
1388
1389def main(argv=None):
1390 """Main program which parses args and runs
1391
1392 Args:
1393 argv: List of command line arguments, if None uses sys.argv.
1394 """
1395 if argv is None:
1396 argv = sys.argv[1:]
Andrew Lambcd33f702020-06-11 10:45:16 -06001397 opts = parse_args(argv)
David Burger7fd1dbe2020-03-26 09:26:55 -06001398 Main(opts.project_configs, opts.program_config, opts.output)
1399
1400
1401if __name__ == '__main__':
1402 sys.exit(main(sys.argv[1:]))