blob: 194583fb126876a0d55078120a5a20c760d346e0 [file] [log] [blame]
#include "terminus.hpp"
#include "libpldm/platform.h"
#include "terminus_manager.hpp"
#include <ranges>
namespace pldm
{
namespace platform_mc
{
Terminus::Terminus(pldm_tid_t tid, uint64_t supportedTypes) :
initialized(false), tid(tid), supportedTypes(supportedTypes)
{}
bool Terminus::doesSupportType(uint8_t type)
{
return supportedTypes.test(type);
}
bool Terminus::doesSupportCommand(uint8_t type, uint8_t command)
{
if (!doesSupportType(type))
{
return false;
}
try
{
const size_t idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (command / 8);
if (idx >= supportedCmds.size())
{
return false;
}
if (supportedCmds[idx] & (1 << (command % 8)))
{
lg2::info(
"PLDM type {TYPE} command {CMD} is supported by terminus {TID}",
"TYPE", type, "CMD", command, "TID", getTid());
return true;
}
}
catch (const std::exception& e)
{
return false;
}
return false;
}
void Terminus::parseTerminusPDRs()
{
std::vector<std::shared_ptr<pldm_numeric_sensor_value_pdr>>
numericSensorPdrs{};
std::vector<std::shared_ptr<pldm_compact_numeric_sensor_pdr>>
compactNumericSensorPdrs{};
for (auto& pdr : pdrs)
{
auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
switch (pdrHdr->type)
{
case PLDM_SENSOR_AUXILIARY_NAMES_PDR:
{
auto sensorAuxNames = parseSensorAuxiliaryNamesPDR(pdr);
if (!sensorAuxNames)
{
lg2::error(
"Failed to parse PDR with type {TYPE} handle {HANDLE}",
"TYPE", pdrHdr->type, "HANDLE",
static_cast<uint32_t>(pdrHdr->record_handle));
continue;
}
sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
break;
}
case PLDM_NUMERIC_SENSOR_PDR:
{
auto parsedPdr = parseNumericSensorPDR(pdr);
if (!parsedPdr)
{
lg2::error(
"Failed to parse PDR with type {TYPE} handle {HANDLE}",
"TYPE", pdrHdr->type, "HANDLE",
static_cast<uint32_t>(pdrHdr->record_handle));
continue;
}
numericSensorPdrs.emplace_back(std::move(parsedPdr));
break;
}
case PLDM_COMPACT_NUMERIC_SENSOR_PDR:
{
auto parsedPdr = parseCompactNumericSensorPDR(pdr);
if (!parsedPdr)
{
lg2::error(
"Failed to parse PDR with type {TYPE} handle {HANDLE}",
"TYPE", pdrHdr->type, "HANDLE",
static_cast<uint32_t>(pdrHdr->record_handle));
continue;
}
auto sensorAuxNames = parseCompactNumericSensorNames(pdr);
if (!sensorAuxNames)
{
lg2::error(
"Failed to parse sensor name PDR with type {TYPE} handle {HANDLE}",
"TYPE", pdrHdr->type, "HANDLE",
static_cast<uint32_t>(pdrHdr->record_handle));
continue;
}
compactNumericSensorPdrs.emplace_back(std::move(parsedPdr));
sensorAuxiliaryNamesTbl.emplace_back(std::move(sensorAuxNames));
break;
}
default:
{
lg2::error("Unsupported PDR with type {TYPE} handle {HANDLE}",
"TYPE", pdrHdr->type, "HANDLE",
static_cast<uint32_t>(pdrHdr->record_handle));
break;
}
}
}
}
std::shared_ptr<SensorAuxiliaryNames>
Terminus::getSensorAuxiliaryNames(SensorId id)
{
auto it = std::find_if(
sensorAuxiliaryNamesTbl.begin(), sensorAuxiliaryNamesTbl.end(),
[id](
const std::shared_ptr<SensorAuxiliaryNames>& sensorAuxiliaryNames) {
const auto& [sensorId, sensorCnt, sensorNames] = *sensorAuxiliaryNames;
return sensorId == id;
});
if (it != sensorAuxiliaryNamesTbl.end())
{
return *it;
}
return nullptr;
};
std::shared_ptr<SensorAuxiliaryNames>
Terminus::parseSensorAuxiliaryNamesPDR(const std::vector<uint8_t>& pdrData)
{
constexpr uint8_t nullTerminator = 0;
auto pdr = reinterpret_cast<const struct pldm_sensor_auxiliary_names_pdr*>(
pdrData.data());
const uint8_t* ptr = pdr->names;
std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>
sensorAuxNames{};
char16_t alignedBuffer[PLDM_STR_UTF_16_MAX_LEN];
for ([[maybe_unused]] const auto& sensor :
std::views::iota(0, static_cast<int>(pdr->sensor_count)))
{
const uint8_t nameStringCount = static_cast<uint8_t>(*ptr);
ptr += sizeof(uint8_t);
std::vector<std::pair<NameLanguageTag, SensorName>> nameStrings{};
for ([[maybe_unused]] const auto& count :
std::views::iota(0, static_cast<int>(nameStringCount)))
{
std::string_view nameLanguageTag(
reinterpret_cast<const char*>(ptr));
ptr += nameLanguageTag.size() + sizeof(nullTerminator);
int u16NameStringLen = 0;
for (int i = 0; ptr[i] != 0 || ptr[i + 1] != 0; i += 2)
{
u16NameStringLen++;
}
/* include terminator */
u16NameStringLen++;
std::fill(std::begin(alignedBuffer), std::end(alignedBuffer), 0);
if (u16NameStringLen > PLDM_STR_UTF_16_MAX_LEN)
{
lg2::error("Sensor name to long.");
return nullptr;
}
memcpy(alignedBuffer, ptr, u16NameStringLen * sizeof(uint16_t));
std::u16string u16NameString(alignedBuffer, u16NameStringLen);
ptr += (u16NameString.size() + sizeof(nullTerminator)) *
sizeof(uint16_t);
std::transform(u16NameString.cbegin(), u16NameString.cend(),
u16NameString.begin(),
[](uint16_t utf16) { return be16toh(utf16); });
std::string nameString =
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
char16_t>{}
.to_bytes(u16NameString);
std::replace(nameString.begin(), nameString.end(), ' ', '_');
auto nullTerminatorPos = nameString.find('\0');
if (nullTerminatorPos != std::string::npos)
{
nameString.erase(nullTerminatorPos);
}
nameStrings.emplace_back(
std::make_pair(nameLanguageTag, nameString));
}
sensorAuxNames.emplace_back(std::move(nameStrings));
}
return std::make_shared<SensorAuxiliaryNames>(
pdr->sensor_id, pdr->sensor_count, std::move(sensorAuxNames));
}
std::shared_ptr<pldm_numeric_sensor_value_pdr>
Terminus::parseNumericSensorPDR(const std::vector<uint8_t>& pdr)
{
const uint8_t* ptr = pdr.data();
auto parsedPdr = std::make_shared<pldm_numeric_sensor_value_pdr>();
auto rc = decode_numeric_sensor_pdr_data(ptr, pdr.size(), parsedPdr.get());
if (rc)
{
return nullptr;
}
return parsedPdr;
}
std::shared_ptr<SensorAuxiliaryNames>
Terminus::parseCompactNumericSensorNames(const std::vector<uint8_t>& sPdr)
{
std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>
sensorAuxNames{};
std::vector<std::pair<NameLanguageTag, SensorName>> nameStrings{};
auto pdr =
reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
if (sPdr.size() <
(sizeof(pldm_compact_numeric_sensor_pdr) - sizeof(uint8_t)))
{
return nullptr;
}
if (!pdr->sensor_name_length ||
(sPdr.size() < (sizeof(pldm_compact_numeric_sensor_pdr) -
sizeof(uint8_t) + pdr->sensor_name_length)))
{
return nullptr;
}
std::string nameString(reinterpret_cast<const char*>(pdr->sensor_name),
pdr->sensor_name_length);
std::replace(nameString.begin(), nameString.end(), ' ', '_');
auto nullTerminatorPos = nameString.find('\0');
if (nullTerminatorPos != std::string::npos)
{
nameString.erase(nullTerminatorPos);
}
nameStrings.emplace_back(std::make_pair("en", nameString));
sensorAuxNames.emplace_back(std::move(nameStrings));
return std::make_shared<SensorAuxiliaryNames>(pdr->sensor_id, 1,
std::move(sensorAuxNames));
}
std::shared_ptr<pldm_compact_numeric_sensor_pdr>
Terminus::parseCompactNumericSensorPDR(const std::vector<uint8_t>& sPdr)
{
auto pdr =
reinterpret_cast<const pldm_compact_numeric_sensor_pdr*>(sPdr.data());
if (sPdr.size() < sizeof(pldm_compact_numeric_sensor_pdr))
{
// Handle error: input data too small to contain valid pdr
return nullptr;
}
auto parsedPdr = std::make_shared<pldm_compact_numeric_sensor_pdr>();
parsedPdr->hdr = pdr->hdr;
parsedPdr->terminus_handle = pdr->terminus_handle;
parsedPdr->sensor_id = pdr->sensor_id;
parsedPdr->entity_type = pdr->entity_type;
parsedPdr->entity_instance = pdr->entity_instance;
parsedPdr->container_id = pdr->container_id;
parsedPdr->sensor_name_length = pdr->sensor_name_length;
parsedPdr->base_unit = pdr->base_unit;
parsedPdr->unit_modifier = pdr->unit_modifier;
parsedPdr->occurrence_rate = pdr->occurrence_rate;
parsedPdr->range_field_support = pdr->range_field_support;
parsedPdr->warning_high = pdr->warning_high;
parsedPdr->warning_low = pdr->warning_low;
parsedPdr->critical_high = pdr->critical_high;
parsedPdr->critical_low = pdr->critical_low;
parsedPdr->fatal_high = pdr->fatal_high;
parsedPdr->fatal_low = pdr->fatal_low;
return parsedPdr;
}
} // namespace platform_mc
} // namespace pldm