diff --git a/CMakeLists.txt b/CMakeLists.txt index c1a222fc..69f40fcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,7 @@ else() endif() add_definitions(-DXMRIG_MINER_PROJECT -DXMRIG_JSON_SINGLE_LINE_ARRAY) -add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE) +add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64) find_package(UV REQUIRED) diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index 0006d006..f02a64ec 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -170,7 +170,7 @@ xmrig::DmiMemory::DmiMemory(dmi_header *h) return; } - m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); + m_speed = std::max(m_speed, dmi_memory_device_speed(dmi_get(h, 0x20), h->length >= 0x5C ? dmi_get(h, 0x58) : 0) * 1000000ULL); if (h->length < 0x28) { return; diff --git a/src/hw/dmi/DmiReader.cpp b/src/hw/dmi/DmiReader.cpp index 66083845..66f1dd5f 100644 --- a/src/hw/dmi/DmiReader.cpp +++ b/src/hw/dmi/DmiReader.cpp @@ -40,14 +40,14 @@ static void dmi_get_header(dmi_header *h, uint8_t *data) bool xmrig::DmiReader::decode(uint8_t *buf) { - if (!buf || !m_count) { + if (!buf) { return false; } uint8_t *data = buf; int i = 0; - while ((i < m_count || !m_count) && data + 4 <= buf + m_size) { + while (data + 4 <= buf + m_size) { dmi_header h{}; dmi_get_header(&h, data); diff --git a/src/hw/dmi/DmiReader.h b/src/hw/dmi/DmiReader.h index 69ba483b..243b5164 100644 --- a/src/hw/dmi/DmiReader.h +++ b/src/hw/dmi/DmiReader.h @@ -36,7 +36,6 @@ public: inline const DmiBoard &board() const { return m_board; } inline const std::vector &memory() const { return m_memory; } - inline uint16_t count() const { return m_count; } inline uint32_t size() const { return m_size; } inline uint32_t version() const { return m_version; } @@ -46,7 +45,6 @@ private: bool decode(uint8_t *buf); DmiBoard m_board; - uint16_t m_count = 0; uint32_t m_size = 0; uint32_t m_version = 0; std::vector m_memory; diff --git a/src/hw/dmi/DmiReader_unix.cpp b/src/hw/dmi/DmiReader_unix.cpp index 4919935f..e9b25abc 100644 --- a/src/hw/dmi/DmiReader_unix.cpp +++ b/src/hw/dmi/DmiReader_unix.cpp @@ -1,6 +1,8 @@ /* XMRig - * Copyright (c) 2018-2021 SChernykh - * Copyright (c) 2016-2021 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 @@ -18,9 +20,171 @@ #include "hw/dmi/DmiReader.h" +#include "hw/dmi/DmiTools.h" + + +#include +#include +#include +#include +#include + + +#define FLAG_NO_FILE_OFFSET (1 << 0) + + +namespace xmrig { + + +static const char *kSysEntryFile = "/sys/firmware/dmi/tables/smbios_entry_point"; +static const char *kSysTableFile = "/sys/firmware/dmi/tables/DMI"; + + + +static int myread(int fd, uint8_t *buf, size_t count, const char *prefix) +{ + ssize_t r = 1; + size_t r2 = 0; + + while (r2 != count && r != 0) { + r = read(fd, buf + r2, count - r2); + if (r == -1) { + if (errno != EINTR) { + return -1; + } + } + else { + r2 += r; + } + } + + if (r2 != count) { + return -1; + } + + return 0; +} + + +/* + * Reads all of file from given offset, up to max_len bytes. + * A buffer of at most max_len bytes is allocated by this function, and + * needs to be freed by the caller. + * This provides a similar usage model to mem_chunk() + * + * Returns a pointer to the allocated buffer, or NULL on error, and + * sets max_len to the length actually read. + */ +static uint8_t *read_file(off_t base, size_t *max_len, const char *filename) +{ + const int fd = open(filename, O_RDONLY); + uint8_t *p = nullptr; + + if (fd == -1) { + return nullptr; + } + + struct stat statbuf{}; + if (fstat(fd, &statbuf) == 0) { + if (base >= statbuf.st_size) { + goto out; + } + + if (*max_len > static_cast(statbuf.st_size) - base) { + *max_len = statbuf.st_size - base; + } + } + + if ((p = reinterpret_cast(malloc(*max_len))) == nullptr) { + goto out; + } + + if (lseek(fd, base, SEEK_SET) == -1) { + goto err_free; + } + + if (myread(fd, p, *max_len, filename) == 0) { + goto out; + } + +err_free: + free(p); + p = nullptr; + +out: + close(fd); + + return p; +} + + +static int checksum(const uint8_t *buf, size_t len) +{ + uint8_t sum = 0; + + for (size_t a = 0; a < len; a++) { + sum += buf[a]; + } + + return (sum == 0); +} + + +static uint8_t *dmi_table(off_t base, uint32_t &len, const char *devmem, uint32_t flags) +{ + uint8_t *buf = nullptr; + + if (flags & FLAG_NO_FILE_OFFSET) { + size_t size = len; + buf = read_file(0, &size, devmem); + len = size; + } + else { + // FIXME + } + + return buf; +} + + +static uint8_t *smbios3_decode(uint8_t *buf, const char *devmem, uint32_t &size, uint32_t &version, uint32_t flags) +{ + if (buf[0x06] > 0x20 || !checksum(buf, buf[0x06])) { + return nullptr; + } + + version = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09]; + size = dmi_get(buf + 0x0C); + const u64 offset = dmi_get(buf + 0x10); + + return dmi_table(((off_t)offset.h << 32) | offset.l, size, devmem, flags);; +} + + +} // namespace xmrig bool xmrig::DmiReader::read() { + size_t size = 0x20; + uint8_t *buf = read_file(0, &size, kSysEntryFile); + + if (buf) { + uint8_t *smb = nullptr; + + if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0) { + smb = smbios3_decode(buf, kSysTableFile, m_size, m_version, FLAG_NO_FILE_OFFSET); + } + + if (smb) { + decode(smb); + + free(smb); + free(buf); + + return true; + } + } + return false; } diff --git a/src/hw/dmi/DmiReader_win.cpp b/src/hw/dmi/DmiReader_win.cpp index 6b8e2ac4..b79f952a 100644 --- a/src/hw/dmi/DmiReader_win.cpp +++ b/src/hw/dmi/DmiReader_win.cpp @@ -41,48 +41,6 @@ struct RawSMBIOSData { }; -/* - * Counts the number of SMBIOS structures present in - * the SMBIOS table. - * - * buf - Pointer that receives the SMBIOS Table address. - * This will be the address of the BYTE array from - * the RawSMBIOSData struct. - * - * len - The length of the SMBIOS Table pointed by buff. - * - * return - The number of SMBIOS strutctures. - * - * Remarks: - * The SMBIOS Table Entry Point has this information, - * however the GetSystemFirmwareTable API doesn't - * return all fields from the Entry Point, and - * DMIDECODE uses this value as a parameter for - * dmi_table function. This is the reason why - * this function was make. - * - * Hugo Weber address@hidden - */ -uint16_t count_smbios_structures(const uint8_t *buf, uint32_t len) -{ - uint16_t count = 0; - uint32_t offset = 0; - - while (offset < len) { - offset += reinterpret_cast(buf + offset)->length; - count++; - - while ((*reinterpret_cast(buf + offset) != 0) && (offset < len)) { - offset++; - } - - offset += 2; - } - - return count; -} - - } // namespace xmrig @@ -103,7 +61,6 @@ bool xmrig::DmiReader::read() m_version = (smb->SMBIOSMajorVersion << 16) + (smb->SMBIOSMinorVersion << 8) + smb->DmiRevision; m_size = smb->Length; - m_count = count_smbios_structures(smb->SMBIOSTableData, m_size); const bool rc = decode(smb->SMBIOSTableData); HeapFree(GetProcessHeap(), 0, smb); diff --git a/src/hw/dmi/DmiTools.h b/src/hw/dmi/DmiTools.h index e929e6fe..65a1dfd7 100644 --- a/src/hw/dmi/DmiTools.h +++ b/src/hw/dmi/DmiTools.h @@ -22,6 +22,7 @@ #define XMRIG_DMITOOLS_H +#include #include @@ -37,6 +38,12 @@ struct dmi_header }; +struct u64 { + uint32_t l; + uint32_t h; +}; + + template inline T dmi_get(const uint8_t *data) { return *reinterpret_cast(data); }