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