]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/Library/DuetBdsLib/BdsPlatform.c
Clean up KbcRestDxe:
[mirror_edk2.git] / DuetPkg / Library / DuetBdsLib / BdsPlatform.c
1 /*++
2
3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 BdsPlatform.c
15
16 Abstract:
17
18 This file include all platform action which can be customized
19 by IBV/OEM.
20
21 --*/
22
23 #include "BdsPlatform.h"
24
25 #define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
26
27 CHAR16 mFirmwareVendor[] = L"TianoCore.org";
28 extern BOOLEAN gConnectAllHappened;
29 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;
30 //
31 // BDS Platform Functions
32 //
33
34 VOID
35 GetSystemTablesFromHob (
36 VOID
37 )
38 /*++
39
40 Routine Description:
41 Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
42
43 Arguments:
44 None
45
46 Returns:
47 None.
48
49 --*/
50 {
51 EFI_PEI_HOB_POINTERS GuidHob;
52 EFI_PEI_HOB_POINTERS HobStart;
53 EFI_PHYSICAL_ADDRESS *Table;
54 UINTN Index;
55 EFI_GUID *TableGuidArray[] = {
56 &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid
57 };
58
59 //
60 // Get Hob List
61 //
62 HobStart.Raw = GetHobList ();
63 //
64 // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
65 //
66 for (Index = 0; Index < sizeof (TableGuidArray) / sizeof (*TableGuidArray); ++Index) {
67 GuidHob.Raw = GetNextGuidHob (TableGuidArray[Index], HobStart.Raw);
68 if (GuidHob.Raw != NULL) {
69 Table = GET_GUID_HOB_DATA (GuidHob.Guid);
70 if (Table != NULL) {
71 //
72 // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
73 // According to UEFI Spec, we should make sure Smbios table,
74 // ACPI table and Mps tables kept in memory of specified type
75 //
76 ConvertSystemTable(TableGuidArray[Index], (VOID**)&Table);
77 gBS->InstallConfigurationTable (TableGuidArray[Index], (VOID *)Table);
78 }
79 }
80 }
81
82 return ;
83 }
84
85 #define EFI_LDR_MEMORY_DESCRIPTOR_GUID \
86 { 0x7701d7e5, 0x7d1d, 0x4432, {0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }}
87
88 EFI_GUID gEfiLdrMemoryDescriptorGuid = EFI_LDR_MEMORY_DESCRIPTOR_GUID;
89
90 #pragma pack(1)
91
92 typedef struct {
93 EFI_HOB_GUID_TYPE Hob;
94 UINTN MemDescCount;
95 EFI_MEMORY_DESCRIPTOR *MemDesc;
96 } MEMORY_DESC_HOB;
97
98 #pragma pack()
99
100 #if 0
101 VOID
102 PrintMemoryMap (
103 VOID
104 )
105 {
106 EFI_MEMORY_DESCRIPTOR *MemMap;
107 EFI_MEMORY_DESCRIPTOR *MemMapPtr;
108 UINTN MemMapSize;
109 UINTN MapKey, DescriptorSize;
110 UINTN Index;
111 UINT32 DescriptorVersion;
112 UINT64 Bytes;
113 EFI_STATUS Status;
114
115 MemMapSize = 0;
116 MemMap = NULL;
117 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
118 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
119 MemMapSize += EFI_PAGE_SIZE;
120 Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap);
121 ASSERT (Status == EFI_SUCCESS);
122 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
123 ASSERT (Status == EFI_SUCCESS);
124 MemMapPtr = MemMap;
125
126 ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);
127
128 for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) {
129 Bytes = LShiftU64 (MemMap->NumberOfPages, 12);
130 DEBUG ((EFI_D_ERROR, "%lX-%lX %lX %lX %X\n",
131 MemMap->PhysicalStart,
132 MemMap->PhysicalStart + Bytes - 1,
133 MemMap->NumberOfPages,
134 MemMap->Attribute,
135 (UINTN)MemMap->Type));
136 MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize);
137 }
138
139 gBS->FreePool (MemMapPtr);
140 }
141 #endif
142
143 VOID
144 UpdateMemoryMap (
145 VOID
146 )
147 {
148 EFI_STATUS Status;
149 EFI_PEI_HOB_POINTERS GuidHob;
150 VOID *Table;
151 MEMORY_DESC_HOB MemoryDescHob;
152 UINTN Index;
153 EFI_PHYSICAL_ADDRESS Memory;
154
155 //
156 // Get Hob List
157 //
158 GuidHob.Raw = GetHobList();
159
160 GuidHob.Raw = GetNextGuidHob (&gEfiLdrMemoryDescriptorGuid, GuidHob.Raw);
161 if (GuidHob.Raw == NULL) {
162 DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
163 return;
164 }
165 Table = GET_GUID_HOB_DATA (GuidHob.Guid);
166 if (Table == NULL) {
167 DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
168 return;
169 }
170 MemoryDescHob.MemDescCount = *(UINTN *)Table;
171 MemoryDescHob.MemDesc = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));
172
173 //
174 // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
175 //
176 for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {
177 if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {
178 continue;
179 }
180 if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000ULL) {
181 continue;
182 }
183 if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||
184 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
185 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||
186 (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
187 (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
188 DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%x, ", MemoryDescHob.MemDesc[Index].PhysicalStart));
189 DEBUG ((EFI_D_ERROR, "PageNumber - 0x%x, ", MemoryDescHob.MemDesc[Index].NumberOfPages));
190 DEBUG ((EFI_D_ERROR, "Type - 0x%x\n", MemoryDescHob.MemDesc[Index].Type));
191 if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
192 (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {
193 //
194 // Skip RuntimeSevicesData and RuntimeServicesCode, they are BFV
195 //
196 continue;
197 }
198 Status = gDS->AddMemorySpace (
199 EfiGcdMemoryTypeSystemMemory,
200 MemoryDescHob.MemDesc[Index].PhysicalStart,
201 LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),
202 MemoryDescHob.MemDesc[Index].Attribute
203 );
204 if (EFI_ERROR (Status)) {
205 DEBUG ((EFI_D_ERROR, "AddMemorySpace fail!\n"));
206 if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
207 (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
208 //
209 // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
210 // For EfiReservedMemoryType, there maybe overlap. So skip check here.
211 //
212 // ASSERT_EFI_ERROR (Status);
213 }
214 continue;
215 }
216
217 Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;
218 Status = gBS->AllocatePages (
219 AllocateAddress,
220 (EFI_MEMORY_TYPE)MemoryDescHob.MemDesc[Index].Type,
221 (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,
222 &Memory
223 );
224 if (EFI_ERROR (Status)) {
225 DEBUG ((EFI_D_ERROR, "AllocatePages fail!\n"));
226 //
227 // For the page added, it must be allocated.
228 //
229 // ASSERT_EFI_ERROR (Status);
230 continue;
231 }
232 }
233 }
234
235 }
236
237 EFI_STATUS
238 DisableUsbLegacySupport(
239 void
240 )
241 /*++
242
243 Routine Description:
244 Disabble the USB legacy Support in all Ehci and Uhci.
245 This function assume all PciIo handles have been created in system.
246
247 Arguments:
248 None
249
250 Returns:
251 EFI_SUCCESS
252 EFI_NOT_FOUND
253 --*/
254 {
255 EFI_STATUS Status;
256 EFI_HANDLE *HandleArray;
257 UINTN HandleArrayCount;
258 UINTN Index;
259 EFI_PCI_IO_PROTOCOL *PciIo;
260 UINT8 Class[3];
261 UINT16 Command;
262 UINT32 HcCapParams;
263 UINT32 ExtendCap;
264 UINT32 Value;
265 UINT32 TimeOut;
266
267 //
268 // Find the usb host controller
269 //
270 Status = gBS->LocateHandleBuffer (
271 ByProtocol,
272 &gEfiPciIoProtocolGuid,
273 NULL,
274 &HandleArrayCount,
275 &HandleArray
276 );
277 if (!EFI_ERROR (Status)) {
278 for (Index = 0; Index < HandleArrayCount; Index++) {
279 Status = gBS->HandleProtocol (
280 HandleArray[Index],
281 &gEfiPciIoProtocolGuid,
282 (VOID **)&PciIo
283 );
284 if (!EFI_ERROR (Status)) {
285 //
286 // Find the USB host controller controller
287 //
288 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
289 if (!EFI_ERROR (Status)) {
290 if ((PCI_CLASS_SERIAL == Class[2]) &&
291 (PCI_CLASS_SERIAL_USB == Class[1])) {
292 if (PCI_CLASSC_PI_UHCI == Class[0]) {
293 //
294 // Found the UHCI, then disable the legacy support
295 //
296 Command = 0;
297 Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command);
298 } else if (PCI_CLASSC_PI_EHCI == Class[0]) {
299 //
300 // Found the EHCI, then disable the legacy support
301 //
302 Status = PciIo->Mem.Read (
303 PciIo,
304 EfiPciIoWidthUint32,
305 0, //EHC_BAR_INDEX
306 (UINT64) 0x08, //EHC_HCCPARAMS_OFFSET
307 1,
308 &HcCapParams
309 );
310
311 ExtendCap = (HcCapParams >> 8) & 0xFF;
312 //
313 // Disable the SMI in USBLEGCTLSTS firstly
314 //
315 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
316 Value &= 0xFFFF0000;
317 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
318
319 //
320 // Get EHCI Ownership from legacy bios
321 //
322 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
323 Value |= (0x1 << 24);
324 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
325
326 TimeOut = 40;
327 while (TimeOut--) {
328 gBS->Stall (500);
329
330 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
331
332 if ((Value & 0x01010000) == 0x01000000) {
333 break;
334 }
335 }
336 }
337 }
338 }
339 }
340 }
341 } else {
342 return Status;
343 }
344 gBS->FreePool (HandleArray);
345 return EFI_SUCCESS;
346 }
347
348
349 VOID
350 PlatformBdsInit (
351 IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
352 )
353 /*++
354
355 Routine Description:
356
357 Platform Bds init. Incude the platform firmware vendor, revision
358 and so crc check.
359
360 Arguments:
361
362 PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
363
364 Returns:
365
366 None.
367
368 --*/
369 {
370 //
371 // set firmwarevendor, here can be IBV/OEM customize
372 //
373 gST->FirmwareVendor = AllocateRuntimeCopyPool (
374 sizeof (mFirmwareVendor),
375 &mFirmwareVendor
376 );
377 ASSERT (gST->FirmwareVendor != NULL);
378
379 gST->FirmwareRevision = 0;
380
381 //
382 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
383 //
384 gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
385
386 GetSystemTablesFromHob ();
387
388 UpdateMemoryMap ();
389
390 //
391 // Append Usb Keyboard short form DevicePath into "ConInDev"
392 //
393 BdsLibUpdateConsoleVariable (
394 VarConsoleInpDev,
395 (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,
396 NULL
397 );
398 }
399
400 UINT64
401 GetPciExpressBaseAddressForRootBridge (
402 IN UINTN HostBridgeNumber,
403 IN UINTN RootBridgeNumber
404 )
405 /*++
406
407 Routine Description:
408 This routine is to get PciExpress Base Address for this RootBridge
409
410 Arguments:
411 HostBridgeNumber - The number of HostBridge
412 RootBridgeNumber - The number of RootBridge
413
414 Returns:
415 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
416
417 --*/
418 {
419 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
420 UINTN BufferSize;
421 UINT32 Index;
422 UINT32 Number;
423 EFI_PEI_HOB_POINTERS GuidHob;
424
425 //
426 // Get PciExpressAddressInfo Hob
427 //
428 PciExpressBaseAddressInfo = NULL;
429 BufferSize = 0;
430 GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);
431 if (GuidHob.Raw != NULL) {
432 PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
433 BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
434 } else {
435 return 0;
436 }
437
438 //
439 // Search the PciExpress Base Address in the Hob for current RootBridge
440 //
441 Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
442 for (Index = 0; Index < Number; Index++) {
443 if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
444 (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
445 return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
446 }
447 }
448
449 //
450 // Do not find the PciExpress Base Address in the Hob
451 //
452 return 0;
453 }
454
455 VOID
456 PatchPciRootBridgeDevicePath (
457 IN UINTN HostBridgeNumber,
458 IN UINTN RootBridgeNumber,
459 IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH *RootBridge
460 )
461 {
462 UINT64 PciExpressBase;
463
464 PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);
465
466 DEBUG ((EFI_D_INFO, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase));
467
468 if (PciExpressBase != 0) {
469 RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);
470 }
471 }
472
473 EFI_STATUS
474 ConnectRootBridge (
475 VOID
476 )
477 /*++
478
479 Routine Description:
480
481 Connect RootBridge
482
483 Arguments:
484
485 None.
486
487 Returns:
488
489 EFI_SUCCESS - Connect RootBridge successfully.
490 EFI_STATUS - Connect RootBridge fail.
491
492 --*/
493 {
494 EFI_STATUS Status;
495 EFI_HANDLE RootHandle;
496
497 //
498 // Patch Pci Root Bridge Device Path
499 //
500 PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);
501
502 //
503 // Make all the PCI_IO protocols on PCI Seg 0 show up
504 //
505 BdsLibConnectDevicePath (gPlatformRootBridges[0]);
506
507 Status = gBS->LocateDevicePath (
508 &gEfiDevicePathProtocolGuid,
509 &gPlatformRootBridges[0],
510 &RootHandle
511 );
512 DEBUG ((EFI_D_INFO, "Pci Root bridge handle is 0x%X\n", RootHandle));
513
514 if (EFI_ERROR (Status)) {
515 return Status;
516 }
517
518 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
519 if (EFI_ERROR (Status)) {
520 return Status;
521 }
522
523 return EFI_SUCCESS;
524 }
525
526 EFI_STATUS
527 PrepareLpcBridgeDevicePath (
528 IN EFI_HANDLE DeviceHandle
529 )
530 /*++
531
532 Routine Description:
533
534 Add IsaKeyboard to ConIn,
535 add IsaSerial to ConOut, ConIn, ErrOut.
536 LPC Bridge: 06 01 00
537
538 Arguments:
539
540 DeviceHandle - Handle of PCIIO protocol.
541
542 Returns:
543
544 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
545 EFI_STATUS - No LPC bridge is added.
546
547 --*/
548 {
549 EFI_STATUS Status;
550 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
551 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
552
553 DevicePath = NULL;
554 Status = gBS->HandleProtocol (
555 DeviceHandle,
556 &gEfiDevicePathProtocolGuid,
557 (VOID*)&DevicePath
558 );
559 if (EFI_ERROR (Status)) {
560 return Status;
561 }
562 TempDevicePath = DevicePath;
563
564 //
565 // Register Keyboard
566 //
567 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
568
569 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
570
571 //
572 // Register COM1
573 //
574 DevicePath = TempDevicePath;
575 gPnp16550ComPortDeviceNode.UID = 0;
576
577 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
578 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
579 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
580
581 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
582 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
583 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
584
585 //
586 // Register COM2
587 //
588 DevicePath = TempDevicePath;
589 gPnp16550ComPortDeviceNode.UID = 1;
590
591 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
592 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
593 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
594
595 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
596 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
597 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
598
599 return EFI_SUCCESS;
600 }
601
602 EFI_STATUS
603 GetGopDevicePath (
604 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
605 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
606 )
607 {
608 UINTN Index;
609 EFI_STATUS Status;
610 EFI_HANDLE PciDeviceHandle;
611 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
612 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
613 UINTN GopHandleCount;
614 EFI_HANDLE *GopHandleBuffer;
615
616 if (PciDevicePath == NULL || GopDevicePath == NULL) {
617 return EFI_INVALID_PARAMETER;
618 }
619
620 //
621 // Initialize the GopDevicePath to be PciDevicePath
622 //
623 *GopDevicePath = PciDevicePath;
624 TempPciDevicePath = PciDevicePath;
625
626 Status = gBS->LocateDevicePath (
627 &gEfiDevicePathProtocolGuid,
628 &TempPciDevicePath,
629 &PciDeviceHandle
630 );
631 if (EFI_ERROR (Status)) {
632 return Status;
633 }
634
635 //
636 // Try to connect this handle, so that GOP dirver could start on this
637 // device and create child handles with GraphicsOutput Protocol installed
638 // on them, then we get device paths of these child handles and select
639 // them as possible console device.
640 //
641 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
642
643 Status = gBS->LocateHandleBuffer (
644 ByProtocol,
645 &gEfiGraphicsOutputProtocolGuid,
646 NULL,
647 &GopHandleCount,
648 &GopHandleBuffer
649 );
650 if (!EFI_ERROR (Status)) {
651 //
652 // Add all the child handles as possible Console Device
653 //
654 for (Index = 0; Index < GopHandleCount; Index++) {
655 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
656 if (EFI_ERROR (Status)) {
657 continue;
658 }
659 if (CompareMem (
660 PciDevicePath,
661 TempDevicePath,
662 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
663 ) == 0) {
664 //
665 // In current implementation, we only enable one of the child handles
666 // as console device, i.e. sotre one of the child handle's device
667 // path to variable "ConOut"
668 // In futhure, we could select all child handles to be console device
669 //
670
671 *GopDevicePath = TempDevicePath;
672
673 //
674 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
675 // Add the integrity GOP device path.
676 //
677 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
678 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
679 }
680 }
681 gBS->FreePool (GopHandleBuffer);
682 }
683
684 return EFI_SUCCESS;
685 }
686
687 EFI_STATUS
688 PreparePciVgaDevicePath (
689 IN EFI_HANDLE DeviceHandle
690 )
691 /*++
692
693 Routine Description:
694
695 Add PCI VGA to ConOut.
696 PCI VGA: 03 00 00
697
698 Arguments:
699
700 DeviceHandle - Handle of PCIIO protocol.
701
702 Returns:
703
704 EFI_SUCCESS - PCI VGA is added to ConOut.
705 EFI_STATUS - No PCI VGA device is added.
706
707 --*/
708 {
709 EFI_STATUS Status;
710 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
711 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
712
713 DevicePath = NULL;
714 Status = gBS->HandleProtocol (
715 DeviceHandle,
716 &gEfiDevicePathProtocolGuid,
717 (VOID*)&DevicePath
718 );
719 if (EFI_ERROR (Status)) {
720 return Status;
721 }
722
723 GetGopDevicePath (DevicePath, &GopDevicePath);
724 DevicePath = GopDevicePath;
725
726 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
727
728 return EFI_SUCCESS;
729 }
730
731 EFI_STATUS
732 PreparePciSerialDevicePath (
733 IN EFI_HANDLE DeviceHandle
734 )
735 /*++
736
737 Routine Description:
738
739 Add PCI Serial to ConOut, ConIn, ErrOut.
740 PCI Serial: 07 00 02
741
742 Arguments:
743
744 DeviceHandle - Handle of PCIIO protocol.
745
746 Returns:
747
748 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
749 EFI_STATUS - No PCI Serial device is added.
750
751 --*/
752 {
753 EFI_STATUS Status;
754 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
755
756 DevicePath = NULL;
757 Status = gBS->HandleProtocol (
758 DeviceHandle,
759 &gEfiDevicePathProtocolGuid,
760 (VOID*)&DevicePath
761 );
762 if (EFI_ERROR (Status)) {
763 return Status;
764 }
765
766 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
767 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
768
769 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
770 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
771 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
772
773 return EFI_SUCCESS;
774 }
775
776 EFI_STATUS
777 DetectAndPreparePlatformPciDevicePath (
778 BOOLEAN DetectVgaOnly
779 )
780 /*++
781
782 Routine Description:
783
784 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
785
786 Arguments:
787
788 DetectVgaOnly - Only detect VGA device if it's TRUE.
789
790 Returns:
791
792 EFI_SUCCESS - PCI Device check and Console variable update successfully.
793 EFI_STATUS - PCI Device check or Console variable update fail.
794
795 --*/
796 {
797 EFI_STATUS Status;
798 UINTN HandleCount;
799 EFI_HANDLE *HandleBuffer;
800 UINTN Index;
801 EFI_PCI_IO_PROTOCOL *PciIo;
802 PCI_TYPE00 Pci;
803
804 //
805 // Start to check all the PciIo to find all possible device
806 //
807 HandleCount = 0;
808 HandleBuffer = NULL;
809 Status = gBS->LocateHandleBuffer (
810 ByProtocol,
811 &gEfiPciIoProtocolGuid,
812 NULL,
813 &HandleCount,
814 &HandleBuffer
815 );
816 if (EFI_ERROR (Status)) {
817 return Status;
818 }
819
820 for (Index = 0; Index < HandleCount; Index++) {
821 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);
822 if (EFI_ERROR (Status)) {
823 continue;
824 }
825
826 //
827 // Check for all PCI device
828 //
829 Status = PciIo->Pci.Read (
830 PciIo,
831 EfiPciIoWidthUint32,
832 0,
833 sizeof (Pci) / sizeof (UINT32),
834 &Pci
835 );
836 if (EFI_ERROR (Status)) {
837 continue;
838 }
839
840 if (!DetectVgaOnly) {
841 //
842 // Here we decide whether it is LPC Bridge
843 //
844 if ((IS_PCI_LPC (&Pci)) ||
845 ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {
846 //
847 // Add IsaKeyboard to ConIn,
848 // add IsaSerial to ConOut, ConIn, ErrOut
849 //
850 DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));
851 PrepareLpcBridgeDevicePath (HandleBuffer[Index]);
852 continue;
853 }
854 //
855 // Here we decide which Serial device to enable in PCI bus
856 //
857 if (IS_PCI_16550SERIAL (&Pci)) {
858 //
859 // Add them to ConOut, ConIn, ErrOut.
860 //
861 DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));
862 PreparePciSerialDevicePath (HandleBuffer[Index]);
863 continue;
864 }
865 }
866
867 //
868 // Here we decide which VGA device to enable in PCI bus
869 //
870 if (IS_PCI_VGA (&Pci)) {
871 //
872 // Add them to ConOut.
873 //
874 DEBUG ((EFI_D_INFO, "Find the VGA device\n"));
875 PreparePciVgaDevicePath (HandleBuffer[Index]);
876 continue;
877 }
878 }
879
880 gBS->FreePool (HandleBuffer);
881
882 return EFI_SUCCESS;
883 }
884
885 EFI_STATUS
886 PlatformBdsConnectConsole (
887 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
888 )
889 /*++
890
891 Routine Description:
892
893 Connect the predefined platform default console device. Always try to find
894 and enable the vga device if have.
895
896 Arguments:
897
898 PlatformConsole - Predfined platform default console device array.
899
900 Returns:
901
902 EFI_SUCCESS - Success connect at least one ConIn and ConOut
903 device, there must have one ConOut device is
904 active vga device.
905
906 EFI_STATUS - Return the status of
907 BdsLibConnectAllDefaultConsoles ()
908
909 --*/
910 {
911 EFI_STATUS Status;
912 UINTN Index;
913 EFI_DEVICE_PATH_PROTOCOL *VarConout;
914 EFI_DEVICE_PATH_PROTOCOL *VarConin;
915 UINTN DevicePathSize;
916
917 //
918 // Connect RootBridge
919 //
920 ConnectRootBridge ();
921
922 VarConout = BdsLibGetVariableAndSize (
923 VarConsoleOut,
924 &gEfiGlobalVariableGuid,
925 &DevicePathSize
926 );
927 VarConin = BdsLibGetVariableAndSize (
928 VarConsoleInp,
929 &gEfiGlobalVariableGuid,
930 &DevicePathSize
931 );
932
933 if (VarConout == NULL || VarConin == NULL) {
934 //
935 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
936 //
937 DetectAndPreparePlatformPciDevicePath (FALSE);
938
939 //
940 // Have chance to connect the platform default console,
941 // the platform default console is the minimue device group
942 // the platform should support
943 //
944 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
945 //
946 // Update the console variable with the connect type
947 //
948 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
949 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
950 }
951 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
952 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
953 }
954 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
955 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
956 }
957 }
958 } else {
959 //
960 // Only detect VGA device and add them to ConOut
961 //
962 DetectAndPreparePlatformPciDevicePath (TRUE);
963 }
964
965 //
966 // The ConIn devices connection will start the USB bus, should disable all
967 // Usb legacy support firstly.
968 // Caution: Must ensure the PCI bus driver has been started. Since the
969 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
970 //
971 Status = DisableUsbLegacySupport();
972
973 //
974 // Connect the all the default console with current cosole variable
975 //
976 Status = BdsLibConnectAllDefaultConsoles ();
977 if (EFI_ERROR (Status)) {
978 return Status;
979 }
980
981 return EFI_SUCCESS;
982 }
983
984 VOID
985 PlatformBdsConnectSequence (
986 VOID
987 )
988 /*++
989
990 Routine Description:
991
992 Connect with predeined platform connect sequence,
993 the OEM/IBV can customize with their own connect sequence.
994
995 Arguments:
996
997 None.
998
999 Returns:
1000
1001 None.
1002
1003 --*/
1004 {
1005 UINTN Index;
1006
1007 Index = 0;
1008
1009 //
1010 // Here we can get the customized platform connect sequence
1011 // Notes: we can connect with new variable which record the
1012 // last time boots connect device path sequence
1013 //
1014 while (gPlatformConnectSequence[Index] != NULL) {
1015 //
1016 // Build the platform boot option
1017 //
1018 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
1019 Index++;
1020 }
1021
1022 }
1023
1024 VOID
1025 PlatformBdsGetDriverOption (
1026 IN OUT LIST_ENTRY *BdsDriverLists
1027 )
1028 /*++
1029
1030 Routine Description:
1031
1032 Load the predefined driver option, OEM/IBV can customize this
1033 to load their own drivers
1034
1035 Arguments:
1036
1037 BdsDriverLists - The header of the driver option link list.
1038
1039 Returns:
1040
1041 None.
1042
1043 --*/
1044 {
1045 UINTN Index;
1046
1047 Index = 0;
1048
1049 //
1050 // Here we can get the customized platform driver option
1051 //
1052 while (gPlatformDriverOption[Index] != NULL) {
1053 //
1054 // Build the platform boot option
1055 //
1056 BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
1057 Index++;
1058 }
1059
1060 }
1061
1062 VOID
1063 PlatformBdsDiagnostics (
1064 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
1065 IN BOOLEAN QuietBoot
1066 )
1067 /*++
1068
1069 Routine Description:
1070
1071 Perform the platform diagnostic, such like test memory. OEM/IBV also
1072 can customize this fuction to support specific platform diagnostic.
1073
1074 Arguments:
1075
1076 MemoryTestLevel - The memory test intensive level
1077
1078 QuietBoot - Indicate if need to enable the quiet boot
1079
1080 Returns:
1081
1082 None.
1083
1084 --*/
1085 {
1086 EFI_STATUS Status;
1087
1088 //
1089 // Here we can decide if we need to show
1090 // the diagnostics screen
1091 // Notes: this quiet boot code should be remove
1092 // from the graphic lib
1093 //
1094 if (QuietBoot) {
1095 Status = EnableQuietBoot (&gEfiDefaultBmpLogoGuid);
1096 if (EFI_ERROR (Status)) {
1097 DisableQuietBoot ();
1098 return;
1099 }
1100
1101 //
1102 // Perform system diagnostic
1103 //
1104 Status = BdsMemoryTest (MemoryTestLevel);
1105 if (EFI_ERROR (Status)) {
1106 DisableQuietBoot ();
1107 }
1108
1109 return ;
1110 }
1111 //
1112 // Perform system diagnostic
1113 //
1114 Status = BdsMemoryTest (MemoryTestLevel);
1115 }
1116
1117 VOID
1118 PlatformBdsPolicyBehavior (
1119 IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
1120 IN OUT LIST_ENTRY *DriverOptionList,
1121 IN OUT LIST_ENTRY *BootOptionList
1122 )
1123 /*++
1124
1125 Routine Description:
1126
1127 The function will excute with as the platform policy, current policy
1128 is driven by boot mode. IBV/OEM can customize this code for their specific
1129 policy action.
1130
1131 Arguments:
1132
1133 PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
1134
1135 DriverOptionList - The header of the driver option link list
1136
1137 BootOptionList - The header of the boot option link list
1138
1139 Returns:
1140
1141 None.
1142
1143 --*/
1144 {
1145 EFI_STATUS Status;
1146 UINT16 Timeout;
1147 EFI_EVENT UserInputDurationTime;
1148 LIST_ENTRY *Link;
1149 BDS_COMMON_OPTION *BootOption;
1150 UINTN Index;
1151 EFI_INPUT_KEY Key;
1152 EFI_TPL OldTpl;
1153
1154 //
1155 // Init the time out value
1156 //
1157 Timeout = BdsLibGetTimeout ();
1158
1159 //
1160 // Load the driver option as the driver option list
1161 //
1162 PlatformBdsGetDriverOption (DriverOptionList);
1163
1164 //
1165 // Get current Boot Mode
1166 //
1167 Status = BdsLibGetBootMode (&PrivateData->BootMode);
1168 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", PrivateData->BootMode));
1169
1170 //
1171 // Go the different platform policy with different boot mode
1172 // Notes: this part code can be change with the table policy
1173 //
1174 ASSERT (PrivateData->BootMode == BOOT_WITH_FULL_CONFIGURATION);
1175 //
1176 // Connect platform console
1177 //
1178 Status = PlatformBdsConnectConsole (gPlatformConsole);
1179 if (EFI_ERROR (Status)) {
1180 //
1181 // Here OEM/IBV can customize with defined action
1182 //
1183 PlatformBdsNoConsoleAction ();
1184 }
1185 //
1186 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1187 //
1188 Status = gBS->CreateEvent (
1189 EVT_TIMER,
1190 0,
1191 NULL,
1192 NULL,
1193 &UserInputDurationTime
1194 );
1195 ASSERT (Status == EFI_SUCCESS);
1196 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1197 ASSERT (Status == EFI_SUCCESS);
1198 //
1199 // Memory test and Logo show
1200 //
1201 PlatformBdsDiagnostics (IGNORE, TRUE);
1202
1203 //
1204 // Perform some platform specific connect sequence
1205 //
1206 PlatformBdsConnectSequence ();
1207
1208 //
1209 // Give one chance to enter the setup if we
1210 // have the time out
1211 //
1212 // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.
1213 Timeout = 5;
1214 if (Timeout != 0) {
1215 PlatformBdsEnterFrontPage (Timeout, FALSE);
1216 }
1217
1218 //
1219 //BdsLibConnectAll ();
1220 //BdsLibEnumerateAllBootOption (BootOptionList);
1221
1222 //
1223 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1224 // checking code in real production tip.
1225 //
1226 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1227 // and do enumerate all the default boot options. But in development system board, the boot mode
1228 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1229 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1230 //
1231 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1232 if (EFI_ERROR(Status)) {
1233 //
1234 // If cannot find "BootOrder" variable, it may be first boot.
1235 // Try to connect all devices and enumerate all boot options here.
1236 //
1237 BdsLibConnectAll ();
1238 BdsLibEnumerateAllBootOption (BootOptionList);
1239 }
1240
1241 //
1242 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1243 // BDS should still give user a chance to enter Setup
1244 //
1245 // Connect first boot option, and then check user input before exit
1246 //
1247 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1248 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1249 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1250 //
1251 // skip the header of the link list, becuase it has no boot option
1252 //
1253 continue;
1254 } else {
1255 //
1256 // Make sure the boot option device path connected, but ignore the BBS device path
1257 //
1258 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1259 BdsLibConnectDevicePath (BootOption->DevicePath);
1260 }
1261 break;
1262 }
1263 }
1264
1265 //
1266 // Check whether the user input after the duration time has expired
1267 //
1268 OldTpl = EfiGetCurrentTpl();
1269 gBS->RestoreTPL (TPL_APPLICATION);
1270 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1271 gBS->CloseEvent (UserInputDurationTime);
1272 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1273 gBS->RaiseTPL (OldTpl);
1274
1275 if (!EFI_ERROR (Status)) {
1276 //
1277 // Enter Setup if user input
1278 //
1279 Timeout = 0xffff;
1280 PlatformBdsEnterFrontPage (Timeout, FALSE);
1281 }
1282
1283 return ;
1284
1285 }
1286
1287 VOID
1288 PlatformBdsBootSuccess (
1289 IN BDS_COMMON_OPTION *Option
1290 )
1291 /*++
1292
1293 Routine Description:
1294
1295 Hook point after a boot attempt succeeds. We don't expect a boot option to
1296 return, so the EFI 1.0 specification defines that you will default to an
1297 interactive mode and stop processing the BootOrder list in this case. This
1298 is alos a platform implementation and can be customized by IBV/OEM.
1299
1300 Arguments:
1301
1302 Option - Pointer to Boot Option that succeeded to boot.
1303
1304 Returns:
1305
1306 None.
1307
1308 --*/
1309 {
1310 CHAR16 *TmpStr;
1311
1312 //
1313 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1314 // select loop then we need to pop up a UI and wait for user input.
1315 //
1316 TmpStr = Option->StatusString;
1317 if (TmpStr != NULL) {
1318 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1319 gBS->FreePool (TmpStr);
1320 }
1321 }
1322
1323 VOID
1324 PlatformBdsBootFail (
1325 IN BDS_COMMON_OPTION *Option,
1326 IN EFI_STATUS Status,
1327 IN CHAR16 *ExitData,
1328 IN UINTN ExitDataSize
1329 )
1330 /*++
1331
1332 Routine Description:
1333
1334 Hook point after a boot attempt fails.
1335
1336 Arguments:
1337
1338 Option - Pointer to Boot Option that failed to boot.
1339
1340 Status - Status returned from failed boot.
1341
1342 ExitData - Exit data returned from failed boot.
1343
1344 ExitDataSize - Exit data size returned from failed boot.
1345
1346 Returns:
1347
1348 None.
1349
1350 --*/
1351 {
1352 CHAR16 *TmpStr;
1353
1354 //
1355 // If Boot returned with failed status then we need to pop up a UI and wait
1356 // for user input.
1357 //
1358 TmpStr = Option->StatusString;
1359 if (TmpStr != NULL) {
1360 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1361 gBS->FreePool (TmpStr);
1362 }
1363
1364 }
1365
1366 EFI_STATUS
1367 PlatformBdsNoConsoleAction (
1368 VOID
1369 )
1370 /*++
1371
1372 Routine Description:
1373
1374 This function is remained for IBV/OEM to do some platform action,
1375 if there no console device can be connected.
1376
1377 Arguments:
1378
1379 None.
1380
1381 Returns:
1382
1383 EFI_SUCCESS - Direct return success now.
1384
1385 --*/
1386 {
1387 return EFI_SUCCESS;
1388 }
1389
1390 EFI_STATUS
1391 ConvertSystemTable (
1392 IN EFI_GUID *TableGuid,
1393 IN OUT VOID **Table
1394 )
1395 /*++
1396
1397 Routine Description:
1398 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1399 Assumption here:
1400 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1401 So here we just check if the range is E/F seg,
1402 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1403
1404 Arguments:
1405 TableGuid - Guid of the table
1406 Table - pointer to the table
1407
1408 Returns:
1409 EFI_SUCEESS - Convert Table successfully
1410 Other - Failed
1411
1412 --*/
1413 {
1414 EFI_STATUS Status;
1415 VOID *AcpiHeader;
1416 UINTN AcpiTableLen;
1417
1418 //
1419 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1420 //
1421 AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));
1422
1423 if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
1424 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
1425 //
1426 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1427 //
1428 AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1429 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
1430 //
1431 // If Acpi 2.0 or later, use RSDP Length fied.
1432 //
1433 AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
1434 } else {
1435 //
1436 // Invalid Acpi Version, return
1437 //
1438 return EFI_UNSUPPORTED;
1439 }
1440 Status = ConvertAcpiTable (AcpiTableLen, Table);
1441 return Status;
1442 }
1443
1444 //
1445 // If matches smbios guid, convert Smbios table.
1446 //
1447 if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
1448 Status = ConvertSmbiosTable (Table);
1449 return Status;
1450 }
1451
1452 //
1453 // If the table is MP table?
1454 //
1455 if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
1456 Status = ConvertMpsTable (Table);
1457 return Status;
1458 }
1459
1460 return EFI_UNSUPPORTED;
1461 }
1462
1463 UINT8
1464 GetBufferCheckSum (
1465 IN VOID * Buffer,
1466 IN UINTN Length
1467 )
1468 /*++
1469
1470 Routine Description:
1471 Caculate buffer checksum (8-bit)
1472
1473 Arguments:
1474 Buffer - Pointer to Buffer that to be caculated
1475 Length - How many bytes are to be caculated
1476
1477 Returns:
1478 Checksum of the buffer
1479
1480 --*/
1481 {
1482 UINT8 CheckSum;
1483 UINT8 *Ptr8;
1484
1485 CheckSum = 0;
1486 Ptr8 = (UINT8 *) Buffer;
1487
1488 while (Length > 0) {
1489 CheckSum = (UINT8) (CheckSum + *Ptr8++);
1490 Length--;
1491 }
1492
1493 return (UINT8)((0xFF - CheckSum) + 1);
1494 }
1495
1496 EFI_STATUS
1497 ConvertAcpiTable (
1498 IN UINTN TableLen,
1499 IN OUT VOID **Table
1500 )
1501 /*++
1502
1503 Routine Description:
1504 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1505 Assumption here:
1506 As in legacy Bios, ACPI table is required to place in E/F Seg,
1507 So here we just check if the range is E/F seg,
1508 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1509
1510 Arguments:
1511 TableLen - Acpi RSDP length
1512 Table - pointer to the table
1513
1514 Returns:
1515 EFI_SUCEESS - Convert Table successfully
1516 Other - Failed
1517
1518 --*/
1519 {
1520 VOID *AcpiTableOri;
1521 VOID *AcpiTableNew;
1522 EFI_STATUS Status;
1523 EFI_PHYSICAL_ADDRESS BufferPtr;
1524
1525
1526 AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table));
1527 if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {
1528 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1529 Status = gBS->AllocatePages (
1530 AllocateMaxAddress,
1531 EfiACPIMemoryNVS,
1532 EFI_SIZE_TO_PAGES(TableLen),
1533 &BufferPtr
1534 );
1535 ASSERT_EFI_ERROR (Status);
1536 AcpiTableNew = (VOID *)(UINTN)BufferPtr;
1537 CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
1538 } else {
1539 AcpiTableNew = AcpiTableOri;
1540 }
1541 //
1542 // Change configuration table Pointer
1543 //
1544 *Table = AcpiTableNew;
1545
1546 return EFI_SUCCESS;
1547 }
1548
1549 EFI_STATUS
1550 ConvertSmbiosTable (
1551 IN OUT VOID **Table
1552 )
1553 /*++
1554
1555 Routine Description:
1556
1557 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1558 Assumption here:
1559 As in legacy Bios, Smbios table is required to place in E/F Seg,
1560 So here we just check if the range is F seg,
1561 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1562 Arguments:
1563 Table - pointer to the table
1564
1565 Returns:
1566 EFI_SUCEESS - Convert Table successfully
1567 Other - Failed
1568
1569 --*/
1570 {
1571 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
1572 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
1573 EFI_STATUS Status;
1574 UINT32 SmbiosEntryLen;
1575 UINT32 BufferLen;
1576 EFI_PHYSICAL_ADDRESS BufferPtr;
1577
1578 SmbiosTableNew = NULL;
1579 SmbiosTableOri = NULL;
1580
1581 //
1582 // Get Smibos configuration Table
1583 //
1584 SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));
1585
1586 if ((SmbiosTableOri == NULL) ||
1587 ((UINTN)SmbiosTableOri > 0x100000) ||
1588 ((UINTN)SmbiosTableOri < 0xF0000)){
1589 return EFI_SUCCESS;
1590 }
1591 //
1592 // Relocate the Smibos memory
1593 //
1594 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1595 if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
1596 SmbiosEntryLen = SmbiosTableOri->EntryPointLength;
1597 } else {
1598 //
1599 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1600 //
1601 SmbiosEntryLen = 0x1F;
1602 }
1603 BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
1604 Status = gBS->AllocatePages (
1605 AllocateMaxAddress,
1606 EfiACPIMemoryNVS,
1607 EFI_SIZE_TO_PAGES(BufferLen),
1608 &BufferPtr
1609 );
1610 ASSERT_EFI_ERROR (Status);
1611 SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
1612 CopyMem (
1613 SmbiosTableNew,
1614 SmbiosTableOri,
1615 SmbiosEntryLen
1616 );
1617 //
1618 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1619 //
1620 BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
1621 CopyMem (
1622 (VOID *)(UINTN)BufferPtr,
1623 (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
1624 SmbiosTableOri->TableLength
1625 );
1626 SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
1627 SmbiosTableNew->IntermediateChecksum = 0;
1628 SmbiosTableNew->IntermediateChecksum =
1629 GetBufferCheckSum ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
1630 //
1631 // Change the SMBIOS pointer
1632 //
1633 *Table = SmbiosTableNew;
1634
1635 return EFI_SUCCESS;
1636 }
1637
1638 EFI_STATUS
1639 ConvertMpsTable (
1640 IN OUT VOID **Table
1641 )
1642 /*++
1643
1644 Routine Description:
1645
1646 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1647 Assumption here:
1648 As in legacy Bios, MP table is required to place in E/F Seg,
1649 So here we just check if the range is E/F seg,
1650 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1651 Arguments:
1652 Table - pointer to the table
1653
1654 Returns:
1655 EFI_SUCEESS - Convert Table successfully
1656 Other - Failed
1657
1658 --*/
1659 {
1660 UINT32 Data32;
1661 UINT32 FPLength;
1662 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
1663 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
1664 EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
1665 EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
1666 VOID *OemTableOri;
1667 VOID *OemTableNew;
1668 EFI_STATUS Status;
1669 EFI_PHYSICAL_ADDRESS BufferPtr;
1670
1671 //
1672 // Get MP configuration Table
1673 //
1674 MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));
1675 if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) &&
1676 ((UINTN)MpsFloatingPointerOri >= 0xF0000))){
1677 return EFI_SUCCESS;
1678 }
1679 //
1680 // Get Floating pointer structure length
1681 //
1682 FPLength = MpsFloatingPointerOri->Length * 16;
1683 Data32 = FPLength + SYS_TABLE_PAD (FPLength);
1684 MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
1685 if (MpsTableOri != NULL) {
1686 Data32 += MpsTableOri->BaseTableLength;
1687 Data32 += MpsTableOri->ExtendedTableLength;
1688 if (MpsTableOri->OemTablePointer != 0x00) {
1689 Data32 += SYS_TABLE_PAD (Data32);
1690 Data32 += MpsTableOri->OemTableSize;
1691 }
1692 } else {
1693 return EFI_SUCCESS;
1694 }
1695 //
1696 // Relocate memory
1697 //
1698 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1699 Status = gBS->AllocatePages (
1700 AllocateMaxAddress,
1701 EfiACPIMemoryNVS,
1702 EFI_SIZE_TO_PAGES(Data32),
1703 &BufferPtr
1704 );
1705 ASSERT_EFI_ERROR (Status);
1706 MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
1707 CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
1708 //
1709 // If Mp Table exists
1710 //
1711 if (MpsTableOri != NULL) {
1712 //
1713 // Get Mps table length, including Ext table
1714 //
1715 BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
1716 MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
1717 CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
1718
1719 if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
1720 BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
1721 BufferPtr += SYS_TABLE_PAD (BufferPtr);
1722 OemTableNew = (VOID *)(UINTN)BufferPtr;
1723 OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
1724 CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
1725 MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
1726 }
1727 MpsTableNew->Checksum = 0;
1728 MpsTableNew->Checksum = GetBufferCheckSum (MpsTableNew, MpsTableOri->BaseTableLength);
1729 MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
1730 MpsFloatingPointerNew->Checksum = 0;
1731 MpsFloatingPointerNew->Checksum = GetBufferCheckSum (MpsFloatingPointerNew, FPLength);
1732 }
1733 //
1734 // Change the pointer
1735 //
1736 *Table = MpsFloatingPointerNew;
1737
1738 return EFI_SUCCESS;
1739 }