1/** @file
2  This driver installs SMBIOS information for OVMF
3
4  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
5  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
6
7  This program and the accompanying materials
8  are licensed and made available under the terms and conditions of the BSD License
9  which accompanies this distribution.  The full text of the license may be found at
10  http://opensource.org/licenses/bsd-license.php
11
12  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15**/
16
17#include "SmbiosPlatformDxe.h"
18
19#define TYPE0_STRINGS \
20  "EFI Development Kit II / OVMF\0"     /* Vendor */ \
21  "0.0.0\0"                             /* BiosVersion */ \
22  "02/06/2015\0"                        /* BiosReleaseDate */
23//
24// Type definition and contents of the default Type 0 SMBIOS table.
25//
26#pragma pack(1)
27typedef struct {
28  SMBIOS_TABLE_TYPE0 Base;
29  UINT8              Strings[sizeof(TYPE0_STRINGS)];
30} OVMF_TYPE0;
31#pragma pack()
32
33STATIC CONST OVMF_TYPE0 mOvmfDefaultType0 = {
34  {
35    // SMBIOS_STRUCTURE Hdr
36    {
37      EFI_SMBIOS_TYPE_BIOS_INFORMATION, // UINT8 Type
38      sizeof (SMBIOS_TABLE_TYPE0),      // UINT8 Length
39    },
40    1,     // SMBIOS_TABLE_STRING       Vendor
41    2,     // SMBIOS_TABLE_STRING       BiosVersion
42    0xE800,// UINT16                    BiosSegment
43    3,     // SMBIOS_TABLE_STRING       BiosReleaseDate
44    0,     // UINT8                     BiosSize
45    {      // MISC_BIOS_CHARACTERISTICS BiosCharacteristics
46      0,     // Reserved                                      :2
47      0,     // Unknown                                       :1
48      1,     // BiosCharacteristicsNotSupported               :1
49             // Remaining BiosCharacteristics bits left unset :60
50    },
51    {      // BIOSCharacteristicsExtensionBytes[2]
52      0,     // BiosReserved
53      0x1C   // SystemReserved = VirtualMachineSupported |
54             //                  UefiSpecificationSupported |
55             //                  TargetContentDistributionEnabled
56    },
57    0,     // UINT8                     SystemBiosMajorRelease
58    0,     // UINT8                     SystemBiosMinorRelease
59    0xFF,  // UINT8                     EmbeddedControllerFirmwareMajorRelease
60    0xFF   // UINT8                     EmbeddedControllerFirmwareMinorRelease
61  },
62  // Text strings (unformatted area)
63  TYPE0_STRINGS
64};
65
66
67/**
68  Get SMBIOS record length.
69
70  @param  SmbiosTable   SMBIOS pointer.
71
72**/
73UINTN
74SmbiosTableLength (
75  IN SMBIOS_STRUCTURE_POINTER SmbiosTable
76  )
77{
78  CHAR8  *AChar;
79  UINTN  Length;
80
81  AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);
82
83  //
84  // Each structure shall be terminated by a double-null (SMBIOS spec.7.1)
85  //
86  while ((*AChar != 0) || (*(AChar + 1) != 0)) {
87    AChar ++;
88  }
89  Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2);
90
91  return Length;
92}
93
94
95/**
96  Install all structures from the given SMBIOS structures block
97
98  @param  Smbios               SMBIOS protocol
99  @param  TableAddress         SMBIOS tables starting address
100
101**/
102EFI_STATUS
103InstallAllStructures (
104  IN EFI_SMBIOS_PROTOCOL       *Smbios,
105  IN UINT8                     *TableAddress
106  )
107{
108  EFI_STATUS                Status;
109  SMBIOS_STRUCTURE_POINTER  SmbiosTable;
110  EFI_SMBIOS_HANDLE         SmbiosHandle;
111  BOOLEAN                   NeedSmbiosType0;
112
113  SmbiosTable.Raw = TableAddress;
114  if (SmbiosTable.Raw == NULL) {
115    return EFI_INVALID_PARAMETER;
116  }
117
118  NeedSmbiosType0 = TRUE;
119
120  while (SmbiosTable.Hdr->Type != 127) {
121    //
122    // Log the SMBIOS data for this structure
123    //
124    SmbiosHandle = SmbiosTable.Hdr->Handle;
125    Status = Smbios->Add (
126                       Smbios,
127                       NULL,
128                       &SmbiosHandle,
129                       (EFI_SMBIOS_TABLE_HEADER*) SmbiosTable.Raw
130                       );
131    ASSERT_EFI_ERROR (Status);
132
133    if (SmbiosTable.Hdr->Type == 0) {
134      NeedSmbiosType0 = FALSE;
135    }
136
137    //
138    // Get the next structure address
139    //
140    SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable));
141  }
142
143  if (NeedSmbiosType0) {
144    //
145    // Add OVMF default Type 0 (BIOS Information) table
146    //
147    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
148    Status = Smbios->Add (
149                       Smbios,
150                       NULL,
151                       &SmbiosHandle,
152                       (EFI_SMBIOS_TABLE_HEADER*) &mOvmfDefaultType0
153                       );
154    ASSERT_EFI_ERROR (Status);
155  }
156
157  return EFI_SUCCESS;
158}
159
160
161/**
162  Installs SMBIOS information for OVMF
163
164  @param ImageHandle     Module's image handle
165  @param SystemTable     Pointer of EFI_SYSTEM_TABLE
166
167  @retval EFI_SUCCESS    Smbios data successfully installed
168  @retval Other          Smbios data was not installed
169
170**/
171EFI_STATUS
172EFIAPI
173SmbiosTablePublishEntry (
174  IN EFI_HANDLE           ImageHandle,
175  IN EFI_SYSTEM_TABLE     *SystemTable
176  )
177{
178  EFI_STATUS                Status;
179  EFI_SMBIOS_PROTOCOL       *Smbios;
180  SMBIOS_TABLE_ENTRY_POINT  *EntryPointStructure;
181  UINT8                     *SmbiosTables;
182
183  //
184  // Find the SMBIOS protocol
185  //
186  Status = gBS->LocateProtocol (
187                  &gEfiSmbiosProtocolGuid,
188                  NULL,
189                  (VOID**)&Smbios
190                  );
191  if (EFI_ERROR (Status)) {
192    return Status;
193  }
194
195  //
196  // Add Xen or QEMU SMBIOS data if found
197  //
198  EntryPointStructure = GetXenSmbiosTables ();
199  if (EntryPointStructure != NULL) {
200    SmbiosTables = (UINT8*)(UINTN)EntryPointStructure->TableAddress;
201  } else {
202    SmbiosTables = GetQemuSmbiosTables ();
203  }
204
205  if (SmbiosTables != NULL) {
206    Status = InstallAllStructures (Smbios, SmbiosTables);
207
208    //
209    // Free SmbiosTables if allocated by Qemu (i.e., NOT by Xen):
210    //
211    if (EntryPointStructure == NULL) {
212      FreePool (SmbiosTables);
213    }
214  }
215
216  return Status;
217}
218