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