gcontini
2020-11-14 f4e683fc6bd6ac76f9979f49d737588b6ddf16b0
windows smbios
7个文件已修改
1个文件已添加
512 ■■■■■ 已修改文件
doc/index.rst 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/other/CREDITS.md 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/inspector/inspector.cpp 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/CMakeLists.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/dmi_info.hpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/dmi_info.cpp 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/smbios.hpp 397 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/library/os/dmi_info_test.cpp 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/index.rst
@@ -46,7 +46,7 @@
*******************
The software is made by 4 main sub-components:
* `licensecc`    : the C++ library with a C api (the part you have to integrate in your software) with minimal (or no) external dependencies. This is the project you're currently looking at.
* ``licensecc``    : the C++ library with a C api (the part you have to integrate in your software) with minimal (or no) external dependencies. This is the project you're currently looking at.
* ``lccinspector`` : a license debugger to be sent to the final customer to diagnose licensing problems or for calculating the hardware id before issuing the license.
* ``lccgen``       : a license generator (github project `lcc-license-generator`_ ) to initialize the library and generate the licenses.
* ``examples``     : usage samples (github project `examples <https://github.com/open-license-manager/examples>`_ ).
doc/other/CREDITS.md
@@ -1,5 +1,5 @@
# Credits 
The following open source code has been used in OpenLicenseManager.
The following open source code has been used in licensecc.
Thanks to every one of the authors of such projects. Without you open license manager would never have been released.  
## [inja](https://github.com/pantor/inja)
@@ -9,11 +9,10 @@
Copyright (c) 2013-2017 Niels Lohmann
## [isVM](https://github.com/0of/isvm)
## [hwid generation](https://github.com/789sdf987s/hwid_generation)
Thanks for the great smbios parsing code. It saved me days.
MIT License
Copyright (c) 2015 Magnus
## [SimpleIni](https://github.com/brofield/simpleini)
src/inspector/inspector.cpp
@@ -127,7 +127,9 @@
    license::os::DmiInfo dmi_info;
    cout << "Bios vendor      :" << dmi_info.bios_vendor() << endl;
    cout << "Bios description :" << dmi_info.bios_description() << endl;
    cout << "System vendor    :" << dmi_info.sys_vendor() << endl << endl;
    cout << "System vendor    :" << dmi_info.sys_vendor() << endl;
    cout << "Cpu Vendor (dmi) :" << dmi_info.cpu_manufacturer() << endl;
    cout << "Cpu Cores  (dmi) :" << dmi_info.cpu_cores() << endl;
    cout << "==================" << endl;
    if (argc == 2) {
        const string fname(argv[1]);
src/library/os/CMakeLists.txt
@@ -16,7 +16,6 @@
          openssl/signature_verifier.cpp 
        execution_environment_common.cpp 
        windows/execution_environment.cpp
        windows/isvm/BIOSReader.cpp
          windows/os_win.cpp
          windows/network.cpp)
    ENDIF(UNIX)
@@ -29,7 +28,6 @@
        windows/signature_verifier.cpp 
        execution_environment_common.cpp 
        windows/execution_environment.cpp
        windows/isvm/BIOSReader.cpp
        windows/os_win.cpp
        windows/network.cpp)
ENDIF(UNIX OR OPENSSL_FOUND)
src/library/os/dmi_info.hpp
@@ -17,6 +17,8 @@
    std::string m_sys_vendor;
    std::string m_bios_vendor;
    std::string m_bios_description;
    std::string m_cpu_manufacturer;
    unsigned int m_cpu_cores = 0;
public:
    DmiInfo();
@@ -24,6 +26,9 @@
    const std::string& bios_vendor() const { return m_bios_vendor; };
    const std::string& sys_vendor() const { return m_sys_vendor; };
    const std::string& bios_description() const { return m_bios_description; };
    // Only Windows
    const std::string& cpu_manufacturer() const { return m_cpu_manufacturer; };
    const unsigned int cpu_cores() const { return m_cpu_cores; };
};
}  // namespace os
src/library/os/windows/dmi_info.cpp
@@ -5,19 +5,98 @@
 *      Author: devel
 */
