blob: cc8e5e014ccd7f9bcdd1a08ab570a0e843be4b51 [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.
5"""Firmware builder controller.
6
LaMont Jonesdec69ad2021-01-27 13:02:00 -07007Handle all firmware builder related functionality. Currently no service module
8exists: all of the work is done here.
Jett Rink17ed0f52020-09-25 17:14:31 -06009"""
10
11import os
12import tempfile
13
14from google.protobuf import json_format
15
16from chromite.api import controller
17from chromite.api import faux
18from chromite.api import validate
19from chromite.api.gen.chromite.api import firmware_pb2
LaMont Jonesdec69ad2021-01-27 13:02:00 -070020from chromite.api.gen.chromiumos import common_pb2
Jett Rink17ed0f52020-09-25 17:14:31 -060021from chromite.lib import constants
22from chromite.lib import cros_build_lib
23
LaMont Jonesdec69ad2021-01-27 13:02:00 -070024def _call_entry(fw_loc, metric_proto, subcmd, **kwargs):
Jett Rink17ed0f52020-09-25 17:14:31 -060025 """Calls into firmware_builder.py with the specified subcmd."""
26
LaMont Jonesdec69ad2021-01-27 13:02:00 -070027 if fw_loc == common_pb2.PLATFORM_EC:
Jett Rink17ed0f52020-09-25 17:14:31 -060028 fw_path = 'src/platform/ec/'
LaMont Jonesdec69ad2021-01-27 13:02:00 -070029 elif fw_loc == common_pb2.PLATFORM_ZEPHYR:
Jett Rink17ed0f52020-09-25 17:14:31 -060030 fw_path = 'src/platform/zephyr-chrome/'
LaMont Jonesdec69ad2021-01-27 13:02:00 -070031 elif fw_loc == common_pb2.PLATFORM_TI50:
Andrew Luo60439f32021-01-26 15:19:28 -080032 fw_path = 'src/platform/ti50/common/'
Jett Rink17ed0f52020-09-25 17:14:31 -060033 else:
LaMont Jonesdec69ad2021-01-27 13:02:00 -070034 cros_build_lib.Die(f'Unknown firmware location {fw_loc}.')
Jett Rink17ed0f52020-09-25 17:14:31 -060035
36 entry_point = os.path.join(constants.SOURCE_ROOT,
37 fw_path, 'firmware_builder.py')
38
LaMont Jonesdec69ad2021-01-27 13:02:00 -070039 with tempfile.NamedTemporaryFile() as tmpfile:
40 cmd = [entry_point, '--metrics', tmpfile.name, subcmd]
41 for key, value in kwargs.items():
42 cmd += [f'--{key.replace("_", "-")}', value]
43
44 result = cros_build_lib.run(cmd, check=False)
45 with open(tmpfile.name, 'r') as f:
Jett Rink17ed0f52020-09-25 17:14:31 -060046 response = f.read()
47
48 # Parse the entire metric file as our metric proto (as a passthru)
49 json_format.Parse(response, metric_proto)
50
51 if result.returncode == 0:
52 return controller.RETURN_CODE_SUCCESS
53 else:
54 return controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY
55
56
57def _BuildAllTotFirmwareResponse(_input_proto, output_proto, _config):
LaMont Jonesdec69ad2021-01-27 13:02:00 -070058 """Add a fw region metric to a successful response."""
Jett Rink17ed0f52020-09-25 17:14:31 -060059
60 metric = output_proto.success.value.add()
61 metric.target_name = 'foo'
62 metric.platform_name = 'bar'
63 fw_section = metric.fw_section.add()
64 fw_section.region = firmware_pb2.FwBuildMetric.FwSection.EC_RO
65 fw_section.used = 100
66 fw_section.total = 150
67
68@faux.success(_BuildAllTotFirmwareResponse)
69@faux.empty_completed_unsuccessfully_error
70@validate.require('firmware_location')
71@validate.validation_complete
72def BuildAllTotFirmware(input_proto, output_proto, _config):
73 """Build all of the firmware targets at the specified location."""
74
75 return _call_entry(input_proto.firmware_location, output_proto.metrics,
76 'build')
77
78
79def _TestAllTotFirmwareResponse(_input_proto, output_proto, _config):
LaMont Jonesdec69ad2021-01-27 13:02:00 -070080 """Add a fw region metric to a successful response."""
Jett Rink17ed0f52020-09-25 17:14:31 -060081
82 metric = output_proto.success.value.add()
83 metric.name = 'foo-test'
84
85@faux.success(_TestAllTotFirmwareResponse)
86@faux.empty_completed_unsuccessfully_error
87@validate.require('firmware_location')
88@validate.validation_complete
89def TestAllTotFirmware(input_proto, output_proto, _config):
90 """Runs all of the firmware tests at the specified location."""
91
92 return _call_entry(input_proto.firmware_location, output_proto.metrics,
93 'test')
LaMont Jonesdec69ad2021-01-27 13:02:00 -070094
95
96def _BuildAllFirmwareResponse(_input_proto, output_proto, _config):
97 """Add a fw region metric to a successful response."""
98
99 metric = output_proto.success.value.add()
100 metric.target_name = 'foo'
101 metric.platform_name = 'bar'
102 fw_section = metric.fw_section.add()
103 fw_section.region = firmware_pb2.FwBuildMetric.FwSection.EC_RO
104 fw_section.used = 100
105 fw_section.total = 150
106
107@faux.success(_BuildAllFirmwareResponse)
108@faux.empty_completed_unsuccessfully_error
109@validate.require('firmware_location')
110@validate.validation_complete
111def BuildAllFirmware(input_proto, output_proto, _config):
112 """Build all of the firmware targets at the specified location."""
113
114 return _call_entry(input_proto.firmware_location, output_proto.metrics,
115 'build')
116
117
118def _TestAllFirmwareResponse(_input_proto, output_proto, _config):
119 """Add a fw region metric to a successful response."""
120
121 metric = output_proto.success.value.add()
122 metric.name = 'foo-test'
123
124@faux.success(_TestAllFirmwareResponse)
125@faux.empty_completed_unsuccessfully_error
126@validate.require('firmware_location')
127@validate.validation_complete
128def TestAllFirmware(input_proto, output_proto, _config):
129 """Runs all of the firmware tests at the specified location."""
130
131 return _call_entry(input_proto.firmware_location, output_proto.metrics,
132 'test')
133
134
135def _BundleFirmwareArtifactsResponse(_input_proto, output_proto, _config):
136 """Add a fw region metric to a successful response."""
137
138 metric = output_proto.success.value.add()
139 metric.name = 'foo-test'
140
141@faux.success(_BundleFirmwareArtifactsResponse)
142@faux.empty_completed_unsuccessfully_error
143@validate.require('firmware_location')
144@validate.validation_complete
145def BundleFirmwareArtifacts(input_proto, output_proto, _config):
146 """Runs all of the firmware tests at the specified location."""
147
148 if len(input_proto.output_artifacts) > 1:
149 raise ValueError('Must have exactly one output_artifact')
150
151 with tempfile.NamedTemporaryFile() as meta:
152 info = input_proto.output_artifacts[0]
153 metadata_path = os.path.join(input_proto.result_path.path, meta.name)
154 resp = _call_entry(
155 info.location, output_proto.metrics, 'bundle',
156 output_dir=input_proto.result_path.path, metadata=metadata_path)
157 if common_pb2.FIRMWARE_TARBALL in info.artifact_types:
158 out = output_proto.artifacts.add()
159 out.artifact_types.append(common_pb2.FIRMWARE_TARBALL)
160 # TODO(b/177907747): gather the paths from the response and add them to
161 # out.paths.
162 out.location = info.location
163 if common_pb2.FIRMWARE_TARBALL_INFO in info.artifact_types:
164 out = output_proto.artifacts.add()
165 out.artifact_types.append(common_pb2.FIRMWARE_TARBALL_INFO)
166 out.paths.append(
167 common_pb2.Path(metadata_path, input_proto.result_path.path.location))
168 return resp