Update for IntelFrameworkModulePkg.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / FileExplorer.c
1 /** @file
2 File explorer related functions.
3
4 Copyright (c) 2004 - 2011, 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 &gFileExploreFormSetGuid,
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 //
165 // Set proper video resolution and text mode for setup.
166 //
167 ChangeModeForSetup ();
168 ExitFileExplorer = TRUE;
169 break;
170
171 case FileExplorerStateAddBootOption:
172 case FileExplorerStateAddDriverOptionState:
173 if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) {
174 FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
175 } else {
176 FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
177 }
178
179 CallbackData->MenuEntry = NewMenuEntry;
180 CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;
181
182 //
183 // Create Subtitle op-code for the display string of the option.
184 //
185 RefreshUpdateData ();
186 mStartLabel->Number = FormId;
187
188 HiiCreateSubTitleOpCode (
189 mStartOpCodeHandle,
190 NewMenuEntry->DisplayStringToken,
191 0,
192 0,
193 0
194 );
195
196 HiiUpdateForm (
197 CallbackData->FeHiiHandle,
198 &gFileExploreFormSetGuid,
199 FormId,
200 mStartOpCodeHandle, // Label FormId
201 mEndOpCodeHandle // LABEL_END
202 );
203 break;
204
205 default:
206 break;
207 }
208 }
209 }
210 exit:
211 return ExitFileExplorer;
212 }
213
214 /**
215 This function processes the results of changes in configuration.
216 When user select a interactive opcode, this callback will be triggered.
217 Based on the Question(QuestionId) that triggers the callback, the corresponding
218 actions is performed. It handles:
219
220 1) the addition of boot option.
221 2) the addition of driver option.
222 3) exit from file browser
223 4) update of file content if a dir is selected.
224 5) boot the file if a file is selected in "boot from file"
225
226
227 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
228 @param Action Specifies the type of action taken by the browser.
229 @param QuestionId A unique value which is sent to the original exporting driver
230 so that it can identify the type of data to expect.
231 @param Type The type of value for the question.
232 @param Value A pointer to the data being sent to the original exporting driver.
233 @param ActionRequest On return, points to the action requested by the callback function.
234
235 @retval EFI_SUCCESS The callback successfully handled the action.
236 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
237 @retval EFI_DEVICE_ERROR The variable could not be saved.
238 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
239 @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL.
240 **/
241 EFI_STATUS
242 EFIAPI
243 FileExplorerCallback (
244 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
245 IN EFI_BROWSER_ACTION Action,
246 IN EFI_QUESTION_ID QuestionId,
247 IN UINT8 Type,
248 IN EFI_IFR_TYPE_VALUE *Value,
249 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
250 )
251 {
252 BMM_CALLBACK_DATA *Private;
253 FILE_EXPLORER_NV_DATA *NvRamMap;
254 EFI_STATUS Status;
255
256 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
257 //
258 // All other action return unsupported.
259 //
260 return EFI_UNSUPPORTED;
261 }
262
263 Status = EFI_SUCCESS;
264 Private = FE_CALLBACK_DATA_FROM_THIS (This);
265
266 //
267 // Retrieve uncommitted data from Form Browser
268 //
269 NvRamMap = &Private->FeFakeNvData;
270 HiiGetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap);
271
272 if (Action == EFI_BROWSER_ACTION_CHANGED) {
273 if ((Value == NULL) || (ActionRequest == NULL)) {
274 return EFI_INVALID_PARAMETER;
275 }
276
277 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
278 //
279 // Apply changes and exit formset
280 //
281 if (FileExplorerStateAddBootOption == Private->FeCurrentState) {
282 Status = Var_UpdateBootOption (Private, NvRamMap);
283 if (EFI_ERROR (Status)) {
284 return Status;
285 }
286
287 BOpt_GetBootOptions (Private);
288 CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);
289 } else if (FileExplorerStateAddDriverOptionState == Private->FeCurrentState) {
290 Status = Var_UpdateDriverOption (
291 Private,
292 Private->FeHiiHandle,
293 NvRamMap->DescriptionData,
294 NvRamMap->OptionalData,
295 NvRamMap->ForceReconnect
296 );
297 if (EFI_ERROR (Status)) {
298 return Status;
299 }
300
301 BOpt_GetDriverOptions (Private);
302 CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);
303 }
304
305 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
306 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {
307 //
308 // Discard changes and exit formset
309 //
310 NvRamMap->OptionalData[0] = 0x0000;
311 NvRamMap->DescriptionData[0] = 0x0000;
312 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
313 } else if (QuestionId < FILE_OPTION_OFFSET) {
314 //
315 // Exit File Explorer formset
316 //
317 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
318 }
319 } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
320 if (Value == NULL) {
321 return EFI_INVALID_PARAMETER;
322 }
323
324 if (QuestionId >= FILE_OPTION_OFFSET) {
325 UpdateFileExplorer (Private, QuestionId);
326 }
327 }
328
329 return Status;
330 }