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