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