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 
18 namespace smbios {
19 
20 enum 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
40 struct Header {
41     StructType type;
42     uint8_t length;
43     uint16_t handle;
44 } __PACKED;
45 static_assert(sizeof(Header) == 4, "");
46 
47 // Utility for working with the table of null-terminated strings after each
48 // struct.
49 class 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.
length()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
GetString(size_t idx)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.
81 struct SpecVersion {
SpecVersionSpecVersion82     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 
91 enum class EntryPointVersion {
92     Unknown,
93     V2_1,
94     V3_0,
95 };
96 
97 // Returning ZX_ERR_STOP aborts the walk.
98 using 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.
102 struct 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 
versionEntryPoint2_1131     SpecVersion version() const { return SpecVersion(major_ver, minor_ver); }
132 
133     void Dump() const;
134 } __PACKED;
135 static_assert(sizeof(EntryPoint2_1) == 0x1f, "");
136 
137 struct 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;
150 static_assert(sizeof(BiosInformationStruct2_0) == 0x12, "");
151 
152 struct 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;
169 static_assert(sizeof(BiosInformationStruct2_4) == 0x18, "");
170 
171 struct 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;
181 static_assert(sizeof(SystemInformationStruct2_0) == 0x8, "");
182 
183 struct 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;
196 static_assert(sizeof(SystemInformationStruct2_1) == 0x19, "");
197 
198 struct 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;
214 static_assert(sizeof(SystemInformationStruct2_4) == 0x1b, "");
215 
216 } // namespace smbios
217