VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/TableConversion.c@ 67974

Last change on this file since 67974 was 62500, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1/* $Id: TableConversion.c 62500 2016-07-22 19:06:59Z vboxsync $ */
2/** @file
3 * TableConversion.c
4 */
5
6/*
7 * Copyright (C) 2009-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*++
28
29 This code is baed on:
30
31 Copyright (c) 2006 - 2007, Intel Corporation
32 All rights reserved. This program and the accompanying materials
33 are licensed and made available under the terms and conditions of the BSD License
34 which accompanies this distribution. The full text of the license may be found at
35 http://opensource.org/licenses/bsd-license.php
36
37 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
38 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
39 --*/
40
41#include <IndustryStandard/Pci.h>
42#include <IndustryStandard/Acpi.h>
43#include <IndustryStandard/SmBios.h>
44#include "LegacyBiosMpTable.h"
45
46#include <Library/DebugLib.h>
47#include <Library/BaseMemoryLib.h>
48#include <Library/UefiBootServicesTableLib.h>
49#include <Library/MemoryAllocationLib.h>
50#include <Library/BaseLib.h>
51
52#include <Guid/Acpi.h>
53#include <Guid/SmBios.h>
54#include <Guid/Mps.h>
55#include <Guid/HobList.h>
56#include <Guid/GlobalVariable.h>
57
58#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )
59#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF
60
61EFI_STATUS
62ConvertAcpiTable (
63 IN UINTN TableLen,
64 IN OUT VOID **Table
65 )
66/*++
67
68 Routine Description:
69 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
70 Assumption here:
71 As in legacy Bios, ACPI table is required to place in E/F Seg,
72 So here we just check if the range is E/F seg,
73 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
74
75 Arguments:
76 TableLen - Acpi RSDP length
77 Table - pointer to the table
78
79 Returns:
80 EFI_SUCCESS - Convert Table successfully
81 Other - Failed
82
83 --*/
84{
85 VOID *AcpiTableOri;
86 VOID *AcpiTableNew;
87 EFI_STATUS Status;
88 EFI_PHYSICAL_ADDRESS BufferPtr;
89
90
91 AcpiTableOri = (VOID *)(UINTN)((*Table));
92
93 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
94 Status = gBS->AllocatePages (
95 AllocateMaxAddress,
96 EfiACPIMemoryNVS,
97 EFI_SIZE_TO_PAGES(TableLen),
98 &BufferPtr
99 );
100 ASSERT_EFI_ERROR (Status);
101 AcpiTableNew = (VOID *)(UINTN)BufferPtr;
102 CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
103
104 //
105 // Change configuration table Pointer
106 //
107 *Table = AcpiTableNew;
108
109 return EFI_SUCCESS;
110}
111
112EFI_STATUS
113ConvertSmbiosTable (
114 IN OUT VOID **Table
115 )
116/*++
117
118 Routine Description:
119
120 Convert Smbios Table if the Location of the SMBios Table is lower than Address 0x100000
121 Assumption here:
122 As in legacy Bios, Smbios table is required to place in E/F Seg,
123 So here we just check if the range is F seg,
124 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
125 Arguments:
126 Table - pointer to the table
127
128 Returns:
129 EFI_SUCCESS - Convert Table successfully
130 Other - Failed
131
132 --*/
133{
134 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
135 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
136 EFI_STATUS Status;
137 UINT32 SmbiosEntryLen;
138 UINT32 BufferLen;
139 EFI_PHYSICAL_ADDRESS BufferPtr;
140
141 SmbiosTableNew = NULL;
142 SmbiosTableOri = NULL;
143
144 //
145 // Get Smibos configuration Table
146 //
147 SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)((*Table));
148
149
150 ASSERT(CalculateSum8((UINT8*)SmbiosTableOri, sizeof(SMBIOS_TABLE_ENTRY_POINT)) == 0);
151 //
152 // Relocate the Smibos memory
153 //
154 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
155 if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
156 SmbiosEntryLen = SmbiosTableOri->EntryPointLength;
157 } else {
158 //
159 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
160 //
161 SmbiosEntryLen = 0x1F;
162 }
163 BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
164 Status = gBS->AllocatePages (
165 AllocateMaxAddress,
166 EfiACPIMemoryNVS,
167 EFI_SIZE_TO_PAGES(BufferLen),
168 &BufferPtr
169 );
170 ASSERT_EFI_ERROR (Status);
171 SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
172 CopyMem (
173 SmbiosTableNew,
174 SmbiosTableOri,
175 SmbiosEntryLen
176 );
177 //
178 // Get Smbios Structure table address, and make sure the start address is 32-bit align
179 //
180 BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
181 CopyMem (
182 (VOID *)(UINTN)BufferPtr,
183 (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
184 SmbiosTableOri->TableLength
185 );
186 SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
187 SmbiosTableNew->IntermediateChecksum = 0;
188 SmbiosTableNew->IntermediateChecksum =
189 CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
190 //
191 // Change the SMBIOS pointer
192 //
193 *Table = SmbiosTableNew;
194
195 return EFI_SUCCESS;
196}
197
198EFI_STATUS
199ConvertMpsTable (
200 IN OUT VOID **Table
201 )
202/*++
203
204 Routine Description:
205
206 Convert MP Table if the Location of the SMBios Table is lower than Address 0x100000
207 Assumption here:
208 As in legacy Bios, MP table is required to place in E/F Seg,
209 So here we just check if the range is E/F seg,
210 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
211 Arguments:
212 Table - pointer to the table
213
214 Returns:
215 EFI_SUCCESS - Convert Table successfully
216 Other - Failed
217
218 --*/
219{
220 UINT32 Data32;
221 UINT32 FPLength;
222 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
223 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
224 EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
225 EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
226 VOID *OemTableOri;
227 VOID *OemTableNew;
228 EFI_STATUS Status;
229 EFI_PHYSICAL_ADDRESS BufferPtr;
230
231 //
232 // Get MP configuration Table
233 //
234 MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*Table);
235 //
236 // Get Floating pointer structure length
237 //
238 FPLength = MpsFloatingPointerOri->Length * 16;
239 ASSERT(CalculateSum8((UINT8*)MpsFloatingPointerOri, FPLength) == 0);
240 Data32 = FPLength + SYS_TABLE_PAD (FPLength);
241 MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
242 ASSERT(MpsTableOri != NULL);
243 ASSERT(CalculateSum8((UINT8*)MpsTableOri, MpsTableOri->BaseTableLength) == 0);
244
245 Data32 += MpsTableOri->BaseTableLength;
246 Data32 += MpsTableOri->ExtendedTableLength;
247 if (MpsTableOri->OemTablePointer != 0x00) {
248 Data32 += SYS_TABLE_PAD (Data32);
249 Data32 += MpsTableOri->OemTableSize;
250 }
251
252 //
253 // Relocate memory
254 //
255 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
256 Status = gBS->AllocatePages (
257 AllocateMaxAddress,
258 EfiACPIMemoryNVS,
259 EFI_SIZE_TO_PAGES(Data32),
260 &BufferPtr
261 );
262 ASSERT_EFI_ERROR (Status);
263 MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
264 CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
265 //
266 // If Mp Table exists
267 //
268 if (MpsTableOri != NULL) {
269 //
270 // Get Mps table length, including Ext table
271 //
272 BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
273 MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
274 CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
275
276 if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
277 BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
278 BufferPtr += SYS_TABLE_PAD (BufferPtr);
279 OemTableNew = (VOID *)(UINTN)BufferPtr;
280 OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
281 CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
282 MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
283 }
284 MpsTableNew->Checksum = 0;
285 MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength);
286 MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
287 MpsFloatingPointerNew->Checksum = 0;
288 MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength);
289 }
290 //
291 // Change the pointer
292 //
293 *Table = MpsFloatingPointerNew;
294
295 return EFI_SUCCESS;
296}
297
298EFI_STATUS
299ConvertSystemTable (
300 IN EFI_GUID *TableGuid,
301 IN OUT VOID **Table
302 )
303/*++
304
305 Routine Description:
306 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
307 Assumption here:
308 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
309 So here we just check if the range is E/F seg,
310 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
311
312 Arguments:
313 TableGuid - Guid of the table
314 Table - pointer to the table
315
316 Returns:
317 EFI_SUCCESS - Convert Table successfully
318 Other - Failed
319
320 --*/
321{
322 EFI_STATUS Status = EFI_SUCCESS;
323 VOID *AcpiHeader;
324 UINTN AcpiTableLen;
325
326 //
327 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
328 //
329
330 if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
331 AcpiHeader = (VOID*)(UINTN)(*Table);
332
333 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
334 //
335 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
336 //
337 AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
338 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
339 //
340 // If Acpi 2.0 or later, use RSDP Length fied.
341 //
342 AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
343 } else {
344 //
345 // Invalid Acpi Version, return
346 //
347 return EFI_UNSUPPORTED;
348 }
349 Status = ConvertAcpiTable (AcpiTableLen, Table);
350 return Status;
351 }
352
353 //
354 // If matches smbios guid, convert Smbios table.
355 //
356 if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
357 Status = ConvertSmbiosTable (Table);
358 return Status;
359 }
360
361 //
362 // If the table is MP table?
363 //
364 if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
365 Status = ConvertMpsTable (Table);
366 return Status;
367 }
368
369 return EFI_UNSUPPORTED;
370}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette