/* XMRig * Copyright (c) 2000-2002 Alan Cox * Copyright (c) 2005-2020 Jean Delvare * Copyright (c) 2018-2021 SChernykh * Copyright (c) 2016-2021 XMRig , * * 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 . */ #include "hw/dmi/DmiMemory.h" #include "3rdparty/fmt/format.h" #include "3rdparty/rapidjson/document.h" #include "hw/dmi/DmiTools.h" #include #include #include 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 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 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(h, 0x08)); m_width = dmi_memory_device_width(dmi_get(h, 0x0A)); auto size = dmi_get(h, 0x0C); if (h->length >= 0x20 && size == 0x7FFF) { m_size = (dmi_get(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(h, 0x15), h->length >= 0x5C ? dmi_get(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(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL; m_speed = configuredSpeed ? configuredSpeed : m_speed; if (h->length < 0x28) { return; } m_voltage = dmi_get(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(); } } }