| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "asset.hpp" |
| |
| #include "google3/host_commands.h" |
| |
| #include "ec_util_interface.hpp" |
| #include "message_util.hpp" |
| |
| #include <stdplus/print.hpp> |
| #include <stdplus/raw.hpp> |
| #include <xyz/openbmc_project/Control/Hoth/error.hpp> |
| |
| #include <array> |
| #include <cctype> |
| #include <cstdint> |
| #include <format> |
| #include <string> |
| #include <type_traits> |
| #include <unordered_map> |
| #include <variant> |
| #include <vector> |
| |
| namespace google |
| { |
| namespace hoth |
| { |
| |
| using internal::EcUtil; |
| |
| constexpr std::string_view kFieldUnknown = "unknown"; |
| |
| constexpr std::string_view kProductNameH1B1P = "H1B1P"; |
| constexpr std::string_view kProductNameH1B2P = "H1B2P"; |
| constexpr std::string_view kProductNameH1B3P = "H1B3P"; |
| constexpr std::string_view kProductNameH1D3P = "H1D3P"; |
| constexpr std::string_view kProductNameTI02 = "TI02"; |
| constexpr std::string_view kProductNameTI03 = "TI03"; |
| |
| constexpr std::string_view kPartNumberH1B1P = "07133954"; |
| constexpr std::string_view kPartNumberH1B2P = "07138244"; |
| constexpr std::string_view kPartNumberH1B3P = "1059594"; |
| constexpr std::string_view kPartNumberH1D3P = "1100336"; |
| constexpr std::string_view kPartNumberTI02 = "1250620"; |
| constexpr std::string_view kPartNumberTI03 = "1229354"; |
| |
| constexpr std::string_view kManufacturerGoogle = "Google"; |
| constexpr std::string_view kManufacturerNuvoton = "Nuvoton"; |
| constexpr std::string_view kModel = "Titan"; |
| |
| Asset::Asset(sdbusplus::bus::bus& bus, const std::string& objPath, |
| const std::string& boardPath, EcUtil* ecUtil) : |
| AssetAssociationObject(bus, objPath.c_str(), |
| AssetAssociationObject::action::defer_emit) |
| { |
| HothChipAssetInfo info = get_hoth_chip_asset_info(*ecUtil); |
| |
| /* Set Crypta Properties */ |
| partNumber(std::string(info.chip_part_number), true); |
| subModel(std::string(info.chip_revision), true); |
| serialNumber(info.chip_serial_number, true); |
| manufacturer(std::string(info.chip_manufacturer), true); |
| model(std::string(kModel), true); |
| |
| /* Set association with chassis/board object that contains the hoth */ |
| associations({std::make_tuple("chassis", "assembly", boardPath)}, true); |
| |
| AssetAssociationObject::emit_object_added(); |
| } |
| |
| // Copied from |
| // [libhoth](https://github.com/google/libhoth/blob/2dafddeafb62b84d3d7731a6014afeac13e84c0a/protocol/chipinfo.c#L58-L90) |
| // and modified |
| static opentitan_device_id parse_opentitan_device_id( |
| const std::array<uint8_t, kOtDeviceIdLenInBytes>& src) |
| { |
| opentitan_device_id dst; |
| |
| dst.creator_id = (uint16_t)(src[31]) | (src[30] << 8); |
| dst.product_id = (uint16_t)(src[29]) | (src[28] << 8); |
| dst.device_year = 2020 + (src[27] & 0x0F); |
| dst.device_week = (src[26] & 0x0F) * 10 + (src[27] >> 4); |
| dst.lot_number = |
| (src[25] >> 4) * 100 + (src[25] & 0x0F) * 10 + (src[26] >> 4); |
| dst.wafer_number = (src[24] >> 4) * 10 + (src[24] & 0x0F); |
| dst.wafer_x = (src[22] & 0x0F) * 100 + (src[23] >> 4) * 10 + |
| (src[23] & 0x0F); |
| dst.wafer_y = (src[21] >> 4) * 100 + (src[21] & 0x0F) * 10 + (src[22] >> 4); |
| dst.reserved_din = src[20]; |
| dst.reserved = (static_cast<uint32_t>(src[16]) << 24) | (src[17] << 16) | |
| (src[18] << 8) | src[19]; |
| dst.package_id = src[15]; |
| dst.ast_config_version = src[14]; |
| for (size_t i = 0; i < 2; i++) |
| { |
| if (std::isprint(src[i + 12])) |
| { |
| dst.otp_id[i] = static_cast<char>(src[i + 12]); |
| } |
| else |
| { |
| dst.otp_id[i] = '?'; |
| } |
| } |
| dst.otp_id[2] = '\0'; |
| dst.otp_version = src[11]; |
| for (size_t i = 0; i < 4; i++) |
| { |
| if (std::isprint(src[i + 4])) |
| { |
| dst.sku_id_string[i] = static_cast<char>(src[i + 4]); |
| } |
| else |
| { |
| dst.sku_id_string[i] = '?'; |
| } |
| } |
| dst.sku_id_string[4] = '\0'; |
| dst.sku_specific_version = src[0]; |
| |
| return dst; |
| } |
| |
| HothChipAssetInfo get_hoth_chip_asset_info(EcUtil& ec_util) |
| { |
| const auto chip_info = ec_util.getHothChipInfo(); |
| |
| return std::visit( |
| [](auto&& arg) { |
| HothChipAssetInfo info = { |
| .chip_serial_number = std::string(kFieldUnknown), |
| .chip_part_number = kFieldUnknown, |
| .chip_revision = kFieldUnknown, |
| .chip_manufacturer = kFieldUnknown, |
| }; |
| using T = std::decay_t<decltype(arg)>; |
| if constexpr (std::is_same_v<T, ec_response_chip_info>) |
| { |
| info.chip_manufacturer = kManufacturerGoogle; |
| |
| info.chip_serial_number = std::format( |
| "{}-{:016x}", static_cast<uint16_t>(arg.hardware_category), |
| static_cast<uint64_t>(arg.hardware_identity)); |
| |
| if (arg.hardware_category == 4) |
| { |
| info.chip_revision = kProductNameH1D3P; |
| info.chip_part_number = kPartNumberH1D3P; |
| } |
| else if ((arg.hardware_category == 1) && |
| (arg.info_variant == 1)) |
| { |
| info.chip_revision = kProductNameH1B3P; |
| info.chip_part_number = kPartNumberH1B3P; |
| } |
| else if (arg.hardware_category == 1) |
| { |
| info.chip_revision = kProductNameH1B2P; |
| info.chip_part_number = kPartNumberH1B2P; |
| } |
| else if (arg.hardware_category == 0) |
| { |
| info.chip_revision = kProductNameH1B1P; |
| info.chip_part_number = kPartNumberH1B1P; |
| } |
| return info; |
| } |
| else if constexpr (std::is_same_v< |
| T, |
| std::array<uint8_t, kOtDeviceIdLenInBytes>>) |
| { |
| info.chip_manufacturer = kManufacturerNuvoton; |
| info.chip_serial_number.clear(); |
| info.chip_serial_number.reserve(2 * kOtDeviceIdLenInBytes); |
| constexpr std::array<char, 16> hex_chars{ |
| '0', '1', '2', '3', '4', '5', '6', '7', |
| '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| for (const auto byte : arg) |
| { |
| info.chip_serial_number.push_back( |
| hex_chars[(byte >> 4) & 0x0F]); |
| info.chip_serial_number.push_back(hex_chars[(byte & 0x0F)]); |
| } |
| |
| constexpr std::string_view kTi02SkuStr = "TI02"; |
| constexpr std::string_view kTi03SkuStr = "TI03"; |
| const opentitan_device_id parsed_device_id = |
| parse_opentitan_device_id(arg); |
| if (parsed_device_id.sku_id_string == kTi03SkuStr) |
| { |
| info.chip_revision = kProductNameTI03; |
| info.chip_part_number = kPartNumberTI03; |
| } |
| else if (parsed_device_id.sku_id_string == kTi02SkuStr) |
| { |
| info.chip_revision = kProductNameTI02; |
| info.chip_part_number = kPartNumberTI02; |
| } |
| return info; |
| } |
| else |
| { |
| static_assert(false, "Unhandled variant for chip info"); |
| // Unreachable. Here to make the compiler happy |
| return info; |
| } |
| }, |
| chip_info); |
| } |
| |
| } // namespace hoth |
| |
| } // namespace google |