Gabriele Contini
2020-03-15 36ce07093b68b07513149577c209ae7a57ab356b
src/library/os/windows/isvm/BIOSReader.cpp
New file
@@ -0,0 +1,121 @@
#include "BIOSReader.h"
#include <cstdint>
#include "Native.h"
struct smbios_structure_header {
   uint8_t type;
   uint8_t length;
   uint16_t handle;
};
//
//   System information
//
struct smbios_type_1 {
   struct smbios_structure_header header;
   uint8_t manufacturer_str;
   uint8_t product_name_str;
   uint8_t version_str;
   uint8_t serial_number_str;
   uint8_t uuid[16];
   uint8_t wake_up_type;
   uint8_t sku_number_str;
   uint8_t family_str;
};
#define _TYPE_COUNT1 6
#define _CONCATE(x, y) x##y
#define CONCATE(x, y) _CONCATE(x, y)
#define TYPE_COUNT(t) CONCATE(_TYPE_COUNT, t)
//
//   Windows
//
#include <windows.h>
#include <tchar.h>
int8_t *parse_smbiod_content(int8_t *addr, int8_t **indexes, int32_t *count) {
   //!   ignore 0
   int8_t parsed_count = 0;
   int8_t *raw_addr = addr;
   //!   first one
   if (indexes) *indexes = raw_addr;
   bool reach_terminal = false;
   while (true) {
      if (0 == *raw_addr++) {
         if (reach_terminal)
            break;
         else {
            ++parsed_count;
            if (count && parsed_count < *count) {
               if (indexes) *(indexes + parsed_count) = raw_addr;
            }
            reach_terminal = true;
         }
      } else {
         reach_terminal = false;
         continue;
      }
   }
   if (count) *count = parsed_count;
   return raw_addr;
}
void read_smbios_type_1(int8_t *addr, SystemInformation *info) {
   smbios_type_1 *t1 = (smbios_type_1 *)addr;
   int32_t offset = ((0x0F) & (t1->header.length >> 4)) * 16 + (t1->header.length & 0x0F);
   int8_t *string_addr[TYPE_COUNT(1)] = {0};
   int32_t count = TYPE_COUNT(1);
   parse_smbiod_content((int8_t *)t1 + offset, string_addr, &count);
   if (0 != t1->manufacturer_str)
      info->Manufacturer = (std::string::traits_type::char_type *)string_addr[t1->manufacturer_str - 1];
   if (0 != t1->product_name_str)
      info->ProductName = (std::string::traits_type::char_type *)string_addr[t1->product_name_str - 1];
   if (0 != t1->serial_number_str)
      info->SerialNum = (std::string::traits_type::char_type *)string_addr[t1->serial_number_str - 1];
   if (0 != t1->version_str)
      info->SysVersion = (std::string::traits_type::char_type *)string_addr[t1->version_str - 1];
   if (0 != t1->family_str) info->family = (std::string::traits_type::char_type *)string_addr[t1->family_str - 1];
}
SystemInformation BIOSReader::readSystemInfo() {
   SystemInformation info;
   uint32_t size = 0;
   RawSMBIOSData *data = (RawSMBIOSData *)(LocateSMBIOS(&size));
   if (NULL == data || 0 == size) return info;
   smbios_structure_header *header = (smbios_structure_header *)(data->SMBIOSTableData);
   while (NULL != header) {
      if (1 == header->type) {
         read_smbios_type_1((int8_t *)header, &info);
         header = NULL;   //!   stop
      } else {
         int32_t offset = ((0x0F) & (header->length >> 4)) * 16 + (header->length & 0x0F);
         header = (smbios_structure_header *)parse_smbiod_content((int8_t *)header + offset, NULL, NULL);
      }
   }
   free(data);
   return info;
}