#include "isvm/BIOSReader.h"
#include "smbios.hpp"
#include "../../base/string_utils.h"
#include "../dmi_info.hpp"
namespace license {
namespace os {
using namespace smbios;
//#pragma pack()
struct RawSMBIOSData {
    BYTE Used20CallingMethod;
    BYTE SMBIOSMajorVersion;
    BYTE SMBIOSMinorVersion;
    BYTE DmiRevision;
    DWORD Length;
    //BYTE SMBIOSTableData[1];
};
bool readSMBIOS(std::vector<uint8_t> &buffer) {
    const DWORD tableSignature = ('R' << 24) | ('S' << 16) | ('M' << 8) | 'B';
    bool can_read = false;
    uint32_t size = GetSystemFirmwareTable(tableSignature, 0, NULL, 0);
    if (size > 0) {
        buffer.resize(size);
        if (GetSystemFirmwareTable(tableSignature, 0, buffer.data(), size)
                > 0) {
            can_read = true;
        }
    }
    return can_read;
}
DmiInfo::DmiInfo() {
        BIOSReader reader;
        SystemInformation info = reader.readSystemInfo();
        m_sys_vendor = toupper_copy(info.Manufacturer);
        m_bios_vendor = toupper_copy(info.ProductName);
        m_bios_description = toupper_copy(info.SysVersion) + toupper_copy(info.family);
    std::vector<uint8_t> raw_smbios_data;
    if (readSMBIOS(raw_smbios_data)) {
        smbios::parser smbios_parser;
        RawSMBIOSData *rawData = reinterpret_cast<RawSMBIOSData *>(raw_smbios_data.data());
        size_t length = static_cast<size_t>(rawData->Length);
        uint8_t* buff= raw_smbios_data.data() + sizeof(RawSMBIOSData);
        smbios_parser.feed(buff, length);
        for (auto &header : smbios_parser.headers) {
            string_array_t strings;
            parser::extract_strings(header, strings);
            switch (header->type) {
                case types::baseboard_info: {
                    auto *const x = reinterpret_cast<baseboard_info *>(header);
                    if (x->length == 0) break;
                    if (x->manufacturer_name > 0 && x->manufacturer_name < x->length) {
                        m_sys_vendor = strings[x->manufacturer_name];
                    }
                } break;
                case types::bios_info: {
                    auto *const x = reinterpret_cast<bios_info *>(header);
                    if (x->length == 0) break;
                    if (x->vendor > 0 && x->vendor < x->length) {
                        m_bios_vendor = strings[x->vendor];
                    }
                } break;
                case types::processor_info: {
                    auto *const x = reinterpret_cast<proc_info *>(header);
                    if (x->length == 0) break;
                    if (x->manufacturer > 0 && x->manufacturer < x->length) {
                        m_cpu_manufacturer = strings[x->manufacturer];
                    }
                    m_cpu_cores = static_cast<unsigned int>(x->cores);
                } break;
                case types::system_info: {
                    auto *const x = reinterpret_cast<system_info *>(header);
                    if (x->length == 0) break;
                    if (x->manufacturer > 0 && x->manufacturer<x->length && x-> product_name > 0 &&
                        x->product_name < x->length) {
                        m_bios_description =
                            std::string(strings[x->manufacturer]) + std::string(strings[x->product_name]);
                    }
                } break;
                default:;
            }
        }
        //smbios_parser.clear();
    }
    else {
    }
}
}
} /* namespace license */
src/library/os/windows/smbios.hpp
New file
@@ -0,0 +1,397 @@
/**
 * Credits to:
 * https://github.com/789sdf987s/hwid_generation
 */
