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