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