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