]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
Per UEFI spec, FORM_OPEN/FORM_CLOSE Callback function should be called for each quest...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
1 /** @file
2 The platform boot manager reference implementation
3
4 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "BootManager.h"
16
17 UINT16 mKeyInput;
18 EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
19 LIST_ENTRY mBootOptionsList;
20 BDS_COMMON_OPTION *gOption;
21
22 HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {
23 {
24 {
25 HARDWARE_DEVICE_PATH,
26 HW_VENDOR_DP,
27 {
28 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
29 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
30 }
31 },
32 //
33 // {1DDDBE15-481D-4d2b-8277-B191EAF66525}
34 //
35 { 0x1dddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } }
36 },
37 {
38 END_DEVICE_PATH_TYPE,
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,
40 {
41 (UINT8) (END_DEVICE_PATH_LENGTH),
42 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
43 }
44 }
45 };
46
47 BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
48 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
49 NULL,
50 NULL,
51 {
52 FakeExtractConfig,
53 FakeRouteConfig,
54 BootManagerCallback
55 }
56 };
57
58 /**
59 This call back function is registered with Boot Manager formset.
60 When user selects a boot option, this call back function will
61 be triggered. The boot option is saved for later processing.
62
63
64 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
65 @param Action Specifies the type of action taken by the browser.
66 @param QuestionId A unique value which is sent to the original exporting driver
67 so that it can identify the type of data to expect.
68 @param Type The type of value for the question.
69 @param Value A pointer to the data being sent to the original exporting driver.
70 @param ActionRequest On return, points to the action requested by the callback function.
71
72 @retval EFI_SUCCESS The callback successfully handled the action.
73 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
74
75 **/
76 EFI_STATUS
77 EFIAPI
78 BootManagerCallback (
79 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
80 IN EFI_BROWSER_ACTION Action,
81 IN EFI_QUESTION_ID QuestionId,
82 IN UINT8 Type,
83 IN EFI_IFR_TYPE_VALUE *Value,
84 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
85 )
86 {
87 BDS_COMMON_OPTION *Option;
88 LIST_ENTRY *Link;
89 UINT16 KeyCount;
90
91 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
92 //
93 // Do nothing for UEFI OPEN/CLOSE Action
94 //
95 return EFI_SUCCESS;
96 }
97
98 if ((Value == NULL) || (ActionRequest == NULL)) {
99 return EFI_INVALID_PARAMETER;
100 }
101
102 //
103 // Initialize the key count
104 //
105 KeyCount = 0;
106
107 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
108 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
109
110 KeyCount++;
111
112 gOption = Option;
113
114 //
115 // Is this device the one chosen?
116 //
117 if (KeyCount == QuestionId) {
118 //
119 // Assigning the returned Key to a global allows the original routine to know what was chosen
120 //
121 mKeyInput = QuestionId;
122
123 //
124 // Request to exit SendForm(), so that we could boot the selected option
125 //
126 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
127 break;
128 }
129 }
130
131 return EFI_SUCCESS;
132 }
133
134 /**
135
136 Registers HII packages for the Boot Manger to HII Database.
137 It also registers the browser call back function.
138
139 @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.
140 @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.
141
142 **/
143 EFI_STATUS
144 InitializeBootManager (
145 VOID
146 )
147 {
148 EFI_STATUS Status;
149
150 //
151 // Install Device Path Protocol and Config Access protocol to driver handle
152 //
153 Status = gBS->InstallMultipleProtocolInterfaces (
154 &gBootManagerPrivate.DriverHandle,
155 &gEfiDevicePathProtocolGuid,
156 &mBootManagerHiiVendorDevicePath,
157 &gEfiHiiConfigAccessProtocolGuid,
158 &gBootManagerPrivate.ConfigAccess,
159 NULL
160 );
161 ASSERT_EFI_ERROR (Status);
162
163 //
164 // Publish our HII data
165 //
166 gBootManagerPrivate.HiiHandle = HiiAddPackages (
167 &mBootManagerGuid,
168 gBootManagerPrivate.DriverHandle,
169 BootManagerVfrBin,
170 BdsDxeStrings,
171 NULL
172 );
173 if (gBootManagerPrivate.HiiHandle == NULL) {
174 Status = EFI_OUT_OF_RESOURCES;
175 } else {
176 Status = EFI_SUCCESS;
177 }
178 return Status;
179 }
180
181 /**
182 This function invokes Boot Manager. If all devices have not a chance to be connected,
183 the connect all will be triggered. It then enumerate all boot options. If
184 a boot option from the Boot Manager page is selected, Boot Manager will boot
185 from this boot option.
186
187 **/
188 VOID
189 CallBootManager (
190 VOID
191 )
192 {
193 EFI_STATUS Status;
194 BDS_COMMON_OPTION *Option;
195 LIST_ENTRY *Link;
196 CHAR16 *ExitData;
197 UINTN ExitDataSize;
198 EFI_STRING_ID Token;
199 EFI_INPUT_KEY Key;
200 CHAR16 *HelpString;
201 EFI_STRING_ID HelpToken;
202 UINT16 *TempStr;
203 EFI_HII_HANDLE HiiHandle;
204 EFI_BROWSER_ACTION_REQUEST ActionRequest;
205 UINTN TempSize;
206 VOID *StartOpCodeHandle;
207 VOID *EndOpCodeHandle;
208 EFI_IFR_GUID_LABEL *StartLabel;
209 EFI_IFR_GUID_LABEL *EndLabel;
210
211 gOption = NULL;
212 InitializeListHead (&mBootOptionsList);
213
214 //
215 // Connect all prior to entering the platform setup menu.
216 //
217 if (!gConnectAllHappened) {
218 BdsLibConnectAllDriversToAllControllers ();
219 gConnectAllHappened = TRUE;
220 }
221
222 BdsLibEnumerateAllBootOption (&mBootOptionsList);
223
224 HiiHandle = gBootManagerPrivate.HiiHandle;
225
226 //
227 // Allocate space for creation of UpdateData Buffer
228 //
229 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
230 ASSERT (StartOpCodeHandle != NULL);
231
232 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
233 ASSERT (EndOpCodeHandle != NULL);
234
235 //
236 // Create Hii Extend Label OpCode as the start opcode
237 //
238 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
239 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
240 StartLabel->Number = LABEL_BOOT_OPTION;
241
242 //
243 // Create Hii Extend Label OpCode as the end opcode
244 //
245 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
246 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
247 EndLabel->Number = LABEL_BOOT_OPTION_END;
248
249 mKeyInput = 0;
250
251 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
252 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
253
254 //
255 // At this stage we are creating a menu entry, thus the Keys are reproduceable
256 //
257 mKeyInput++;
258
259 //
260 // Don't display the boot option marked as LOAD_OPTION_HIDDEN
261 //
262 if ((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) {
263 continue;
264 }
265
266 ASSERT (Option->Description != NULL);
267
268 Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);
269
270 TempStr = DevicePathToStr (Option->DevicePath);
271 TempSize = StrSize (TempStr);
272 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
273 ASSERT (HelpString != NULL);
274 StrCat (HelpString, L"Device Path : ");
275 StrCat (HelpString, TempStr);
276
277 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
278
279 HiiCreateActionOpCode (
280 StartOpCodeHandle,
281 mKeyInput,
282 Token,
283 HelpToken,
284 EFI_IFR_FLAG_CALLBACK,
285 0
286 );
287 }
288
289 HiiUpdateForm (
290 HiiHandle,
291 &mBootManagerGuid,
292 BOOT_MANAGER_FORM_ID,
293 StartOpCodeHandle,
294 EndOpCodeHandle
295 );
296
297 HiiFreeOpCodeHandle (StartOpCodeHandle);
298 HiiFreeOpCodeHandle (EndOpCodeHandle);
299
300 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
301 Status = gFormBrowser2->SendForm (
302 gFormBrowser2,
303 &HiiHandle,
304 1,
305 &mBootManagerGuid,
306 0,
307 NULL,
308 &ActionRequest
309 );
310 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
311 EnableResetRequired ();
312 }
313
314 if (gOption == NULL) {
315 return ;
316 }
317
318 //
319 // Will leave browser, check any reset required change is applied? if yes, reset system
320 //
321 SetupResetReminder ();
322
323 //
324 // parse the selected option
325 //
326 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
327
328 if (!EFI_ERROR (Status)) {
329 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
330 PlatformBdsBootSuccess (gOption);
331 } else {
332 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
333 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
334 gST->ConOut->OutputString (
335 gST->ConOut,
336 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
337 );
338 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
339 }
340 }