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