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