]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/Library/DuetBdsLib/BdsPlatform.c
Fix some bugs in FSVariable and BdsPlatform for duet platform.
[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], &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 >= 0x100000000) {
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 &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, &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 &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 &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, &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 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 = EnableQuietBootEx (&gEfiDefaultBmpLogoGuid, mBdsImageHandle);
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 = BdsLibGetTimeout ();
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 EFI_EVENT_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 if (Timeout != 0) {
1215 PlatformBdsEnterFrontPage (Timeout, FALSE);
1216 }
1217
1218 //
1219 //BdsLibConnectAll ();
1220 //BdsLibEnumerateAllBootOption (BootOptionList);
1221
1222 //
1223 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1224 // checking code in real production tip.
1225 //
1226 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1227 // and do enumerate all the default boot options. But in development system board, the boot mode
1228 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1229 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1230 //
1231 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1232 if (EFI_ERROR(Status)) {
1233 //
1234 // If cannot find "BootOrder" variable, it may be first boot.
1235 // Try to connect all devices and enumerate all boot options here.
1236 //
1237 BdsLibConnectAll ();
1238 BdsLibEnumerateAllBootOption (BootOptionList);
1239 }
1240
1241 //
1242 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1243 // BDS should still give user a chance to enter Setup
1244 //
1245 // Connect first boot option, and then check user input before exit
1246 //
1247 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
1248 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
1249 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
1250 //
1251 // skip the header of the link list, becuase it has no boot option
1252 //
1253 continue;
1254 } else {
1255 //
1256 // Make sure the boot option device path connected, but ignore the BBS device path
1257 //
1258 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
1259 BdsLibConnectDevicePath (BootOption->DevicePath);
1260 }
1261 break;
1262 }
1263 }
1264
1265 //
1266 // Check whether the user input after the duration time has expired
1267 //
1268 OldTpl = EfiGetCurrentTpl();
1269 gBS->RestoreTPL (TPL_APPLICATION);
1270 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
1271 gBS->CloseEvent (UserInputDurationTime);
1272 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1273 gBS->RaiseTPL (OldTpl);
1274
1275 if (!EFI_ERROR (Status)) {
1276 //
1277 // Enter Setup if user input
1278 //
1279 Timeout = 0xffff;
1280 PlatformBdsEnterFrontPage (Timeout, FALSE);
1281 }
1282
1283 return ;
1284
1285 }
1286
1287 VOID
1288 PlatformBdsBootSuccess (
1289 IN BDS_COMMON_OPTION *Option
1290 )
1291 /*++
1292
1293 Routine Description:
1294
1295 Hook point after a boot attempt succeeds. We don't expect a boot option to
1296 return, so the EFI 1.0 specification defines that you will default to an
1297 interactive mode and stop processing the BootOrder list in this case. This
1298 is alos a platform implementation and can be customized by IBV/OEM.
1299
1300 Arguments:
1301
1302 Option - Pointer to Boot Option that succeeded to boot.
1303
1304 Returns:
1305
1306 None.
1307
1308 --*/
1309 {
1310 CHAR16 *TmpStr;
1311
1312 //
1313 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1314 // select loop then we need to pop up a UI and wait for user input.
1315 //
1316 TmpStr = Option->StatusString;
1317 if (TmpStr != NULL) {
1318 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1319 gBS->FreePool (TmpStr);
1320 }
1321 }
1322
1323 VOID
1324 PlatformBdsBootFail (
1325 IN BDS_COMMON_OPTION *Option,
1326 IN EFI_STATUS Status,
1327 IN CHAR16 *ExitData,
1328 IN UINTN ExitDataSize
1329 )
1330 /*++
1331
1332 Routine Description:
1333
1334 Hook point after a boot attempt fails.
1335
1336 Arguments:
1337
1338 Option - Pointer to Boot Option that failed to boot.
1339
1340 Status - Status returned from failed boot.
1341
1342 ExitData - Exit data returned from failed boot.
1343
1344 ExitDataSize - Exit data size returned from failed boot.
1345
1346 Returns:
1347
1348 None.
1349
1350 --*/
1351 {
1352 CHAR16 *TmpStr;
1353
1354 //
1355 // If Boot returned with failed status then we need to pop up a UI and wait
1356 // for user input.
1357 //
1358 TmpStr = Option->StatusString;
1359 if (TmpStr != NULL) {
1360 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1361 gBS->FreePool (TmpStr);
1362 }
1363
1364 }
1365
1366 EFI_STATUS
1367 PlatformBdsNoConsoleAction (
1368 VOID
1369 )
1370 /*++
1371
1372 Routine Description:
1373
1374 This function is remained for IBV/OEM to do some platform action,
1375 if there no console device can be connected.
1376
1377 Arguments:
1378
1379 None.
1380
1381 Returns:
1382
1383 EFI_SUCCESS - Direct return success now.
1384
1385 --*/
1386 {
1387 return EFI_SUCCESS;
1388 }
1389
1390 EFI_STATUS
1391 ConvertSystemTable (
1392 IN EFI_GUID *TableGuid,
1393 IN OUT VOID **Table
1394 )
1395 /*++
1396
1397 Routine Description:
1398 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1399 Assumption here:
1400 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1401 So here we just check if the range is E/F seg,
1402 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1403
1404 Arguments:
1405 TableGuid - Guid of the table
1406 Table - pointer to the table
1407
1408 Returns:
1409 EFI_SUCEESS - Convert Table successfully
1410 Other - Failed
1411
1412 --*/
1413 {
1414 EFI_STATUS Status;
1415 VOID *AcpiHeader;
1416 UINTN AcpiTableLen;
1417
1418 //
1419 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1420 //
1421 AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));
1422
1423 if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
1424 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
1425 //
1426 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1427 //
1428 AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1429 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
1430 //
1431 // If Acpi 2.0 or later, use RSDP Length fied.
1432 //
1433 AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
1434 } else {
1435 //
1436 // Invalid Acpi Version, return
1437 //
1438 return EFI_UNSUPPORTED;
1439 }
1440 Status = ConvertAcpiTable (AcpiTableLen, Table);
1441 return Status;
1442 }
1443
1444 //
1445 // If matches smbios guid, convert Smbios table.
1446 //
1447 if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
1448 Status = ConvertSmbiosTable (Table);
1449 return Status;
1450 }
1451
1452 //
1453 // If the table is MP table?
1454 //
1455 if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
1456 Status = ConvertMpsTable (Table);
1457 return Status;
1458 }
1459
1460 return EFI_UNSUPPORTED;
1461 }
1462
1463 UINT8
1464 GetBufferCheckSum (
1465 IN VOID * Buffer,
1466 IN UINTN Length
1467 )
1468 /*++
1469
1470 Routine Description:
1471 Caculate buffer checksum (8-bit)
1472
1473 Arguments:
1474 Buffer - Pointer to Buffer that to be caculated
1475 Length - How many bytes are to be caculated
1476
1477 Returns:
1478 Checksum of the buffer
1479
1480 --*/
1481 {
1482 UINT8 CheckSum;
1483 UINT8 *Ptr8;
1484
1485 CheckSum = 0;
1486 Ptr8 = (UINT8 *) Buffer;
1487
1488 while (Length > 0) {
1489 CheckSum = (UINT8) (CheckSum + *Ptr8++);
1490 Length--;
1491 }
1492
1493 return ((0xFF - CheckSum) + 1);
1494 }
1495
1496 EFI_STATUS
1497 ConvertAcpiTable (
1498 IN UINTN TableLen,
1499 IN OUT VOID **Table
1500 )
1501 /*++
1502
1503 Routine Description:
1504 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1505 Assumption here:
1506 As in legacy Bios, ACPI table is required to place in E/F Seg,
1507 So here we just check if the range is E/F seg,
1508 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1509
1510 Arguments:
1511 TableLen - Acpi RSDP length
1512 Table - pointer to the table
1513
1514 Returns:
1515 EFI_SUCEESS - Convert Table successfully
1516 Other - Failed
1517
1518 --*/
1519 {
1520 VOID *AcpiTableOri;
1521 VOID *AcpiTableNew;
1522 EFI_STATUS Status;
1523 EFI_PHYSICAL_ADDRESS BufferPtr;
1524
1525
1526 AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table));
1527 if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {
1528 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1529 Status = gBS->AllocatePages (
1530 AllocateMaxAddress,
1531 EfiACPIMemoryNVS,
1532 EFI_SIZE_TO_PAGES(TableLen),
1533 &BufferPtr
1534 );
1535 ASSERT_EFI_ERROR (Status);
1536 AcpiTableNew = (VOID *)(UINTN)BufferPtr;
1537 CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
1538 } else {
1539 AcpiTableNew = AcpiTableOri;
1540 }
1541 //
1542 // Change configuration table Pointer
1543 //
1544 *Table = AcpiTableNew;
1545
1546 return EFI_SUCCESS;
1547 }
1548
1549 EFI_STATUS
1550 ConvertSmbiosTable (
1551 IN OUT VOID **Table
1552 )
1553 /*++
1554
1555 Routine Description:
1556
1557 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1558 Assumption here:
1559 As in legacy Bios, Smbios table is required to place in E/F Seg,
1560 So here we just check if the range is F seg,
1561 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1562 Arguments:
1563 Table - pointer to the table
1564
1565 Returns:
1566 EFI_SUCEESS - Convert Table successfully
1567 Other - Failed
1568
1569 --*/
1570 {
1571 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
1572 SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
1573 EFI_STATUS Status;
1574 UINT32 SmbiosEntryLen;
1575 UINT32 BufferLen;
1576 EFI_PHYSICAL_ADDRESS BufferPtr;
1577
1578 SmbiosTableNew = NULL;
1579 SmbiosTableOri = NULL;
1580
1581 //
1582 // Get Smibos configuration Table
1583 //
1584 SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));
1585
1586 if ((SmbiosTableOri == NULL) ||
1587 ((UINTN)SmbiosTableOri > 0x100000) ||
1588 ((UINTN)SmbiosTableOri < 0xF0000)){
1589 return EFI_SUCCESS;
1590 }
1591 //
1592 // Relocate the Smibos memory
1593 //
1594 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1595 if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
1596 SmbiosEntryLen = SmbiosTableOri->EntryPointLength;
1597 } else {
1598 //
1599 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1600 //
1601 SmbiosEntryLen = 0x1F;
1602 }
1603 BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
1604 Status = gBS->AllocatePages (
1605 AllocateMaxAddress,
1606 EfiACPIMemoryNVS,
1607 EFI_SIZE_TO_PAGES(BufferLen),
1608 &BufferPtr
1609 );
1610 ASSERT_EFI_ERROR (Status);
1611 SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
1612 CopyMem (
1613 SmbiosTableNew,
1614 SmbiosTableOri,
1615 SmbiosEntryLen
1616 );
1617 //
1618 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1619 //
1620 BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
1621 CopyMem (
1622 (VOID *)(UINTN)BufferPtr,
1623 (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
1624 SmbiosTableOri->TableLength
1625 );
1626 SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
1627 SmbiosTableNew->IntermediateChecksum = 0;
1628 SmbiosTableNew->IntermediateChecksum =
1629 GetBufferCheckSum ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
1630 //
1631 // Change the SMBIOS pointer
1632 //
1633 *Table = SmbiosTableNew;
1634
1635 return EFI_SUCCESS;
1636 }
1637
1638 EFI_STATUS
1639 ConvertMpsTable (
1640 IN OUT VOID **Table
1641 )
1642 /*++
1643
1644 Routine Description:
1645
1646 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1647 Assumption here:
1648 As in legacy Bios, MP table is required to place in E/F Seg,
1649 So here we just check if the range is E/F seg,
1650 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1651 Arguments:
1652 Table - pointer to the table
1653
1654 Returns:
1655 EFI_SUCEESS - Convert Table successfully
1656 Other - Failed
1657
1658 --*/
1659 {
1660 UINT32 Data32;
1661 UINT32 FPLength;
1662 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
1663 EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
1664 EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
1665 EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
1666 VOID *OemTableOri;
1667 VOID *OemTableNew;
1668 EFI_STATUS Status;
1669 EFI_PHYSICAL_ADDRESS BufferPtr;
1670
1671 //
1672 // Get MP configuration Table
1673 //
1674 MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));
1675 if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) &&
1676 ((UINTN)MpsFloatingPointerOri >= 0xF0000))){
1677 return EFI_SUCCESS;
1678 }
1679 //
1680 // Get Floating pointer structure length
1681 //
1682 FPLength = MpsFloatingPointerOri->Length * 16;
1683 Data32 = FPLength + SYS_TABLE_PAD (FPLength);
1684 MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
1685 if (MpsTableOri != NULL) {
1686 Data32 += MpsTableOri->BaseTableLength;
1687 Data32 += MpsTableOri->ExtendedTableLength;
1688 if (MpsTableOri->OemTablePointer != 0x00) {
1689 Data32 += SYS_TABLE_PAD (Data32);
1690 Data32 += MpsTableOri->OemTableSize;
1691 }
1692 } else {
1693 return EFI_SUCCESS;
1694 }
1695 //
1696 // Relocate memory
1697 //
1698 BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
1699 Status = gBS->AllocatePages (
1700 AllocateMaxAddress,
1701 EfiACPIMemoryNVS,
1702 EFI_SIZE_TO_PAGES(Data32),
1703 &BufferPtr
1704 );
1705 ASSERT_EFI_ERROR (Status);
1706 MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
1707 CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
1708 //
1709 // If Mp Table exists
1710 //
1711 if (MpsTableOri != NULL) {
1712 //
1713 // Get Mps table length, including Ext table
1714 //
1715 BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
1716 MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
1717 CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
1718
1719 if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
1720 BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
1721 BufferPtr += SYS_TABLE_PAD (BufferPtr);
1722 OemTableNew = (VOID *)(UINTN)BufferPtr;
1723 OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
1724 CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
1725 MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
1726 }
1727 MpsTableNew->Checksum = 0;
1728 MpsTableNew->Checksum = GetBufferCheckSum (MpsTableNew, MpsTableOri->BaseTableLength);
1729 MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
1730 MpsFloatingPointerNew->Checksum = 0;
1731 MpsFloatingPointerNew->Checksum = GetBufferCheckSum (MpsFloatingPointerNew, FPLength);
1732 }
1733 //
1734 // Change the pointer
1735 //
1736 *Table = MpsFloatingPointerNew;
1737
1738 return EFI_SUCCESS;
1739 }