blob: f84ab85674398edb8e9de657fa357c4efc717b5d [file] [log] [blame]
Gwendal Grignouf9533dd2023-06-08 04:31:471// Copyright 2023 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Yong Hongb3c83572024-12-10 02:23:525#include "libsegmentation/feature_management_hwid.h"
6
Gwendal Grignouf9533dd2023-06-08 04:31:477#include <optional>
8
9#include <base/logging.h>
Allen Shih87ce1a12025-04-17 05:22:3410#include <brillo/hwid/hwid_utils.h>
Gwendal Grignouf9533dd2023-06-08 04:31:4711
12#include "libsegmentation/device_info.pb.h"
Gwendal Grignouf9533dd2023-06-08 04:31:4713#include "libsegmentation/feature_management_interface.h"
14#include "libsegmentation/feature_management_util.h"
15
16namespace segmentation {
17
18using chromiumos::feature_management::api::software::DeviceSelection;
19using chromiumos::feature_management::api::software::SelectionBundle;
20
21std::optional<DeviceSelection> FeatureManagementHwid::GetSelectionFromHWID(
22 const SelectionBundle& selection_bundle_,
23 const std::string& user_readable_hwid,
24 bool check_prefix_only) {
25 const std::optional<std::string> hwid =
Allen Shih87ce1a12025-04-17 05:22:3426 brillo::hwid::DecodeHWID(user_readable_hwid);
George Burgess IV3f504202024-11-06 16:26:4327 if (!hwid) {
Gwendal Grignouf9533dd2023-06-08 04:31:4728 return std::nullopt;
George Burgess IV3f504202024-11-06 16:26:4329 }
Gwendal Grignouf9533dd2023-06-08 04:31:4730 for (const auto& selection : selection_bundle_.selections()) {
31 for (const auto& hwid_profile : selection.hwid_profiles()) {
32 // Look into the database for a prefix match.
33 bool prefix_match = false;
34 for (const auto& prefix : hwid_profile.prefixes()) {
35 if (user_readable_hwid.rfind(prefix, 0) == 0) {
36 prefix_match = true;
37 break;
38 }
39 }
George Burgess IV3f504202024-11-06 16:26:4340 if (!prefix_match) {
Gwendal Grignouf9533dd2023-06-08 04:31:4741 continue;
George Burgess IV3f504202024-11-06 16:26:4342 }
43 if (check_prefix_only) {
Gwendal Grignouf9533dd2023-06-08 04:31:4744 return selection;
George Burgess IV3f504202024-11-06 16:26:4345 }
Gwendal Grignouf9533dd2023-06-08 04:31:4746
47 bool all_requirement_met = true;
48 for (const auto& requirement : hwid_profile.encoding_requirements()) {
49 std::string bit_value = "";
50 for (auto bit_location : requirement.bit_locations()) {
51 bit_value.append(1, bit_location < hwid.value().size()
52 ? hwid.value()[bit_location]
53 : '0');
54 }
55 bool pattern_found = false;
56 for (auto required_value : requirement.required_values()) {
57 if (bit_value == required_value) {
58 pattern_found = true;
59 break;
60 }
61 }
62 if (!pattern_found) {
63 all_requirement_met = false;
64 break;
65 }
66 }
67 if (all_requirement_met) {
68 return selection;
69 }
70 }
71 }
72 return std::nullopt;
73}
74
75libsegmentation::DeviceInfo_FeatureLevel HwComplianceVersionToFeatureLevel(
76 int32_t hw_compliance_version) {
77 switch (hw_compliance_version) {
78 case 0:
79 return libsegmentation::DeviceInfo_FeatureLevel::
80 DeviceInfo_FeatureLevel_FEATURE_LEVEL_0;
81 case 1:
82 return libsegmentation::DeviceInfo_FeatureLevel::
83 DeviceInfo_FeatureLevel_FEATURE_LEVEL_1;
Yong Hongb3c83572024-12-10 02:23:5284 case 2:
85 return libsegmentation::DeviceInfo_FeatureLevel::
86 DeviceInfo_FeatureLevel_FEATURE_LEVEL_2;
Gwendal Grignouf9533dd2023-06-08 04:31:4787 default:
88 return libsegmentation::DeviceInfo_FeatureLevel::
89 DeviceInfo_FeatureLevel_FEATURE_LEVEL_UNKNOWN;
90 }
91}
92
93libsegmentation::DeviceInfo_ScopeLevel HwComplianceVersionToScopeLevel(
94 bool is_chassis_x_branded) {
George Burgess IV3f504202024-11-06 16:26:4395 if (is_chassis_x_branded) {
Gwendal Grignouf9533dd2023-06-08 04:31:4796 return libsegmentation::DeviceInfo_ScopeLevel::
97 DeviceInfo_ScopeLevel_SCOPE_LEVEL_1;
George Burgess IV3f504202024-11-06 16:26:4398 }
Gwendal Grignouf9533dd2023-06-08 04:31:4799
100 return libsegmentation::DeviceInfo_ScopeLevel::
101 DeviceInfo_ScopeLevel_SCOPE_LEVEL_0;
102}
103
104libsegmentation::DeviceInfo FeatureManagementHwid::GetDeviceInfo(
105 FeatureManagementHwid::GetDeviceSelectionFn get_selection,
106 bool is_chassis_x_branded,
107 int32_t hw_compliance_version) {
108 libsegmentation::DeviceInfo device_info_result;
109
110 // Implementing decision tree from go/cros-tiering-dd.
111 if (is_chassis_x_branded || hw_compliance_version > 0) {
112 if (is_chassis_x_branded) {
113 device_info_result.set_feature_level(
114 HwComplianceVersionToFeatureLevel(hw_compliance_version));
115 device_info_result.set_scope_level(HwComplianceVersionToScopeLevel(true));
116 } else {
Gwendal Grignoudc011ea2023-07-25 00:36:27117 if (get_selection(/* check_prefix_only */ true)) {
Gwendal Grignouf9533dd2023-06-08 04:31:47118 device_info_result.set_feature_level(
119 HwComplianceVersionToFeatureLevel(hw_compliance_version));
120 } else {
121 device_info_result.set_feature_level(
122 libsegmentation::DeviceInfo_FeatureLevel::
123 DeviceInfo_FeatureLevel_FEATURE_LEVEL_0);
124 }
125 device_info_result.set_scope_level(
126 HwComplianceVersionToScopeLevel(false));
127 }
128 } else {
Gwendal Grignoudc011ea2023-07-25 00:36:27129 std::optional<DeviceSelection> selection =
130 get_selection(/* check_prefix_only */ false);
Gwendal Grignouf9533dd2023-06-08 04:31:47131 if (selection) {
132 device_info_result.set_feature_level(
133 HwComplianceVersionToFeatureLevel(selection->feature_level()));
134 } else {
135 device_info_result.set_feature_level(
136 libsegmentation::DeviceInfo_FeatureLevel::
137 DeviceInfo_FeatureLevel_FEATURE_LEVEL_0);
138 }
139 device_info_result.set_scope_level(HwComplianceVersionToScopeLevel(false));
140 }
141 return device_info_result;
142}
143
144} // namespace segmentation