Skip to content

Commit

Permalink
fix: stop decoding without error if EOF encountered during header read
Browse files Browse the repository at this point in the history
Linux v6.6.39 stops decoding with EOF in this situation but maintains
the already decoded structures. See /drivers/firmware/dmi_scan.c

Fixes #16

Signed-off-by: Mike Beaumont <mjboamail@gmail.com>
Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
michaelbeaumont authored and smira committed Aug 23, 2024
1 parent 6a719a6 commit e781237
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
)
Expand Down Expand Up @@ -99,11 +100,21 @@ func (d *Decoder) next() (*Structure, error) {
return nil, err
}

if h == nil {
// unexpected structure end, pretend we hit the end of the table
return &Structure{
Header: Header{
Type: typeEndOfTable,
},
}, nil
}

// Length of formatted section is length specified by header, minus
// the length of the header itself.
l := int(h.Length) - headerLen

// Hyper-V SMBIOS tables seem to be broken, implement a workaround
// Some SMBIOS tables, for example Hyper-V, seem to be broken, implement a
// workaround
if h.Length == 0 && h.Type == 0 {
return &Structure{
Header: Header{
Expand Down Expand Up @@ -132,6 +143,12 @@ func (d *Decoder) next() (*Structure, error) {
// parseHeader parses a Structure's Header from the stream.
func (d *Decoder) parseHeader() (*Header, error) {
if _, err := io.ReadFull(d.br, d.b[:headerLen]); err != nil {
// We do the same thing the kernel does in drivers/firmware/dmi_scan.c
// since v6.6.39 and return early if we don't have enough bytes for a header
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {
return nil, nil //nolint:nilnil
}

return nil, fmt.Errorf("error reading header: %w", err)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func TestDecoder(t *testing.T) {
{
name: "short header",
b: []byte{0x00},
ss: []*smbios.Structure{{
Header: smbios.Header{
Type: 127,
},
}},
ok: true,
},
{
name: "length too short",
Expand All @@ -49,14 +55,6 @@ func TestDecoder(t *testing.T) {
'a', 'b', 'c', 'd',
},
},
{
name: "no end of table",
b: []byte{
0x01, 0x04, 0x01, 0x00,
0x00,
0x00,
},
},
{
name: "bad second message",
b: []byte{
Expand All @@ -67,6 +65,46 @@ func TestDecoder(t *testing.T) {

0xff,
},
ss: []*smbios.Structure{
{
Header: smbios.Header{
Type: 1,
Length: 12,
Handle: 2,
},
Formatted: []uint8{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
Strings: []string{"deadbeef"},
},
{
Header: smbios.Header{
Type: 127,
},
},
},
ok: true,
},
{
name: "no end of table",
b: []byte{
0x01, 0x04, 0x01, 0x00,
0x00,
0x00,
},
ss: []*smbios.Structure{
{
Header: smbios.Header{
Type: 1,
Length: 4,
Handle: 1,
},
},
{
Header: smbios.Header{
Type: 127,
},
},
},
ok: true,
},
{
name: "OK, one, no format, no strings",
Expand Down
1 change: 1 addition & 0 deletions smbios/smbios_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestDecode(t *testing.T) {
"SuperMicro-Dual-Xeon",
"SuperMicro-Quad-Opteron",
"HyperV",
"Beelink-EQ12",
} {
t.Run(name, func(t *testing.T) {
t.Parallel()
Expand Down
Binary file added smbios/testdata/Beelink-EQ12.dmi
Binary file not shown.
187 changes: 187 additions & 0 deletions smbios/testdata/Beelink-EQ12.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
{
"Version": {
"Major": 3,
"Minor": 3,
"Revision": 0
},
"BIOSInformation": {
"Vendor": "",
"Version": "",
"ReleaseDate": ""
},
"SystemInformation": {
"Manufacturer": "AZW",
"ProductName": "EQ",
"Version": "Default string",
"SerialNumber": "BN1004GH10075",
"UUID": "03000200-0400-0500-0006-000700080009",
"WakeUpType": 6,
"SKUNumber": "Default string",
"Family": "Default string"
},
"BaseboardInformation": {
"Manufacturer": "AZW",
"Product": "EQ",
"Version": "Default string",
"SerialNumber": "Default string",
"AssetTag": "Default string",
"LocationInChassis": "Default string",
"BoardType": 10
},
"SystemEnclosure": {
"Manufacturer": "Default string",
"Version": "Default string",
"SerialNumber": "Default string",
"AssetTagNumber": "",
"SKUNumber": "Default string"
},
"ProcessorInformation": [
{
"SocketDesignation": "U3E1",
"ProcessorManufacturer": "Intel(R) Corporation",
"ProcessorVersion": "Intel(R) N100",
"MaxSpeed": 3400,
"CurrentSpeed": 2871,
"Status": 65,
"SerialNumber": "",
"AssetTag": "",
"PartNumber": "",
"CoreCount": 4,
"CoreEnabled": 4,
"ThreadCount": 4
}
],
"CacheInformation": [
{
"SocketDesignation": "L1 Cache"
},
{
"SocketDesignation": "L1 Cache"
},
{
"SocketDesignation": "L2 Cache"
},
{
"SocketDesignation": "L3 Cache"
}
],
"PortConnectorInformation": [
{
"InternalReferenceDesignator": "Internal Connector 1",
"ExternalReferenceDesignator": "External Connector 1"
},
{
"InternalReferenceDesignator": "Internal Connector 2",
"ExternalReferenceDesignator": "External Connector 2"
},
{
"InternalReferenceDesignator": "Internal Connector 3",
"ExternalReferenceDesignator": "External Connector 3"
},
{
"InternalReferenceDesignator": "Internal Connector 4",
"ExternalReferenceDesignator": "External Connector 4"
},
{
"InternalReferenceDesignator": "Internal Connector 5",
"ExternalReferenceDesignator": "External Connector 5"
}
],
"SystemSlots": [
{
"SlotDesignation": "Slot 1"
},
{
"SlotDesignation": "Slot 2"
},
{
"SlotDesignation": "Slot 3"
},
{
"SlotDesignation": "Slot 4"
},
{
"SlotDesignation": "Slot 5"
}
],
"OEMStrings": {
"Strings": [
"Default string"
],
"Count": 1
},
"SystemConfigurationOptions": {
"Strings": [
"Default string"
],
"Count": 1
},
"BIOSLanguageInformation": {
"CurrentLanguage": "en|US|iso8859-1",
"InstallableLanguages": [
"en|US|iso8859-1"
]
},
"GroupAssociations": {
"GroupName": ""
},
"PhysicalMemoryArray": {
"Location": 3,
"Use": 3,
"MemoryErrorCorrection": 3,
"MaximumCapacity": 67108864,
"MemoryErrorInformationHandle": 65534,
"NumberOfMemoryDevices": 2,
"ExtendedMaximumCapacity": 0
},
"MemoryDevices": [
{
"PhysicalMemoryArrayHandle": 39,
"MemoryErrorInformationHandle": 65534,
"TotalWidth": 64,
"DataWidth": 64,
"Size": 16384,
"FormFactor": 13,
"DeviceSet": "",
"DeviceLocator": "Controller0-ChannelA-DIMM0",
"BankLocator": "BANK 0",
"MemoryType": 34,
"TypeDetail": 128,
"Speed": 5600,
"Manufacturer": "Crucial Technology",
"SerialNumber": "E8FBFFE2",
"AssetTag": "9876543210",
"PartNumber": "CT16G56C46S5.M8G1",
"Attributes": 1,
"ExtendedSize": 0,
"ConfiguredMemorySpeed": 4800,
"MinimumVoltage": 1100,
"MaximumVoltage": 1100,
"ConfiguredVoltage": 1100
},
{
"PhysicalMemoryArrayHandle": 39,
"MemoryErrorInformationHandle": 65534,
"TotalWidth": 0,
"DataWidth": 0,
"Size": 0,
"FormFactor": 2,
"DeviceSet": "",
"DeviceLocator": "Controller1-ChannelA-DIMM0",
"BankLocator": "BANK 0",
"MemoryType": 2,
"TypeDetail": 0,
"Speed": 0,
"Manufacturer": "",
"SerialNumber": "",
"AssetTag": "",
"PartNumber": "",
"Attributes": 0,
"ExtendedSize": 0,
"ConfiguredMemorySpeed": 0,
"MinimumVoltage": 0,
"MaximumVoltage": 0,
"ConfiguredVoltage": 0
}
]
}

0 comments on commit e781237

Please sign in to comment.