diff --git a/Kernel/ACPI/DMIDecoder.cpp b/Kernel/ACPI/DMIDecoder.cpp new file mode 100644 index 0000000000..8683ff71a9 --- /dev/null +++ b/Kernel/ACPI/DMIDecoder.cpp @@ -0,0 +1,260 @@ +#include +#include +#include + +static DMIDecoder* s_dmi_decoder; + +//#define SMBIOS_DEBUG + +#define SMBIOS_BASE_SEARCH_ADDR 0xf0000 +#define SMBIOS_END_SEARCH_ADDR 0xfffff +#define SMBIOS_SEARCH_AREA_SIZE (SMBIOS_END_SEARCH_ADDR - SMBIOS_BASE_SEARCH_ADDR) + +DMIDecoder& DMIDecoder::the() +{ + if (s_dmi_decoder == nullptr) { + s_dmi_decoder = new DMIDecoder(true); + } + return *s_dmi_decoder; +} + +void DMIDecoder::initialize() +{ + if (s_dmi_decoder == nullptr) { + s_dmi_decoder = new DMIDecoder(true); + } +} + +void DMIDecoder::initialize_untrusted() +{ + if (s_dmi_decoder == nullptr) { + s_dmi_decoder = new DMIDecoder(false); + } +} + +void DMIDecoder::initialize_parser() +{ + if (m_entry32bit_point != nullptr || m_entry64bit_point != nullptr) { + m_operable = true; + kprintf("DMI Decoder is enabled\n"); + if (m_entry64bit_point != nullptr) { + kprintf("DMIDecoder: SMBIOS 64bit Entry point @ P 0x%x\n", m_entry64bit_point); + m_use_64bit_entry = true; + m_structure_table = (SMBIOS::TableHeader*)m_entry64bit_point->table_ptr; + m_structures_count = m_entry64bit_point->table_maximum_size; + m_table_length = m_entry64bit_point->table_maximum_size; + } else if (m_entry32bit_point != nullptr) { + kprintf("DMIDecoder: SMBIOS 32bit Entry point @ P 0x%x\n", m_entry32bit_point); + m_use_64bit_entry = false; + m_structure_table = (SMBIOS::TableHeader*)m_entry32bit_point->legacy_structure.smbios_table_ptr; + m_structures_count = m_entry32bit_point->legacy_structure.smbios_tables_count; + m_table_length = m_entry32bit_point->legacy_structure.smboios_table_length; + } + kprintf("DMIDecoder: Data table @ P 0x%x\n", m_structure_table); + enumerate_smbios_tables(); + } else { + m_operable = false; + kprintf("DMI Decoder is disabled. Cannot find SMBIOS tables.\n"); + } +} + +void DMIDecoder::enumerate_smbios_tables() +{ + u32 table_length = m_table_length; + SMBIOS::TableHeader* physical_table = m_structure_table; + + auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(table_length), "DMI Decoder Entry Point Finding", Region::Access::Read); + PhysicalAddress paddr = PhysicalAddress((u32)physical_table & PAGE_MASK); + mmap_region(*region, paddr); + + auto* v_smbios_table = (SMBIOS::TableHeader*)(region->vaddr().get() + ((u32)physical_table & (~PAGE_MASK))); + + u32 structures_count = 0; + while (table_length > 0) { +#ifdef SMBIOS_DEBUG + dbgprintf("DMIDecoder: Examining table @ P 0x%x\n", physical_table); +#endif + structures_count++; + if (v_smbios_table->type == (u32)SMBIOS::TableType::EndOfTable) { + kprintf("DMIDecoder: Detected table with type 127, End of SMBIOS data.\n"); + break; + } + m_smbios_tables.append(physical_table); + table_length -= v_smbios_table->length; + kprintf("DMIDecoder: Detected table with type %u\n", v_smbios_table->type); + SMBIOS::TableHeader* physical_next_table = get_next_physical_table(*physical_table); +#ifdef SMBIOS_DEBUG + dbgprintf("DMIDecoder: Next table @ P 0x%x\n", physical_next_table); +#endif + if (physical_next_table == nullptr) + break; + + v_smbios_table = (SMBIOS::TableHeader*)(region->vaddr().get() + (u32)physical_next_table - paddr.get()); + physical_table = physical_next_table; + } + m_structures_count = structures_count; +} + +size_t DMIDecoder::get_table_size(SMBIOS::TableHeader& table) +{ + // FIXME: Make sure we have some mapping here so we don't rely on existing identity mapping... +#ifdef SMBIOS_DEBUG + dbgprintf("DMIDecoder: table legnth - 0x%x\n", table.length); +#endif + const char* strtab = (char*)&table + table.length; + size_t index = 1; + while (strtab[index - 1] != '\0' || strtab[index] != '\0') { + if (index > m_table_length) { + ASSERT_NOT_REACHED(); // FIXME: Instead of halting, find a better solution (Hint: use m_operable to disallow further use of DMIDecoder) + } + index++; + } +#ifdef SMBIOS_DEBUG + dbgprintf("DMIDecoder: table size - 0x%x\n", table.length + i + 1); +#endif + return table.length + index + 1; +} + +SMBIOS::TableHeader* DMIDecoder::get_next_physical_table(SMBIOS::TableHeader& p_table) +{ + return (SMBIOS::TableHeader*)((u32)&p_table + get_table_size(p_table)); +} + +SMBIOS::TableHeader* DMIDecoder::get_smbios_physical_table_by_handle(u16 handle) +{ + auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(PAGE_SIZE * 2), "DMI Decoder Finding Table", Region::Access::Read); + + for (auto* table : m_smbios_tables) { + if (!table) + continue; + PhysicalAddress paddr = PhysicalAddress((u32)table & PAGE_MASK); + mmap_region(*region, paddr); + SMBIOS::TableHeader* table_v_ptr = (SMBIOS::TableHeader*)(region->vaddr().get() + ((u32)table & (~PAGE_MASK))); + if (table_v_ptr->handle == handle) { + return table; + } + } + return nullptr; +} +SMBIOS::TableHeader* DMIDecoder::get_smbios_physical_table_by_type(u8 table_type) +{ + auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(PAGE_SIZE * 2), "DMI Decoder Finding Table", Region::Access::Read); + + for (auto* table : m_smbios_tables) { + if (!table) + continue; + PhysicalAddress paddr = PhysicalAddress((u32)table & PAGE_MASK); + mmap_region(*region, paddr); + SMBIOS::TableHeader* table_v_ptr = (SMBIOS::TableHeader*)(region->vaddr().get() + ((u32)table & (~PAGE_MASK))); + if (table_v_ptr->type == table_type) { + return table; + } + } + return nullptr; +} + +DMIDecoder::DMIDecoder(bool trusted) + : m_entry32bit_point(find_entry32bit_point()) + , m_entry64bit_point(find_entry64bit_point()) + , m_structure_table(nullptr) + , m_untrusted(!trusted) +{ + if (!trusted) { + kprintf("DMI Decoder initialized as untrusted due to user request.\n"); + } + initialize_parser(); +} + +SMBIOS::EntryPoint64bit* DMIDecoder::find_entry64bit_point() +{ + auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(SMBIOS_SEARCH_AREA_SIZE), "DMI Decoder Entry Point Finding", Region::Access::Read); + PhysicalAddress paddr = PhysicalAddress(SMBIOS_BASE_SEARCH_ADDR); + mmap_region(*region, paddr); + + char* tested_physical_ptr = (char*)paddr.get(); + for (char* entry_str = (char*)(region->vaddr().get()); entry_str < (char*)(region->vaddr().get() + (SMBIOS_SEARCH_AREA_SIZE)); entry_str += 16) { +#ifdef SMBIOS_DEBUG + dbgprintf("DMI Decoder: Looking for 64 bit Entry point @ P 0x%x\n", entry_str, tested_physical_ptr); +#endif + if (!strncmp("_SM3_", entry_str, strlen("_SM3_"))) + return (SMBIOS::EntryPoint64bit*)tested_physical_ptr; + + tested_physical_ptr += 16; + } + return nullptr; +} + +SMBIOS::EntryPoint32bit* DMIDecoder::find_entry32bit_point() +{ + auto region = MM.allocate_kernel_region(PAGE_ROUND_UP(SMBIOS_SEARCH_AREA_SIZE), "DMI Decoder Entry Point Finding", Region::Access::Read); + PhysicalAddress paddr = PhysicalAddress(SMBIOS_BASE_SEARCH_ADDR); + mmap_region(*region, paddr); + + char* tested_physical_ptr = (char*)paddr.get(); + for (char* entry_str = (char*)(region->vaddr().get()); entry_str < (char*)(region->vaddr().get() + (SMBIOS_SEARCH_AREA_SIZE)); entry_str += 16) { +#ifdef SMBIOS_DEBUG + dbgprintf("DMI Decoder: Looking for 32 bit Entry point @ P 0x%x\n", tested_physical_ptr); +#endif + if (!strncmp("_SM_", entry_str, strlen("_SM_"))) + return (SMBIOS::EntryPoint32bit*)tested_physical_ptr; + + tested_physical_ptr += 16; + } + return nullptr; +} + +void DMIDecoder::mmap(VirtualAddress vaddr, PhysicalAddress paddr, u32 length) +{ + unsigned i = 0; + while (length >= PAGE_SIZE) { + MM.map_for_kernel(VirtualAddress(vaddr.offset(i * PAGE_SIZE).get()), PhysicalAddress(paddr.offset(i * PAGE_SIZE).get())); +#ifdef SMBIOS_DEBUG + dbgprintf("DMI Decoder: map - V 0x%x -> P 0x%x\n", vaddr.offset(i * PAGE_SIZE).get(), paddr.offset(i * PAGE_SIZE).get()); +#endif + length -= PAGE_SIZE; + i++; + } + if (length > 0) { + MM.map_for_kernel(vaddr.offset(i * PAGE_SIZE), paddr.offset(i * PAGE_SIZE), true); + } +#ifdef SMBIOS_DEBUG + dbgprintf("DMI Decoder: Finished mapping\n"); +#endif +} + +void DMIDecoder::mmap_region(Region& region, PhysicalAddress paddr) +{ +#ifdef SMBIOS_DEBUG + dbgprintf("DMI Decoder: Mapping region, size - %u\n", region.size()); +#endif + mmap(region.vaddr(), paddr, region.size()); +} + +Vector& DMIDecoder::get_physical_memory_areas() +{ + // FIXME: Implement it... + kprintf("DMIDecoder::get_physical_memory_areas() is not implemented.\n"); + ASSERT_NOT_REACHED(); +} +bool DMIDecoder::is_reliable() +{ + return !m_untrusted; +} +u64 DMIDecoder::get_bios_characteristics() +{ + // FIXME: Make sure we have some mapping here so we don't rely on existing identity mapping... + ASSERT(m_operable == true); + SMBIOS::BIOSInfo* bios_info = (SMBIOS::BIOSInfo*)get_smbios_physical_table_by_type(0); + ASSERT(bios_info != nullptr); + kprintf("DMIDecoder: BIOS info @ P 0x%x\n", bios_info); + return bios_info->bios_characteristics; +} + +char* DMIDecoder::get_smbios_string(SMBIOS::TableHeader&, u8) +{ + // FIXME: Implement it... + // FIXME: Make sure we have some mapping here so we don't rely on existing identity mapping... + kprintf("DMIDecoder::get_smbios_string() is not implemented.\n"); + ASSERT_NOT_REACHED(); + return nullptr; +} diff --git a/Kernel/ACPI/DMIDecoder.h b/Kernel/ACPI/DMIDecoder.h new file mode 100644 index 0000000000..be8b10e566 --- /dev/null +++ b/Kernel/ACPI/DMIDecoder.h @@ -0,0 +1,1341 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace SMBIOS { +struct LegacyEntryPoint32bit { + char legacy_sig[5]; + u8 checksum2; + u16 smboios_table_length; + u32 smbios_table_ptr; + u16 smbios_tables_count; + u8 smbios_bcd_revision; +} __attribute__((packed)); + +struct EntryPoint32bit { + char sig[4]; + u8 checksum; + u8 length; + u8 major_version; + u8 minor_version; + u16 maximum_structure_size; + u8 implementation_revision; + char formatted_area[5]; + LegacyEntryPoint32bit legacy_structure; +} __attribute__((packed)); + +struct EntryPoint64bit { + char sig[5]; + u8 checksum; + u8 length; + u8 major_version; + u8 minor_version; + u8 document_revision; + u8 revision; + u8 reserved; + u32 table_maximum_size; + u64 table_ptr; +} __attribute__((packed)); + +struct TableHeader { + u8 type; + u8 length; + u16 handle; +} __attribute__((packed)); + +enum class TableType { + BIOSInfo = 0, + SysInfo = 1, + ModuleInfo = 2, + SysEnclosure = 3, + ProcessorInfo = 4, + CacheInfo = 7, + PortConnectorInfo = 8, + SystemSlots = 9, + OEMStrings = 11, + SysConfigOptions = 12, + BIOSLanguageInfo = 13, + GroupAssociations = 14, + SysEventLog = 15, + PhysicalMemoryArray = 16, + MemoryDevice = 17, + MemoryErrorInfo32Bit = 18, + MemoryArrayMappedAddress = 19, + MemoryDeviceMappedAddress = 20, + BuiltinPointingDevice = 21, + PortableBattery = 22, + SysReset = 23, + HardwareSecurity = 24, + SysPowerControls = 25, + VoltageProbe = 26, + CoolingDevice = 27, + TemperatureProbe = 28, + ElectricalCurrentProbe = 29, + OutOfBandRemoteAccess = 30, + SystemBootInfo = 32, + MemoryErrorInfo64Bit = 33, + ManagementDevice = 34, + ManagementDeviceComponent = 35, + ManagementDeviceThresholdData = 36, + MemoryChannel = 37, + IPMIDeviceInfo = 38, + SysPowerSupply = 39, + AdditionalInfo = 40, + OnboardDevicesExtendedInfo = 41, + ManagementControllerHostInterface = 42, + TPMDevice = 43, + ProcessorAdditionalInfo = 44, + Inactive = 126, + EndOfTable = 127 +}; + +struct BIOSInfo { // Type 0 + TableHeader h; + u8 bios_vendor_str_number; + u8 bios_version_str_number; + u16 bios_segment; + u8 bios_release_date_str_number; + u8 bios_rom_size; + u64 bios_characteristics; + u8 ext_bios_characteristics[]; +} __attribute__((packed)); + +enum class BIOSCharacteristics { + Unknown = (1 << 2), + NotSupported = (1 << 3), + ISA_support = (1 << 4), + MCA_support = (1 << 5), + EISA_support = (1 << 6), + PCI_support = (1 << 7), + PCMCIA_support = (1 << 8), + PnP_support = (1 << 9), + APM_support = (1 << 10), + UpgradeableBIOS = (1 << 11), + Shadowing_BIOS = (1 << 12), + VL_VESA_support = (1 << 13), + ESCD_support = (1 << 14), + CD_boot_support = (1 << 15), + select_boot_support = (1 << 16), + BIOS_ROM_socketed = (1 << 17), + PCMCIA_boot_support = (1 << 18), + EDD_spec_support = (1 << 19), + floppy_nec98_1200k_support = (1 << 20), + floppy_toshiba_1200k_support = (1 << 21), + floppy_360k_support = (1 << 22), + floppy_1200k_services_support = (1 << 23), + floppy_720k_services_support = (1 << 24), + floppy_2880k_services_support = (1 << 25), + int5_print_screen_support = (1 << 26), + int9_8042_keyboard_support = (1 << 27), + int14_serial_support = (1 << 28), + int17_printer_support = (1 << 29), + int10_video_support = (1 << 30), + nec_pc98 = (1 << 31) +}; + +struct ExtBIOSInfo { + u8 bios_major_release; + u8 bios_minor_release; + u8 embedded_controller_firmware_major_release; + u8 embedded_controller_firmware_minor_release; + u16 ext_bios_rom_size; +} __attribute__((packed)); + +struct SysInfo { // Type 1 + TableHeader h; + u8 manufacturer_str_number; + u8 product_name_str_number; + u8 version_str_number; + u8 serial_number_str_number; + u64 uuid[2]; + u8 wake_up_type; + u8 sku_str_number; + u8 family_str_number; + +} __attribute__((packed)); + +enum class WakeUpType { + Reserved = 0, + Other = 1, + Unknown = 2, + APM_TIMER = 3, + MODEM_RING = 4, + LAN_REMOTE = 5, + POWER_SWTCH = 6, + PCI_PME = 7, + AC_RESTORE = 8, +}; + +struct ModuleInfo { // Type 2 + TableHeader h; + u8 manufacturer_str_number; + u8 product_name_str_number; + u8 version_str_number; + u8 serial_number_str_number; + u8 asset_tag_str_number; + u8 feature_flags; + u8 chassis_location; + u16 chassis_handle; + u8 board_type; + u8 contained_object_handles_count; + u16 contained_object_handles[]; +} __attribute__((packed)); + +enum class BoardType { + Unkown = 0x1, + Other = 0x2, + Server_Blade = 0x3, + Connectivity_Switch = 0x4, + System_Management_Module = 0x5, + Processor_Module = 0x6, + IO_Module = 0x7, + Memory_Module = 0x8, + Daughter_Board = 0x9, + Motherboard = 0xA, + Processor_Memory_Module = 0xB, + Processor_IO_Module = 0xC, + Interconnect_Board = 0xD, +}; + +struct SysEnclosure { // Type 3 + TableHeader h; + u8 manufacturer_str_number; + u8 type; + u8 version_str_number; + u8 serial_number_str_number; + u8 asset_tag_str_number; + u8 boot_up_state; + u8 power_supply_state; + u8 thermal_state; + u8 security_status; + u32 vendor_specific_info; + u8 height; + u8 power_cords_number; + u8 contained_element_count; + u8 contained_element_record_length; +} __attribute__((packed)); + +struct ExtSysEnclosure { + u8 sku_str_number; +} __attribute__((packed)); + +enum class SysEnclosureType { + Other = 0x1, + Unknown = 0x2, + Desktop = 0x3, + Low_Profile_Desktop = 0x4, + Pizza_Box = 0x5, + Mini_Tower = 0x6, + Tower = 0x7, + Portable = 0x8, + Laptop = 0x9, + Notebook = 0xA, + Hand_Held = 0xB, + Docking_Station = 0xC, + AIO = 0xD, + Sub_Notebook = 0xE, + Space_Saving = 0xF, + Lunch_Box = 0x10, + Main_Server_Chassis = 0x11, + Expansion_Chassis = 0x12, + Sub_Chassis = 0x13, + Bus_Expansion_Chassis = 0x14, + Peripheral_Chassis = 0x15, + RAID_Chassis = 0x16, + Rack_MOunt_Chassis = 0x17, + Sealed_case_PC = 0x18, + Multi_System_Chasis = 0x19, + Compact_PCI = 0x1A, + Advanced_TCA = 0x1B, + Blade = 0x1C, + Blade_Enclosure = 0x1D, + Tablet = 0x1E, + Convertible = 0x1F, + Detachable = 0x20, + IoT_Gateway = 0x21, + Embedded_PC = 0x22, + Mini_PC = 0x23, + Stick_PC = 0x24, +}; + +enum class SysEnclosureState { + Other = 0x1, + Unknown = 0x2, + Safe = 0x3, + Warning = 0x4, + Critical = 0x5, + Non_Recoverable = 0x6, +}; + +enum class SysEnclosureSecurityStatus { + Other = 0x1, + Unknown = 0x2, + None = 0x3, + External_Interface_Locked_Out = 0x4, + External_Interface_Enabled = 0x5, +}; + +struct SysEnclosureContainedElement { + u8 type; + u8 min_contained_element_count; + u8 max_contained_element_count; +} __attribute__((packed)); + +struct ProcessorInfo { // Type 4 + TableHeader h; + u8 socket_designation_str_number; + u8 processor_type; + u8 processor_family; + u8 processor_manufacturer_str_number; + u64 processor_id; + u8 processor_version_str_number; + u8 voltage; + u16 external_clock; + u16 max_speed; + u16 current_speed; + u8 status; + u8 processor_upgrade; + u16 l1_cache_handle; + u16 l2_cache_handle; + u16 l3_cache_handle; + u8 serial_number_str_number; + u8 asset_tag_str_number; + u8 part_number_str_number; + u8 core_count; + u8 core_enabled; + u8 thread_count; + u16 processor_characteristics; + u16 processor_family2; + u16 core_count2; + u16 core_enabled2; + u16 thread_count2; +} __attribute__((packed)); + +enum class ProcessorType { + Other = 0x1, + Unknown = 0x2, + Central_Processor = 0x3, + Math_Processor = 0x4, + DSP_Processor = 0x5, + Video_Processor = 0x6, +}; + +enum class ProcessorUpgrade { + Other = 0x1, + Unknown = 0x2, + Daughter_Board = 0x3, + ZIF_Socket = 0x4, + Replaceable_Piggy_Back = 0x5, + None = 0x6, + LIF_Sokcet = 0x7, + Slot_1 = 0x8, + Slot_2 = 0x9, + Socket_370_pin = 0xA, + Slot_A = 0xB, + Slot_M = 0xC, + Socket_423 = 0xD, + Socket_A_462 = 0xE, + Socket_478 = 0xF, + Socket_754 = 0x10, + Socket_940 = 0x11, + Socket_939 = 0x12, + Socket_mPGA604 = 0x13, + Socket_LGA771 = 0x14, + Socket_LGA775 = 0x15, + Socket_S1 = 0x16, + Socket_AM2 = 0x17, + Socket_F_1207 = 0x18, + Socket_LGA1366 = 0x19, + Socket_G34 = 0x1A, + Socket_AM3 = 0x1B, + Socket_C32 = 0x1C, + Socket_LGA1156 = 0x1D, + Socket_LGA1567 = 0x1E, + Socket_PGA988A = 0x1F, + Socket_BGA1288 = 0x20, + Socket_rPGA988B = 0x21, + Socket_BGA1023 = 0x22, + Socket_BGA1224 = 0x23, + Socket_LGA1155 = 0x24, + Socket_LGA1356 = 0x25, + Socket_LGA2011 = 0x26, + Socket_FS1 = 0x27, + Socket_FS2 = 0x28, + Socket_FM1 = 0x29, + Socket_FM2 = 0x2A, + Socket_LGA2011_3 = 0x2B, + Socket_LGA1356_3 = 0x2C, + Socket_LGA1150 = 0x2D, + Socket_BGA1168 = 0x2E, + Socket_BGA1234 = 0x2F, + Socket_BGA1364 = 0x30, + Socket_AM4 = 0x31, + Socket_LGA1151 = 0x32, + Socket_BGA1356 = 0x33, + Socket_BGA1440 = 0x34, + Socket_BGA1515 = 0x35, + Socket_LGA3647_1 = 0x36, + Socket_SP3 = 0x37, + Socket_SP3r2 = 0x38, + Socket_LGA2066 = 0x39, + Socket_BGA1392 = 0x3A, + Socket_BGA1510 = 0x3B, + Socket_BGA1528 = 0x3C +}; + +struct CacheInfo { // Type 7 + TableHeader h; + u8 socket_designation_str_number; + u16 cache_config; + u16 max_cache_size; + u16 installed_size; + u16 supported_sram_type; + u16 current_sram_type; + u8 cache_speed; + u8 error_correction_type; + u8 system_cache_type; + u8 associativity; + u32 max_cache_size2; + u32 installed_size2; +} __attribute__((packed)); + +struct PortConnectorInfo { // Type 8 + TableHeader h; + u8 internal_reference_designator_str_number; + u8 internal_connector_type; + u8 external_reference_designator_str_number; + u8 external_connector_type; + u8 port_type; +} __attribute__((packed)); + +enum class ConnectorType { + None = 0x0, + Centronics = 0x1, + Mini_Centronics = 0x2, + Proprietary = 0x3, + DB_25_pin_male = 0x4, + DB_25_pin_female = 0x5, + DB_15_pin_male = 0x6, + DB_15_pin_female = 0x7, + DB_9_pin_male = 0x8, + DB_9_pin_female = 0x9, + RJ_11 = 0xA, + RJ_45 = 0xB, + MiniSCSI_50_pin = 0xC, + MiniDIN = 0xD, + MicroDIN = 0xE, + PS2 = 0xF, + Infrared = 0x10, + HP_HIL = 0x11, + AccessBus_USB = 0x12, + SSA_SCSI = 0x13, + Circular_DIN8_male = 0x14, + Circular_DIN8_female = 0x15, + OnBoard_IDE = 0x16, + OnBoard_Floppy = 0x17, + Dual_Inline_9pin = 0x18, + Dual_Inline_25pin = 0x19, + Dual_Inline_50pin = 0x1A, + Dual_Inline_68pin = 0x1B, + OnBoard_SoundInput_CDROM = 0x1C, + Mini_Centronics_Type14 = 0x1D, + Mini_Centronics_Type26 = 0x1E, + Mini_Jack_Headphones = 0x1F, + BNC = 0x20, + Connector_1394 = 0x21, + SAS_SATA_Plug_Receptacle = 0x22, + USB_TypeC_Receptacle = 0x23, + PC98 = 0xA0, + PC98_Hireso = 0xA1, + PC_H98 = 0xA2, + PC98_Note = 0xA3, + PC98_Full = 0xA4, + Other = 0xFF +}; + +enum class PortType { + None = 0x0, + Parallel_Port_XT_AT_Compatible = 0x1, + Parallel_Port_PS2 = 0x2, + Parallel_Port_ECP = 0x3, + Parallel_Port_EPP = 0x4, + Parallel_Port_ECP_EPP = 0x5, + Serial_Port_XT_AT_Compatible = 0x6, + Serial_Port_16450_Compatible = 0x7, + Serial_Port_16550_Compatible = 0x8, + Serial_Port_16550A_Compatible = 0x9, + SCSI_Port = 0xA, + MIDI_Port = 0xB, + Joy_Stick_Port = 0xC, + Keyboard_Port = 0xD, + Mouse_Port = 0xE, + SSA_SCSI = 0xF, + USB = 0x10, + FireWire = 0x11, + PCMCIA_Type1 = 0x12, + PCMCIA_Type2 = 0x13, + PCMCIA_Type3 = 0x14, + Cardbus = 0x15, + AccessBus_Port = 0x16, + SCSI_2 = 0x17, + SCSI_Wide = 0x18, + PC98 = 0x19, + PC98_Hireso = 0x1A, + PC_H98 = 0x1B, + Video_Port = 0x1C, + Audio_Port = 0x1D, + Modem_Port = 0x1E, + Network_Port = 0x1F, + SATA = 0x20, + SAS = 0x21, + MFDP = 0x22, + Thunderbolt = 0x23, + Intel_8251_Compatible = 0xA0, + Intel_8251_FIFO_Compatible = 0xA1, + Other = 0xFF +}; + +struct SystemSlotPeerGroup { + u16 segment_group_number; + u8 bus_number; + u8 device_function_number; + u8 data_bus_width; +} __attribute__((packed)); + +struct SystemSlots { // Type 9 + TableHeader h; + u8 slot_designation_str_number; + u8 slot_type; + u8 slot_data_bus_width; + u8 current_stage; + u8 slot_length; + u16 slot_id; + u8 slot_characteristics_1; + u8 slot_characteristics_2; + u16 segment_group_number; + u8 bus_number; + u8 device_function_number; + u8 data_bus_width; + u8 peer_grouping_count; + SystemSlotPeerGroup peer_groups[]; +} __attribute__((packed)); + +enum class SlotType { + Other = 0x1, + Unknown = 0x2, + ISA = 0x3, + MCA = 0x4, + EISA = 0x5, + PCI = 0x6, + PCMCIA = 0x7, + VL_VESA = 0x8, + Proprietary = 0x9, + Processor_Card_Slot = 0xA, + Proprietary_Memory_Card_Slot = 0xB, + IO_Riser_Card_Slot = 0xC, + NuBus = 0xD, + PCI_66MHZ_Capable = 0xE, + AGP = 0xF, + AGP_2X = 0x10, + AGP_4X = 0x11, + PCI_X = 0x12, + AGP_8X = 0x13, + M_Dot_2_Socket_1_DP = 0x14, + M_Dot_2_Socket_1_SD = 0x15, + M_Dot_2_Socket_2 = 0x16, + M_Dot_2_Socket_3 = 0x17, + MXM_Type1 = 0x18, + MXM_Type2 = 0x19, + MXM_Type3_Standard = 0x1A, + MXM_Type3_HE = 0x1B, + MXM_Type4 = 0x1C, + MXM_3_Type_A = 0x1D, + MXM_3_Type_B = 0x1E, + PCI_Express_Gen2 = 0x1F, + PCI_Express_Gen3 = 0x20, + PCI_Express_Mini_52pin_Type1 = 0x21, + PCI_Express_Mini_52pin_Type2 = 0x22, + PCI_Express_Mini_76pin = 0x23, + CXL_Flexbus_1_0 = 0x30, + PC98_C20 = 0xA0, + PC98_C24 = 0xA1, + PC98_E = 0xA2, + PC98_Local_Bus = 0xA3, + PC98_Card = 0xA4, + PCI_Express = 0xA5, + PCI_Express_x1 = 0xA6, + PCI_Express_x2 = 0xA7, + PCI_Express_x4 = 0xA8, + PCI_Express_x8 = 0xA9, + PCI_Express_x16 = 0xAA, + PCI_Express_Gen_2 = 0xAB, + PCI_Express_Gen_2_x1 = 0xAC, + PCI_Express_Gen_2_x2 = 0xAD, + PCI_Express_Gen_2_x4 = 0xAE, + PCI_Express_Gen_2_x8 = 0xAF, + PCI_Express_Gen_2_x16 = 0xB0, + PCI_Express_Gen_3 = 0xB1, + PCI_Express_Gen_3_x1 = 0xB2, + PCI_Express_Gen_3_x2 = 0xB3, + PCI_Express_Gen_3_x4 = 0xB4, + PCI_Express_Gen_3_x8 = 0xB5, + PCI_Express_Gen_3_x16 = 0xB6, + PCI_Express_Gen_4 = 0xB8, + PCI_Express_Gen_4_x1 = 0xB9, + PCI_Express_Gen_4_x2 = 0xBA, + PCI_Express_Gen_4_x4 = 0xBB, + PCI_Express_Gen_4_x8 = 0xBC, + PCI_Express_Gen_4_x16 = 0xBD +}; + +enum class SlotDataBusWidth { + Other = 0x1, + Unknown = 0x2, + _8_bit = 0x3, + _16_bit = 0x4, + _32_bit = 0x5, + _64_bit = 0x6, + _128_bit = 0x7, + _1x_x1 = 0x8, + _2x_x2 = 0x9, + _4x_x4 = 0xA, + _8x_x8 = 0xB, + _12x_x12 = 0xC, + _16x_x16 = 0xD, + _32x_x32 = 0xE +}; + +enum class SlotCurrentUsage { + Other = 0x1, + Unknown = 0x2, + Available = 0x3, + In_Use = 0x4, + Unavailable = 0x5 +}; + +enum class SlotLength { + Other = 0x1, + Unknown = 0x2, + Short_Length = 0x3, + Long_Length = 0x4, + _2_5_Drive_Form_Factor = 0x5, + _3_5_Drive_Form_Factor = 0x6 +}; + +enum class SlotCharacteristics1 { + Unknown = (1 << 0), + Provides_5volt = (1 << 1), + Provides_3_3volt = (1 << 2), + Shared_Slot = (1 << 3), + Support_PC_Card_16 = (1 << 4), + Support_CardBus = (1 << 5), + Support_Zoom_Video = (1 << 6), + Support_Modem_Ring_Resume = (1 << 7) +}; + +enum class SlotCharacteristics2 { + Support_PCI_PME = (1 << 0), + Support_Hot_Plug = (1 << 1), + Support_SMBus = (1 << 2), + Support_Bifurcation = (1 << 3), +}; + +struct OEMStrings { // Type 11 + TableHeader h; + u8 strings_count; +} __attribute__((packed)); + +struct SysConfigOptions { // Type 12 + TableHeader h; + u8 strings_count; +} __attribute__((packed)); + +struct BIOSLanguageInfo { // Type 13 + TableHeader h; + u8 installable_langs_counts; + u8 flags; + u8 reserved[15]; + u8 current_lang_str_number; // String number (one-based) of the currently installed language +} __attribute__((packed)); + +struct GroupAssociations { // Type 14 + TableHeader h; + u8 group_name_str_number; + u8 item_type; + u16 item_handle; +} __attribute__((packed)); + +struct SysEventLog { // Type 15 + TableHeader h; + u16 log_area_length; + u16 log_header_start_offset; + u16 log_data_start_offset; + u8 access_method; + u8 log_status; + u32 log_change_token; + u32 access_method_address; + u8 log_header_format; + u8 supported_log_type_descriptors_count; + u8 log_type_descriptor_length; + u8 supported_event_log_type_descriptor_list[]; +} __attribute__((packed)); + +struct PhysicalMemoryArray { // Type 16 + TableHeader h; + u8 location; + u8 use; + u8 memory_error_correction; + u32 max_capacity; + u16 memory_error_info_handle; + u16 memory_devices_count; + u64 ext_max_capacity; +} __attribute__((packed)); + +enum class MemoryArrayLocation { + Other = 0x1, + Unknown = 0x2, + Motherboard = 0x3, + ISA_addon_card = 0x4, + EISA_addon_card = 0x5, + PCI_addon_card = 0x6, + MCA_addon_card = 0x7, + PCMCIA_addon_card = 0x8, + Proprietary_addon_card = 0x9, + NuBus = 0xA, + PC98_C20_addon_card = 0xA0, + PC98_C24_addon_card = 0xA1, + PC98_E_addon_card = 0xA2, + PC98_Local_Bus_addon_card = 0xA3, + CXL_Flexbus_1_0_addon_card = 0xA4 +}; + +enum class MemoryArrayUse { + Other = 0x1, + Unknown = 0x2, + System_Memory = 0x3, + Video_Memory = 0x4, + Flash_Memory = 0x5, + Non_Volatile_RAM = 0x6, + Cache_Memory = 0x7 +}; + +enum class MemoryArrayErrorCorrectionType { + Other = 0x1, + Unknown = 0x2, + None = 0x3, + Parity = 0x4, + SingleBit_ECC = 0x5, + MultiBit_ECC = 0x6, + CRC = 0x7 +}; + +struct MemoryDevice { // Type 17 + TableHeader h; + u16 physical_memory_array_handle; + u16 memory_error_info_handle; + u16 total_width; + u16 data_width; + u16 size; + u8 form_factor; + u8 device_set; + u8 device_locator_str_number; + u8 bank_locator_str_number; + u8 memory_type; + u16 type_detail; + u16 speed; + u8 manufacturer_str_number; + u8 serial_number_str_number; + u8 asset_tag_str_number; + u8 part_number_str_number; + u8 attributes; + u32 ext_size; + u16 configured_memory_speed; + u16 min_voltage; + u16 max_voltage; + u16 configured_voltage; + u8 memory_technology; + u16 memory_operating_mode_capability; + u8 firmware_version_str_number; + u16 module_manufacturer_id; + u16 module_product_id; + u16 memory_subsystem_controller_manufacturer_id; + u16 memory_subsystem_controller_product_id; + u64 non_volatile_size; + u64 volatile_size; + u64 cache_size; + u64 logical_size; + u32 ext_speed; + u32 ext_configured_memory_speed; +} __attribute__((packed)); + +enum class MemoryDeviceFormFactor { + Other = 0x1, + Unknown = 0x2, + SIMM = 0x3, + SIP = 0x4, + Chip = 0x5, + DIP = 0x6, + ZIP = 0x7, + ProprietaryCard = 0x8, + DIMM = 0x9, + TSOP = 0xA, + Chips_Row = 0xB, + RIMM = 0xC, + SODIMM = 0xD, + SRIMM = 0xE, + FB_DIMM = 0xF, + Die = 0x10 +}; + +enum class MemoryDeviceType { + Other = 0x1, + Unknown = 0x2, + DRAM = 0x3, + EDRAM = 0x4, + VRAM = 0x5, + SRAM = 0x6, + RAM = 0x7, + ROM = 0x8, + FLASH = 0x9, + EEPROM = 0xA, + FEPROM = 0xB, + EPROM = 0xC, + CDRAM = 0xD, + _3DRAM = 0xE, + SDRAM = 0xF, + SGRAM = 0x10, + RDRAM = 0x11, + DDR = 0x12, + DDR2 = 0x13, + DDR2_FB_DIMM = 0x14, + DDR3 = 0x18, + FBD2 = 0x19, + DDR4 = 0x1A, + LPDDR = 0x1B, + LPDDR2 = 0x1C, + LPDDR3 = 0x1D, + LPDDR4 = 0x1E, + Logical_Non_Volatile_Device = 0x1F, + HBM = 0x20, // (High Bandwidth Memory) + HBM2 = 0x21, // (High Bandwidth Memory Generation 2) +}; + +enum class MemoryDeviceTypeDetail { + Other = (1 << 1), + Unknown = (1 << 2), + Fast_paged = (1 << 3), + Static_Column = (1 << 4), + Pseudo_Static = (1 << 5), + RAMBUS = (1 << 6), + Synchronous = (1 << 7), + CMOS = (1 << 8), + EDO = (1 << 9), + Window_DRAM = (1 << 10), + Cache_DRAM = (1 << 11), + Non_volatile = (1 << 12), + Registered_Buffered = (1 << 13), + Unbuffered_Unregistered = (1 << 14), + LRDIMM = (1 << 15) +}; + +enum class MemoryDeviceTechnology { + Other = 0x1, + Unknown = 0x2, + DRAM = 0x3, + NVDIMM_N = 0x4, + NVDIMM_F = 0x5, + NVDIMM_P = 0x6, + Intel_Optane_DC_Persistent_Memory = 0x7 +}; + +enum class MemoryDeviceOperatingModeCapability { + Other = (1 << 1), + Unknown = (1 << 2), + Volatile_Memory = (1 << 3), + Byte_accessible_persistent_memory = (1 << 4), + Block_accessible_persistent_memory = (1 << 5), +}; + +struct MemoryErrorInfo32Bit { // Type 18 + TableHeader h; + u8 error_type; + u8 error_granularity; + u8 error_operation; + u32 vendor_syndrome; + u32 memory_array_error_address; + u32 device_error_address; + u32 error_resolution; +} __attribute__((packed)); + +enum class MemoryErrorType { + Other = 0x1, + Unknown = 0x2, + OK = 0x3, + Bad_read = 0x4, + Parity_error = 0x5, + SingleBit_error = 0x6, + DoubleBit_error = 0x7, + MultiBit_error = 0x8, + Nibble_error = 0x9, + Checksum_error = 0xA, + CRC_error = 0xB, + Corrected_SingleBit_error = 0xC, + Corrected_error = 0xD, + Uncorrectable_error = 0xE +}; + +enum class MemoryErrorGranularity { + Other = 0x1, + Unknown = 0x2, + Device_level = 0x3, + Memory_partition_level = 0x4 +}; + +enum class MemoryErrorOperation { + Other = 0x1, + Unknown = 0x2, + Read = 0x3, + Write = 0x4, + Partial_Write = 0x5 +}; + +struct MemoryArrayMappedAddress { // Type 19 + TableHeader h; + u32 starting_address; + u32 ending_address; + u16 memory_array_handle; + u8 partition_width; + u64 ext_starting_address; + u64 ext_ending_address; +} __attribute__((packed)); + +struct MemoryDeviceMappedAddress { // Type 20 + TableHeader h; + u32 starting_address; + u32 ending_address; + u16 memory_device_handle; + u16 memory_array_mapped_handle; + u8 partition_row_position; + u8 interleave_position; + u8 interleaved_data_depth; + u64 ext_starting_address; + u64 ext_ending_address; + +} __attribute__((packed)); + +struct BuiltinPointingDevice { // Type 21 + TableHeader h; + u8 type; + u8 interface; + u8 buttons_count; +} __attribute__((packed)); + +enum class PointingDeviceType { + Other = 0x1, + Unknown = 0x2, + Mouse = 0x3, + Track_Ball = 0x4, + Track_Point = 0x5, + Glide_Point = 0x6, + Touch_Pad = 0x7, + Touch_Screen = 0x8, + Optical_Sensor = 0x9 +}; + +enum class PointingDeviceInterface { + Other = 0x1, + Unknown = 0x2, + Serial = 0x3, + PS2 = 0x4, + Infrared = 0x5, + HP_HIL = 0x6, + Bus_mouse = 0x7, + AppleDesktopBus = 0x8, + Bus_mouse_DB9 = 0xA0, + Bus_mouse_microDIN = 0xA1, + USB = 0xA2 +}; + +struct PortableBattery { // Type 22 + TableHeader h; + u8 location_str_number; + u8 manufacturer_str_number; + u8 manufacture_date_str_number; + u8 serial_number_str_number; + u8 device_name_str_number; + u8 device_chemistry; + u16 design_capacity; + u16 design_voltage; + u8 sbds_version_number; + u8 max_error_battery_data; + u16 sbds_serial_number; + u16 sbds_manufacture_date; + u8 sbds_device_chemistry_str_number; + u8 design_capacity_multiplier; + u32 oem_specific; +} __attribute__((packed)); + +enum class PortableBatteryChemistry { + Other = 0x1, + Unknown = 0x2, + Lead_Acid = 0x3, + Nickel_Cadmium = 0x4, + Nickel_metal_hydride = 0x5, + Lithium_ion = 0x6, + Zinc_air = 0x7, + Lithium_polymer = 0x8 +}; + +struct SysReset { // Type 23 + TableHeader h; + u8 capabilities; + u16 reset_count; + u16 reset_limit; + u16 timer_interval; + u16 timeout; +} __attribute__((packed)); + +struct HardwareSecurity { // Type 24 + TableHeader h; + u8 hardware_security_settings; +} __attribute__((packed)); + +struct SysPowerControls { // Type 25 + TableHeader h; + u8 next_scheduled_power_on_month; + u8 next_scheduled_power_on_day_of_month; + u8 next_scheduled_power_on_hour; + u8 next_scheduled_power_on_minute; + u8 next_scheduled_power_on_second; +} __attribute__((packed)); + +struct VoltageProbe { // Type 26 + TableHeader h; + u8 description_str_number; + u8 location_and_status; + u16 max_value; + u16 min_value; + u16 resolution; + u16 tolerance; + u16 accuracy; + u32 oem_defined; + u16 nominal_value; +} __attribute__((packed)); + +struct CoolingDevice { // Type 27 + TableHeader h; + u16 temperature_probe_handle; + u8 device_type_and_status; + u8 cooling_unit_group; + u32 oem_defined; + u16 nominal_speed; + u8 description_str_number; +} __attribute__((packed)); + +struct TemperatureProbe { // Type 28 + TableHeader h; + u8 description_str_number; + u8 location_and_status; + u16 max_value; + u16 min_value; + u16 resolution; + u16 tolerance; + u16 accuracy; + u32 oem_defined; + u16 nominal_value; +} __attribute__((packed)); + +struct ElectricalCurrentProbe { // Type 29 + TableHeader h; + u8 description_str_number; + u8 location_and_status; + u16 max_value; + u16 min_value; + u16 resolution; + u16 tolerance; + u16 accuracy; + u32 oem_defined; + u16 nominal_value; +} __attribute__((packed)); + +struct OutOfBandRemoteAccess { // Type 30 + TableHeader h; + u8 manufacturer_name_str_number; + u8 connections; +} __attribute__((packed)); + +struct SystemBootInfo { // Type 32 + TableHeader h; + u8 reserved[6]; + u8 boot_status[10]; +} __attribute__((packed)); + +struct MemoryErrorInfo64Bit { // Type 33 + TableHeader h; + u8 error_type; + u8 error_granularity; + u8 error_operation; + u32 vendor_syndrome; + u64 memory_array_error_address; + u64 device_error_address; + u32 error_resolution; +} __attribute__((packed)); + +struct ManagementDevice { // Type 34 + TableHeader h; + u8 description_str_number; + u8 type; + u32 address; + u8 address_type; +} __attribute__((packed)); + +enum class ManagementDeviceType { + Other = 0x1, + Unknown = 0x2, + LM75 = 0x3, + LM78 = 0x4, + LM79 = 0x5, + LM80 = 0x6, + LM81 = 0x7, + ADM9240 = 0x8, + DS1780 = 0x9, + Maxim_1617 = 0xA, + GL518SM = 0xB, // Genesys GL518SM + W83781D = 0xC, // Winbond W83781D + HT82H791 = 0xD // Holtek HT82H791 +}; + +enum class ManagementDeviceAddressType { + Other = 0x1, + Unknown = 0x2, + IO_Port = 0x3, + Memory = 0x4, + SMBus = 0x5 +}; + +struct ManagementDeviceComponent { // Type 35 + TableHeader h; + u8 description_str_number; + u16 management_device_handle; + u16 component_handle; + u16 threshold_handle; +} __attribute__((packed)); + +struct ManagementDeviceThresholdData { // Type 36 + TableHeader h; + u16 lower_threshold_non_critical; + u16 upper_threshold_non_critical; + u16 lower_threshold_critical; + u16 upper_threshold_critical; + u16 lower_threshold_non_recoverable; + u16 upper_threshold_non_recoverable; +} __attribute__((packed)); + +struct MemoryDeviceDescriptor { + u8 device_load; + u16 device_handle; +} __attribute__((packed)); + +struct MemoryChannel { // Type 37 + TableHeader h; + u8 channel_type; + u8 memory_device_count; + MemoryDeviceDescriptor memory_devices_descriptors[]; +} __attribute__((packed)); + +enum class MemroryChannelType { + Other = 0x1, + Unknown = 0x2, + RamBus = 0x3, + SyncLink = 0x4 +}; + +struct IPMIDeviceInfo { // Type 38 + TableHeader h; + u8 interface_type; + u8 ipmi_spec_revision; + u8 i2c_slave_address; + u8 nv_storage_device_address; + u64 base_address; + u8 base_address_modifier; + u8 interrupt_number; +} __attribute__((packed)); + +enum class IPMIDeviceInfoBMCInterfaceType { + Unknown = 0x1, + KCS = 0x2, // KCS: Keyboard Controller Style + SMIC = 0x3, // SMIC: Server Management Interface Chip + BT = 0x4, // BT: Block Transfer + SSIF = 0x5 // SSIF: SMBus System Interface +}; + +struct SysPowerSupply { // Type 39 + TableHeader h; + u8 power_unit_group; + u8 location_str_number; + u8 device_name_str_number; + u8 manufacturer_str_number; + u8 serial_number_str_number; + u8 asset_tag_number_str_number; + u8 model_part_number_str_number; + u8 revision_level_str_number; + u16 max_power_capacity; + u16 power_supply_characteristics; + u16 input_voltage_probe_handle; + u16 cooling_device_handle; + u16 input_current_probe_handle; +} __attribute__((packed)); + +struct AdditionalInfoEntry { + u8 entry_length; + u16 referenced_handle; + u8 referenced_offset; + u8 string_number; + u8 value[]; +} __attribute__((packed)); + +struct AdditionalInfo { // Type 40 + TableHeader h; + u8 additional_info_entries_count; + AdditionalInfoEntry entries[]; +} __attribute__((packed)); + +struct OnboardDevicesExtendedInfo { // Type 41 + TableHeader h; + u8 reference_designation_str_number; + u8 device_type; + u8 device_type_instance; + u16 segment_group_number; + u8 bus_number; + u8 device_function_number; +} __attribute__((packed)); + +enum class OnboardDeviceType { + Other = 0x1, + Unknown = 0x2, + Video = 0x3, + SCSI_Controller = 0x4, + Ethernet = 0x5, + Token_Ring = 0x6, + Sound = 0x7, + PATA_Controller = 0x8, + SATA_Controller = 0x9, + SAS_Controller = 0xA +}; + +struct ManagementControllerHostInterface { // Type 42 + TableHeader h; + u8 interface_type; + u8 interface_type_specific_data_length; + u8 interface_type_specific_data[]; +} __attribute__((packed)); + +struct ProtocolRecordData { + u8 protocol_type; + u8 protocol_type_specific_data_length; + u8 protocol_type_specific_data[]; +} __attribute__((packed)); + +struct ExtManagementControllerHostInterface { // Type 42 Ext + u8 protocol_records_count; + ProtocolRecordData protocol_records[]; +} __attribute__((packed)); + +enum class ManagementControllerHostInterfaceProtocolType { + IPMI = 0x2, + MCTP = 0x3, + RedfishOverIP = 0x4 +}; + +struct TPMDevice { // Type 43 + TableHeader h; + char vendor_id[4]; + u8 major_spec_version; + u8 minor_spec_version; + u32 firmware_version_1; + u32 firmware_version_2; + u8 description_str_number; + u64 characteristics; + u32 oem_defined; +} __attribute__((packed)); + +enum class TPMDeviceCharacteristics { + Characteristics_not_supported = (1 << 2), + Family_Configurable_1 = (1 << 3), // Family configurable via firmware update; for example, switching between TPM 1.2 and TPM 2.0. + Family_Configurable_2 = (1 << 4), // Family configurable via platform software support, such as BIOS Setup; for example, switching between TPM 1.2 and TPM 2.0. + Family_Configurable_3 = (1 << 5), // Family configurable via OEM proprietary mechanism; for example, switching between TPM 1.2 and TPM 2.0. +}; + +struct ProcessorSpecificBlock { + u8 block_length; + u8 processor_type; + u8 processor_specific_data[]; +} __attribute__((packed)); + +struct ProcessorAdditionalInfo { // Type 44 + TableHeader h; + u16 referenced_handle; + ProcessorSpecificBlock blocks[]; +} __attribute__((packed)); + +enum class ProcessorArchitectureType { + IA32 = 0x1, + x86_64 = 0x2, + Itanium = 0x3, + ARM32bit = 0x4, + ARM64bit = 0x5, + RISC_V_32bit = 0x6, + RISC_V_64bit = 0x7, + RISC_V_128bit = 0x8 +}; + +struct Inactive { // Type 126 + TableHeader h; +} __attribute__((packed)); + +struct EndOfTable { // Type 127 + TableHeader h; +} __attribute__((packed)); +} + +class DMIDecoder { +public: + static DMIDecoder& the(); + static void initialize(); + static void initialize_untrusted(); + Vector& get_physical_memory_areas(); + bool is_reliable(); + u64 get_bios_characteristics(); + +private: + void enumerate_smbios_tables(); + SMBIOS::TableHeader* get_next_physical_table(SMBIOS::TableHeader& p_table); + SMBIOS::TableHeader* get_smbios_physical_table_by_handle(u16 handle); + SMBIOS::TableHeader* get_smbios_physical_table_by_type(u8 table_type); + char* get_smbios_string(SMBIOS::TableHeader& p_table, u8 string_number); + size_t get_table_size(SMBIOS::TableHeader& table); + + explicit DMIDecoder(bool trusted); + void initialize_parser(); + + SMBIOS::EntryPoint32bit* find_entry32bit_point(); + SMBIOS::EntryPoint64bit* find_entry64bit_point(); + + void mmap(VirtualAddress vaddr, PhysicalAddress paddr, u32 length); + void mmap_region(Region& region, PhysicalAddress paddr); + + SMBIOS::EntryPoint32bit* m_entry32bit_point; + SMBIOS::EntryPoint64bit* m_entry64bit_point; + SMBIOS::TableHeader* m_structure_table; + u32 m_structures_count; + u32 m_table_length; + bool m_use_64bit_entry; + bool m_operable; + bool m_untrusted; + + SinglyLinkedList m_smbios_tables; +};