blob: 955717351dc718e80f20dca0743f88c43a747b38 [file] [log] [blame]
Jett Rink17ed0f52020-09-25 17:14:31 -06001# -*- coding: utf-8 -*-
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
LaMont Jonesed9a5de2021-02-03 11:06:12 -07005
Jett Rink17ed0f52020-09-25 17:14:31 -06006"""Firmware builder controller.
7
LaMont Jonesdec69ad2021-01-27 13:02:00 -07008Handle all firmware builder related functionality. Currently no service module
9exists: all of the work is done here.
Jett Rink17ed0f52020-09-25 17:14:31 -060010"""
11
12import os
13import tempfile
14
15from google.protobuf import json_format
16
17from chromite.api import controller
18from chromite.api import faux
19from chromite.api import validate
20from chromite.api.gen.chromite.api import firmware_pb2
LaMont Jonesdec69ad2021-01-27 13:02:00 -070021from chromite.api.gen.chromiumos import common_pb2
Jett Rink17ed0f52020-09-25 17:14:31 -060022from chromite.lib import constants
23from chromite.lib import cros_build_lib
LaMont Jonesed9a5de2021-02-03 11:06:12 -070024from chromite.lib import osutils
25
Jett Rink17ed0f52020-09-25 17:14:31 -060026
LaMont Jonesdec69ad2021-01-27 13:02:00 -070027def _call_entry(fw_loc, metric_proto, subcmd, **kwargs):
Jett Rink17ed0f52020-09-25 17:14:31 -060028 """Calls into firmware_builder.py with the specified subcmd."""
29
LaMont Jonesdec69ad2021-01-27 13:02:00 -070030 if fw_loc == common_pb2.PLATFORM_EC:
Jett Rink17ed0f52020-09-25 17:14:31 -060031 fw_path = 'src/platform/ec/'
LaMont Jonesdec69ad2021-01-27 13:02:00 -070032 elif fw_loc == common_pb2.PLATFORM_ZEPHYR:
Jett Rink17ed0f52020-09-25 17:14:31 -060033 fw_path = 'src/platform/zephyr-chrome/'
LaMont Jonesdec69ad2021-01-27 13:02:00 -070034 elif fw_loc == common_pb2.PLATFORM_TI50:
Andrew Luo60439f32021-01-26 15:19:28 -080035 fw_path = 'src/platform/ti50/common/'
Jett Rink17ed0f52020-09-25 17:14:31 -060036 else:
LaMont Jonesdec69ad2021-01-27 13:02:00 -070037 cros_build_lib.Die(f'Unknown firmware location {fw_loc}.')
Jett Rink17ed0f52020-09-25 17:14:31 -060038
LaMont Jonesed9a5de2021-02-03 11:06:12 -070039 entry_point = os.path.join(constants.SOURCE_ROOT, fw_path,
40 'firmware_builder.py')
Jett Rink17ed0f52020-09-25 17:14:31 -060041
LaMont Jonesdec69ad2021-01-27 13:02:00 -070042 with tempfile.NamedTemporaryFile() as tmpfile:
LaMont Jonesed9a5de2021-02-03 11:06:12 -070043 cmd = [entry_point, '--metrics', tmpfile.name]
LaMont Jonesdec69ad2021-01-27 13:02:00 -070044 for key, value in kwargs.items():
45 cmd += [f'--{key.replace("_", "-")}', value]
LaMont Jonesed9a5de2021-02-03 11:06:12 -070046 cmd += [subcmd]
LaMont Jonesdec69ad2021-01-27 13:02:00 -070047
48 result = cros_build_lib.run(cmd, check=False)
49 with open(tmpfile.name, 'r') as f:
Jett Rink17ed0f52020-09-25 17:14:31 -060050 response = f.read()
51
LaMont Jonesed9a5de2021-02-03 11:06:12 -070052 if metric_proto:
53 # Parse the entire metric file as our metric proto (as a passthru).
54 # TODO(b/177907747): BundleFirmwareArtifacts doesn't use this (yet?), but
55 # firmware_builder.py requires it.
56 json_format.Parse(response, metric_proto)
Jett Rink17ed0f52020-09-25 17:14:31 -060057
58 if result.returncode == 0:
59 return controller.RETURN_CODE_SUCCESS
60 else:
61 return controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY
62
63
64def _BuildAllTotFirmwareResponse(_input_proto, output_proto, _config):
LaMont Jonesdec69ad2021-01-27 13:02:00 -070065 """Add a fw region metric to a successful response."""
Jett Rink17ed0f52020-09-25 17:14:31 -060066
67 metric = output_proto.success.value.add()
68 metric.target_name = 'foo'
69 metric.platform_name = 'bar'
70 fw_section = metric.fw_section.add()
71 fw_section.region = firmware_pb2.FwBuildMetric.FwSection.EC_RO
72 fw_section.used = 100
73 fw_section.total = 150
74
LaMont Jonesed9a5de2021-02-03 11:06:12 -070075
Jett Rink17ed0f52020-09-25 17:14:31 -060076@faux.success(_BuildAllTotFirmwareResponse)
77@faux.empty_completed_unsuccessfully_error
78@validate.require('firmware_location')
79@validate.validation_complete
80def BuildAllTotFirmware(input_proto, output_proto, _config):
81 """Build all of the firmware targets at the specified location."""
82
83 return _call_entry(input_proto.firmware_location, output_proto.metrics,
84 'build')
85
86
87def _TestAllTotFirmwareResponse(_input_proto, output_proto, _config):
LaMont Jonesdec69ad2021-01-27 13:02:00 -070088 """Add a fw region metric to a successful response."""
Jett Rink17ed0f52020-09-25 17:14:31 -060089
90 metric = output_proto.success.value.add()
91 metric.name = 'foo-test'
92
LaMont Jonesed9a5de2021-02-03 11:06:12 -070093
Jett Rink17ed0f52020-09-25 17:14:31 -060094@faux.success(_TestAllTotFirmwareResponse)
95@faux.empty_completed_unsuccessfully_error
96@validate.require('firmware_location')
97@validate.validation_complete
98def TestAllTotFirmware(input_proto, output_proto, _config):
99 """Runs all of the firmware tests at the specified location."""
100
101 return _call_entry(input_proto.firmware_location, output_proto.metrics,
102 'test')
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700103
104
105def _BuildAllFirmwareResponse(_input_proto, output_proto, _config):
106 """Add a fw region metric to a successful response."""
107
108 metric = output_proto.success.value.add()
109 metric.target_name = 'foo'
110 metric.platform_name = 'bar'
111 fw_section = metric.fw_section.add()
112 fw_section.region = firmware_pb2.FwBuildMetric.FwSection.EC_RO
113 fw_section.used = 100
114 fw_section.total = 150
115
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700116
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700117@faux.success(_BuildAllFirmwareResponse)
118@faux.empty_completed_unsuccessfully_error
119@validate.require('firmware_location')
120@validate.validation_complete
121def BuildAllFirmware(input_proto, output_proto, _config):
122 """Build all of the firmware targets at the specified location."""
123
124 return _call_entry(input_proto.firmware_location, output_proto.metrics,
125 'build')
126
127
128def _TestAllFirmwareResponse(_input_proto, output_proto, _config):
129 """Add a fw region metric to a successful response."""
130
131 metric = output_proto.success.value.add()
132 metric.name = 'foo-test'
133
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700134
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700135@faux.success(_TestAllFirmwareResponse)
136@faux.empty_completed_unsuccessfully_error
137@validate.require('firmware_location')
138@validate.validation_complete
139def TestAllFirmware(input_proto, output_proto, _config):
140 """Runs all of the firmware tests at the specified location."""
141
142 return _call_entry(input_proto.firmware_location, output_proto.metrics,
143 'test')
144
145
146def _BundleFirmwareArtifactsResponse(_input_proto, output_proto, _config):
147 """Add a fw region metric to a successful response."""
148
149 metric = output_proto.success.value.add()
150 metric.name = 'foo-test'
151
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700152
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700153@faux.success(_BundleFirmwareArtifactsResponse)
154@faux.empty_completed_unsuccessfully_error
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700155@validate.validation_complete
156def BundleFirmwareArtifacts(input_proto, output_proto, _config):
157 """Runs all of the firmware tests at the specified location."""
158
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700159 if len(input_proto.artifacts.output_artifacts) > 1:
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700160 raise ValueError('Must have exactly one output_artifact')
161
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700162 with osutils.TempDir(delete=False) as tmpdir:
163 info = input_proto.artifacts.output_artifacts[0]
164 metadata_path = os.path.join(tmpdir, 'firmware_metadata.jsonpb')
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700165 resp = _call_entry(
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700166 info.location,
167 None,
168 'bundle',
169 output_dir=tmpdir,
170 metadata=metadata_path)
171 if input_proto.artifacts.FIRMWARE_TARBALL in info.artifact_types:
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700172 # TODO(b/177907747): gather the paths from the response and add them to
173 # out.paths.
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700174 out = output_proto.artifacts.artifacts.add(
175 artifact_type=input_proto.artifacts.FIRMWARE_TARBALL, paths=[])
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700176 out.location = info.location
LaMont Jonesed9a5de2021-02-03 11:06:12 -0700177 if (input_proto.artifacts.FIRMWARE_TARBALL_INFO in info.artifact_types and
178 os.path.exists(metadata_path)):
179 out = output_proto.artifacts.artifacts.add(
180 artifact_type=input_proto.artifacts.FIRMWARE_TARBALL_INFO,
181 paths=[
182 common_pb2.Path(
183 path=metadata_path, location=common_pb2.Path.INSIDE)
184 ])
LaMont Jonesdec69ad2021-01-27 13:02:00 -0700185 return resp