blob: 1171b198cee53301e917bb51943151961b368066 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rmad/utils/vpd_utils_impl.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/check.h>
#include <base/strings/string_number_conversions.h>
#include <base/logging.h>
#include "rmad/utils/cmd_utils_impl.h"
namespace {
const char kVpdCmdPath[] = "/usr/sbin/vpd";
constexpr char kVpdKeySerialNumber[] = "serial_number";
constexpr char kVpdKeyWhitelabelTag[] = "whitelabel_tag";
constexpr char kVpdKeyRegion[] = "region";
constexpr char kVpdKeyUbindAttribute[] = "ubind_attribute";
constexpr char kVpdKeyGbindAttribute[] = "gbind_attribute";
constexpr char kVpdKeyStableDeviceSecret[] =
"stable_device_secret_DO_NOT_SHARE";
} // namespace
namespace rmad {
VpdUtilsImpl::VpdUtilsImpl() : VpdUtils() {
cmd_utils_ = std::make_unique<CmdUtilsImpl>();
}
VpdUtilsImpl::VpdUtilsImpl(std::unique_ptr<CmdUtils> cmd_utils)
: VpdUtils(), cmd_utils_(std::move(cmd_utils)) {}
// We flush all caches into
VpdUtilsImpl::~VpdUtilsImpl() {
FlushOutRoVpdCache();
FlushOutRwVpdCache();
}
bool VpdUtilsImpl::GetSerialNumber(std::string* serial_number) const {
CHECK(serial_number);
return GetRoVpd(kVpdKeySerialNumber, serial_number);
}
bool VpdUtilsImpl::GetWhitelabelTag(std::string* whitelabel_tag) const {
CHECK(whitelabel_tag);
// We can allow whitelabel-tag to be empty.
if (!GetRoVpd(kVpdKeyWhitelabelTag, whitelabel_tag)) {
*whitelabel_tag = "";
}
return true;
}
bool VpdUtilsImpl::GetRegion(std::string* region) const {
CHECK(region);
return GetRoVpd(kVpdKeyRegion, region);
}
bool VpdUtilsImpl::GetCalibbias(const std::vector<std::string>& entries,
std::vector<int>* calibbias) const {
CHECK(calibbias);
std::vector<int> values;
for (const std::string& entry : entries) {
std::string str;
int val;
if (!GetRoVpd(entry, &str) || !base::StringToInt(str, &val)) {
LOG(ERROR) << "Failed to get int value of " << entry << " from vpd.";
return false;
}
values.push_back(val);
}
*calibbias = values;
return true;
}
bool VpdUtilsImpl::GetRegistrationCode(std::string* ubind,
std::string* gbind) const {
CHECK(ubind);
CHECK(gbind);
std::string temp_ubind, temp_gbind;
if (!GetRwVpd(kVpdKeyUbindAttribute, &temp_ubind) ||
!GetRwVpd(kVpdKeyGbindAttribute, &temp_gbind)) {
return false;
}
*ubind = temp_ubind;
*gbind = temp_gbind;
return true;
}
bool VpdUtilsImpl::GetStableDeviceSecret(
std::string* stable_device_secret) const {
CHECK(stable_device_secret);
return GetRoVpd(kVpdKeyStableDeviceSecret, stable_device_secret);
}
bool VpdUtilsImpl::SetSerialNumber(const std::string& serial_number) {
cache_ro_[kVpdKeySerialNumber] = serial_number;
return true;
}
bool VpdUtilsImpl::SetWhitelabelTag(const std::string& whitelabel_tag) {
cache_ro_[kVpdKeyWhitelabelTag] = whitelabel_tag;
return true;
}
bool VpdUtilsImpl::SetRegion(const std::string& region) {
cache_ro_[kVpdKeyRegion] = region;
return true;
}
bool VpdUtilsImpl::SetCalibbias(const std::map<std::string, int>& calibbias) {
for (const auto& [key, value] : calibbias) {
cache_ro_[key] = base::NumberToString(value);
}
return true;
}
bool VpdUtilsImpl::SetRegistrationCode(const std::string& ubind,
const std::string& gbind) {
cache_rw_[kVpdKeyUbindAttribute] = ubind;
cache_rw_[kVpdKeyGbindAttribute] = gbind;
return true;
}
bool VpdUtilsImpl::SetStableDeviceSecret(
const std::string& stable_device_secret) {
cache_ro_[kVpdKeyStableDeviceSecret] = stable_device_secret;
return true;
}
bool VpdUtilsImpl::FlushOutRoVpdCache() {
if (cache_ro_.size() && !SetRoVpd(cache_ro_)) {
return false;
}
cache_ro_.clear();
return true;
}
bool VpdUtilsImpl::FlushOutRwVpdCache() {
if (cache_rw_.size() && !SetRwVpd(cache_rw_)) {
return false;
}
cache_rw_.clear();
return true;
}
bool VpdUtilsImpl::SetRoVpd(
const std::map<std::string, std::string>& key_value_map) {
std::string log_msg;
std::vector<std::string> argv{kVpdCmdPath, "-i", "RO_VPD"};
for (const auto& [key, value] : key_value_map) {
argv.push_back("-s");
std::string key_value_pair = key + "=" + value;
argv.push_back(key_value_pair);
log_msg += key_value_pair + " ";
}
static std::string unused_output;
if (!cmd_utils_->GetOutput(argv, &unused_output)) {
LOG(ERROR) << "Failed to flush " << log_msg << "into RO_PVD.";
return false;
}
return true;
}
bool VpdUtilsImpl::GetRoVpd(const std::string& key, std::string* value) const {
CHECK(value);
if (auto it = cache_ro_.find(key); it != cache_ro_.end()) {
*value = it->second;
return true;
}
std::vector<std::string> argv{kVpdCmdPath, "-i", "RO_VPD", "-g", key};
return cmd_utils_->GetOutput(argv, value);
}
bool VpdUtilsImpl::SetRwVpd(
const std::map<std::string, std::string>& key_value_map) {
std::string log_msg;
std::vector<std::string> argv{kVpdCmdPath, "-i", "RW_VPD"};
for (const auto& [key, value] : key_value_map) {
argv.push_back("-s");
std::string key_value_pair = key + "=" + value;
argv.push_back(key_value_pair);
log_msg += key_value_pair + " ";
}
static std::string unused_output;
if (!cmd_utils_->GetOutput(argv, &unused_output)) {
LOG(ERROR) << "Failed to flush " << log_msg << "into RW_PVD.";
return false;
}
return true;
}
bool VpdUtilsImpl::GetRwVpd(const std::string& key, std::string* value) const {
CHECK(value);
if (auto it = cache_rw_.find(key); it != cache_rw_.end()) {
*value = it->second;
return true;
}
std::vector<std::string> argv{kVpdCmdPath, "-i", "RW_VPD", "-g", key};
return cmd_utils_->GetOutput(argv, value);
}
} // namespace rmad