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