#ifndef SMBIOS_H
#define SMBIOS_H
#pragma once
#include <Windows.h>
#include <cstdint>
#include <vector>
namespace smbios {
namespace types {
enum {
    bios_info = 0,
    // Required
    system_info = 1,
    // Required
    baseboard_info = 2,
    module_info = 2,
    system_enclosure = 3,
    // Required
    system_chassis = 3,
    // Required
    processor_info = 4,
    // Required
    memory_controller_info = 5,
    // Obsolete
    memory_module_info = 6,
    // Obsolete
    cache_info = 7,
    // Required
    port_connector_info = 8,
    system_slots = 9,
    // Required
    onboard_device_info = 10,
    // Obsolete
    oem_strings = 11,
    system_config_options = 12,
    language_info = 13,
    group_associations = 14,
    system_event_log = 15,
    memory_array = 16,
    // Required
    memory_device = 17,
    // Required
    memory_error_info_32_bit = 18,
    memory_array_mapped_addr = 19,
    // Required
    memory_device_mapped_addr = 20,
    builtin_pointing_device = 21,
    portable_battery = 22,
    system_reset = 23,
    hardware_security = 24,
    system_power_controls = 25,
    voltage_probe = 26,
    cooling_device = 27,
    temperature_probe = 28,
    electrical_current_probe = 29,
    out_of_band_remote_access = 30,
    bis_entry_point = 31,
    // Required
    system_boot_info = 32,
    // Required
    memory_error_info_64_bit = 33,
    management_device = 34,
    management_device_component = 35,
    management_device_threshold = 36,
    memory_channel = 37,
    ipmi_device_info = 38,
    system_power_supply = 39,
    additional_info = 40,
    onboard_device_extinfo = 41,
    management_controller_host = 42,
    inactive = 126,
    end_of_table = 127,
// Always last structure
};
}
typedef uint8_t byte_t;
typedef uint16_t word_t;
typedef uint32_t dword_t;
#ifdef _MSC_VER
    typedef __int64 qword_t;
#else
#ifdef INT64_C
    typedef uint64_t qword_t;
#else
typedef (unsigned long long int) qwordt_t;
#endif
#endif
typedef byte_t str_id;
typedef byte_t enum_t;
typedef std::vector<char*> string_array_t;
struct header;
#pragma pack(push, 1)
struct raw_smbios_data {
    BYTE used20_calling_method;
    BYTE smbios_major_version;
    BYTE smbios_minor_version;
    BYTE dmi_revision;
    DWORD length;
    BYTE smbios_table_data[1];
};
struct header {
    byte_t type;
    byte_t length;
    word_t handle;
};
struct string_list: header {
    byte_t count;
};
struct baseboard_info: header {
    byte_t manufacturer_name;
    byte_t product_name;
    byte_t version;
    byte_t serial_number;
    byte_t product;
    byte_t version1;
    byte_t serial_number1;
};
struct bios_info: header {
    // 2.0
    str_id vendor;
    str_id version;
    word_t starting_segment;
    str_id release_date;
    byte_t rom_size;
    qword_t characteristics;
    // 2.4
    byte_t ext_char1;
    byte_t ext_char2;
    byte_t sb_major;
    byte_t sb_minor;
    byte_t ec_major;
    byte_t ec_minor;
};
struct system_info: header {
    // 2.0
    str_id manufacturer;
    str_id product_name;
    str_id version;
    str_id serial_number;
    // 2.1
    struct {
        dword_t time_low;
        word_t time_mid;
        word_t time_hi_and_version;
        byte_t clock_seq_hi_and_reserved;
        byte_t clock_seq_low;
        byte_t node[6];
    } uuid;
    enum_t wakeup_type;
    // 2.4
    str_id sku;
    str_id family;
};
struct system_chassis: header {
    // 2.0
    str_id manufacturer;
    byte_t type;
    str_id version;
    str_id serial_number;
    str_id assert_tag;
    // 2.1
    enum_t bootup_state;
    enum_t power_supply_state;
    enum_t thermal_state;
    enum_t security_status;
    // 2.3
    dword_t oem;
    byte_t height;
    byte_t cords;
};
struct proc_info: header {
    // 2.0
    str_id socket_designation;
    enum_t type;
    enum_t family;
    str_id manufacturer;
    qword_t id;
    str_id version;
    byte_t voltage;
    word_t clock;
    word_t speed_max;
    word_t speed_cur;
    byte_t status;
    enum_t upgrade;
    // 2.1
    word_t l1;
    word_t l2;
    word_t l3;
    // 2.3
    str_id serial_number;
    str_id assert_tag;
    str_id part_number;
    // 2.5
    byte_t cores;
    byte_t cores_enabled;
    byte_t threads;
    word_t characteristics;
    enum_t family2;
};
struct cache_info: header {
    // 2.0
    str_id socket_designation;
    word_t config;
    word_t size_max;
    word_t size_cur;
    word_t sram_supported;
    word_t sram_cur;
    // 2.1
    byte_t speed;
    enum_t error_correction_type;
    enum_t system_cache_type;
    enum_t associativity;
};
struct slot: header {
    // 2.0
    str_id slot_designation;
    enum_t type;
    enum_t data_bus_width;
    enum_t current_usage;
    enum_t length;
    word_t id;
    byte_t characteristics;
    // 2.1
    byte_t characteristics2;
    // 2.6
    word_t segment_group;
    byte_t bus;
    byte_t device;
};
typedef string_list oem_strings;
typedef string_list system_config_options;
struct lang_info: header {
    byte_t installed_langs;
    byte_t flags;
    byte_t reserved[15];
    str_id current_lang;
};
struct mem_arr: header {
    // 2.1
    enum_t location;
    enum_t use;
    enum_t error_correction;
    dword_t capacity;
    word_t error_info_handle;
    word_t devices_number;
    // 2.7
    qword_t capacity_ext;
};
struct mem_device: header {
    // 2.1
    word_t mem_arr_handle;
    word_t mem_arr_error_info_handle;
    word_t total_width;
    word_t data_width;
    word_t size;
    enum_t form_factor;
    byte_t device_set;
    str_id device_locator;
    str_id bank_locator;
    enum_t type;
    word_t type_detail;
    // 2.3
    word_t speed;
    str_id manufacturer;
    str_id serial_number;
    str_id assert_tag;
    str_id part_number;
    // 2.6
    byte_t attributes;
    // 2.7
    dword_t size_ext;
    word_t clock_speed;
    // 2.8
    word_t voltage_min;
    word_t voltage_max;
    word_t voltage;
};
#pragma pack(pop)
class parser final {
public:
    parser() = default;
    parser(const parser &x) {
        feed(x.raw_data_, x.raw_size_);
    }
    ~parser() {
        clear();
    }
    std::vector<header*> headers;
    static byte_t* skip(byte_t*);
    static header* extract_strings(header*, string_array_t&);
    void feed(const void *raw_smbios, size_t size);
    void clear();
protected:
    byte_t *raw_data_ { };
    size_t raw_size_ { };
};
inline byte_t* parser::skip(byte_t *x) {
    auto *ptr = x + reinterpret_cast<header*>(x)->length;
    size_t len;
    if (*ptr == 0)
        ptr += 2;
    else
        do {
            len = strlen(reinterpret_cast<const char*>(ptr));
            ptr += len + 1;
        } while (len > 0);
    return ptr;
}
inline header* parser::extract_strings(header *x, string_array_t &a) {
    auto *ptr = reinterpret_cast<byte_t*>(x) + x->length;
    a.clear();
    a.push_back(nullptr);
    if (*ptr == 0)
        ptr += 2;
    else
        for (;;) {
            auto *str = reinterpret_cast<char*>(ptr);
            const auto len = strlen(str);
            ptr += len + 1;
            if (len == 0)
                break;
            a.push_back(str);
        }
    return reinterpret_cast<header*>(ptr);
}
inline void parser::feed(const void *raw_smbios, const size_t size) {
    clear();
    raw_size_ = size;
    raw_data_ = new byte_t[raw_size_];
    memcpy(raw_data_, raw_smbios, size);
    auto *x = raw_data_;
    while (static_cast<size_t>(x - raw_data_) < raw_size_) {
        headers.push_back(reinterpret_cast<header*>(x));
        x = skip(x);
    }
}
inline void parser::clear() {
    headers.clear();
    delete[] raw_data_;
    raw_size_ = 0;
}
} // namespace smbios
#endif
test/library/os/dmi_info_test.cpp
@@ -12,13 +12,11 @@
BOOST_AUTO_TEST_CASE(dmi_info) {
    os::DmiInfo dmiInfo;
//windows bug
#ifdef __unix__
    BOOST_CHECK_MESSAGE(dmiInfo.bios_vendor().size()>0, "Bios vendor OK");
    BOOST_CHECK_MESSAGE(dmiInfo.bios_description().size() > 0, "Bios description OK");
    BOOST_CHECK_MESSAGE(dmiInfo.sys_vendor().size() > 0, "Sys vendor OK");
#endif
}
}  // namespace test