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