]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / FileExplorer.c
1 /** @file
2 File explorer related functions.
3
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "BootMaint.h"
10
11 /**
12 Update the File Explore page.
13
14 @param CallbackData The BMM context data.
15 @param MenuOption Pointer to menu options to display.
16
17 **/
18 VOID
19 UpdateFileExplorePage (
20 IN BMM_CALLBACK_DATA *CallbackData,
21 BM_MENU_OPTION *MenuOption
22 )
23 {
24 UINTN Index;
25 BM_MENU_ENTRY *NewMenuEntry;
26 BM_FILE_CONTEXT *NewFileContext;
27 EFI_FORM_ID FormId;
28
29 NewMenuEntry = NULL;
30 NewFileContext = NULL;
31 FormId = 0;
32
33 RefreshUpdateData ();
34 mStartLabel->Number = FORM_FILE_EXPLORER_ID;
35
36 for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
37 NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
38 NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
39
40 if (NewFileContext->IsBootLegacy) {
41 continue;
42 }
43
44 if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) {
45 //
46 // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile.
47 //
48 HiiCreateActionOpCode (
49 mStartOpCodeHandle,
50 (UINT16) (FILE_OPTION_OFFSET + Index),
51 NewMenuEntry->DisplayStringToken,
52 STRING_TOKEN (STR_NULL_STRING),
53 EFI_IFR_FLAG_CALLBACK,
54 0
55 );
56 } else {
57 //
58 // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState.
59 //
60 if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) {
61 FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
62 } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) {
63 FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
64 }
65
66 HiiCreateGotoOpCode (
67 mStartOpCodeHandle,
68 FormId,
69 NewMenuEntry->DisplayStringToken,
70 STRING_TOKEN (STR_NULL_STRING),
71 EFI_IFR_FLAG_CALLBACK,
72 (UINT16) (FILE_OPTION_GOTO_OFFSET + Index)
73 );
74 }
75 }
76
77 HiiUpdateForm (
78 CallbackData->FeHiiHandle,
79 &gFileExploreFormSetGuid,
80 FORM_FILE_EXPLORER_ID,
81 mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID
82 mEndOpCodeHandle // LABEL_END
83 );
84 }
85
86 /**
87 Update the file explower page with the refershed file system.
88
89
90 @param CallbackData BMM context data
91 @param KeyValue Key value to identify the type of data to expect.
92
93 @retval TRUE Inform the caller to create a callback packet to exit file explorer.
94 @retval FALSE Indicate that there is no need to exit file explorer.
95
96 **/
97 BOOLEAN
98 UpdateFileExplorer (
99 IN BMM_CALLBACK_DATA *CallbackData,
100 IN UINT16 KeyValue
101 )
102 {
103 UINT16 FileOptionMask;
104 BM_MENU_ENTRY *NewMenuEntry;
105 BM_FILE_CONTEXT *NewFileContext;
106 EFI_FORM_ID FormId;
107 BOOLEAN ExitFileExplorer;
108 EFI_STATUS Status;
109
110 NewMenuEntry = NULL;
111 NewFileContext = NULL;
112 ExitFileExplorer = FALSE;
113
114 FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
115
116 if (FileExplorerDisplayUnknown == CallbackData->FeDisplayContext) {
117 //
118 // First in, display file system.
119 //
120 BOpt_FreeMenu (&FsOptionMenu);
121 BOpt_FindFileSystem (CallbackData);
122 CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);
123
124 UpdateFileExplorePage (CallbackData, &FsOptionMenu);
125
126 CallbackData->FeDisplayContext = FileExplorerDisplayFileSystem;
127 } else {
128 if (FileExplorerDisplayFileSystem == CallbackData->FeDisplayContext) {
129 NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);
130 } else if (FileExplorerDisplayDirectory == CallbackData->FeDisplayContext) {
131 NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);
132 }
133
134 NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
135
136 if (NewFileContext->IsDir ) {
137 CallbackData->FeDisplayContext = FileExplorerDisplayDirectory;
138
139 RemoveEntryList (&NewMenuEntry->Link);
140 BOpt_FreeMenu (&DirectoryMenu);
141 Status = BOpt_FindFiles (CallbackData, NewMenuEntry);
142 if (EFI_ERROR (Status)) {
143 ExitFileExplorer = TRUE;
144 goto exit;
145 }
146 CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);
147 BOpt_DestroyMenuEntry (NewMenuEntry);
148
149 UpdateFileExplorePage (CallbackData, &DirectoryMenu);
150
151 } else {
152 switch (CallbackData->FeCurrentState) {
153 case FileExplorerStateBootFromFile:
154 //
155 // Restore to original mode before launching boot option.
156 //
157 BdsSetConsoleMode (FALSE);
158
159 //
160 // Here boot from file
161 //
162 BootThisFile (NewFileContext);
163 //
164 // Set proper video resolution and text mode for setup.
165 //
166 BdsSetConsoleMode (TRUE);
167 ExitFileExplorer = TRUE;
168 break;
169
170 case FileExplorerStateAddBootOption:
171 case FileExplorerStateAddDriverOptionState:
172 if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) {
173 FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
174 if (!CallbackData->FeFakeNvData.BootOptionChanged) {
175 ZeroMem (CallbackData->FeFakeNvData.BootOptionalData, sizeof (CallbackData->FeFakeNvData.BootOptionalData));
176 ZeroMem (CallbackData->FeFakeNvData.BootDescriptionData, sizeof (CallbackData->FeFakeNvData.BootDescriptionData));
177 }
178 } else {
179 FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
180 if (!CallbackData->FeFakeNvData.DriverOptionChanged) {
181 ZeroMem (CallbackData->FeFakeNvData.DriverOptionalData, sizeof (CallbackData->FeFakeNvData.DriverOptionalData));
182 ZeroMem (CallbackData->FeFakeNvData.DriverDescriptionData, sizeof (CallbackData->FeFakeNvData.DriverDescriptionData));
183 }
184 }
185
186 CallbackData->MenuEntry = NewMenuEntry;
187 CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;
188
189 //
190 // Create Subtitle op-code for the display string of the option.
191 //
192 RefreshUpdateData ();
193 mStartLabel->Number = FormId;
194
195 HiiCreateSubTitleOpCode (
196 mStartOpCodeHandle,
197 NewMenuEntry->DisplayStringToken,
198 0,
199 0,
200 0
201 );
202
203 HiiUpdateForm (
204 CallbackData->FeHiiHandle,
205 &gFileExploreFormSetGuid,
206 FormId,
207 mStartOpCodeHandle, // Label FormId
208 mEndOpCodeHandle // LABEL_END
209 );
210 break;
211
212 default:
213 break;
214 }
215 }
216 }
217 exit:
218 return ExitFileExplorer;
219 }
220
221 /**
222 This function applies changes in a driver's configuration.
223 Input is a Configuration, which has the routing data for this
224 driver followed by name / value configuration pairs. The driver
225 must apply those pairs to its configurable storage. If the
226 driver's configuration is stored in a linear block of data
227 and the driver's name / value pairs are in <BlockConfig>
228 format, it may use the ConfigToBlock helper function (above) to
229 simplify the job. Currently not implemented.
230
231 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
232 @param[in] Configuration A null-terminated Unicode string in
233 <ConfigString> format.
234 @param[out] Progress A pointer to a string filled in with the
235 offset of the most recent '&' before the
236 first failing name / value pair (or the
237 beginn ing of the string if the failure
238 is in the first name / value pair) or
239 the terminating NULL if all was
240 successful.
241
242 @retval EFI_SUCCESS The results have been distributed or are
243 awaiting distribution.
244 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
245 parts of the results that must be
246 stored awaiting possible future
247 protocols.
248 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
249 Results parameter would result
250 in this type of error.
251 @retval EFI_NOT_FOUND Target for the specified routing data
252 was not found.
253 **/
254 EFI_STATUS
255 EFIAPI
256 FileExplorerRouteConfig (
257 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
258 IN CONST EFI_STRING Configuration,
259 OUT EFI_STRING *Progress
260 )
261 {
262 EFI_STATUS Status;
263 UINTN BufferSize;
264 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
265 FILE_EXPLORER_NV_DATA *FeData;
266 BMM_CALLBACK_DATA *Private;
267
268 if (Progress == NULL) {
269 return EFI_INVALID_PARAMETER;
270 }
271 *Progress = Configuration;
272
273 if (Configuration == NULL) {
274 return EFI_INVALID_PARAMETER;
275 }
276
277 //
278 // Check routing data in <ConfigHdr>.
279 // Note: there is no name for Name/Value storage, only GUID will be checked
280 //
281 if (!HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) {
282 return EFI_NOT_FOUND;
283 }
284
285 Status = gBS->LocateProtocol (
286 &gEfiHiiConfigRoutingProtocolGuid,
287 NULL,
288 (VOID**) &ConfigRouting
289 );
290 if (EFI_ERROR (Status)) {
291 return Status;
292 }
293
294 Private = FE_CALLBACK_DATA_FROM_THIS (This);
295 //
296 // Get Buffer Storage data from EFI variable
297 //
298 BufferSize = sizeof (FILE_EXPLORER_NV_DATA );
299 FeData = &Private->FeFakeNvData;
300
301 //
302 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
303 //
304 Status = ConfigRouting->ConfigToBlock (
305 ConfigRouting,
306 Configuration,
307 (UINT8 *) FeData,
308 &BufferSize,
309 Progress
310 );
311 ASSERT_EFI_ERROR (Status);
312
313 if (FeData->BootDescriptionData[0] != 0x00 || FeData->BootOptionalData[0] != 0x00) {
314 Status = Var_UpdateBootOption (Private, FeData);
315 if (EFI_ERROR (Status)) {
316 return Status;
317 }
318
319 BOpt_GetBootOptions (Private);
320 CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);
321 }
322
323 if (FeData->DriverDescriptionData[0] != 0x00 || FeData->DriverOptionalData[0] != 0x00) {
324 Status = Var_UpdateDriverOption (
325 Private,
326 Private->FeHiiHandle,
327 FeData->DriverDescriptionData,
328 FeData->DriverOptionalData,
329 FeData->ForceReconnect
330 );
331 if (EFI_ERROR (Status)) {
332 return Status;
333 }
334
335 BOpt_GetDriverOptions (Private);
336 CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);
337 }
338
339 return EFI_SUCCESS;
340 }
341
342 /**
343 This function processes the results of changes in configuration.
344 When user select a interactive opcode, this callback will be triggered.
345 Based on the Question(QuestionId) that triggers the callback, the corresponding
346 actions is performed. It handles:
347
348 1) the addition of boot option.
349 2) the addition of driver option.
350 3) exit from file browser
351 4) update of file content if a dir is selected.
352 5) boot the file if a file is selected in "boot from file"
353
354
355 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
356 @param Action Specifies the type of action taken by the browser.
357 @param QuestionId A unique value which is sent to the original exporting driver
358 so that it can identify the type of data to expect.
359 @param Type The type of value for the question.
360 @param Value A pointer to the data being sent to the original exporting driver.
361 @param ActionRequest On return, points to the action requested by the callback function.
362
363 @retval EFI_SUCCESS The callback successfully handled the action.
364 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
365 @retval EFI_DEVICE_ERROR The variable could not be saved.
366 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
367 @retval EFI_INVALID_PARAMETER If parameter Value or ActionRequest is NULL.
368 **/
369 EFI_STATUS
370 EFIAPI
371 FileExplorerCallback (
372 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
373 IN EFI_BROWSER_ACTION Action,
374 IN EFI_QUESTION_ID QuestionId,
375 IN UINT8 Type,
376 IN EFI_IFR_TYPE_VALUE *Value,
377 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
378 )
379 {
380 BMM_CALLBACK_DATA *Private;
381 FILE_EXPLORER_NV_DATA *NvRamMap;
382 EFI_STATUS Status;
383
384 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
385 //
386 // All other action return unsupported.
387 //
388 return EFI_UNSUPPORTED;
389 }
390
391 Status = EFI_SUCCESS;
392 Private = FE_CALLBACK_DATA_FROM_THIS (This);
393
394 //
395 // Retrieve uncommitted data from Form Browser
396 //
397 NvRamMap = &Private->FeFakeNvData;
398 HiiGetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap);
399
400 if (Action == EFI_BROWSER_ACTION_CHANGED) {
401 if ((Value == NULL) || (ActionRequest == NULL)) {
402 return EFI_INVALID_PARAMETER;
403 }
404
405 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) {
406 NvRamMap->BootOptionChanged = FALSE;
407 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
408 } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
409 NvRamMap->DriverOptionChanged = FALSE;
410 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
411 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {
412 //
413 // Discard changes and exit formset
414 //
415 NvRamMap->DriverOptionalData[0] = 0x0000;
416 NvRamMap->DriverDescriptionData[0] = 0x0000;
417 NvRamMap->DriverOptionChanged = FALSE;
418 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
419 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) {
420 //
421 // Discard changes and exit formset
422 //
423 NvRamMap->BootOptionalData[0] = 0x0000;
424 NvRamMap->BootDescriptionData[0] = 0x0000;
425 NvRamMap->BootOptionChanged = FALSE;
426 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
427 } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) {
428 NvRamMap->BootOptionChanged = TRUE;
429 } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) {
430 NvRamMap->DriverOptionChanged = TRUE;
431 } else if (QuestionId < FILE_OPTION_OFFSET) {
432 //
433 // Exit File Explorer formset
434 //
435 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
436 } else if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) {
437 //
438 // Update forms may return TRUE or FALSE, need to check here.
439 //
440 if (UpdateFileExplorer (Private, QuestionId)) {
441 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
442 }
443 }
444 } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
445 if (Value == NULL) {
446 return EFI_INVALID_PARAMETER;
447 }
448
449 if (QuestionId >= FILE_OPTION_GOTO_OFFSET) {
450 //
451 // function will always return FALSE, no need to check here.
452 //
453 UpdateFileExplorer (Private, QuestionId);
454 }
455 }
456
457 //
458 // Pass changed uncommitted data back to Form Browser
459 //
460 HiiSetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap, NULL);
461
462 return Status;
463 }