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