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