diff --git a/pkg/facter/report.go b/pkg/facter/report.go index 0e4d7d0..355cbcf 100644 --- a/pkg/facter/report.go +++ b/pkg/facter/report.go @@ -2,7 +2,6 @@ package facter import ( "fmt" - "slices" "github.com/numtide/nixos-facter/pkg/build" "github.com/numtide/nixos-facter/pkg/hwinfo" @@ -10,18 +9,10 @@ import ( ) type Report struct { - Virtualisation virt.Type `json:"virtualisation"` Hardware []*hwinfo.HardwareItem `json:"hardware"` + Smbios []hwinfo.Smbios `json:"smbios,omitempty"` System string `json:"system"` -} - -func (r *Report) AddHardwareItem(item *hwinfo.HardwareItem) { - r.Hardware = append(r.Hardware, item) - - // canonically sort by device index - slices.SortFunc(r.Hardware, func(a, b *hwinfo.HardwareItem) int { - return int(a.Index) - int(b.Index) - }) + Virtualisation virt.Type `json:"virtualisation"` } func GenerateReport() (*Report, error) { @@ -32,14 +23,12 @@ func GenerateReport() (*Report, error) { } report.System = build.System - if err := hwinfo.Scan(func(item *hwinfo.HardwareItem) error { - report.AddHardwareItem(item) - return nil - }); err != nil { + var err error + report.Smbios, report.Hardware, err = hwinfo.Scan() + if err != nil { return nil, fmt.Errorf("failed to scan hardware: %w", err) } - var err error if report.Virtualisation, err = virt.Detect(); err != nil { return nil, fmt.Errorf("failed to detect virtualisation: %w", err) } diff --git a/pkg/hwinfo/hwinfo.go b/pkg/hwinfo/hwinfo.go index 396e697..9a491b4 100644 --- a/pkg/hwinfo/hwinfo.go +++ b/pkg/hwinfo/hwinfo.go @@ -4,27 +4,46 @@ package hwinfo #cgo pkg-config: hwinfo #include #include + +// CGO cannot access union type fields, so we do this as a workaround +hd_smbios_t* hd_smbios_next(hd_smbios_t *sm) { return sm->next; } */ import "C" import ( + "slices" "unsafe" ) -func Scan(f func(item *HardwareItem) error) error { +func Scan() ([]Smbios, []*HardwareItem, error) { data := (*C.hd_data_t)(unsafe.Pointer(C.calloc(1, C.size_t(unsafe.Sizeof(C.hd_data_t{}))))) C.hd_set_probe_feature(data, C.enum_probe_feature(ProbeFeatureAll)) C.hd_scan(data) defer C.hd_free_hd_data(data) + var smbiosItems []Smbios + for sm := data.smbios; sm != nil; sm = C.hd_smbios_next(sm) { + item, err := NewSmbios(sm) + if err != nil { + return nil, nil, err + } + smbiosItems = append(smbiosItems, item) + } + + var hardwareItems []*HardwareItem for hd := data.hd; hd != nil; hd = hd.next { if item, err := NewHardwareItem(hd); err != nil { - return err - } else if err = f(item); err != nil { - return err + return nil, nil, err + } else { + hardwareItems = append(hardwareItems, item) } } - return nil + // canonically sort by device index + slices.SortFunc(hardwareItems, func(a, b *HardwareItem) int { + return int(a.Index) - int(b.Index) + }) + + return smbiosItems, hardwareItems, nil } diff --git a/pkg/hwinfo/smbios.go b/pkg/hwinfo/smbios.go new file mode 100644 index 0000000..215d365 --- /dev/null +++ b/pkg/hwinfo/smbios.go @@ -0,0 +1,161 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include + +// CGO cannot access union type fields, so we do this as a workaround +hd_smbios_type_t hd_smbios_get_type(hd_smbios_t *sm) { return sm->any.type; } +smbios_biosinfo_t hd_smbios_get_biosinfo(hd_smbios_t *sm) { return sm->biosinfo; } +smbios_sysinfo_t hd_smbios_get_sysinfo(hd_smbios_t *sm) { return sm->sysinfo; } +smbios_boardinfo_t hd_smbios_get_boardinfo(hd_smbios_t *sm) { return sm->boardinfo; } +smbios_chassis_t hd_smbios_get_chassis(hd_smbios_t *sm) { return sm->chassis; } +smbios_processor_t hd_smbios_get_processor(hd_smbios_t *sm) { return sm->processor; } +smbios_cache_t hd_smbios_get_cache(hd_smbios_t *sm) { return sm->cache; } +smbios_connect_t hd_smbios_get_connect(hd_smbios_t *sm) { return sm->connect; } +smbios_slot_t hd_smbios_get_slot(hd_smbios_t *sm) { return sm->slot; } +smbios_onboard_t hd_smbios_get_onboard(hd_smbios_t *sm) { return sm->onboard; } +smbios_oem_t hd_smbios_get_oem(hd_smbios_t *sm) { return sm->oem; } +smbios_config_t hd_smbios_get_config(hd_smbios_t *sm) { return sm->config; } +smbios_lang_t hd_smbios_get_lang(hd_smbios_t *sm) { return sm->lang; } +smbios_group_t hd_smbios_get_group(hd_smbios_t *sm) { return sm->group; } +smbios_memarray_t hd_smbios_get_memarray(hd_smbios_t *sm) { return sm->memarray; } +smbios_memarraymap_t hd_smbios_get_memarraymap(hd_smbios_t *sm) { return sm->memarraymap; } +smbios_memdevice_t hd_smbios_get_memdevice(hd_smbios_t *sm) { return sm->memdevice; } +smbios_memerror_t hd_smbios_get_memerror(hd_smbios_t *sm) { return sm->memerror; } +smbios_mem64error_t hd_smbios_get_mem64error(hd_smbios_t *sm) { return sm->mem64error; } +smbios_memdevicemap_t hd_smbios_get_memdevicemap(hd_smbios_t *sm) { return sm->memdevicemap; } +smbios_mouse_t hd_smbios_get_mouse(hd_smbios_t *sm) { return sm->mouse; } +smbios_secure_t hd_smbios_get_secure(hd_smbios_t *sm) { return sm->secure; } +smbios_power_t hd_smbios_get_power(hd_smbios_t *sm) { return sm->power; } +smbios_any_t hd_smbios_get_any(hd_smbios_t *sm) { return sm->any; } +*/ +import "C" + +//go:generate enumer -type=SmbiosType -json -transform=snake -trimprefix SmbiosType -output=./smbios_enum_type.go +type SmbiosType uint + +// For a full list of types see https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.6.0.pdf. +// hwinfo doesn't provide structs for all of these, but we've ensured we at least have their ids so they format +// well in the json output when used with the Any type. +const ( + SmbiosTypeBios SmbiosType = iota + SmbiosTypeSystem + SmbiosTypeBoard + SmbiosTypeChassis + + SmbiosTypeProcessor + SmbiosTypeMemoryController + SmbiosTypeMemoryModule + SmbiosTypeCache + + SmbiosTypePortConnector + SmbiosTypeSlot + SmbiosTypeOnboard + SmbiosTypeOEMStrings + + SmbiosTypeConfig + SmbiosTypeLanguage + SmbiosTypeGroupAssociations + SmbiosTypeEventLog + + SmbiosTypeMemoryArray + SmbiosTypeMemoryDevice + SmbiosTypeMemoryError + SmbiosTypeMemoryArrayMappedAddress + + SmbiosTypeMemoryDeviceMappedAddress + SmbiosTypePointingDevice + SmbiosTypeBattery + SmbiosTypeSystemReset + + SmbiosTypeHardwareSecurity + SmbiosTypePowerControls + SmbiosTypeVoltage + SmbiosTypeCoolingDevice + + SmbiosTypeTemperature + SmbiosTypeCurrent + SmbiosTypeOutOfBandRemoteAccess + SmbiosTypeBootIntegrityServices + + SmbiosTypeSystemBoot + SmbiosTypeMemory64Error + SmbiosTypeManagementDevice + SmbiosTypeManDeviceComponent + SmbiosTypeManDeviceThreshold + SmbiosTypeMemoryChannel + SmbiosTypeIPMIDevice + + SmbiosTypeSystemPowerSupply + SmbiosTypeAdditionalInfo + SmbiosTypeOnboardExtended + SmbiosTypeManagementControllerHostInterface + SmbiosTypeTPM + SmbiosTypeProcessorAdditional + SmbiosFirmwareInventory + + SmbiosTypeInactive SmbiosType = 126 + SmbiosTypeEndOfTable SmbiosType = 127 +) + +type Smbios interface { + SmbiosType() SmbiosType +} + +func NewSmbios(smbios *C.hd_smbios_t) (Smbios, error) { + if smbios == nil { + return nil, nil + } + + smbiosType := SmbiosType(C.hd_smbios_get_type(smbios)) + + switch smbiosType { + case SmbiosTypeBios: + return NewSmbiosBiosInfo(C.hd_smbios_get_biosinfo(smbios)) + case SmbiosTypeSystem: + return NewSmbiosSysInfo(C.hd_smbios_get_sysinfo(smbios)) + case SmbiosTypeBoard: + return NewSmbiosBoardInfo(C.hd_smbios_get_boardinfo(smbios)) + case SmbiosTypeChassis: + return NewSmbiosChassis(C.hd_smbios_get_chassis(smbios)) + case SmbiosTypeProcessor: + return NewSmbiosProcessor(C.hd_smbios_get_processor(smbios)) + case SmbiosTypeCache: + return NewSmbiosCache(C.hd_smbios_get_cache(smbios)) + case SmbiosTypePortConnector: + return NewSmbiosConnect(C.hd_smbios_get_connect(smbios)) + case SmbiosTypeSlot: + return NewSmbiosSlot(C.hd_smbios_get_slot(smbios)) + case SmbiosTypeOnboard: + return NewSmbiosOnboard(C.hd_smbios_get_onboard(smbios)) + case SmbiosTypeOEMStrings: + return NewSmbiosOEM(C.hd_smbios_get_oem(smbios)) + case SmbiosTypeConfig: + return NewSmbiosConfig(C.hd_smbios_get_config(smbios)) + case SmbiosTypeLanguage: + return NewSmbiosLang(C.hd_smbios_get_lang(smbios)) + case SmbiosTypeGroupAssociations: + return NewSmbiosGroup(C.hd_smbios_get_group(smbios)) + case SmbiosTypeMemoryArray: + return NewSmbiosMemArray(C.hd_smbios_get_memarray(smbios)) + case SmbiosTypeMemoryDevice: + return NewSmbiosMemDevice(C.hd_smbios_get_memdevice(smbios)) + case SmbiosTypeMemoryError: + return NewSmbiosMemError(C.hd_smbios_get_memerror(smbios)) + case SmbiosTypeMemory64Error: + return NewSmbiosMem64Error(C.hd_smbios_get_mem64error(smbios)) + case SmbiosTypeMemoryArrayMappedAddress: + return NewSmbiosMemArrayMap(C.hd_smbios_get_memarraymap(smbios)) + case SmbiosTypeMemoryDeviceMappedAddress: + return NewSmbiosMemDeviceMap(C.hd_smbios_get_memdevicemap(smbios)) + case SmbiosTypePointingDevice: + return NewSmbiosMouse(C.hd_smbios_get_mouse(smbios)) + case SmbiosTypeHardwareSecurity: + return NewSmbiosSecure(C.hd_smbios_get_secure(smbios)) + case SmbiosTypePowerControls: + return NewSmbiosPower(C.hd_smbios_get_power(smbios)) + default: + return NewSmbiosAny(smbiosType, C.hd_smbios_get_any(smbios)) + } +} diff --git a/pkg/hwinfo/smbios_any.go b/pkg/hwinfo/smbios_any.go new file mode 100644 index 0000000..ed95b14 --- /dev/null +++ b/pkg/hwinfo/smbios_any.go @@ -0,0 +1,33 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +import ( + "fmt" + "unsafe" +) + +// SmbiosAny captures generic smbios data. +type SmbiosAny struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Data string `json:"data"` + Strings []string `json:"strings,omitempty"` +} + +func (s SmbiosAny) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosAny(smbiosType SmbiosType, info C.smbios_any_t) (Smbios, error) { + return SmbiosAny{ + Type: smbiosType, + Handle: int(info.handle), + Data: fmt.Sprintf("0x%x", ReadByteArray(unsafe.Pointer(info.data), int(info.data_len))), + Strings: ReadStringList(info.strings), + }, nil +} diff --git a/pkg/hwinfo/smbios_bios.go b/pkg/hwinfo/smbios_bios.go new file mode 100644 index 0000000..1183374 --- /dev/null +++ b/pkg/hwinfo/smbios_bios.go @@ -0,0 +1,40 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +import ( + "fmt" +) + +// SmbiosBios captures BIOS related information. +type SmbiosBios struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Vendor string `json:"vendor"` + Version string `json:"version"` + Date string `json:"date"` + Features []string `json:"features"` + StartAddress string `json:"start_address"` + RomSize uint `json:"rom_size"` +} + +func (s SmbiosBios) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosBiosInfo(info C.smbios_biosinfo_t) (Smbios, error) { + return SmbiosBios{ + Type: SmbiosTypeBios, + Handle: int(info.handle), + Vendor: C.GoString(info.vendor), + Version: C.GoString(info.version), + Date: C.GoString(info.date), + Features: ReadStringList(info.feature.str), + StartAddress: fmt.Sprintf("0x%x", uint(info.start)), + RomSize: uint(info.rom_size), + }, nil +} diff --git a/pkg/hwinfo/smbios_board.go b/pkg/hwinfo/smbios_board.go new file mode 100644 index 0000000..b9e7b45 --- /dev/null +++ b/pkg/hwinfo/smbios_board.go @@ -0,0 +1,45 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" +import "unsafe" + +// SmbiosBoard captures motherboard related information. +type SmbiosBoard struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Manufacturer string `json:"manufacturer"` + Product string `json:"product"` + Version string `json:"version"` + Serial string `json:"-"` // omit from json output + AssetTag string `json:"asset_tag,omitempty"` + BoardType *Id `json:"board_type"` + Features []string `json:"features"` + Location string `json:"location"` // location in chassis + Chassis int `json:"chassis"` // handle of chassis + Objects []int `json:"objects,omitempty"` // array of object handles +} + +func (s SmbiosBoard) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosBoardInfo(info C.smbios_boardinfo_t) (Smbios, error) { + return SmbiosBoard{ + Type: SmbiosTypeBoard, + Handle: int(info.handle), + Manufacturer: C.GoString(info.manuf), + Product: C.GoString(info.product), + Version: C.GoString(info.version), + Serial: C.GoString(info.serial), + AssetTag: C.GoString(info.asset), + BoardType: NewId(info.board_type), + Features: ReadStringList(info.feature.str), + Location: C.GoString(info.location), + Chassis: int(info.chassis), + Objects: ReadIntArray(unsafe.Pointer(info.objects), int(info.objects_len)), + }, nil +} diff --git a/pkg/hwinfo/smbios_cache.go b/pkg/hwinfo/smbios_cache.go new file mode 100644 index 0000000..7b57b1a --- /dev/null +++ b/pkg/hwinfo/smbios_cache.go @@ -0,0 +1,52 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosCache captures processor information. +type SmbiosCache struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Socket string `json:"socket"` // socket designation + SizeMax uint `json:"size_max"` // max cache size in kbytes + SizeCurrent uint `json:"size_current"` // current size in kbytes + Speed uint `json:"speed"` // cache speed in nanoseconds + Mode *Id `json:"mode"` // operational mode + Enabled bool `json:"enabled"` + Location *Id `json:"location"` // cache location + Socketed bool `json:"socketed"` + Level uint `json:"level"` // cache level (0 = L1, 1 = L2, ...) + ECC *Id `json:"ecc"` // error correction type + CacheType *Id `json:"cache_type"` // logical cache type + Associativity *Id `json:"associativity"` // cache associativity + SRAMType []string `json:"sram_type_current"` + SRAMTypes []string `json:"sram_type_supported"` +} + +func (s SmbiosCache) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosCache(info C.smbios_cache_t) (Smbios, error) { + return SmbiosCache{ + Type: SmbiosTypeCache, + Handle: int(info.handle), + Socket: C.GoString(info.socket), + SizeMax: uint(info.max_size), + SizeCurrent: uint(info.current_size), + Speed: uint(info.speed), + Mode: NewId(info.mode), + Enabled: uint(info.state) == 1, + Location: NewId(info.location), + Socketed: uint(info.socketed) == 1, + Level: uint(info.level), + ECC: NewId(info.ecc), + CacheType: NewId(info.cache_type), + Associativity: NewId(info.assoc), + SRAMType: ReadStringList(info.sram.str), + SRAMTypes: ReadStringList(info.supp_sram.str), + }, nil +} diff --git a/pkg/hwinfo/smbios_chassis.go b/pkg/hwinfo/smbios_chassis.go new file mode 100644 index 0000000..b454f01 --- /dev/null +++ b/pkg/hwinfo/smbios_chassis.go @@ -0,0 +1,47 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" +import "fmt" + +// SmbiosChassis captures motherboard related information. +type SmbiosChassis struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Manufacturer string `json:"manufacturer"` + Version string `json:"version"` + Serial string `json:"-"` // omit from json output + AssetTag string `json:"asset_tag,omitempty"` // asset tag + ChassisType *Id `json:"chassis_type"` + LockPresent bool `json:"lock_present"` // true: lock present, false: not present or unknown + BootupState *Id `json:"bootup_state"` + PowerState *Id `json:"power_state"` // power supply state (at last boot) + ThermalState *Id `json:"thermal_state"` // thermal state (at last boot) + SecurityState *Id `json:"security_state"` // security state (at last boot) + OEM string `json:"oem"` // oem-specific information" +} + +func (s SmbiosChassis) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosChassis(info C.smbios_chassis_t) (Smbios, error) { + return SmbiosChassis{ + Type: SmbiosTypeChassis, + Handle: int(info.handle), + Manufacturer: C.GoString(info.manuf), + Version: C.GoString(info.version), + Serial: C.GoString(info.serial), + AssetTag: C.GoString(info.asset), + ChassisType: NewId(info.ch_type), + LockPresent: uint(info.lock) == 1, + BootupState: NewId(info.bootup), + PowerState: NewId(info.power), + ThermalState: NewId(info.thermal), + SecurityState: NewId(info.security), + OEM: fmt.Sprintf("0x%x", uint(info.oem)), + }, nil +} diff --git a/pkg/hwinfo/smbios_config.go b/pkg/hwinfo/smbios_config.go new file mode 100644 index 0000000..abee11b --- /dev/null +++ b/pkg/hwinfo/smbios_config.go @@ -0,0 +1,26 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosConfig captures system config information. +type SmbiosConfig struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Options []string `json:"options,omitempty"` +} + +func (s SmbiosConfig) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosConfig(info C.smbios_config_t) (Smbios, error) { + return SmbiosConfig{ + Type: SmbiosTypeConfig, + Handle: int(info.handle), + Options: ReadStringList(info.options), + }, nil +} diff --git a/pkg/hwinfo/smbios_enum_type.go b/pkg/hwinfo/smbios_enum_type.go new file mode 100644 index 0000000..058b514 --- /dev/null +++ b/pkg/hwinfo/smbios_enum_type.go @@ -0,0 +1,291 @@ +// Code generated by "enumer -type=SmbiosType -json -transform=snake -trimprefix SmbiosType -output=./smbios_enum_type.go"; DO NOT EDIT. + +package hwinfo + +import ( + "encoding/json" + "fmt" + "strings" +) + +const ( + _SmbiosTypeName_0 = "biossystemboardchassisprocessormemory_controllermemory_modulecacheport_connectorslotonboardoem_stringsconfiglanguagegroup_associationsevent_logmemory_arraymemory_devicememory_errormemory_array_mapped_addressmemory_device_mapped_addresspointing_devicebatterysystem_resethardware_securitypower_controlsvoltagecooling_devicetemperaturecurrentout_of_band_remote_accessboot_integrity_servicessystem_bootmemory64_errormanagement_deviceman_device_componentman_device_thresholdmemory_channelipmi_devicesystem_power_supplyadditional_infoonboard_extendedmanagement_controller_host_interfacetpmprocessor_additionalsmbios_firmware_inventory" + _SmbiosTypeLowerName_0 = "biossystemboardchassisprocessormemory_controllermemory_modulecacheport_connectorslotonboardoem_stringsconfiglanguagegroup_associationsevent_logmemory_arraymemory_devicememory_errormemory_array_mapped_addressmemory_device_mapped_addresspointing_devicebatterysystem_resethardware_securitypower_controlsvoltagecooling_devicetemperaturecurrentout_of_band_remote_accessboot_integrity_servicessystem_bootmemory64_errormanagement_deviceman_device_componentman_device_thresholdmemory_channelipmi_devicesystem_power_supplyadditional_infoonboard_extendedmanagement_controller_host_interfacetpmprocessor_additionalsmbios_firmware_inventory" + _SmbiosTypeName_1 = "inactiveend_of_table" + _SmbiosTypeLowerName_1 = "inactiveend_of_table" +) + +var ( + _SmbiosTypeIndex_0 = [...]uint16{0, 4, 10, 15, 22, 31, 48, 61, 66, 80, 84, 91, 102, 108, 116, 134, 143, 155, 168, 180, 207, 235, 250, 257, 269, 286, 300, 307, 321, 332, 339, 364, 387, 398, 412, 429, 449, 469, 483, 494, 513, 528, 544, 580, 583, 603, 628} + _SmbiosTypeIndex_1 = [...]uint8{0, 8, 20} +) + +func (i SmbiosType) String() string { + switch { + case 0 <= i && i <= 45: + return _SmbiosTypeName_0[_SmbiosTypeIndex_0[i]:_SmbiosTypeIndex_0[i+1]] + case 126 <= i && i <= 127: + i -= 126 + return _SmbiosTypeName_1[_SmbiosTypeIndex_1[i]:_SmbiosTypeIndex_1[i+1]] + default: + return fmt.Sprintf("SmbiosType(%d)", i) + } +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _SmbiosTypeNoOp() { + var x [1]struct{} + _ = x[SmbiosTypeBios-(0)] + _ = x[SmbiosTypeSystem-(1)] + _ = x[SmbiosTypeBoard-(2)] + _ = x[SmbiosTypeChassis-(3)] + _ = x[SmbiosTypeProcessor-(4)] + _ = x[SmbiosTypeMemoryController-(5)] + _ = x[SmbiosTypeMemoryModule-(6)] + _ = x[SmbiosTypeCache-(7)] + _ = x[SmbiosTypePortConnector-(8)] + _ = x[SmbiosTypeSlot-(9)] + _ = x[SmbiosTypeOnboard-(10)] + _ = x[SmbiosTypeOEMStrings-(11)] + _ = x[SmbiosTypeConfig-(12)] + _ = x[SmbiosTypeLanguage-(13)] + _ = x[SmbiosTypeGroupAssociations-(14)] + _ = x[SmbiosTypeEventLog-(15)] + _ = x[SmbiosTypeMemoryArray-(16)] + _ = x[SmbiosTypeMemoryDevice-(17)] + _ = x[SmbiosTypeMemoryError-(18)] + _ = x[SmbiosTypeMemoryArrayMappedAddress-(19)] + _ = x[SmbiosTypeMemoryDeviceMappedAddress-(20)] + _ = x[SmbiosTypePointingDevice-(21)] + _ = x[SmbiosTypeBattery-(22)] + _ = x[SmbiosTypeSystemReset-(23)] + _ = x[SmbiosTypeHardwareSecurity-(24)] + _ = x[SmbiosTypePowerControls-(25)] + _ = x[SmbiosTypeVoltage-(26)] + _ = x[SmbiosTypeCoolingDevice-(27)] + _ = x[SmbiosTypeTemperature-(28)] + _ = x[SmbiosTypeCurrent-(29)] + _ = x[SmbiosTypeOutOfBandRemoteAccess-(30)] + _ = x[SmbiosTypeBootIntegrityServices-(31)] + _ = x[SmbiosTypeSystemBoot-(32)] + _ = x[SmbiosTypeMemory64Error-(33)] + _ = x[SmbiosTypeManagementDevice-(34)] + _ = x[SmbiosTypeManDeviceComponent-(35)] + _ = x[SmbiosTypeManDeviceThreshold-(36)] + _ = x[SmbiosTypeMemoryChannel-(37)] + _ = x[SmbiosTypeIPMIDevice-(38)] + _ = x[SmbiosTypeSystemPowerSupply-(39)] + _ = x[SmbiosTypeAdditionalInfo-(40)] + _ = x[SmbiosTypeOnboardExtended-(41)] + _ = x[SmbiosTypeManagementControllerHostInterface-(42)] + _ = x[SmbiosTypeTPM-(43)] + _ = x[SmbiosTypeProcessorAdditional-(44)] + _ = x[SmbiosFirmwareInventory-(45)] + _ = x[SmbiosTypeInactive-(126)] + _ = x[SmbiosTypeEndOfTable-(127)] +} + +var _SmbiosTypeValues = []SmbiosType{SmbiosTypeBios, SmbiosTypeSystem, SmbiosTypeBoard, SmbiosTypeChassis, SmbiosTypeProcessor, SmbiosTypeMemoryController, SmbiosTypeMemoryModule, SmbiosTypeCache, SmbiosTypePortConnector, SmbiosTypeSlot, SmbiosTypeOnboard, SmbiosTypeOEMStrings, SmbiosTypeConfig, SmbiosTypeLanguage, SmbiosTypeGroupAssociations, SmbiosTypeEventLog, SmbiosTypeMemoryArray, SmbiosTypeMemoryDevice, SmbiosTypeMemoryError, SmbiosTypeMemoryArrayMappedAddress, SmbiosTypeMemoryDeviceMappedAddress, SmbiosTypePointingDevice, SmbiosTypeBattery, SmbiosTypeSystemReset, SmbiosTypeHardwareSecurity, SmbiosTypePowerControls, SmbiosTypeVoltage, SmbiosTypeCoolingDevice, SmbiosTypeTemperature, SmbiosTypeCurrent, SmbiosTypeOutOfBandRemoteAccess, SmbiosTypeBootIntegrityServices, SmbiosTypeSystemBoot, SmbiosTypeMemory64Error, SmbiosTypeManagementDevice, SmbiosTypeManDeviceComponent, SmbiosTypeManDeviceThreshold, SmbiosTypeMemoryChannel, SmbiosTypeIPMIDevice, SmbiosTypeSystemPowerSupply, SmbiosTypeAdditionalInfo, SmbiosTypeOnboardExtended, SmbiosTypeManagementControllerHostInterface, SmbiosTypeTPM, SmbiosTypeProcessorAdditional, SmbiosFirmwareInventory, SmbiosTypeInactive, SmbiosTypeEndOfTable} + +var _SmbiosTypeNameToValueMap = map[string]SmbiosType{ + _SmbiosTypeName_0[0:4]: SmbiosTypeBios, + _SmbiosTypeLowerName_0[0:4]: SmbiosTypeBios, + _SmbiosTypeName_0[4:10]: SmbiosTypeSystem, + _SmbiosTypeLowerName_0[4:10]: SmbiosTypeSystem, + _SmbiosTypeName_0[10:15]: SmbiosTypeBoard, + _SmbiosTypeLowerName_0[10:15]: SmbiosTypeBoard, + _SmbiosTypeName_0[15:22]: SmbiosTypeChassis, + _SmbiosTypeLowerName_0[15:22]: SmbiosTypeChassis, + _SmbiosTypeName_0[22:31]: SmbiosTypeProcessor, + _SmbiosTypeLowerName_0[22:31]: SmbiosTypeProcessor, + _SmbiosTypeName_0[31:48]: SmbiosTypeMemoryController, + _SmbiosTypeLowerName_0[31:48]: SmbiosTypeMemoryController, + _SmbiosTypeName_0[48:61]: SmbiosTypeMemoryModule, + _SmbiosTypeLowerName_0[48:61]: SmbiosTypeMemoryModule, + _SmbiosTypeName_0[61:66]: SmbiosTypeCache, + _SmbiosTypeLowerName_0[61:66]: SmbiosTypeCache, + _SmbiosTypeName_0[66:80]: SmbiosTypePortConnector, + _SmbiosTypeLowerName_0[66:80]: SmbiosTypePortConnector, + _SmbiosTypeName_0[80:84]: SmbiosTypeSlot, + _SmbiosTypeLowerName_0[80:84]: SmbiosTypeSlot, + _SmbiosTypeName_0[84:91]: SmbiosTypeOnboard, + _SmbiosTypeLowerName_0[84:91]: SmbiosTypeOnboard, + _SmbiosTypeName_0[91:102]: SmbiosTypeOEMStrings, + _SmbiosTypeLowerName_0[91:102]: SmbiosTypeOEMStrings, + _SmbiosTypeName_0[102:108]: SmbiosTypeConfig, + _SmbiosTypeLowerName_0[102:108]: SmbiosTypeConfig, + _SmbiosTypeName_0[108:116]: SmbiosTypeLanguage, + _SmbiosTypeLowerName_0[108:116]: SmbiosTypeLanguage, + _SmbiosTypeName_0[116:134]: SmbiosTypeGroupAssociations, + _SmbiosTypeLowerName_0[116:134]: SmbiosTypeGroupAssociations, + _SmbiosTypeName_0[134:143]: SmbiosTypeEventLog, + _SmbiosTypeLowerName_0[134:143]: SmbiosTypeEventLog, + _SmbiosTypeName_0[143:155]: SmbiosTypeMemoryArray, + _SmbiosTypeLowerName_0[143:155]: SmbiosTypeMemoryArray, + _SmbiosTypeName_0[155:168]: SmbiosTypeMemoryDevice, + _SmbiosTypeLowerName_0[155:168]: SmbiosTypeMemoryDevice, + _SmbiosTypeName_0[168:180]: SmbiosTypeMemoryError, + _SmbiosTypeLowerName_0[168:180]: SmbiosTypeMemoryError, + _SmbiosTypeName_0[180:207]: SmbiosTypeMemoryArrayMappedAddress, + _SmbiosTypeLowerName_0[180:207]: SmbiosTypeMemoryArrayMappedAddress, + _SmbiosTypeName_0[207:235]: SmbiosTypeMemoryDeviceMappedAddress, + _SmbiosTypeLowerName_0[207:235]: SmbiosTypeMemoryDeviceMappedAddress, + _SmbiosTypeName_0[235:250]: SmbiosTypePointingDevice, + _SmbiosTypeLowerName_0[235:250]: SmbiosTypePointingDevice, + _SmbiosTypeName_0[250:257]: SmbiosTypeBattery, + _SmbiosTypeLowerName_0[250:257]: SmbiosTypeBattery, + _SmbiosTypeName_0[257:269]: SmbiosTypeSystemReset, + _SmbiosTypeLowerName_0[257:269]: SmbiosTypeSystemReset, + _SmbiosTypeName_0[269:286]: SmbiosTypeHardwareSecurity, + _SmbiosTypeLowerName_0[269:286]: SmbiosTypeHardwareSecurity, + _SmbiosTypeName_0[286:300]: SmbiosTypePowerControls, + _SmbiosTypeLowerName_0[286:300]: SmbiosTypePowerControls, + _SmbiosTypeName_0[300:307]: SmbiosTypeVoltage, + _SmbiosTypeLowerName_0[300:307]: SmbiosTypeVoltage, + _SmbiosTypeName_0[307:321]: SmbiosTypeCoolingDevice, + _SmbiosTypeLowerName_0[307:321]: SmbiosTypeCoolingDevice, + _SmbiosTypeName_0[321:332]: SmbiosTypeTemperature, + _SmbiosTypeLowerName_0[321:332]: SmbiosTypeTemperature, + _SmbiosTypeName_0[332:339]: SmbiosTypeCurrent, + _SmbiosTypeLowerName_0[332:339]: SmbiosTypeCurrent, + _SmbiosTypeName_0[339:364]: SmbiosTypeOutOfBandRemoteAccess, + _SmbiosTypeLowerName_0[339:364]: SmbiosTypeOutOfBandRemoteAccess, + _SmbiosTypeName_0[364:387]: SmbiosTypeBootIntegrityServices, + _SmbiosTypeLowerName_0[364:387]: SmbiosTypeBootIntegrityServices, + _SmbiosTypeName_0[387:398]: SmbiosTypeSystemBoot, + _SmbiosTypeLowerName_0[387:398]: SmbiosTypeSystemBoot, + _SmbiosTypeName_0[398:412]: SmbiosTypeMemory64Error, + _SmbiosTypeLowerName_0[398:412]: SmbiosTypeMemory64Error, + _SmbiosTypeName_0[412:429]: SmbiosTypeManagementDevice, + _SmbiosTypeLowerName_0[412:429]: SmbiosTypeManagementDevice, + _SmbiosTypeName_0[429:449]: SmbiosTypeManDeviceComponent, + _SmbiosTypeLowerName_0[429:449]: SmbiosTypeManDeviceComponent, + _SmbiosTypeName_0[449:469]: SmbiosTypeManDeviceThreshold, + _SmbiosTypeLowerName_0[449:469]: SmbiosTypeManDeviceThreshold, + _SmbiosTypeName_0[469:483]: SmbiosTypeMemoryChannel, + _SmbiosTypeLowerName_0[469:483]: SmbiosTypeMemoryChannel, + _SmbiosTypeName_0[483:494]: SmbiosTypeIPMIDevice, + _SmbiosTypeLowerName_0[483:494]: SmbiosTypeIPMIDevice, + _SmbiosTypeName_0[494:513]: SmbiosTypeSystemPowerSupply, + _SmbiosTypeLowerName_0[494:513]: SmbiosTypeSystemPowerSupply, + _SmbiosTypeName_0[513:528]: SmbiosTypeAdditionalInfo, + _SmbiosTypeLowerName_0[513:528]: SmbiosTypeAdditionalInfo, + _SmbiosTypeName_0[528:544]: SmbiosTypeOnboardExtended, + _SmbiosTypeLowerName_0[528:544]: SmbiosTypeOnboardExtended, + _SmbiosTypeName_0[544:580]: SmbiosTypeManagementControllerHostInterface, + _SmbiosTypeLowerName_0[544:580]: SmbiosTypeManagementControllerHostInterface, + _SmbiosTypeName_0[580:583]: SmbiosTypeTPM, + _SmbiosTypeLowerName_0[580:583]: SmbiosTypeTPM, + _SmbiosTypeName_0[583:603]: SmbiosTypeProcessorAdditional, + _SmbiosTypeLowerName_0[583:603]: SmbiosTypeProcessorAdditional, + _SmbiosTypeName_0[603:628]: SmbiosFirmwareInventory, + _SmbiosTypeLowerName_0[603:628]: SmbiosFirmwareInventory, + _SmbiosTypeName_1[0:8]: SmbiosTypeInactive, + _SmbiosTypeLowerName_1[0:8]: SmbiosTypeInactive, + _SmbiosTypeName_1[8:20]: SmbiosTypeEndOfTable, + _SmbiosTypeLowerName_1[8:20]: SmbiosTypeEndOfTable, +} + +var _SmbiosTypeNames = []string{ + _SmbiosTypeName_0[0:4], + _SmbiosTypeName_0[4:10], + _SmbiosTypeName_0[10:15], + _SmbiosTypeName_0[15:22], + _SmbiosTypeName_0[22:31], + _SmbiosTypeName_0[31:48], + _SmbiosTypeName_0[48:61], + _SmbiosTypeName_0[61:66], + _SmbiosTypeName_0[66:80], + _SmbiosTypeName_0[80:84], + _SmbiosTypeName_0[84:91], + _SmbiosTypeName_0[91:102], + _SmbiosTypeName_0[102:108], + _SmbiosTypeName_0[108:116], + _SmbiosTypeName_0[116:134], + _SmbiosTypeName_0[134:143], + _SmbiosTypeName_0[143:155], + _SmbiosTypeName_0[155:168], + _SmbiosTypeName_0[168:180], + _SmbiosTypeName_0[180:207], + _SmbiosTypeName_0[207:235], + _SmbiosTypeName_0[235:250], + _SmbiosTypeName_0[250:257], + _SmbiosTypeName_0[257:269], + _SmbiosTypeName_0[269:286], + _SmbiosTypeName_0[286:300], + _SmbiosTypeName_0[300:307], + _SmbiosTypeName_0[307:321], + _SmbiosTypeName_0[321:332], + _SmbiosTypeName_0[332:339], + _SmbiosTypeName_0[339:364], + _SmbiosTypeName_0[364:387], + _SmbiosTypeName_0[387:398], + _SmbiosTypeName_0[398:412], + _SmbiosTypeName_0[412:429], + _SmbiosTypeName_0[429:449], + _SmbiosTypeName_0[449:469], + _SmbiosTypeName_0[469:483], + _SmbiosTypeName_0[483:494], + _SmbiosTypeName_0[494:513], + _SmbiosTypeName_0[513:528], + _SmbiosTypeName_0[528:544], + _SmbiosTypeName_0[544:580], + _SmbiosTypeName_0[580:583], + _SmbiosTypeName_0[583:603], + _SmbiosTypeName_0[603:628], + _SmbiosTypeName_1[0:8], + _SmbiosTypeName_1[8:20], +} + +// SmbiosTypeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func SmbiosTypeString(s string) (SmbiosType, error) { + if val, ok := _SmbiosTypeNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _SmbiosTypeNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to SmbiosType values", s) +} + +// SmbiosTypeValues returns all values of the enum +func SmbiosTypeValues() []SmbiosType { + return _SmbiosTypeValues +} + +// SmbiosTypeStrings returns a slice of all String values of the enum +func SmbiosTypeStrings() []string { + strs := make([]string, len(_SmbiosTypeNames)) + copy(strs, _SmbiosTypeNames) + return strs +} + +// IsASmbiosType returns "true" if the value is listed in the enum definition. "false" otherwise +func (i SmbiosType) IsASmbiosType() bool { + for _, v := range _SmbiosTypeValues { + if i == v { + return true + } + } + return false +} + +// MarshalJSON implements the json.Marshaler interface for SmbiosType +func (i SmbiosType) MarshalJSON() ([]byte, error) { + return json.Marshal(i.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for SmbiosType +func (i *SmbiosType) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return fmt.Errorf("SmbiosType should be a string, got %s", data) + } + + var err error + *i, err = SmbiosTypeString(s) + return err +} diff --git a/pkg/hwinfo/smbios_group_associations.go b/pkg/hwinfo/smbios_group_associations.go new file mode 100644 index 0000000..b5aba38 --- /dev/null +++ b/pkg/hwinfo/smbios_group_associations.go @@ -0,0 +1,29 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" +import "unsafe" + +// SmbiosGroupAssociations captures group associations. +type SmbiosGroupAssociations struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Name string `json:"name"` // group name + Handles []int `json:"handles,omitempty"` // array of item handles +} + +func (s SmbiosGroupAssociations) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosGroup(info C.smbios_group_t) (Smbios, error) { + return SmbiosGroupAssociations{ + Type: SmbiosTypeGroupAssociations, + Handle: int(info.handle), + Name: C.GoString(info.name), + Handles: ReadIntArray(unsafe.Pointer(info.item_handles), int(info.items_len)), + }, nil +} diff --git a/pkg/hwinfo/smbios_hardware_security.go b/pkg/hwinfo/smbios_hardware_security.go new file mode 100644 index 0000000..f57f15c --- /dev/null +++ b/pkg/hwinfo/smbios_hardware_security.go @@ -0,0 +1,32 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosHardwareSecurity captures hardware security information. +type SmbiosHardwareSecurity struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Power *Id `json:"power"` // power-on password status + Keyboard *Id `json:"keyboard"` // keyboard password status + Admin *Id `json:"admin"` // admin password status + Reset *Id `json:"reset"` // front panel reset status +} + +func (s SmbiosHardwareSecurity) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosSecure(info C.smbios_secure_t) (Smbios, error) { + return SmbiosHardwareSecurity{ + Type: SmbiosTypeHardwareSecurity, + Handle: int(info.handle), + Power: NewId(info.power), + Keyboard: NewId(info.keyboard), + Admin: NewId(info.admin), + Reset: NewId(info.reset), + }, nil +} diff --git a/pkg/hwinfo/smbios_language.go b/pkg/hwinfo/smbios_language.go new file mode 100644 index 0000000..1e11820 --- /dev/null +++ b/pkg/hwinfo/smbios_language.go @@ -0,0 +1,28 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosLanguage captures language information. +type SmbiosLanguage struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Languages []string `json:"languages,omitempty"` + CurrentLanguage string `json:"current_language"` +} + +func (s SmbiosLanguage) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosLang(info C.smbios_lang_t) (Smbios, error) { + return SmbiosLanguage{ + Type: SmbiosTypeLanguage, + Handle: int(info.handle), + Languages: ReadStringList(info.strings), + CurrentLanguage: C.GoString(info.current), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory64_error.go b/pkg/hwinfo/smbios_memory64_error.go new file mode 100644 index 0000000..637ad6a --- /dev/null +++ b/pkg/hwinfo/smbios_memory64_error.go @@ -0,0 +1,38 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemory64Error captures 32-bit memory error information. +type SmbiosMemory64Error struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + ErrorType *Id `json:"error_type"` // error type memory + Granularity *Id `json:"granularity"` // memory array or memory partition + Operation *Id `json:"operation"` // mem operation causing the rror + Syndrome uint `json:"syndrome"` // vendor-specific ECC syndrome; 0: unknown + ArrayAddress uint `json:"array_address"` // fault address relative to mem array; 0x80000000: unknown + DeviceAddress uint `json:"device_address"` // fault address relative to mem array; 0x80000000: unknown + Range uint `json:"range"` // range, within which the error can be determined; 0x80000000: unknown +} + +func (s SmbiosMemory64Error) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMem64Error(info C.smbios_mem64error_t) (Smbios, error) { + return SmbiosMemory64Error{ + Type: SmbiosTypeMemory64Error, + Handle: int(info.handle), + ErrorType: NewId(info.err_type), + Granularity: NewId(info.granularity), + Operation: NewId(info.operation), + Syndrome: uint(info.syndrome), + ArrayAddress: uint(info.array_addr), + DeviceAddress: uint(info.device_addr), + Range: uint(info._range), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory_array.go b/pkg/hwinfo/smbios_memory_array.go new file mode 100644 index 0000000..9cc8bc7 --- /dev/null +++ b/pkg/hwinfo/smbios_memory_array.go @@ -0,0 +1,36 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemoryArray captures physical memory array information (consists of several memory devices). +type SmbiosMemoryArray struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Location *Id `json:"location"` // memory device location + Usage *Id `json:"usage"` // memory usage + ECC *Id `json:"ecc"` // ECC types + MaxSize uint `json:"max_size"` // max memory size in KB + ErrorHandle int `json:"error_handle"` // points to error info record; 0xfffe: not supported, 0xffff: no error + Slots uint `json:"slots"` // slots or sockets for this device +} + +func (s SmbiosMemoryArray) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMemArray(info C.smbios_memarray_t) (Smbios, error) { + return SmbiosMemoryArray{ + Type: SmbiosTypeMemoryArray, + Handle: int(info.handle), + Location: NewId(info.location), + Usage: NewId(info.use), + ECC: NewId(info.ecc), + MaxSize: uint(info.max_size), + ErrorHandle: int(info.error_handle), + Slots: uint(info.slots), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory_array_mapped_address.go b/pkg/hwinfo/smbios_memory_array_mapped_address.go new file mode 100644 index 0000000..543842b --- /dev/null +++ b/pkg/hwinfo/smbios_memory_array_mapped_address.go @@ -0,0 +1,32 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemoryArrayMappedAddress captures physical memory array information (consists of several memory devices). +type SmbiosMemoryArrayMappedAddress struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + ArrayHandle int `json:"array_handle"` // memory array this mapping belongs to + StartAddress uint64 `json:"start_address"` // memory range start address + EndAddress uint64 `json:"end_address"` // end address + PartWidth uint `json:"part_width"` // number of memory devices +} + +func (s SmbiosMemoryArrayMappedAddress) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMemArrayMap(info C.smbios_memarraymap_t) (Smbios, error) { + return SmbiosMemoryArrayMappedAddress{ + Type: SmbiosTypeMemoryArrayMappedAddress, + Handle: int(info.handle), + ArrayHandle: int(info.array_handle), + StartAddress: uint64(info.start_addr), + EndAddress: uint64(info.end_addr), + PartWidth: uint(info.part_width), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory_device.go b/pkg/hwinfo/smbios_memory_device.go new file mode 100644 index 0000000..be93a3e --- /dev/null +++ b/pkg/hwinfo/smbios_memory_device.go @@ -0,0 +1,56 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemoryDevice captures system slot information. +type SmbiosMemoryDevice struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Location string `json:"location"` // device location + BankLocation string `json:"bank_location"` // bank location + Manufacturer string `json:"manufacturer"` + Serial string `json:"-"` // omit from json + AssetTag string `json:"asset_tag,omitempty"` + PartNumber string `json:"part_number"` + ArrayHandle int `json:"array_handle"` // memory array this device belongs to + ErrorHandle int `json:"error_handle"` // points to error info record; 0xfffe: not supported, 0xffff: no error + Width uint `json:"width"` // data width in bits + ECCBits uint `json:"ecc_bits"` // ecc bits + Size uint `json:"size"` // kB + FormFactor *Id `json:"form_factor"` + Set uint `json:"set"` // 0: does not belong to a set; 1-0xfe: set number; 0xff: unknown + MemoryType *Id `json:"memory_type"` + MemoryTypeDetails []string `json:"memory_type_details"` + Speed uint `json:"speed"` // MHz +} + +func (s SmbiosMemoryDevice) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMemDevice(info C.smbios_memdevice_t) (Smbios, error) { + return SmbiosMemoryDevice{ + Type: SmbiosTypeMemoryDevice, + Handle: int(info.handle), + Location: C.GoString(info.location), + BankLocation: C.GoString(info.bank), + Manufacturer: C.GoString(info.manuf), + Serial: C.GoString(info.serial), + AssetTag: C.GoString(info.asset), + PartNumber: C.GoString(info.part), + ArrayHandle: int(info.array_handle), + ErrorHandle: int(info.error_handle), + Width: uint(info.width), + ECCBits: uint(info.eccbits), + Size: uint(info.size), + FormFactor: NewId(info.form), + Set: uint(info.set), + MemoryType: NewId(info.mem_type), + MemoryTypeDetails: ReadStringList(info.type_detail.str), + Speed: uint(info.speed), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory_device_mapped_address.go b/pkg/hwinfo/smbios_memory_device_mapped_address.go new file mode 100644 index 0000000..b354caa --- /dev/null +++ b/pkg/hwinfo/smbios_memory_device_mapped_address.go @@ -0,0 +1,38 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemoryDeviceMappedAddress captures physical memory array information (consists of several memory devices). +type SmbiosMemoryDeviceMappedAddress struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + MemoryDeviceHandle int `json:"memory_device_handle"` + ArrayMapHandle int `json:"array_map_handle"` + StartAddress uint64 `json:"start_address"` + EndAddress uint64 `json:"end_address"` + RowPosition uint `json:"row_position"` // position of the referenced memory device in a row of the address partition + InterleavePosition uint `json:"interleave_position"` // dto, in an interleave + InterleaveDepth uint `json:"interleave_depth"` // number of consecutive rows +} + +func (s SmbiosMemoryDeviceMappedAddress) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMemDeviceMap(info C.smbios_memdevicemap_t) (Smbios, error) { + return SmbiosMemoryDeviceMappedAddress{ + Type: SmbiosTypeMemoryDeviceMappedAddress, + Handle: int(info.handle), + MemoryDeviceHandle: int(info.memdevice_handle), + ArrayMapHandle: int(info.arraymap_handle), + StartAddress: uint64(info.start_addr), + EndAddress: uint64(info.end_addr), + RowPosition: uint(info.row_pos), + InterleavePosition: uint(info.interleave_pos), + InterleaveDepth: uint(info.interleave_depth), + }, nil +} diff --git a/pkg/hwinfo/smbios_memory_error.go b/pkg/hwinfo/smbios_memory_error.go new file mode 100644 index 0000000..ef90f20 --- /dev/null +++ b/pkg/hwinfo/smbios_memory_error.go @@ -0,0 +1,38 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosMemoryError captures 32-bit memory error information. +type SmbiosMemoryError struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + ErrorType *Id `json:"error_type"` // error type memory + Granularity *Id `json:"granularity"` // memory array or memory partition + Operation *Id `json:"operation"` // mem operation causing the rror + Syndrome uint `json:"syndrome"` // vendor-specific ECC syndrome; 0: unknown + ArrayAddress uint `json:"array_address"` // fault address relative to mem array; 0x80000000: unknown + DeviceAddress uint `json:"device_address"` // fault address relative to mem array; 0x80000000: unknown + Range uint `json:"range"` // range, within which the error can be determined; 0x80000000: unknown +} + +func (s SmbiosMemoryError) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMemError(info C.smbios_memerror_t) (Smbios, error) { + return SmbiosMemoryError{ + Type: SmbiosTypeMemoryError, + Handle: int(info.handle), + ErrorType: NewId(info.err_type), + Granularity: NewId(info.granularity), + Operation: NewId(info.operation), + Syndrome: uint(info.syndrome), + ArrayAddress: uint(info.array_addr), + DeviceAddress: uint(info.device_addr), + Range: uint(info._range), + }, nil +} diff --git a/pkg/hwinfo/smbios_oem_strings.go b/pkg/hwinfo/smbios_oem_strings.go new file mode 100644 index 0000000..82af2ed --- /dev/null +++ b/pkg/hwinfo/smbios_oem_strings.go @@ -0,0 +1,26 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosOEMStrings captures OEM information. +type SmbiosOEMStrings struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Strings []string `json:"strings,omitempty"` +} + +func (s SmbiosOEMStrings) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosOEM(info C.smbios_oem_t) (Smbios, error) { + return SmbiosOEMStrings{ + Type: SmbiosTypeOEMStrings, + Handle: int(info.handle), + Strings: ReadStringList(info.oem_strings), + }, nil +} diff --git a/pkg/hwinfo/smbios_onboard.go b/pkg/hwinfo/smbios_onboard.go new file mode 100644 index 0000000..9aad364 --- /dev/null +++ b/pkg/hwinfo/smbios_onboard.go @@ -0,0 +1,45 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include + +char* smbios_onboard_get_name(smbios_onboard_t sm, int i) { return sm.dev[i].name; } +hd_id_t smbios_onboard_get_type(smbios_onboard_t sm, int i) { return sm.dev[i].type; } +unsigned smbios_onboard_get_status(smbios_onboard_t sm, int i) { return sm.dev[i].status; } +*/ +import "C" + +type OnboardDevice struct { + Name string `json:"name"` + Type *Id `json:"type"` + Enabled bool `json:"enabled"` +} + +// SmbiosOnboard captures overall system related information. +type SmbiosOnboard struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Devices []OnboardDevice `json:"devices,omitempty"` +} + +func (s SmbiosOnboard) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosOnboard(info C.smbios_onboard_t) (Smbios, error) { + var devices []OnboardDevice + for i := 0; i < int(info.dev_len); i++ { + devices = append(devices, OnboardDevice{ + Name: C.GoString(C.smbios_onboard_get_name(info, C.int(i))), + Type: NewId(C.smbios_onboard_get_type(info, C.int(i))), + Enabled: uint(C.smbios_onboard_get_status(info, C.int(i))) == 1, + }) + } + + return SmbiosOnboard{ + Type: SmbiosTypeOnboard, + Handle: int(info.handle), + Devices: devices, + }, nil +} diff --git a/pkg/hwinfo/smbios_pointing_device.go b/pkg/hwinfo/smbios_pointing_device.go new file mode 100644 index 0000000..fdede7e --- /dev/null +++ b/pkg/hwinfo/smbios_pointing_device.go @@ -0,0 +1,30 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosPointingDevice captures pointing device (aka 'mouse') information. +type SmbiosPointingDevice struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + MouseType *Id `json:"mouse_type"` + Interface *Id `json:"interface"` + Buttons uint `json:"buttons"` +} + +func (s SmbiosPointingDevice) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosMouse(info C.smbios_mouse_t) (Smbios, error) { + return SmbiosPointingDevice{ + Type: SmbiosTypePointingDevice, + Handle: int(info.handle), + MouseType: NewId(info.mtype), + Interface: NewId(info._interface), + Buttons: uint(info.buttons), + }, nil +} diff --git a/pkg/hwinfo/smbios_port_connector.go b/pkg/hwinfo/smbios_port_connector.go new file mode 100644 index 0000000..c7c25ff --- /dev/null +++ b/pkg/hwinfo/smbios_port_connector.go @@ -0,0 +1,34 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosPortConnector captures port connector information. +type SmbiosPortConnector struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + PortType *Id `json:"port_type"` + InternalConnectorType *Id `json:"internal_connector_type,omitempty"` + InternalReferenceDesignator string `json:"internal_reference_designator,omitempty"` + ExternalConnectorType *Id `json:"external_connector_type,omitempty"` + ExternalReferenceDesignator string `json:"external_reference_designator,omitempty"` +} + +func (s SmbiosPortConnector) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosConnect(info C.smbios_connect_t) (Smbios, error) { + return SmbiosPortConnector{ + Type: SmbiosTypePortConnector, + Handle: int(info.handle), + PortType: NewId(info.port_type), + InternalConnectorType: NewId(info.i_type), + InternalReferenceDesignator: C.GoString(info.i_des), + ExternalConnectorType: NewId(info.x_type), + ExternalReferenceDesignator: C.GoString(info.x_des), + }, nil +} diff --git a/pkg/hwinfo/smbios_power_controls.go b/pkg/hwinfo/smbios_power_controls.go new file mode 100644 index 0000000..320e18f --- /dev/null +++ b/pkg/hwinfo/smbios_power_controls.go @@ -0,0 +1,34 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosPowerControls captures system power controls information. +type SmbiosPowerControls struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Month uint `json:"month"` // next scheduled power-on month + Day uint `json:"day"` // dto, day + Hour uint `json:"hour"` // dto, hour + Minute uint `json:"minute"` // dto, minute + Second uint `json:"second"` // dto, second +} + +func (s SmbiosPowerControls) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosPower(info C.smbios_power_t) (Smbios, error) { + return SmbiosPowerControls{ + Type: SmbiosTypePowerControls, + Handle: int(info.handle), + Month: uint(info.month), + Day: uint(info.day), + Hour: uint(info.hour), + Minute: uint(info.minute), + Second: uint(info.second), + }, nil +} diff --git a/pkg/hwinfo/smbios_processor.go b/pkg/hwinfo/smbios_processor.go new file mode 100644 index 0000000..b7b01d6 --- /dev/null +++ b/pkg/hwinfo/smbios_processor.go @@ -0,0 +1,62 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosProcessor captures processor information. +type SmbiosProcessor struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Socket string `json:"socket"` + SocketType *Id `json:"socket_type"` + SocketPopulated bool `json:"socket_populated"` // true: populated, false: empty + Manufacturer string `json:"manufacturer"` + Version string `json:"version"` + Serial string `json:"-"` // omit from json output + AssetTag string `json:"asset_tag"` // asset tag + Part string `json:"part"` // part number + ProcessorType *Id `json:"processor_type"` + ProcessorFamily *Id `json:"processor_family"` + ProcessorId uint64 `json:"-"` // omit from json + ProcessorStatus *Id `json:"processor_status"` + Voltage uint `json:"voltage"` + ClockExt uint `json:"clock_ext"` // MHz + ClockMax uint `json:"clock_max"` // MHz + ClockCurrent uint `json:"clock_current"` // MHz + CacheHandleL1 int `json:"cache_handle_l1"` // handle of L1 cache + CacheHandleL2 int `json:"cache_handle_l2"` // handle of L2 cache + CacheHandleL3 int `json:"cache_handle_l3"` // handle of L3 cache +} + +func (s SmbiosProcessor) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosProcessor(info C.smbios_processor_t) (Smbios, error) { + return SmbiosProcessor{ + Type: SmbiosTypeProcessor, + Handle: int(info.handle), + Socket: C.GoString(info.socket), + SocketType: NewId(info.upgrade), + SocketPopulated: uint(info.sock_status) == 1, + Manufacturer: C.GoString(info.manuf), + Version: C.GoString(info.version), + Serial: C.GoString(info.serial), + AssetTag: C.GoString(info.asset), + Part: C.GoString(info.part), + ProcessorType: NewId(info.pr_type), + ProcessorFamily: NewId(info.family), + ProcessorId: uint64(info.cpu_id), + ProcessorStatus: NewId(info.cpu_status), + Voltage: uint(info.voltage), + ClockExt: uint(info.ext_clock), + ClockMax: uint(info.max_speed), + ClockCurrent: uint(info.current_speed), + CacheHandleL1: int(info.l1_cache), + CacheHandleL2: int(info.l2_cache), + CacheHandleL3: int(info.l3_cache), + }, nil +} diff --git a/pkg/hwinfo/smbios_slot.go b/pkg/hwinfo/smbios_slot.go new file mode 100644 index 0000000..4bb15ed --- /dev/null +++ b/pkg/hwinfo/smbios_slot.go @@ -0,0 +1,38 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosSlot captures system slot information. +type SmbiosSlot struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Designation string `json:"designation,omitempty"` + SlotType *Id `json:"slot_type"` + BusWidth *Id `json:"bus_width"` + Usage *Id `json:"usage"` + Length *Id `json:"length"` + Id uint `json:"id"` + Features []string `json:"features,omitempty"` +} + +func (s SmbiosSlot) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosSlot(info C.smbios_slot_t) (Smbios, error) { + return SmbiosSlot{ + Type: SmbiosTypeSlot, + Handle: int(info.handle), + Designation: C.GoString(info.desig), + SlotType: NewId(info.slot_type), + BusWidth: NewId(info.bus_width), + Usage: NewId(info.usage), + Length: NewId(info.length), + Id: uint(info.id), + Features: ReadStringList(info.feature.str), + }, nil +} diff --git a/pkg/hwinfo/smbios_sys_info.go b/pkg/hwinfo/smbios_sys_info.go new file mode 100644 index 0000000..df2e845 --- /dev/null +++ b/pkg/hwinfo/smbios_sys_info.go @@ -0,0 +1,36 @@ +package hwinfo + +/* +#cgo pkg-config: hwinfo +#include +*/ +import "C" + +// SmbiosSystem captures overall system related information. +type SmbiosSystem struct { + Type SmbiosType `json:"type"` + Handle int `json:"handle"` + Manufacturer string `json:"manufacturer"` + Product string `json:"product"` + Version string `json:"version"` + Serial string `json:"-"` // omit from json output + UUID string `json:"-"` // universal unique id; all 0x00: undef, all 0xff: undef but settable, omit from json + WakeUp *Id `json:"wake_up"` // wake-up type +} + +func (s SmbiosSystem) SmbiosType() SmbiosType { + return s.Type +} + +func NewSmbiosSysInfo(info C.smbios_sysinfo_t) (Smbios, error) { + return SmbiosSystem{ + Type: SmbiosTypeSystem, + Handle: int(info.handle), + Manufacturer: C.GoString(info.manuf), + Product: C.GoString(info.product), + Version: C.GoString(info.version), + Serial: C.GoString(info.serial), + // todo uuid + WakeUp: NewId(info.wake_up), + }, nil +} diff --git a/pkg/hwinfo/utils.go b/pkg/hwinfo/utils.go index 38c524a..bd5dc76 100644 --- a/pkg/hwinfo/utils.go +++ b/pkg/hwinfo/utils.go @@ -34,6 +34,17 @@ func ReadUintArray(arr unsafe.Pointer, length int) []uint { return result } +func ReadIntArray(arr unsafe.Pointer, length int) []int { + // TODO see if we can use generics to combine some of these methods + start := uintptr(arr) + result := make([]int, length) + for i := range result { + next := start + uintptr(i*C.sizeof_uint) + result[i] = *((*int)(unsafe.Pointer(next))) + } + return result +} + func ReadByteArray(arr unsafe.Pointer, length int) []byte { start := uintptr(arr) result := make([]byte, length)