243 lines
6 KiB
C++
243 lines
6 KiB
C++
/* XMRig
|
|
* Copyright (c) 2000-2002 Alan Cox <alan@redhat.com>
|
|
* Copyright (c) 2005-2020 Jean Delvare <jdelvare@suse.de>
|
|
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
|
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "hw/dmi/DmiMemory.h"
|
|
#include "3rdparty/fmt/format.h"
|
|
#include "3rdparty/rapidjson/document.h"
|
|
#include "hw/dmi/DmiTools.h"
|
|
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <regex>
|
|
|
|
|
|
namespace xmrig {
|
|
|
|
|
|
static const char *kIdFormat = "DIMM_{}{}";
|
|
|
|
|
|
static inline uint16_t dmi_memory_device_width(uint16_t code)
|
|
{
|
|
return (code == 0xFFFF || code == 0) ? 0 : code;
|
|
}
|
|
|
|
|
|
static const char *dmi_memory_device_form_factor(uint8_t code)
|
|
{
|
|
static const std::array<const char *, 0x10> form_factor
|
|
{
|
|
"Other",
|
|
"Unknown",
|
|
"SIMM",
|
|
"SIP",
|
|
"Chip",
|
|
"DIP",
|
|
"ZIP",
|
|
"Proprietary Card",
|
|
"DIMM",
|
|
"TSOP",
|
|
"Row Of Chips",
|
|
"RIMM",
|
|
"SODIMM",
|
|
"SRIMM",
|
|
"FB-DIMM",
|
|
"Die"
|
|
};
|
|
|
|
if (code >= 0x01 && code <= form_factor.size()) {
|
|
return form_factor[code - 0x01];
|
|
}
|
|
|
|
return form_factor[1];
|
|
}
|
|
|
|
|
|
static const char *dmi_memory_device_type(uint8_t code)
|
|
{
|
|
static const std::array<const char *, 0x23> type
|
|
{
|
|
"Other", /* 0x01 */
|
|
"Unknown",
|
|
"DRAM",
|
|
"EDRAM",
|
|
"VRAM",
|
|
"SRAM",
|
|
"RAM",
|
|
"ROM",
|
|
"Flash",
|
|
"EEPROM",
|
|
"FEPROM",
|
|
"EPROM",
|
|
"CDRAM",
|
|
"3DRAM",
|
|
"SDRAM",
|
|
"SGRAM",
|
|
"RDRAM",
|
|
"DDR",
|
|
"DDR2",
|
|
"DDR2 FB-DIMM",
|
|
"Reserved",
|
|
"Reserved",
|
|
"Reserved",
|
|
"DDR3",
|
|
"FBD2",
|
|
"DDR4",
|
|
"LPDDR",
|
|
"LPDDR2",
|
|
"LPDDR3",
|
|
"LPDDR4",
|
|
"Logical non-volatile device",
|
|
"HBM",
|
|
"HBM2",
|
|
"DDR5",
|
|
"LPDDR5"
|
|
};
|
|
|
|
if (code >= 0x01 && code <= type.size()) {
|
|
return type[code - 0x01];
|
|
}
|
|
|
|
return type[1];
|
|
}
|
|
|
|
|
|
static uint64_t dmi_memory_device_speed(uint16_t code1, uint32_t code2)
|
|
{
|
|
return (code1 == 0xFFFF) ? code2 : code1;
|
|
}
|
|
|
|
|
|
} // namespace xmrig
|
|
|
|
|
|
|
|
xmrig::DmiMemory::DmiMemory(dmi_header *h)
|
|
{
|
|
if (h->length < 0x15) {
|
|
return;
|
|
}
|
|
|
|
m_totalWidth = dmi_memory_device_width(dmi_get<uint16_t>(h, 0x08));
|
|
m_width = dmi_memory_device_width(dmi_get<uint16_t>(h, 0x0A));
|
|
|
|
auto size = dmi_get<uint16_t>(h, 0x0C);
|
|
if (h->length >= 0x20 && size == 0x7FFF) {
|
|
m_size = (dmi_get<uint32_t>(h, 0x1C) & 0x7FFFFFFFUL) * 1024ULL * 1024ULL;
|
|
}
|
|
else if (size) {
|
|
m_size = (1024ULL * (size & 0x7FFF) * ((size & 0x8000) ? 1 : 1024ULL));
|
|
}
|
|
|
|
setId(dmi_string(h, 0x10), dmi_string(h, 0x11));
|
|
|
|
m_formFactor = h->data[0x0E];
|
|
m_type = h->data[0x12];
|
|
|
|
if (!m_size || h->length < 0x17) {
|
|
return;
|
|
}
|
|
|
|
m_speed = dmi_memory_device_speed(dmi_get<uint16_t>(h, 0x15), h->length >= 0x5C ? dmi_get<uint32_t>(h, 0x54) : 0) * 1000000ULL;
|
|
|
|
if (h->length < 0x1B) {
|
|
return;
|
|
}
|
|
|
|
m_vendor = dmi_string(h, 0x17);
|
|
m_product = dmi_string(h, 0x1A);
|
|
|
|
if (h->length < 0x1C) {
|
|
return;
|
|
}
|
|
|
|
m_rank = h->data[0x1B] & 0x0F;
|
|
|
|
if (h->length < 0x22) {
|
|
return;
|
|
}
|
|
|
|
const uint64_t configuredSpeed = dmi_memory_device_speed(dmi_get<uint16_t>(h, 0x20), h->length >= 0x5C ? dmi_get<uint32_t>(h, 0x58) : 0) * 1000000ULL;
|
|
m_speed = configuredSpeed ? configuredSpeed : m_speed;
|
|
|
|
if (h->length < 0x28) {
|
|
return;
|
|
}
|
|
|
|
m_voltage = dmi_get<uint16_t>(h, 0x26);
|
|
}
|
|
|
|
|
|
const char *xmrig::DmiMemory::formFactor() const
|
|
{
|
|
return dmi_memory_device_form_factor(m_formFactor);
|
|
}
|
|
|
|
|
|
const char *xmrig::DmiMemory::type() const
|
|
{
|
|
return dmi_memory_device_type(m_type);
|
|
}
|
|
|
|
|
|
#ifdef XMRIG_FEATURE_API
|
|
rapidjson::Value xmrig::DmiMemory::toJSON(rapidjson::Document &doc) const
|
|
{
|
|
using namespace rapidjson;
|
|
|
|
auto &allocator = doc.GetAllocator();
|
|
Value out(kObjectType);
|
|
out.AddMember("id", id().toJSON(doc), allocator);
|
|
out.AddMember("slot", m_slot.toJSON(doc), allocator);
|
|
out.AddMember("type", StringRef(type()), allocator);
|
|
out.AddMember("form_factor", StringRef(formFactor()), allocator);
|
|
out.AddMember("size", m_size, allocator);
|
|
out.AddMember("speed", m_speed, allocator);
|
|
out.AddMember("rank", m_rank, allocator);
|
|
out.AddMember("voltage", m_voltage, allocator);
|
|
out.AddMember("width", m_width, allocator);
|
|
out.AddMember("total_width", m_totalWidth, allocator);
|
|
out.AddMember("vendor", m_vendor.toJSON(doc), allocator);
|
|
out.AddMember("product", m_product.toJSON(doc), allocator);
|
|
out.AddMember("bank", m_bank.toJSON(doc), allocator);
|
|
|
|
return out;
|
|
}
|
|
#endif
|
|
|
|
|
|
void xmrig::DmiMemory::setId(const char *slot, const char *bank)
|
|
{
|
|
m_slot = slot;
|
|
m_bank = bank;
|
|
|
|
std::cmatch cm;
|
|
if (std::regex_match(slot, cm, std::regex("^Channel([A-Z])-DIMM(\\d+)$"))) {
|
|
m_id = fmt::format(kIdFormat, cm.str(1), cm.str(2)).c_str();
|
|
}
|
|
else if (std::regex_search(bank, cm, std::regex("CHANNEL ([A-Z])$"))) {
|
|
std::cmatch cm2;
|
|
if (std::regex_match(slot, cm2, std::regex("^DIMM (\\d+)$"))) {
|
|
m_id = fmt::format(kIdFormat, cm.str(1), cm2.str(1)).c_str();
|
|
}
|
|
}
|
|
}
|