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