1 /** @file
2   This file include all platform action which can be customized
3   by IBV/OEM.
4 
5 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "PlatformBootManager.h"
11 #include "PlatformConsole.h"
12 
13 VOID
InstallReadyToLock(VOID)14 InstallReadyToLock (
15   VOID
16   )
17 {
18   EFI_STATUS                            Status;
19   EFI_HANDLE                            Handle;
20   EFI_SMM_ACCESS2_PROTOCOL              *SmmAccess;
21 
22   DEBUG((DEBUG_INFO,"InstallReadyToLock  entering......\n"));
23   //
24   // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
25   // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
26   //
27   EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
28   DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n"));
29 
30   //
31   // Install DxeSmmReadyToLock protocol in order to lock SMM
32   //
33   Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **) &SmmAccess);
34   if (!EFI_ERROR (Status)) {
35     Handle = NULL;
36     Status = gBS->InstallProtocolInterface (
37                     &Handle,
38                     &gEfiDxeSmmReadyToLockProtocolGuid,
39                     EFI_NATIVE_INTERFACE,
40                     NULL
41                     );
42     ASSERT_EFI_ERROR (Status);
43   }
44 
45   DEBUG((DEBUG_INFO,"InstallReadyToLock  end\n"));
46   return;
47 }
48 
49 /**
50   Return the index of the load option in the load option array.
51 
52   The function consider two load options are equal when the
53   OptionType, Attributes, Description, FilePath and OptionalData are equal.
54 
55   @param Key    Pointer to the load option to be found.
56   @param Array  Pointer to the array of load options to be found.
57   @param Count  Number of entries in the Array.
58 
59   @retval -1          Key wasn't found in the Array.
60   @retval 0 ~ Count-1 The index of the Key in the Array.
61 **/
62 INTN
PlatformFindLoadOption(IN CONST EFI_BOOT_MANAGER_LOAD_OPTION * Key,IN CONST EFI_BOOT_MANAGER_LOAD_OPTION * Array,IN UINTN Count)63 PlatformFindLoadOption (
64   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
65   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
66   IN UINTN                              Count
67 )
68 {
69   UINTN                             Index;
70 
71   for (Index = 0; Index < Count; Index++) {
72     if ((Key->OptionType == Array[Index].OptionType) &&
73         (Key->Attributes == Array[Index].Attributes) &&
74         (StrCmp (Key->Description, Array[Index].Description) == 0) &&
75         (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
76         (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
77         (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
78       return (INTN) Index;
79     }
80   }
81 
82   return -1;
83 }
84 
85 /**
86   Register a boot option using a file GUID in the FV.
87 
88   @param FileGuid     The file GUID name in FV.
89   @param Description  The boot option description.
90   @param Attributes   The attributes used for the boot option loading.
91 **/
92 VOID
PlatformRegisterFvBootOption(EFI_GUID * FileGuid,CHAR16 * Description,UINT32 Attributes)93 PlatformRegisterFvBootOption (
94   EFI_GUID                         *FileGuid,
95   CHAR16                           *Description,
96   UINT32                           Attributes
97 )
98 {
99   EFI_STATUS                        Status;
100   UINTN                             OptionIndex;
101   EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
102   EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
103   UINTN                             BootOptionCount;
104   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
105   EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
106   EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
107 
108   Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
109   ASSERT_EFI_ERROR (Status);
110 
111   EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
112   DevicePath = AppendDevicePathNode (
113                  DevicePathFromHandle (LoadedImage->DeviceHandle),
114                  (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
115                );
116 
117   Status = EfiBootManagerInitializeLoadOption (
118              &NewOption,
119              LoadOptionNumberUnassigned,
120              LoadOptionTypeBoot,
121              Attributes,
122              Description,
123              DevicePath,
124              NULL,
125              0
126            );
127   if (!EFI_ERROR (Status)) {
128     BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
129 
130     OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
131 
132     if (OptionIndex == -1) {
133       Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);
134       ASSERT_EFI_ERROR (Status);
135     }
136     EfiBootManagerFreeLoadOption (&NewOption);
137     EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
138   }
139 }
140 
141 /**
142   Do the platform specific action before the console is connected.
143 
144   Such as:
145     Update console variable;
146     Register new Driver#### or Boot####;
147     Signal ReadyToLock event.
148 **/
149 VOID
150 EFIAPI
PlatformBootManagerBeforeConsole(VOID)151 PlatformBootManagerBeforeConsole (
152   VOID
153 )
154 {
155   EFI_INPUT_KEY                Enter;
156   EFI_INPUT_KEY                F2;
157   EFI_INPUT_KEY                Down;
158   EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
159 
160   PlatformConsoleInit ();
161 
162   //
163   // Register ENTER as CONTINUE key
164   //
165   Enter.ScanCode    = SCAN_NULL;
166   Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
167   EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
168 
169   //
170   // Map F2 to Boot Manager Menu
171   //
172   F2.ScanCode    = SCAN_F2;
173   F2.UnicodeChar = CHAR_NULL;
174   EfiBootManagerGetBootManagerMenu (&BootOption);
175   EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);
176 
177   //
178   // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.
179   //
180   Down.ScanCode    = SCAN_DOWN;
181   Down.UnicodeChar = CHAR_NULL;
182   EfiBootManagerGetBootManagerMenu (&BootOption);
183   EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &Down, NULL);
184 
185   //
186   // Install ready to lock.
187   // This needs to be done before option rom dispatched.
188   //
189   InstallReadyToLock ();
190 
191   //
192   // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
193   //
194   EfiBootManagerDispatchDeferredImages ();
195 }
196 
197 /**
198   Do the platform specific action after the console is connected.
199 
200   Such as:
201     Dynamically switch output mode;
202     Signal console ready platform customized event;
203     Run diagnostics like memory testing;
204     Connect certain devices;
205     Dispatch additional option roms.
206 **/
207 VOID
208 EFIAPI
PlatformBootManagerAfterConsole(VOID)209 PlatformBootManagerAfterConsole (
210   VOID
211 )
212 {
213   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
214   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
215 
216   Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
217   White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
218 
219   EfiBootManagerConnectAll ();
220   EfiBootManagerRefreshAllBootOption ();
221 
222   //
223   // Register UEFI Shell
224   //
225   PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);
226 
227   Print (
228     L"\n"
229     L"F2 or Down      to enter Boot Manager Menu.\n"
230     L"ENTER           to boot directly.\n"
231     L"\n"
232   );
233 
234 }
235 
236 /**
237   This function is called each second during the boot manager waits the timeout.
238 
239   @param TimeoutRemain  The remaining timeout.
240 **/
241 VOID
242 EFIAPI
PlatformBootManagerWaitCallback(UINT16 TimeoutRemain)243 PlatformBootManagerWaitCallback (
244   UINT16          TimeoutRemain
245 )
246 {
247   return;
248 }
249 
250 /**
251   The function is called when no boot option could be launched,
252   including platform recovery options and options pointing to applications
253   built into firmware volumes.
254 
255   If this function returns, BDS attempts to enter an infinite loop.
256 **/
257 VOID
258 EFIAPI
PlatformBootManagerUnableToBoot(VOID)259 PlatformBootManagerUnableToBoot (
260   VOID
261   )
262 {
263   return;
264 }
265 
266