1// Copyright 2017 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#pragma once
8
9#include <fbl/macros.h>
10#include <fbl/ref_ptr.h>
11#include <stdint.h>
12#include <zircon/types.h>
13
14#define SMBIOS2_ANCHOR "_SM_"
15#define SMBIOS2_INTERMEDIATE_ANCHOR "_DMI_"
16#define SMBIOS3_ANCHOR "_SM3_"
17
18namespace smbios {
19
20enum class StructType : uint8_t {
21    BiosInfo = 0,
22    SystemInfo = 1,
23    Baseboard = 2,
24    SystemEnclosure = 3,
25    Processor = 4,
26    MemoryController = 5,
27    MemoryModule = 6,
28    Cache = 7,
29    PortConnector = 8,
30    SystemSlots = 9,
31    OnBoardDevices = 10,
32    OemStrings = 11,
33    SystemConfigOptions = 12,
34    BiosLanguage = 13,
35
36    EndOfTable = 127,
37};
38
39// SMBIOS common struct header
40struct Header {
41    StructType type;
42    uint8_t length;
43    uint16_t handle;
44} __PACKED;
45static_assert(sizeof(Header) == 4, "");
46
47// Utility for working with the table of null-terminated strings after each
48// struct.
49class StringTable {
50 public:
51  StringTable();
52  ~StringTable();
53
54  // Construct a StringTable from a header and a max possible length.  The
55  // length includes the formatted portion (h->length).
56  zx_status_t Init(const Header* h, size_t max_struct_len);
57
58  // Return the length of the StringTable, in bytes, including terminating NUL.
59  size_t length() const { return length_; }
60
61  // This operation is slow, and indexed from 1.  |*out| is always assigned a
62  // null-terminated string, even on error.
63  zx_status_t GetString(size_t idx, const char** out) const;
64  // Convenience version that does not identify the error
65  const char* GetString(size_t idx) const {
66      const char* p;
67      GetString(idx, &p);
68      return p;
69  }
70
71  void Dump() const;
72 private:
73  DISALLOW_COPY_ASSIGN_AND_MOVE(StringTable);
74
75  const char* start_ = nullptr;
76  size_t length_ = 0;
77};
78
79// Utility for comparing specification versions.  Used to select which version
80// of the spec to use for interpreting a struct.
81struct SpecVersion {
82    SpecVersion(uint8_t major, uint8_t minor) : major_ver(major), minor_ver(minor) { }
83
84    // Returns true if this support for at least the queried version.
85    bool IncludesVersion(uint8_t spec_major_ver, uint8_t spec_minor_ver) const;
86
87    uint8_t major_ver;
88    uint8_t minor_ver;
89};
90
91enum class EntryPointVersion {
92    Unknown,
93    V2_1,
94    V3_0,
95};
96
97// Returning ZX_ERR_STOP aborts the walk.
98using StructWalkCallback = zx_status_t (*)(SpecVersion version, const Header* h,
99                                           const StringTable& st, void* ctx);
100
101// System structure identifying where the SMBIOS structs are in memory.
102struct EntryPoint2_1 {
103    uint8_t anchor_string[4]; // _SM_
104    uint8_t checksum;
105    uint8_t length;
106
107    // SMBIOS specification revision
108    uint8_t major_ver;
109    uint8_t minor_ver;
110
111    uint16_t max_struct_size;
112
113    uint8_t ep_rev; // Should be 0x00 for version SMBIOS 2.1 entry point
114    uint8_t formatted_area[5]; // Should be all 0x00 for ver 2.1
115
116    uint8_t intermediate_anchor_string[5]; // _DMI_
117    uint8_t intermediate_checksum;
118
119    uint16_t struct_table_length;
120    uint32_t struct_table_phys;
121    uint16_t struct_count;
122
123    uint8_t bcd_rev; // Should be 0x21
124
125    bool IsValid() const;
126
127    // Walk the known SMBIOS structures, assuming they are mapped at struct_table_virt.  The
128    // callback will be called once for each structure found.
129    zx_status_t WalkStructs(uintptr_t struct_table_virt, StructWalkCallback cb, void* ctx) const;
130
131    SpecVersion version() const { return SpecVersion(major_ver, minor_ver); }
132
133    void Dump() const;
134} __PACKED;
135static_assert(sizeof(EntryPoint2_1) == 0x1f, "");
136
137struct BiosInformationStruct2_0 {
138    Header hdr;
139
140    uint8_t vendor_str_idx;
141    uint8_t bios_version_str_idx;
142    uint16_t bios_starting_address_segment;
143    uint8_t bios_release_date_str_idx;
144    uint8_t bios_rom_size;
145    uint64_t bios_characteristics;
146    uint8_t bios_characteristics_ext[0];
147
148    void Dump(const StringTable& st) const;
149} __PACKED;
150static_assert(sizeof(BiosInformationStruct2_0) == 0x12, "");
151
152struct BiosInformationStruct2_4 {
153    Header hdr;
154
155    uint8_t vendor_str_idx; uint8_t bios_version_str_idx;
156    uint16_t bios_starting_address_segment;
157    uint8_t bios_release_date_str_idx;
158    uint8_t bios_rom_size;
159    uint64_t bios_characteristics;
160    uint16_t bios_characteristics_ext;
161
162    uint8_t bios_major_release;
163    uint8_t bios_minor_release;
164    uint8_t ec_major_release;
165    uint8_t ec_minor_release;
166
167    void Dump(const StringTable& st) const;
168} __PACKED;
169static_assert(sizeof(BiosInformationStruct2_4) == 0x18, "");
170
171struct SystemInformationStruct2_0 {
172    Header hdr;
173
174    uint8_t manufacturer_str_idx;
175    uint8_t product_name_str_idx;
176    uint8_t version_str_idx;
177    uint8_t serial_number_str_idx;
178
179    void Dump(const StringTable& st) const;
180} __PACKED;
181static_assert(sizeof(SystemInformationStruct2_0) == 0x8, "");
182
183struct SystemInformationStruct2_1 {
184    Header hdr;
185
186    uint8_t manufacturer_str_idx;
187    uint8_t product_name_str_idx;
188    uint8_t version_str_idx;
189    uint8_t serial_number_str_idx;
190
191    uint8_t uuid[16];
192    uint8_t wakeup_type;
193
194    void Dump(const StringTable& st) const;
195} __PACKED;
196static_assert(sizeof(SystemInformationStruct2_1) == 0x19, "");
197
198struct SystemInformationStruct2_4 {
199    Header hdr;
200
201    uint8_t manufacturer_str_idx;
202    uint8_t product_name_str_idx;
203    uint8_t version_str_idx;
204    uint8_t serial_number_str_idx;
205
206    uint8_t uuid[16];
207    uint8_t wakeup_type;
208
209    uint8_t sku_number_str_idx;
210    uint8_t family_str_idx;
211
212    void Dump(const StringTable& st) const;
213} __PACKED;
214static_assert(sizeof(SystemInformationStruct2_4) == 0x1b, "");
215
216} // namespace smbios
217