]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/Library/DuetBdsLib/BdsPlatform.c
Add UINT64 type cast when AND/OR with UINT64 Supports.
[mirror_edk2.git] / DuetPkg / Library / DuetBdsLib / BdsPlatform.c
1 /*++
2
3 Copyright (c) 2006 - 2011, 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 Status = gBS->HandleProtocol (
726 DeviceHandle,
727 &gEfiDevicePathProtocolGuid,
728 (VOID*)&DevicePath
729 );
730 if (EFI_ERROR (Status)) {
731 return Status;
732 }
733
734 GetGopDevicePath (DevicePath, &GopDevicePath);
735 DevicePath = GopDevicePath;
736
737 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
738
739 return EFI_SUCCESS;
740 }
741
742 EFI_STATUS
743 PreparePciSerialDevicePath (
744 IN EFI_HANDLE DeviceHandle
745 )
746 /*++
747
748 Routine Description:
749
750 Add PCI Serial to ConOut, ConIn, ErrOut.
751 PCI Serial: 07 00 02
752
753 Arguments:
754
755 DeviceHandle - Handle of PCIIO protocol.
756
757 Returns:
758
759 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
760 EFI_STATUS - No PCI Serial device is added.
761
762 --*/
763 {
764 EFI_STATUS Status;
765 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
766
767 DevicePath = NULL;
768 Status = gBS->HandleProtocol (
769 DeviceHandle,
770 &gEfiDevicePathProtocolGuid,
771 (VOID*)&DevicePath
772 );
773 if (EFI_ERROR (Status)) {
774 return Status;
775 }
776
777 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
778 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
779
780 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
781 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
782 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
783
784 return EFI_SUCCESS;
785 }
786
787 EFI_STATUS
788 DetectAndPreparePlatformPciDevicePath (
789 BOOLEAN DetectVgaOnly
790 )
791 /*++
792
793 Routine Description:
794
795 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
796
797 Arguments:
798
799 DetectVgaOnly - Only detect VGA device if it's TRUE.
800
801 Returns:
802
803 EFI_SUCCESS - PCI Device check and Console variable update successfully.
804 EFI_STATUS - PCI Device check or Console variable update fail.
805
806 --*/
807 {
808 EFI_STATUS Status;
809 UINTN HandleCount;
810 EFI_HANDLE *HandleBuffer;
811 UINTN Index;
812 EFI_PCI_IO_PROTOCOL *PciIo;
813 PCI_TYPE00 Pci;
814
815 //
816 // Start to check all the PciIo to find all possible device
817 //
818 HandleCount = 0;
819 HandleBuffer = NULL;
820 Status = gBS->LocateHandleBuffer (
821 ByProtocol,
822 &gEfiPciIoProtocolGuid,
823 NULL,
824 &HandleCount,
825 &HandleBuffer
826 );
827 if (EFI_ERROR (Status)) {
828 return Status;
829 }
830
831 for (Index = 0; Index < HandleCount; Index++) {
832 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);
833 if (EFI_ERROR (Status)) {
834 continue;
835 }
836
837 //
838 // Check for all PCI device
839 //
840 Status = PciIo->Pci.Read (
841 PciIo,
842 EfiPciIoWidthUint32,
843 0,
844 sizeof (Pci) / sizeof (UINT32),
845 &Pci
846 );
847 if (EFI_ERROR (Status)) {
848 continue;
849 }
850
851 if (!DetectVgaOnly) {
852 //
853 // Here we decide whether it is LPC Bridge
854 //
855 if ((IS_PCI_LPC (&Pci)) ||
856 ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {
857 //
858 // Add IsaKeyboard to ConIn,
859 // add IsaSerial to ConOut, ConIn, ErrOut
860 //
861 DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));
862 PrepareLpcBridgeDevicePath (HandleBuffer[Index]);
863 continue;
864 }
865 //
866 // Here we decide which Serial device to enable in PCI bus
867 //
868 if (IS_PCI_16550SERIAL (&Pci)) {
869 //
870 // Add them to ConOut, ConIn, ErrOut.
871 //
872 DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));
873 PreparePciSerialDevicePath (HandleBuffer[Index]);
874 continue;
875 }
876 }
877
878 //
879 // Here we decide which VGA device to enable in PCI bus
880 //
881 if (IS_PCI_VGA (&Pci)) {
882 //
883 // Add them to ConOut.
884 //
885 DEBUG ((EFI_D_INFO, "Find the VGA device\n"));
886 PreparePciVgaDevicePath (HandleBuffer[Index]);
887 continue;
888 }
889 }
890
891 gBS->FreePool (HandleBuffer);
892
893 return EFI_SUCCESS;
894 }
895
896 EFI_STATUS
897 PlatformBdsConnectConsole (
898 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
899 )
900 /*++
901
902 Routine Description:
903
904 Connect the predefined platform default console device. Always try to find
905 and enable the vga device if have.
906
907 Arguments:
908
909 PlatformConsole - Predfined platform default console device array.
910
911 Returns:
912
913 EFI_SUCCESS - Success connect at least one ConIn and ConOut
914 device, there must have one ConOut device is
915 active vga device.
916
917 EFI_STATUS - Return the status of
918 BdsLibConnectAllDefaultConsoles ()
919
920 --*/
921 {
922 EFI_STATUS Status;
923 UINTN Index;
924 EFI_DEVICE_PATH_PROTOCOL *VarConout;
925 EFI_DEVICE_PATH_PROTOCOL *VarConin;
926 UINTN DevicePathSize;
927
928 //
929 // Connect RootBridge
930 //
931 ConnectRootBridge ();
932
933 VarConout = BdsLibGetVariableAndSize (
934 VarConsoleOut,
935 &gEfiGlobalVariableGuid,
936 &DevicePathSize
937 );
938 VarConin = BdsLibGetVariableAndSize (
939 VarConsoleInp,
940 &gEfiGlobalVariableGuid,
941 &DevicePathSize
942 );
943
944 if (VarConout == NULL || VarConin == NULL) {
945 //
946 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
947 //
948 DetectAndPreparePlatformPciDevicePath (FALSE);
949
950 //
951 // Have chance to connect the platform default console,
952 // the platform default console is the minimue device group
953 // the platform should support
954 //
955 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
956 //
957 // Update the console variable with the connect type
958 //
959 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
960 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
961 }
962 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
963 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
964 }
965 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
966 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
967 }
968 }
969 } else {
970 //
971 // Only detect VGA device and add them to ConOut
972 //
973 DetectAndPreparePlatformPciDevicePath (TRUE);
974 }
975
976 //
977 // The ConIn devices connection will start the USB bus, should disable all
978 // Usb legacy support firstly.
979 // Caution: Must ensure the PCI bus driver has been started. Since the
980 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
981 //
982 Status = DisableUsbLegacySupport();
983
984 //
985 // Connect the all the default console with current cosole variable
986 //
987 Status = BdsLibConnectAllDefaultConsoles ();
988 if (EFI_ERROR (Status)) {
989 return Status;
990 }
991
992 return EFI_SUCCESS;
993 }
994
995 VOID
996 PlatformBdsConnectSequence (
997 VOID
998 )
999 /*++
1000
1001 Routine Description:
1002
1003 Connect with predeined platform connect sequence,
1004 the OEM/IBV can customize with their own connect sequence.
1005
1006 Arguments:
1007
1008 None.
1009
1010 Returns:
1011
1012 None.
1013
1014 --*/
1015 {
1016 UINTN Index;
1017
1018 Index = 0;
1019
1020 //
1021 // Here we can get the customized platform connect sequence
1022 // Notes: we can connect with new variable which record the
1023 // last time boots connect device path sequence
1024 //
1025 while (gPlatformConnectSequence[Index] != NULL) {
1026 //
1027 // Build the platform boot option
1028 //
1029 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
1030 Index++;
1031 }
1032
1033 }
1034
1035 VOID
1036 PlatformBdsGetDriverOption (
1037 IN OUT LIST_ENTRY *BdsDriverLists
1038 )
1039 /*++
1040
1041 Routine Description:
1042
1043 Load the predefined driver option, OEM/IBV can customize this
1044 to load their own drivers
1045
1046 Arguments:
1047
1048 BdsDriverLists - The header of the driver option link list.
1049
1050 Returns:
1051
1052 None.
1053
1054 --*/
1055 {
1056 UINTN Index;
1057
1058 Index = 0;
1059
1060 //
1061 // Here we can get the customized platform driver option
1062 //
1063 while (gPlatformDriverOption[Index] != NULL) {
1064 //
1065 // Build the platform boot option
1066 //
1067 BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
1068 Index++;
1069 }
1070
1071 }
1072
1073 VOID
1074 PlatformBdsDiagnostics (
1075 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
1076 IN BOOLEAN QuietBoot,
1077 IN BASEM_MEMORY_TEST BaseMemoryTest
1078 )
1079 /*++
1080
1081 Routine Description:
1082
1083 Perform the platform diagnostic, such like test memory. OEM/IBV also
1084 can customize this fuction to support specific platform diagnostic.
1085
1086 Arguments:
1087
1088 MemoryTestLevel - The memory test intensive level
1089
1090 QuietBoot - Indicate if need to enable the quiet boot
1091
1092 BaseMemoryTest - A pointer to BdsMemoryTest()
1093
1094 Returns:
1095
1096 None.
1097
1098 --*/
1099 {
1100 EFI_STATUS Status;
1101
1102 //
1103 // Here we can decide if we need to show
1104 // the diagnostics screen
1105 // Notes: this quiet boot code should be remove
1106 // from the graphic lib
1107 //
1108 if (QuietBoot) {
1109 Status = EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1110 if (EFI_ERROR (Status)) {
1111 DisableQuietBoot ();
1112 return;
1113 }
1114
1115 //
1116 // Perform system diagnostic
1117 //
1118 Status = BaseMemoryTest (MemoryTestLevel);
1119 if (EFI_ERROR (Status)) {
1120 DisableQuietBoot ();
1121 }
1122
1123 return ;
1124 }
1125 //
1126 // Perform system diagnostic
1127 //
1128 Status = BaseMemoryTest (MemoryTestLevel);
1129 }
1130
1131 VOID
1132 EFIAPI
1133 PlatformBdsPolicyBehavior (
1134 IN OUT LIST_ENTRY *DriverOptionList,
1135 IN OUT LIST_ENTRY *BootOptionList,
1136 IN PROCESS_CAPSULES ProcessCapsules,
1137 IN BASEM_MEMORY_TEST BaseMemoryTest
1138 )
1139 /*++
1140
1141 Routine Description:
1142
1143 The function will excute with as the platform policy, current policy
1144 is driven by boot mode. IBV/OEM can customize this code for their specific
1145 policy action.
1146
1147 Arguments:
1148
1149 DriverOptionList - The header of the driver option link list
1150
1151 BootOptionList - The header of the boot option link list
1152
1153 Returns:
1154
1155 None.
1156
1157 --*/
1158 {
1159 EFI_STATUS Status;
1160 UINT16 Timeout;
1161 EFI_EVENT UserInputDurationTime;
1162 UINTN Index;
1163 EFI_INPUT_KEY Key;
1164 EFI_BOOT_MODE BootMode;
1165
1166 //
1167 // Init the time out value
1168 //
1169 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1170
1171 //
1172 // Load the driver option as the driver option list
1173 //
1174 PlatformBdsGetDriverOption (DriverOptionList);
1175
1176 //
1177 // Get current Boot Mode
1178 //
1179 Status = BdsLibGetBootMode (&BootMode);
1180 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1181
1182 //
1183 // Go the different platform policy with different boot mode
1184 // Notes: this part code can be change with the table policy
1185 //
1186 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1187 //
1188 // Connect platform console
1189 //
1190 Status = PlatformBdsConnectConsole (gPlatformConsole);
1191 if (EFI_ERROR (Status)) {
1192 //
1193 // Here OEM/IBV can customize with defined action
1194 //
1195 PlatformBdsNoConsoleAction ();
1196 }
1197 //
1198 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1199 //
1200 Status = gBS->CreateEvent (
1201 EVT_TIMER,
1202 0,
1203 NULL,
1204 NULL,
1205 &UserInputDurationTime
1206 );
1207 ASSERT (Status == EFI_SUCCESS);
1208 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
1209 ASSERT (Status == EFI_SUCCESS);
1210 //
1211 // Memory test and Logo show
1212 //
1213 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1214
1215 //
1216 // Perform some platform specific connect sequence
1217 //
1218 PlatformBdsConnectSequence ();
1219
1220 //
1221 // Give one chance to enter the setup if we
1222 // have the time out
1223 //
1224 // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.
1225 Timeout = 5;
1226 if (Timeout != 0) {
1227 PlatformBdsEnterFrontPage (Timeout, FALSE);
1228 }
1229
1230 //
1231 //BdsLibConnectAll ();
1232 //BdsLibEnumerateAllBootOption (BootOptionList);
1233
1234 //
1235 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1236 // checking code in real production tip.
1237 //
1238 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1239 // and do enumerate all the default boot options. But in development system board, the boot mode
1240 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1241 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1242 //
1243 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1244 if (EFI_ERROR(Status)) {
1245 //
1246 // If cannot find "BootOrder" variable, it may be first boot.
1247 // Try to connect all devices and enumerate all boot options here.
1248 //
1249 BdsLibConnectAll ();
1250 BdsLibEnumerateAllBootOption (BootOptionList);
1251 }
1252
1253 //
1254 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1255 // BDS should still give user a chance to enter Setup
1256 // Check whether the user input after the duration time has expired
1257 //
1258 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1259 gBS->CloseEvent (UserInputDurationTime);
1260 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1261
1262 if (!EFI_ERROR (Status)) {
1263 //
1264 // Enter Setup if user input
1265 //
1266 Timeout = 0xffff;
1267 PlatformBdsEnterFrontPage (Timeout, FALSE);
1268 }
1269
1270 return ;
1271
1272 }
1273
1274 VOID
1275 EFIAPI
1276 PlatformBdsBootSuccess (
1277 IN BDS_COMMON_OPTION *Option
1278 )
1279 /*++
1280
1281 Routine Description:
1282
1283 Hook point after a boot attempt succeeds. We don't expect a boot option to
1284 return, so the EFI 1.0 specification defines that you will default to an
1285 interactive mode and stop processing the BootOrder list in this case. This
1286 is alos a platform implementation and can be customized by IBV/OEM.
1287
1288 Arguments:
1289
1290 Option - Pointer to Boot Option that succeeded to boot.
1291
1292 Returns:
1293
1294 None.
1295
1296 --*/
1297 {
1298 CHAR16 *TmpStr;
1299
1300 //
1301 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1302 // select loop then we need to pop up a UI and wait for user input.
1303 //
1304 TmpStr = Option->StatusString;
1305 if (TmpStr != NULL) {
1306 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1307 gBS->FreePool (TmpStr);
1308 }
1309 }
1310
1311 VOID
1312 EFIAPI
1313 PlatformBdsBootFail (
1314 IN BDS_COMMON_OPTION *Option,
1315 IN EFI_STATUS Status,
1316 IN CHAR16 *ExitData,
1317 IN UINTN ExitDataSize
1318 )
1319 /*++
1320
1321 Routine Description:
1322
1323 Hook point after a boot attempt fails.
1324
1325 Arguments:
1326
1327 Option - Pointer to Boot Option that failed to boot.
1328
1329 Status - Status returned from failed boot.
1330
1331 ExitData - Exit data returned from failed boot.
1332
1333 ExitDataSize - Exit data size returned from failed boot.
1334
1335 Returns:
1336
1337 None.
1338
1339 --*/
1340 {
1341 CHAR16 *TmpStr;
1342
1343 //
1344 // If Boot returned with failed status then we need to pop up a UI and wait
1345 // for user input.
1346 //
1347 TmpStr = Option->StatusString;
1348 if (TmpStr != NULL) {
1349 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1350 gBS->FreePool (TmpStr);
1351 }
1352
1353 }
1354
1355 EFI_STATUS
1356 PlatformBdsNoConsoleAction (
1357 VOID
1358 )
1359 /*++
1360
1361 Routine Description:
1362
1363 This function is remained for IBV/OEM to do some platform action,
1364 if there no console device can be connected.
1365
1366 Arguments:
1367
1368 None.
1369
1370 Returns:
1371
1372 EFI_SUCCESS - Direct return success now.
1373
1374 --*/
1375 {
1376 return EFI_SUCCESS;
1377 }
1378
1379 EFI_STATUS
1380 ConvertSystemTable (
1381 IN EFI_GUID *TableGuid,
1382 IN OUT VOID **Table
1383 )
1384 /*++
1385
1386 Routine Description:
1387 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1388 Assumption here:
1389 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1390 So here we just check if the range is E/F seg,
1391 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1392
1393 Arguments:
1394 TableGuid - Guid of the table
1395 Table - pointer to the table
1396
1397 Returns:
1398 EFI_SUCEESS - Convert Table successfully
1399 Other - Failed
1400
1401 --*/
1402 {
1403 EFI_STATUS Status;
1404 VOID *AcpiHeader;
1405 UINTN AcpiTableLen;
1406
1407 //
1408 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1409 //
1410 AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));
1411
1412 if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
1413 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
1414 //
1415 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1416 //
1417 AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1418 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
1419 //
1420 // If Acpi 2.0 or later, use RSDP Length fied.
1421 //
1422 AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
1423 } else {
1424 //
1425 // Invalid Acpi Version, return
1426 //
1427 return EFI_UNSUPPORTED;
1428 }
1429 Status = ConvertAcpiTable (AcpiTableLen, Table);
1430 return Status;
1431 }
1432
1433 //
1434 // If matches smbios guid, convert Smbios table.
1435 //
1436 if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
1437 Status = ConvertSmbiosTable (Table);
1438 return Status;
1439 }
1440
1441 //
1442 // If the table is MP table?
1443 //
1444 if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
1445 Status = ConvertMpsTable (Table);
1446 return Status;
1447 }
1448
1449 return EFI_UNSUPPORTED;
1450 }
1451
1452
1453 EFI_STATUS
1454 ConvertAcpiTable (
1455 IN UINTN TableLen,
1456 IN OUT VOID **Table
1457 )
1458 /*++
1459
1460 Routine Description:
1461 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1462 Assumption here:
1463 As in legacy Bios, ACPI table is required to place in E/F Seg,
1464 So here we just check if the range is E/F seg,
1465 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1466
1467 Arguments:
1468 TableLen - Acpi RSDP length
1469 Table - pointer to the table
1470
1471 Returns:
1472 EFI_SUCEESS - Convert Table successfully
1473 Other - Failed
1474
1475 --*/
1476 {
1477 VOID *AcpiTableOri;
1478 VOID *AcpiTableNew;
1479 EFI_STATUS Status;
1480 EFI_PHYSICAL_ADDRESS BufferPtr;
1481
1482
1483 AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table));
1484 if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {
1485 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1486 Status = gBS->AllocatePages (
1487 AllocateMaxAddress,
1488 EfiACPIMemoryNVS,
1489 EFI_SIZE_TO_PAGES(TableLen),
1490 &BufferPtr
1491 );
1492 ASSERT_EFI_ERROR (Status);
1493 AcpiTableNew = (VOID *)(UINTN)BufferPtr;
1494 CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
1495 } else {
1496 AcpiTableNew = AcpiTableOri;
1497 }
1498 //
1499 // Change configuration table Pointer
1500 //
1501 *Table = AcpiTableNew;
1502
1503 return EFI_SUCCESS;
1504 }
1505
1506 EFI_STATUS
1507 ConvertSmbiosTable (
1508 IN OUT VOID **Table
1509 )
1510 /*++
1511
1512 Routine Description:
1513
1514 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1515 Assumption here:
1516 As in legacy Bios, Smbios table is required to place in E/F Seg,
1517 So here we just check if the range is F seg,
1518 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1519 Arguments:
1520 Table - pointer to the table
1521
1522 Returns:
1523 EFI_SUCEESS - Convert Table successfully
1524 Other - Failed
1525
1526 --*/
1527 {
1528 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
1529 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
1530 EFI_STATUS Status;
1531 UINT32 SmbiosEntryLen;
1532 UINT32 BufferLen;
1533 EFI_PHYSICAL_ADDRESS BufferPtr;
1534
1535 SmbiosTableNew = NULL;
1536 SmbiosTableOri = NULL;
1537
1538 //
1539 // Get Smibos configuration Table
1540 //
1541 SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));
1542
1543 if ((SmbiosTableOri == NULL) ||
1544 ((UINTN)SmbiosTableOri > 0x100000) ||
1545 ((UINTN)SmbiosTableOri < 0xF0000)){
1546 return EFI_SUCCESS;
1547 }
1548 //
1549 // Relocate the Smibos memory
1550 //
1551 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1552 if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
1553 SmbiosEntryLen = SmbiosTableOri->EntryPointLength;
1554 } else {
1555 //
1556 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1557 //
1558 SmbiosEntryLen = 0x1F;
1559 }
1560 BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
1561 Status = gBS->AllocatePages (
1562 AllocateMaxAddress,
1563 EfiACPIMemoryNVS,
1564 EFI_SIZE_TO_PAGES(BufferLen),
1565 &BufferPtr
1566 );
1567 ASSERT_EFI_ERROR (Status);
1568 SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
1569 CopyMem (
1570 SmbiosTableNew,
1571 SmbiosTableOri,
1572 SmbiosEntryLen
1573 );
1574 //
1575 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1576 //
1577 BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
1578 CopyMem (
1579 (VOID *)(UINTN)BufferPtr,
1580 (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
1581 SmbiosTableOri->TableLength
1582 );
1583 SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
1584 SmbiosTableNew->IntermediateChecksum = 0;
1585 SmbiosTableNew->IntermediateChecksum =
1586 CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
1587 //
1588 // Change the SMBIOS pointer
1589 //
1590 *Table = SmbiosTableNew;
1591
1592 return EFI_SUCCESS;
1593 }
1594
1595 EFI_STATUS
1596 ConvertMpsTable (
1597 IN OUT VOID **Table
1598 )
1599 /*++
1600
1601 Routine Description:
1602
1603 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1604 Assumption here:
1605 As in legacy Bios, MP table is required to place in E/F Seg,
1606 So here we just check if the range is E/F seg,
1607 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1608 Arguments:
1609 Table - pointer to the table
1610
1611 Returns:
1612 EFI_SUCEESS - Convert Table successfully
1613 Other - Failed
1614
1615 --*/
1616 {
1617 UINT32 Data32;
1618 UINT32 FPLength;
1619 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
1620 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
1621 EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
1622 EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
1623 VOID *OemTableOri;
1624 VOID *OemTableNew;
1625 EFI_STATUS Status;
1626 EFI_PHYSICAL_ADDRESS BufferPtr;
1627
1628 //
1629 // Get MP configuration Table
1630 //
1631 MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));
1632 if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) &&
1633 ((UINTN)MpsFloatingPointerOri >= 0xF0000))){
1634 return EFI_SUCCESS;
1635 }
1636 //
1637 // Get Floating pointer structure length
1638 //
1639 FPLength = MpsFloatingPointerOri->Length * 16;
1640 Data32 = FPLength + SYS_TABLE_PAD (FPLength);
1641 MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
1642 if (MpsTableOri != NULL) {
1643 Data32 += MpsTableOri->BaseTableLength;
1644 Data32 += MpsTableOri->ExtendedTableLength;
1645 if (MpsTableOri->OemTablePointer != 0x00) {
1646 Data32 += SYS_TABLE_PAD (Data32);
1647 Data32 += MpsTableOri->OemTableSize;
1648 }
1649 } else {
1650 return EFI_SUCCESS;
1651 }
1652 //
1653 // Relocate memory
1654 //
1655 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1656 Status = gBS->AllocatePages (
1657 AllocateMaxAddress,
1658 EfiACPIMemoryNVS,
1659 EFI_SIZE_TO_PAGES(Data32),
1660 &BufferPtr
1661 );
1662 ASSERT_EFI_ERROR (Status);
1663 MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
1664 CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
1665 //
1666 // If Mp Table exists
1667 //
1668 if (MpsTableOri != NULL) {
1669 //
1670 // Get Mps table length, including Ext table
1671 //
1672 BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
1673 MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
1674 CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
1675
1676 if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
1677 BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
1678 BufferPtr += SYS_TABLE_PAD (BufferPtr);
1679 OemTableNew = (VOID *)(UINTN)BufferPtr;
1680 OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
1681 CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
1682 MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
1683 }
1684 MpsTableNew->Checksum = 0;
1685 MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength);
1686 MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
1687 MpsFloatingPointerNew->Checksum = 0;
1688 MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength);
1689 }
1690 //
1691 // Change the pointer
1692 //
1693 *Table = MpsFloatingPointerNew;
1694
1695 return EFI_SUCCESS;
1696 }
1697
1698 /**
1699 Lock the ConsoleIn device in system table. All key
1700 presses will be ignored until the Password is typed in. The only way to
1701 disable the password is to type it in to a ConIn device.
1702
1703 @param Password Password used to lock ConIn device.
1704
1705 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1706 @retval EFI_UNSUPPORTED Password not found
1707
1708 **/
1709 EFI_STATUS
1710 EFIAPI
1711 LockKeyboards (
1712 IN CHAR16 *Password
1713 )
1714 {
1715 return EFI_UNSUPPORTED;
1716 }
1717
1718 /**
1719 This function locks platform flash that is not allowed to be updated during normal boot path.
1720 The flash layout is platform specific.
1721
1722 **/
1723 VOID
1724 EFIAPI
1725 PlatformBdsLockNonUpdatableFlash (
1726 VOID
1727 )
1728 {
1729 return;
1730 }