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