From f4e683fc6bd6ac76f9979f49d737588b6ddf16b0 Mon Sep 17 00:00:00 2001 From: gcontini <1121667+gcontini@users.noreply.github.com> Date: 周六, 14 11月 2020 22:13:13 +0800 Subject: [PATCH] windows smbios --- src/library/os/windows/dmi_info.cpp | 93 +++++++++ doc/other/CREDITS.md | 5 src/inspector/inspector.cpp | 4 src/library/os/dmi_info.hpp | 5 src/library/os/windows/smbios.hpp | 397 ++++++++++++++++++++++++++++++++++++++++++++ test/library/os/dmi_info_test.cpp | 4 src/library/os/CMakeLists.txt | 2 doc/index.rst | 2 8 files changed, 495 insertions(+), 17 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 38aba77..e7b1c53 100644 --- a/doc/index.rst +++ b/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>`_ ). diff --git a/doc/other/CREDITS.md b/doc/other/CREDITS.md index 7ee3c93..21794f8 100644 --- a/doc/other/CREDITS.md +++ b/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) diff --git a/src/inspector/inspector.cpp b/src/inspector/inspector.cpp index c4283a1..7af061e 100644 --- a/src/inspector/inspector.cpp +++ b/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]); diff --git a/src/library/os/CMakeLists.txt b/src/library/os/CMakeLists.txt index 732d076..ef19453 100644 --- a/src/library/os/CMakeLists.txt +++ b/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) diff --git a/src/library/os/dmi_info.hpp b/src/library/os/dmi_info.hpp index 94c7a3c..7bdc77c 100644 --- a/src/library/os/dmi_info.hpp +++ b/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 diff --git a/src/library/os/windows/dmi_info.cpp b/src/library/os/windows/dmi_info.cpp index 478b517..a88e76d 100644 --- a/src/library/os/windows/dmi_info.cpp +++ b/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 */ diff --git a/src/library/os/windows/smbios.hpp b/src/library/os/windows/smbios.hpp new file mode 100644 index 0000000..1209758 --- /dev/null +++ b/src/library/os/windows/smbios.hpp @@ -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 diff --git a/test/library/os/dmi_info_test.cpp b/test/library/os/dmi_info_test.cpp index ac29cc6..5f44d62 100644 --- a/test/library/os/dmi_info_test.cpp +++ b/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 -- Gitblit v1.9.1