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