blob: 02300d4f32362f056e16fa954509b5513aee51b4 [file]
// 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