]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
MdeModulePkg/BootMaintManagerUiLib: Declare EFIAPI for ChooseFile handler
[mirror_edk2.git] / MdeModulePkg / Library / BootMaintenanceManagerUiLib / BootMaintenance.c
CommitLineData
4af04335
DB
1/** @file\r
2The functions for Boot Maintainence Main menu.\r
3\r
c7d310dd 4Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
4af04335
DB
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 "BootMaintenanceManager.h"\r
16\r
17#define FRONT_PAGE_KEY_OFFSET 0x4000\r
18//\r
19// Boot video resolution and text mode.\r
20//\r
21UINT32 mBmmBootHorizontalResolution = 0;\r
22UINT32 mBmmBootVerticalResolution = 0;\r
23UINT32 mBmmBootTextModeColumn = 0;\r
24UINT32 mBmmBootTextModeRow = 0;\r
25//\r
26// BIOS setup video resolution and text mode.\r
27//\r
28UINT32 mBmmSetupTextModeColumn = 0;\r
29UINT32 mBmmSetupTextModeRow = 0;\r
30UINT32 mBmmSetupHorizontalResolution = 0;\r
31UINT32 mBmmSetupVerticalResolution = 0;\r
32\r
33EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {\r
34 {\r
35 END_DEVICE_PATH_TYPE,\r
36 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
37 {\r
38 END_DEVICE_PATH_LENGTH,\r
39 0\r
40 }\r
41 }\r
42};\r
43\r
44HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = {\r
45 {\r
46 {\r
47 HARDWARE_DEVICE_PATH,\r
48 HW_VENDOR_DP,\r
49 {\r
50 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
51 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
52 }\r
53 },\r
54 //\r
55 // {165A028F-0BB2-4b5f-8747-77592E3F6499}\r
56 //\r
57 { 0x165a028f, 0xbb2, 0x4b5f, { 0x87, 0x47, 0x77, 0x59, 0x2e, 0x3f, 0x64, 0x99 } }\r
58 },\r
59 {\r
60 END_DEVICE_PATH_TYPE,\r
61 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
62 { \r
63 (UINT8) (END_DEVICE_PATH_LENGTH),\r
64 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
65 }\r
66 }\r
67};\r
68\r
69EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;\r
70\r
71CHAR16 mBootMaintStorageName[] = L"BmmData";\r
72BMM_CALLBACK_DATA gBootMaintenancePrivate = {\r
73 BMM_CALLBACK_DATA_SIGNATURE,\r
74 NULL,\r
75 NULL,\r
76 {\r
77 BootMaintExtractConfig,\r
78 BootMaintRouteConfig,\r
79 BootMaintCallback\r
80 }\r
81};\r
82\r
83BMM_CALLBACK_DATA *mBmmCallbackInfo = &gBootMaintenancePrivate;\r
84BOOLEAN mAllMenuInit = FALSE;\r
85\r
86/**\r
87 Init all memu.\r
88\r
89 @param CallbackData The BMM context data.\r
90\r
91**/\r
92VOID\r
93InitAllMenu (\r
94 IN BMM_CALLBACK_DATA *CallbackData\r
95 );\r
96\r
97/**\r
98 Free up all Menu Option list.\r
99\r
100**/\r
101VOID\r
102FreeAllMenu (\r
103 VOID\r
104 );\r
105\r
106/**\r
107 This function will change video resolution and text mode\r
108 according to defined setup mode or defined boot mode \r
109\r
110 @param IsSetupMode Indicate mode is changed to setup mode or boot mode. \r
111\r
112 @retval EFI_SUCCESS Mode is changed successfully.\r
113 @retval Others Mode failed to be changed.\r
114\r
115**/\r
116EFI_STATUS\r
117EFIAPI\r
118BmmBdsSetConsoleMode (\r
119 BOOLEAN IsSetupMode\r
120 )\r
121{\r
122 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
123 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
124 UINTN SizeOfInfo;\r
125 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
126 UINT32 MaxGopMode;\r
127 UINT32 MaxTextMode;\r
128 UINT32 ModeNumber;\r
129 UINT32 NewHorizontalResolution;\r
130 UINT32 NewVerticalResolution;\r
131 UINT32 NewColumns;\r
132 UINT32 NewRows;\r
133 UINTN HandleCount;\r
134 EFI_HANDLE *HandleBuffer;\r
135 EFI_STATUS Status;\r
136 UINTN Index;\r
137 UINTN CurrentColumn;\r
138 UINTN CurrentRow; \r
139\r
140 MaxGopMode = 0;\r
141 MaxTextMode = 0;\r
142\r
143 //\r
144 // Get current video resolution and text mode \r
145 //\r
146 Status = gBS->HandleProtocol (\r
147 gST->ConsoleOutHandle,\r
148 &gEfiGraphicsOutputProtocolGuid,\r
149 (VOID**)&GraphicsOutput\r
150 );\r
151 if (EFI_ERROR (Status)) {\r
152 GraphicsOutput = NULL;\r
153 }\r
154\r
155 Status = gBS->HandleProtocol (\r
156 gST->ConsoleOutHandle,\r
157 &gEfiSimpleTextOutProtocolGuid,\r
158 (VOID**)&SimpleTextOut\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 SimpleTextOut = NULL;\r
162 } \r
163\r
164 if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r
165 return EFI_UNSUPPORTED;\r
166 }\r
167\r
168 if (IsSetupMode) {\r
169 //\r
170 // The requried resolution and text mode is setup mode.\r
171 //\r
172 NewHorizontalResolution = mBmmSetupHorizontalResolution;\r
173 NewVerticalResolution = mBmmSetupVerticalResolution;\r
174 NewColumns = mBmmSetupTextModeColumn;\r
175 NewRows = mBmmSetupTextModeRow;\r
176 } else {\r
177 //\r
178 // The required resolution and text mode is boot mode.\r
179 //\r
180 NewHorizontalResolution = mBmmBootHorizontalResolution;\r
181 NewVerticalResolution = mBmmBootVerticalResolution;\r
182 NewColumns = mBmmBootTextModeColumn;\r
183 NewRows = mBmmBootTextModeRow; \r
184 }\r
185\r
186 if (GraphicsOutput != NULL) {\r
187 MaxGopMode = GraphicsOutput->Mode->MaxMode;\r
188 } \r
189\r
190 if (SimpleTextOut != NULL) {\r
191 MaxTextMode = SimpleTextOut->Mode->MaxMode;\r
192 }\r
193\r
194 //\r
195 // 1. If current video resolution is same with required video resolution,\r
196 // video resolution need not be changed.\r
197 // 1.1. If current text mode is same with required text mode, text mode need not be changed.\r
198 // 1.2. If current text mode is different from required text mode, text mode need be changed.\r
199 // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.\r
200 //\r
201 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {\r
202 Status = GraphicsOutput->QueryMode (\r
203 GraphicsOutput,\r
204 ModeNumber,\r
205 &SizeOfInfo,\r
206 &Info\r
207 );\r
208 if (!EFI_ERROR (Status)) {\r
209 if ((Info->HorizontalResolution == NewHorizontalResolution) &&\r
210 (Info->VerticalResolution == NewVerticalResolution)) {\r
211 if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&\r
212 (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {\r
213 //\r
214 // Current resolution is same with required resolution, check if text mode need be set\r
215 //\r
216 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);\r
217 ASSERT_EFI_ERROR (Status);\r
218 if (CurrentColumn == NewColumns && CurrentRow == NewRows) {\r
219 //\r
220 // If current text mode is same with required text mode. Do nothing\r
221 //\r
222 FreePool (Info);\r
223 return EFI_SUCCESS;\r
224 } else {\r
225 //\r
226 // If current text mode is different from requried text mode. Set new video mode\r
227 //\r
228 for (Index = 0; Index < MaxTextMode; Index++) {\r
229 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r
230 if (!EFI_ERROR(Status)) {\r
231 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {\r
232 //\r
233 // Required text mode is supported, set it.\r
234 //\r
235 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);\r
236 ASSERT_EFI_ERROR (Status);\r
237 //\r
238 // Update text mode PCD.\r
239 //\r
e750958b
DB
240 Status = PcdSet32S (PcdConOutColumn, mBmmSetupTextModeColumn);\r
241 ASSERT_EFI_ERROR (Status);\r
242 Status = PcdSet32S (PcdConOutRow, mBmmSetupTextModeRow);\r
243 ASSERT_EFI_ERROR (Status);\r
4af04335
DB
244 FreePool (Info);\r
245 return EFI_SUCCESS;\r
246 }\r
247 }\r
248 }\r
249 if (Index == MaxTextMode) {\r
250 //\r
251 // If requried text mode is not supported, return error.\r
252 //\r
253 FreePool (Info);\r
254 return EFI_UNSUPPORTED;\r
255 }\r
256 }\r
257 } else {\r
258 //\r
259 // If current video resolution is not same with the new one, set new video resolution.\r
260 // In this case, the driver which produces simple text out need be restarted.\r
261 //\r
262 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);\r
263 if (!EFI_ERROR (Status)) {\r
264 FreePool (Info);\r
265 break;\r
266 }\r
267 }\r
268 }\r
269 FreePool (Info);\r
270 }\r
271 }\r
272\r
273 if (ModeNumber == MaxGopMode) {\r
274 //\r
275 // If the resolution is not supported, return error.\r
276 //\r
277 return EFI_UNSUPPORTED;\r
278 }\r
279\r
280 //\r
281 // Set PCD to Inform GraphicsConsole to change video resolution.\r
282 // Set PCD to Inform Consplitter to change text mode.\r
283 //\r
e750958b
DB
284 Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);\r
285 ASSERT_EFI_ERROR (Status);\r
286 Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);\r
287 ASSERT_EFI_ERROR (Status);\r
288 Status = PcdSet32S (PcdConOutColumn, NewColumns);\r
289 ASSERT_EFI_ERROR (Status);\r
290 Status = PcdSet32S (PcdConOutRow, NewRows);\r
291 ASSERT_EFI_ERROR (Status);\r
4af04335
DB
292\r
293 //\r
294 // Video mode is changed, so restart graphics console driver and higher level driver.\r
295 // Reconnect graphics console driver and higher level driver.\r
296 // Locate all the handles with GOP protocol and reconnect it.\r
297 //\r
298 Status = gBS->LocateHandleBuffer (\r
299 ByProtocol,\r
300 &gEfiSimpleTextOutProtocolGuid,\r
301 NULL,\r
302 &HandleCount,\r
303 &HandleBuffer\r
304 );\r
305 if (!EFI_ERROR (Status)) {\r
306 for (Index = 0; Index < HandleCount; Index++) {\r
307 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
308 }\r
309 for (Index = 0; Index < HandleCount; Index++) {\r
310 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
311 }\r
312 if (HandleBuffer != NULL) {\r
313 FreePool (HandleBuffer);\r
314 }\r
315 }\r
316\r
317 return EFI_SUCCESS;\r
318}\r
319\r
320/**\r
321 This function converts an input device structure to a Unicode string.\r
322\r
323 @param DevPath A pointer to the device path structure.\r
324\r
325 @return A new allocated Unicode string that represents the device path.\r
326\r
327**/\r
328CHAR16 *\r
329UiDevicePathToStr (\r
330 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
331 )\r
332{\r
333 EFI_STATUS Status;\r
334 CHAR16 *ToText;\r
335 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
336\r
337 if (DevPath == NULL) {\r
338 return NULL;\r
339 }\r
340\r
341 Status = gBS->LocateProtocol (\r
342 &gEfiDevicePathToTextProtocolGuid,\r
343 NULL,\r
344 (VOID **) &DevPathToText\r
345 );\r
346 ASSERT_EFI_ERROR (Status);\r
347 ToText = DevPathToText->ConvertDevicePathToText (\r
348 DevPath,\r
349 FALSE,\r
350 TRUE\r
351 );\r
352 ASSERT (ToText != NULL);\r
353 return ToText;\r
354}\r
355\r
356/**\r
357 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.\r
358 The caller is responsible for freeing the allocated buffer using FreePool().\r
359\r
360 @param DevicePath Device path.\r
361\r
362 @return A new allocated string that represents the file name.\r
363\r
364**/\r
365CHAR16 *\r
366ExtractFileNameFromDevicePath (\r
367 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
368 )\r
369{\r
370 CHAR16 *String;\r
371 CHAR16 *MatchString;\r
372 CHAR16 *LastMatch;\r
373 CHAR16 *FileName;\r
374 UINTN Length;\r
375\r
376 ASSERT(DevicePath != NULL);\r
377\r
378 String = UiDevicePathToStr(DevicePath);\r
379 MatchString = String;\r
380 LastMatch = String;\r
381\r
382 while(MatchString != NULL){\r
383 LastMatch = MatchString + 1;\r
384 MatchString = StrStr(LastMatch,L"\\");\r
385 }\r
386\r
387 Length = StrLen(LastMatch);\r
388 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
389 *(FileName + Length) = 0;\r
390\r
391 FreePool(String);\r
392\r
393 return FileName;\r
394}\r
395\r
396/**\r
397 Extract device path for given HII handle and class guid.\r
398\r
399 @param Handle The HII handle.\r
400\r
401 @retval NULL Fail to get the device path string.\r
402 @return PathString Get the device path string.\r
403\r
404**/\r
405CHAR16 *\r
406BmmExtractDevicePathFromHiiHandle (\r
407 IN EFI_HII_HANDLE Handle\r
408 )\r
409{\r
410 EFI_STATUS Status;\r
411 EFI_HANDLE DriverHandle;\r
412\r
413 ASSERT (Handle != NULL);\r
414\r
415 if (Handle == NULL) {\r
416 return NULL;\r
417 }\r
418\r
419 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);\r
420 if (EFI_ERROR (Status)) {\r
421 return NULL;\r
422 }\r
423\r
424 //\r
425 // Get device path string.\r
426 //\r
427 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE);\r
428\r
429}\r
430\r
431/**\r
432 This function allows a caller to extract the current configuration for one\r
433 or more named elements from the target driver.\r
434\r
435 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
436 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
437 @param Progress On return, points to a character in the Request string.\r
438 Points to the string's null terminator if request was successful.\r
439 Points to the most recent '&' before the first failing name/value\r
440 pair (or the beginning of the string if the failure is in the\r
441 first name/value pair) if the request was not successful.\r
442 @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
443 has all values filled in for the names in the Request string.\r
444 String to be allocated by the called function.\r
445\r
446 @retval EFI_SUCCESS The Results is filled with the requested values.\r
447 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
448 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
449 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
450\r
451**/\r
452EFI_STATUS\r
453EFIAPI\r
454BootMaintExtractConfig (\r
455 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
456 IN CONST EFI_STRING Request,\r
457 OUT EFI_STRING *Progress,\r
458 OUT EFI_STRING *Results\r
459 )\r
460{\r
461 EFI_STATUS Status;\r
462 UINTN BufferSize;\r
463 BMM_CALLBACK_DATA *Private;\r
464 EFI_STRING ConfigRequestHdr;\r
465 EFI_STRING ConfigRequest;\r
466 BOOLEAN AllocatedRequest;\r
467 UINTN Size;\r
468\r
469 if (Progress == NULL || Results == NULL) {\r
470 return EFI_INVALID_PARAMETER;\r
471 }\r
472\r
473 *Progress = Request;\r
474 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mBootMaintGuid, mBootMaintStorageName)) {\r
475 return EFI_NOT_FOUND;\r
476 }\r
477\r
478 ConfigRequestHdr = NULL;\r
479 ConfigRequest = NULL;\r
480 AllocatedRequest = FALSE;\r
481 Size = 0;\r
482\r
483 Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
484 //\r
485 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
486 //\r
487 BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
488 ConfigRequest = Request;\r
489 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
490 //\r
491 // Request has no request element, construct full request string.\r
492 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
493 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
494 //\r
495 ConfigRequestHdr = HiiConstructConfigHdr (&mBootMaintGuid, mBootMaintStorageName, Private->BmmDriverHandle);\r
496 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
497 ConfigRequest = AllocateZeroPool (Size);\r
498 ASSERT (ConfigRequest != NULL);\r
499 AllocatedRequest = TRUE;\r
500 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
501 FreePool (ConfigRequestHdr);\r
502 }\r
503\r
504 Status = gHiiConfigRouting->BlockToConfig (\r
505 gHiiConfigRouting,\r
506 ConfigRequest,\r
507 (UINT8 *) &Private->BmmFakeNvData,\r
508 BufferSize,\r
509 Results,\r
510 Progress\r
511 );\r
512 //\r
513 // Free the allocated config request string.\r
514 //\r
515 if (AllocatedRequest) {\r
516 FreePool (ConfigRequest);\r
517 ConfigRequest = NULL;\r
518 }\r
519 //\r
520 // Set Progress string to the original request string.\r
521 //\r
522 if (Request == NULL) {\r
523 *Progress = NULL;\r
524 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
525 *Progress = Request + StrLen (Request);\r
526 }\r
527\r
528 return Status;\r
529}\r
530\r
531/**\r
532 This function applies changes in a driver's configuration.\r
533 Input is a Configuration, which has the routing data for this\r
534 driver followed by name / value configuration pairs. The driver\r
535 must apply those pairs to its configurable storage. If the\r
536 driver's configuration is stored in a linear block of data\r
537 and the driver's name / value pairs are in <BlockConfig>\r
538 format, it may use the ConfigToBlock helper function (above) to\r
539 simplify the job. Currently not implemented.\r
540\r
541 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
542 @param[in] Configuration A null-terminated Unicode string in\r
543 <ConfigString> format. \r
544 @param[out] Progress A pointer to a string filled in with the\r
545 offset of the most recent '&' before the\r
546 first failing name / value pair (or the\r
547 beginn ing of the string if the failure\r
548 is in the first name / value pair) or\r
549 the terminating NULL if all was\r
550 successful.\r
551\r
552 @retval EFI_SUCCESS The results have been distributed or are\r
553 awaiting distribution. \r
554 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
555 parts of the results that must be\r
556 stored awaiting possible future\r
557 protocols.\r
558 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
559 Results parameter would result\r
560 in this type of error.\r
561 @retval EFI_NOT_FOUND Target for the specified routing data\r
562 was not found.\r
563**/\r
564EFI_STATUS\r
565EFIAPI\r
566BootMaintRouteConfig (\r
567 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
568 IN CONST EFI_STRING Configuration,\r
569 OUT EFI_STRING *Progress\r
570 )\r
571{\r
572 EFI_STATUS Status;\r
573 UINTN BufferSize;\r
574 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;\r
575 BMM_FAKE_NV_DATA *NewBmmData;\r
576 BMM_FAKE_NV_DATA *OldBmmData;\r
577 BM_CONSOLE_CONTEXT *NewConsoleContext;\r
578 BM_TERMINAL_CONTEXT *NewTerminalContext;\r
579 BM_MENU_ENTRY *NewMenuEntry;\r
580 BM_LOAD_CONTEXT *NewLoadContext;\r
581 UINT16 Index;\r
582 BOOLEAN TerminalAttChange;\r
583 BMM_CALLBACK_DATA *Private; \r
584\r
585 if (Progress == NULL) {\r
586 return EFI_INVALID_PARAMETER;\r
587 }\r
588 *Progress = Configuration;\r
589\r
590 if (Configuration == NULL) {\r
591 return EFI_INVALID_PARAMETER;\r
592 }\r
593\r
594 //\r
595 // Check routing data in <ConfigHdr>.\r
596 // Note: there is no name for Name/Value storage, only GUID will be checked\r
597 //\r
598 if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)) {\r
599 return EFI_NOT_FOUND;\r
600 }\r
601\r
602 Status = gBS->LocateProtocol (\r
603 &gEfiHiiConfigRoutingProtocolGuid, \r
604 NULL, \r
605 (VOID **)&ConfigRouting\r
606 );\r
607 if (EFI_ERROR (Status)) {\r
608 return Status;\r
609 }\r
610\r
611 Private = BMM_CALLBACK_DATA_FROM_THIS (This); \r
612 //\r
613 // Get Buffer Storage data from EFI variable\r
614 //\r
615 BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
616 OldBmmData = &Private->BmmOldFakeNVData;\r
617 NewBmmData = &Private->BmmFakeNvData;\r
618 //\r
619 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
620 //\r
621 Status = ConfigRouting->ConfigToBlock (\r
622 ConfigRouting,\r
623 Configuration,\r
624 (UINT8 *) NewBmmData,\r
625 &BufferSize,\r
626 Progress\r
627 );\r
628 ASSERT_EFI_ERROR (Status); \r
629 //\r
630 // Compare new and old BMM configuration data and only do action for modified item to \r
631 // avoid setting unnecessary non-volatile variable\r
632 //\r
633\r
634 //\r
635 // Check data which located in BMM main page and save the settings if need\r
636 // \r
637 if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) {\r
638 Status = Var_UpdateBootNext (Private);\r
639 }\r
640\r
641 //\r
642 // Check data which located in Boot Options Menu and save the settings if need\r
643 // \r
644 if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { \r
645 for (Index = 0; \r
646 ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); \r
647 Index ++) {\r
648 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
649 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
650 NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index];\r
651 NewBmmData->BootOptionDel[Index] = FALSE;\r
652 NewBmmData->BootOptionDelMark[Index] = FALSE;\r
653 }\r
654\r
655 Var_DelBootOption ();\r
656 }\r
657\r
658 if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {\r
659 Status = Var_UpdateBootOrder (Private);\r
660 }\r
661\r
662 if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0){\r
663 Status = gRT->SetVariable(\r
664 L"Timeout",\r
665 &gEfiGlobalVariableGuid,\r
666 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
667 sizeof(UINT16),\r
668 &(NewBmmData->BootTimeOut)\r
669 );\r
c7d310dd
DB
670 if (EFI_ERROR (Status)) {\r
671 //\r
672 // If set variable fail, and don't have the appropriate error status for RouteConfig fuction to return,\r
673 // just return the EFI_NOT_FOUND.\r
674 //\r
675 if (Status == EFI_OUT_OF_RESOURCES) {\r
676 return Status;\r
677 } else {\r
678 return EFI_NOT_FOUND;\r
679 }\r
680 }\r
4af04335
DB
681 Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut;\r
682 }\r
683\r
684 //\r
685 // Check data which located in Driver Options Menu and save the settings if need\r
686 // \r
687 if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { \r
688 for (Index = 0; \r
689 ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); \r
690 Index++) {\r
691 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
692 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
693 NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index];\r
694 NewBmmData->DriverOptionDel[Index] = FALSE;\r
695 NewBmmData->DriverOptionDelMark[Index] = FALSE;\r
696 }\r
697 Var_DelDriverOption (); \r
698 }\r
699\r
700 if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { \r
701 Status = Var_UpdateDriverOrder (Private);\r
702 }\r
703\r
704 if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){\r
705 Var_UpdateConMode(Private);\r
706 }\r
707\r
708 TerminalAttChange = FALSE;\r
709 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
710\r
711 //\r
712 // only need update modified items\r
713 //\r
714 if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 &&\r
715 CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 &&\r
716 CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 &&\r
717 CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 &&\r
718 CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 &&\r
719 CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) {\r
720 continue;\r
721 }\r
722\r
723 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
724 ASSERT (NewMenuEntry != NULL);\r
725 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
726 NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index];\r
727 ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));\r
728 NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value;\r
729 NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index];\r
730 ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));\r
731 NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value;\r
732 NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index];\r
733 ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));\r
734 NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value;\r
735 NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index];\r
736 ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0])));\r
737 NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value;\r
738 NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index];\r
739 NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index];\r
740 ChangeTerminalDevicePath (\r
741 NewTerminalContext->DevicePath,\r
742 FALSE\r
743 );\r
744 TerminalAttChange = TRUE;\r
745 }\r
746 if (TerminalAttChange) {\r
747 Var_UpdateConsoleInpOption ();\r
748 Var_UpdateConsoleOutOption ();\r
749 Var_UpdateErrorOutOption ();\r
750 }\r
751 //\r
752 // Check data which located in Console Options Menu and save the settings if need\r
753 //\r
754 if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0){\r
755 for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){\r
756 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleInpMenu, Index);\r
757 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
758 ASSERT (Index < MAX_MENU_NUMBER);\r
759 NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index];\r
760 }\r
761 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
762 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
763 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
764 ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER);\r
765 NewTerminalContext->IsConIn = NewBmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber];\r
766 }\r
767 Var_UpdateConsoleInpOption();\r
768 }\r
769\r
770 if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0){\r
771 for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){\r
772 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleOutMenu, Index);\r
773 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
774 ASSERT (Index < MAX_MENU_NUMBER);\r
775 NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index];\r
776 }\r
777 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
778 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
779 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
780 ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER);\r
781 NewTerminalContext->IsConOut = NewBmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber];\r
782 }\r
783 Var_UpdateConsoleOutOption();\r
784 }\r
785\r
786 if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0){\r
787 for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){\r
788 NewMenuEntry = BOpt_GetMenuEntry(&ConsoleErrMenu, Index);\r
789 NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
790 ASSERT (Index < MAX_MENU_NUMBER);\r
791 NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index];\r
792 }\r
793 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
794 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
795 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
796 ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER);\r
797 NewTerminalContext->IsStdErr = NewBmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber];\r
798 }\r
799 Var_UpdateErrorOutOption();\r
800 }\r
801\r
802 if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0 ||\r
803 CompareMem (NewBmmData->BootOptionalData, OldBmmData->BootOptionalData, sizeof (NewBmmData->BootOptionalData)) != 0) {\r
804 Status = Var_UpdateBootOption (Private);\r
805 NewBmmData->BootOptionChanged = FALSE;\r
806 if (EFI_ERROR (Status)) {\r
807 return Status;\r
808 }\r
809 BOpt_GetBootOptions (Private);\r
810 }\r
811\r
812 if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0 ||\r
813 CompareMem (NewBmmData->DriverOptionalData, OldBmmData->DriverOptionalData, sizeof (NewBmmData->DriverOptionalData)) != 0) {\r
814 Status = Var_UpdateDriverOption (\r
815 Private,\r
816 Private->BmmHiiHandle,\r
817 NewBmmData->DriverDescriptionData,\r
818 NewBmmData->DriverOptionalData,\r
819 NewBmmData->ForceReconnect\r
820 );\r
821 NewBmmData->DriverOptionChanged = FALSE;\r
822 NewBmmData->ForceReconnect = TRUE;\r
823 if (EFI_ERROR (Status)) {\r
824 return Status;\r
825 }\r
826\r
827 BOpt_GetDriverOptions (Private);\r
828 }\r
829\r
830 //\r
831 // After user do the save action, need to update OldBmmData.\r
832 //\r
833 CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));\r
834\r
835 return EFI_SUCCESS;\r
836}\r
837\r
838/**\r
839 This function processes the results of changes in configuration.\r
840\r
841\r
842 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
843 @param Action Specifies the type of action taken by the browser.\r
844 @param QuestionId A unique value which is sent to the original exporting driver\r
845 so that it can identify the type of data to expect.\r
846 @param Type The type of value for the question.\r
847 @param Value A pointer to the data being sent to the original exporting driver.\r
848 @param ActionRequest On return, points to the action requested by the callback function.\r
849\r
850 @retval EFI_SUCCESS The callback successfully handled the action.\r
851 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
852 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
853 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
854 @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.\r
855**/\r
856EFI_STATUS\r
857EFIAPI\r
858BootMaintCallback (\r
859 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
860 IN EFI_BROWSER_ACTION Action,\r
861 IN EFI_QUESTION_ID QuestionId,\r
862 IN UINT8 Type,\r
863 IN EFI_IFR_TYPE_VALUE *Value,\r
864 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
865 )\r
866{\r
867 BMM_CALLBACK_DATA *Private;\r
868 BM_MENU_ENTRY *NewMenuEntry;\r
869 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
870 UINTN OldValue;\r
871 UINTN NewValue;\r
872 UINTN Number;\r
873 UINTN Index;\r
874 EFI_DEVICE_PATH_PROTOCOL * File;\r
875\r
876 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
877 //\r
878 // Do nothing for other UEFI Action. Only do call back when data is changed.\r
879 //\r
880 return EFI_UNSUPPORTED;\r
881 }\r
882 OldValue = 0;\r
883 NewValue = 0;\r
884 Number = 0;\r
885\r
886 Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
887 //\r
888 // Retrive uncommitted data from Form Browser\r
889 //\r
890 CurrentFakeNVMap = &Private->BmmFakeNvData;\r
891 HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);\r
892\r
893 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
894 if (Value == NULL) {\r
895 return EFI_INVALID_PARAMETER;\r
896 }\r
897 \r
898 UpdatePageId (Private, QuestionId);\r
899\r
900 if (QuestionId < FILE_OPTION_OFFSET) {\r
901 if (QuestionId < CONFIG_OPTION_OFFSET) {\r
902 switch (QuestionId) {\r
903 case FORM_BOOT_ADD_ID:\r
904 // Leave BMM and enter FileExplorer. \r
905 ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) CreateBootOptionFromFile, &File);\r
906 break;\r
907\r
908 case FORM_DRV_ADD_FILE_ID:\r
909 // Leave BMM and enter FileExplorer.\r
910 ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) CreateDriverOptionFromFile, &File);\r
911 break;\r
912\r
913 case FORM_DRV_ADD_HANDLE_ID:\r
914 CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
915 UpdateDrvAddHandlePage (Private);\r
916 break;\r
917\r
918 case FORM_BOOT_DEL_ID:\r
919 CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
920 UpdateBootDelPage (Private);\r
921 break;\r
922\r
923 case FORM_BOOT_CHG_ID:\r
924 case FORM_DRV_CHG_ID:\r
925 UpdatePageBody (QuestionId, Private);\r
926 break;\r
927\r
928 case FORM_DRV_DEL_ID:\r
929 CleanUpPage (FORM_DRV_DEL_ID, Private);\r
930 UpdateDrvDelPage (Private);\r
931 break;\r
932\r
933 case FORM_BOOT_NEXT_ID:\r
934 CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
935 UpdateBootNextPage (Private);\r
936 break;\r
937\r
938 case FORM_TIME_OUT_ID:\r
939 CleanUpPage (FORM_TIME_OUT_ID, Private);\r
940 UpdateTimeOutPage (Private);\r
941 break;\r
942\r
943 case FORM_CON_IN_ID:\r
944 case FORM_CON_OUT_ID:\r
945 case FORM_CON_ERR_ID:\r
946 UpdatePageBody (QuestionId, Private);\r
947 break;\r
948\r
949 case FORM_CON_MODE_ID:\r
950 CleanUpPage (FORM_CON_MODE_ID, Private);\r
951 UpdateConModePage (Private);\r
952 break;\r
953\r
954 case FORM_CON_COM_ID:\r
955 CleanUpPage (FORM_CON_COM_ID, Private);\r
956 UpdateConCOMPage (Private);\r
957 break;\r
958\r
959 default:\r
960 break;\r
961 }\r
962 } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
963 Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
964 Private->CurrentTerminal = Index;\r
965\r
966 CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
967 UpdateTerminalPage (Private);\r
968\r
969 } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
970 Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
971\r
972 NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
973 ASSERT (NewMenuEntry != NULL);\r
974 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
975\r
976 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
977\r
978 Private->MenuEntry = NewMenuEntry;\r
979 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;\r
980\r
981 UpdateDriverAddHandleDescPage (Private);\r
982 }\r
983 }\r
984 if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){\r
985 // Leave BMM and enter FileExplorer.\r
986 ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) BootFromFile, &File);\r
987 }\r
988 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
989 if ((Value == NULL) || (ActionRequest == NULL)) {\r
990 return EFI_INVALID_PARAMETER;\r
991 }\r
992 \r
993 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) {\r
994 CurrentFakeNVMap->BootOptionChanged = FALSE;\r
995 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
996 } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
997 CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
998 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
999 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
1000 //\r
1001 // Discard changes and exit formset\r
1002 //\r
1003 CurrentFakeNVMap->DriverOptionalData[0] = 0x0000;\r
1004 CurrentFakeNVMap->DriverDescriptionData[0] = 0x0000;\r
1005 CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
1006 CurrentFakeNVMap->ForceReconnect = TRUE;\r
1007 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1008 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) {\r
1009 //\r
1010 // Discard changes and exit formset\r
1011 //\r
1012 CurrentFakeNVMap->BootOptionalData[0] = 0x0000;\r
1013 CurrentFakeNVMap->BootDescriptionData[0] = 0x0000;\r
1014 CurrentFakeNVMap->BootOptionChanged = FALSE;\r
1015 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1016 } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) {\r
1017 CurrentFakeNVMap->BootOptionChanged = TRUE;\r
1018 } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) {\r
1019 CurrentFakeNVMap->DriverOptionChanged = TRUE;\r
1020 } \r
1021\r
1022 if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {\r
1023 if (Value->b){\r
1024 //\r
1025 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.\r
1026 //\r
1027 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE;\r
1028 } else {\r
1029 //\r
1030 // Means user remove the old check status.\r
1031 //\r
1032 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE;\r
1033 }\r
1034 } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {\r
1035 if (Value->b){\r
1036 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE;\r
1037 } else {\r
1038 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE;\r
1039 }\r
1040 } else {\r
1041 switch (QuestionId) {\r
1042 case KEY_VALUE_SAVE_AND_EXIT:\r
1043 case KEY_VALUE_NO_SAVE_AND_EXIT:\r
1044 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
1045 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
1046 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
1047 DiscardChangeHandler (Private, CurrentFakeNVMap);\r
1048 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1049 }\r
1050\r
1051 break;\r
1052\r
1053 case FORM_RESET:\r
1054 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
1055 return EFI_UNSUPPORTED;\r
1056\r
1057 default:\r
1058 break;\r
1059 }\r
1060 }\r
1061 }\r
1062\r
1063 //\r
1064 // Pass changed uncommitted data back to Form Browser\r
1065 //\r
1066 HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL);\r
1067\r
1068 return EFI_SUCCESS;\r
1069}\r
1070\r
1071/**\r
1072 Discard all changes done to the BMM pages such as Boot Order change,\r
1073 Driver order change.\r
1074\r
1075 @param Private The BMM context data.\r
1076 @param CurrentFakeNVMap The current Fack NV Map.\r
1077\r
1078**/\r
1079VOID\r
1080DiscardChangeHandler (\r
1081 IN BMM_CALLBACK_DATA *Private,\r
1082 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
1083 )\r
1084{\r
1085 UINT16 Index;\r
1086\r
1087 switch (Private->BmmPreviousPageId) {\r
1088 case FORM_BOOT_CHG_ID:\r
1089 CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder));\r
1090 break;\r
1091\r
1092 case FORM_DRV_CHG_ID:\r
1093 CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder));\r
1094 break;\r
1095\r
1096 case FORM_BOOT_DEL_ID:\r
1097 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));\r
1098 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
1099 CurrentFakeNVMap->BootOptionDel[Index] = FALSE;\r
1100 }\r
1101 break;\r
1102\r
1103 case FORM_DRV_DEL_ID:\r
1104 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));\r
1105 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
1106 CurrentFakeNVMap->DriverOptionDel[Index] = FALSE;\r
1107 }\r
1108 break;\r
1109\r
1110 case FORM_BOOT_NEXT_ID:\r
1111 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
1112 break;\r
1113\r
1114 case FORM_TIME_OUT_ID:\r
1115 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
1116 break;\r
1117\r
1118 case FORM_DRV_ADD_HANDLE_DESC_ID:\r
1119 case FORM_DRV_ADD_FILE_ID:\r
1120 case FORM_DRV_ADD_HANDLE_ID:\r
1121 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;\r
1122 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;\r
1123 break;\r
1124\r
1125 default:\r
1126 break;\r
1127 }\r
1128}\r
1129\r
1130/**\r
1131 Create dynamic code for BMM.\r
1132\r
1133 @param BmmCallbackInfo The BMM context data.\r
1134\r
1135**/\r
1136VOID\r
1137InitializeDrivers(\r
1138 IN BMM_CALLBACK_DATA *BmmCallbackInfo\r
1139 )\r
1140{\r
1141 EFI_HII_HANDLE HiiHandle;\r
1142 VOID *StartOpCodeHandle;\r
1143 VOID *EndOpCodeHandle;\r
1144 EFI_IFR_GUID_LABEL *StartLabel;\r
1145 EFI_IFR_GUID_LABEL *EndLabel;\r
1146 UINTN Index; \r
1147 EFI_STRING String;\r
1148 EFI_STRING_ID Token;\r
1149 EFI_STRING_ID TokenHelp; \r
1150 EFI_HII_HANDLE *HiiHandles;\r
1151 EFI_GUID FormSetGuid;\r
1152 CHAR16 *DevicePathStr;\r
1153 EFI_STRING_ID DevicePathId;\r
1154 EFI_IFR_FORM_SET *Buffer; \r
1155 UINTN BufferSize; \r
1156 UINT8 ClassGuidNum; \r
1157 EFI_GUID *ClassGuid; \r
1158 UINTN TempSize;\r
1159 UINT8 *Ptr;\r
1160 EFI_STATUS Status;\r
1161\r
1162 TempSize =0;\r
1163 BufferSize = 0;\r
1164 Buffer = NULL;\r
1165\r
1166 HiiHandle = BmmCallbackInfo->BmmHiiHandle;\r
1167 //\r
1168 // Allocate space for creation of UpdateData Buffer\r
1169 //\r
1170 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1171 ASSERT (StartOpCodeHandle != NULL);\r
1172\r
1173 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1174 ASSERT (EndOpCodeHandle != NULL);\r
1175\r
1176 //\r
1177 // Create Hii Extend Label OpCode as the start opcode\r
1178 //\r
1179 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1180 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1181 StartLabel->Number = LABEL_BMM_PLATFORM_INFORMATION;\r
1182\r
1183 //\r
1184 // Create Hii Extend Label OpCode as the end opcode\r
1185 //\r
1186 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1187 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1188 EndLabel->Number = LABEL_END;\r
1189\r
1190 //\r
1191 // Get all the Hii handles\r
1192 //\r
1193 HiiHandles = HiiGetHiiHandles (NULL);\r
1194 ASSERT (HiiHandles != NULL);\r
1195\r
1196 //\r
1197 // Search for formset of each class type\r
1198 //\r
1199 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
1200 Status = HiiGetFormSetFromHiiHandle(HiiHandles[Index], &Buffer,&BufferSize);\r
1201 if (EFI_ERROR (Status)) {\r
1202 continue;\r
1203 }\r
1204\r
1205 Ptr = (UINT8 *)Buffer;\r
1206 while(TempSize < BufferSize) {\r
1207 TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
1208\r
1209 if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){\r
1210 Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
1211 continue;\r
1212 }\r
1213\r
1214 //\r
1215 // Find FormSet OpCode\r
1216 //\r
1217 ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);\r
1218 ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));\r
1219 while (ClassGuidNum-- > 0) {\r
1220 if (CompareGuid (&gEfiIfrBootMaintenanceGuid, ClassGuid) == 0){\r
1221 ClassGuid ++;\r
1222 continue;\r
1223 }\r
1224\r
1225 String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL);\r
1226 if (String == NULL) {\r
1227 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
1228 ASSERT (String != NULL);\r
1229 }\r
1230 Token = HiiSetString (HiiHandle, 0, String, NULL);\r
1231 FreePool (String);\r
1232\r
1233 String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL);\r
1234 if (String == NULL) {\r
1235 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
1236 ASSERT (String != NULL);\r
1237 }\r
1238 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
1239 FreePool (String);\r
1240\r
1241 FormSetGuid = ((EFI_IFR_FORM_SET *)Ptr)->Guid;\r
1242\r
1243 DevicePathStr = BmmExtractDevicePathFromHiiHandle(HiiHandles[Index]);\r
1244 DevicePathId = 0;\r
1245 if (DevicePathStr != NULL){\r
1246 DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
1247 FreePool (DevicePathStr);\r
1248 }\r
1249 HiiCreateGotoExOpCode (\r
1250 StartOpCodeHandle,\r
1251 0,\r
1252 Token,\r
1253 TokenHelp,\r
1254 0,\r
1255 (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_OFFSET),\r
1256 0,\r
1257 &FormSetGuid,\r
1258 DevicePathId\r
1259 );\r
1260 break;\r
1261 }\r
1262 Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
1263 }\r
1264\r
1265 FreePool(Buffer);\r
1266 Buffer = NULL;\r
1267 TempSize = 0;\r
1268 BufferSize = 0;\r
1269 } \r
1270 \r
1271 HiiUpdateForm (\r
1272 HiiHandle,\r
1273 &mBootMaintGuid,\r
1274 FORM_MAIN_ID,\r
1275 StartOpCodeHandle,\r
1276 EndOpCodeHandle\r
1277 );\r
1278\r
1279 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1280 HiiFreeOpCodeHandle (EndOpCodeHandle); \r
1281 FreePool (HiiHandles);\r
1282}\r
1283\r
1284/**\r
1285 Create dynamic code for BMM and initialize all of BMM configuration data in BmmFakeNvData and\r
1286 BmmOldFakeNVData member in BMM context data.\r
1287\r
1288 @param CallbackData The BMM context data.\r
1289\r
1290**/\r
1291VOID\r
1292InitializeBmmConfig (\r
1293 IN BMM_CALLBACK_DATA *CallbackData\r
1294 )\r
1295{\r
1296 BM_MENU_ENTRY *NewMenuEntry;\r
1297 BM_LOAD_CONTEXT *NewLoadContext;\r
1298 UINT16 Index;\r
1299\r
1300 ASSERT (CallbackData != NULL);\r
1301\r
1302 InitializeDrivers (CallbackData);\r
1303\r
1304 //\r
1305 // Initialize data which located in BMM main page\r
1306 //\r
f7986526 1307 CallbackData->BmmFakeNvData.BootNext = NONE_BOOTNEXT_VALUE;\r
4af04335
DB
1308 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
1309 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
1310 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1311\r
1312 if (NewLoadContext->IsBootNext) {\r
1313 CallbackData->BmmFakeNvData.BootNext = Index;\r
1314 break;\r
1315 }\r
1316 }\r
1317\r
1318 CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);\r
1319\r
1320 //\r
1321 // Initialize data which located in Boot Options Menu\r
1322 //\r
1323 GetBootOrder (CallbackData);\r
1324\r
1325 //\r
1326 // Initialize data which located in Driver Options Menu\r
1327 //\r
1328 GetDriverOrder (CallbackData);\r
1329\r
1330 //\r
1331 // Initialize data which located in Console Options Menu\r
1332 //\r
1333 GetConsoleOutMode (CallbackData);\r
1334 GetConsoleInCheck (CallbackData);\r
1335 GetConsoleOutCheck (CallbackData);\r
1336 GetConsoleErrCheck (CallbackData);\r
1337 GetTerminalAttribute (CallbackData);\r
1338\r
1339 CallbackData->BmmFakeNvData.ForceReconnect = TRUE;\r
1340\r
1341 //\r
1342 // Backup Initialize BMM configuartion data to BmmOldFakeNVData\r
1343 //\r
1344 CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));\r
1345}\r
1346\r
1347/**\r
1348 Initialized all Menu Option List.\r
1349\r
1350 @param CallbackData The BMM context data.\r
1351\r
1352**/\r
1353VOID\r
1354InitAllMenu (\r
1355 IN BMM_CALLBACK_DATA *CallbackData\r
1356 )\r
1357{\r
1358 InitializeListHead (&BootOptionMenu.Head);\r
1359 InitializeListHead (&DriverOptionMenu.Head);\r
1360 BOpt_GetBootOptions (CallbackData);\r
1361 BOpt_GetDriverOptions (CallbackData);\r
1362 BOpt_FindDrivers ();\r
1363 InitializeListHead (&ConsoleInpMenu.Head);\r
1364 InitializeListHead (&ConsoleOutMenu.Head);\r
1365 InitializeListHead (&ConsoleErrMenu.Head);\r
1366 InitializeListHead (&TerminalMenu.Head);\r
1367 LocateSerialIo ();\r
1368 GetAllConsoles ();\r
1369 mAllMenuInit = TRUE;\r
1370}\r
1371\r
1372/**\r
1373 Free up all Menu Option list.\r
1374\r
1375**/\r
1376VOID\r
1377FreeAllMenu (\r
1378 VOID\r
1379 )\r
1380{\r
1381 if (!mAllMenuInit){\r
1382 return;\r
1383 }\r
1384 BOpt_FreeMenu (&BootOptionMenu);\r
1385 BOpt_FreeMenu (&DriverOptionMenu);\r
1386 BOpt_FreeMenu (&DriverMenu);\r
1387 FreeAllConsoles ();\r
1388 mAllMenuInit = FALSE;\r
1389}\r
1390\r
1391/**\r
1392\r
1393 Install Boot Maintenance Manager Menu driver.\r
1394\r
1395 @param ImageHandle The image handle.\r
1396 @param SystemTable The system table.\r
1397\r
1398 @retval EFI_SUCEESS Install Boot manager menu success.\r
1399 @retval Other Return error status.\r
1400\r
1401**/\r
1402EFI_STATUS\r
1403EFIAPI\r
13c4e864 1404BootMaintenanceManagerUiLibConstructor (\r
4af04335
DB
1405 IN EFI_HANDLE ImageHandle,\r
1406 IN EFI_SYSTEM_TABLE *SystemTable\r
1407 )\r
1408\r
1409{\r
1410 EFI_STATUS Status;\r
1411 UINT8 *Ptr;\r
1412\r
1413 Status = EFI_SUCCESS;\r
1414\r
1415 //\r
1416 // Install Device Path Protocol and Config Access protocol to driver handle\r
1417 //\r
1418 Status = gBS->InstallMultipleProtocolInterfaces (\r
1419 &mBmmCallbackInfo->BmmDriverHandle,\r
1420 &gEfiDevicePathProtocolGuid,\r
1421 &mBmmHiiVendorDevicePath,\r
1422 &gEfiHiiConfigAccessProtocolGuid,\r
1423 &mBmmCallbackInfo->BmmConfigAccess,\r
1424 NULL\r
1425 );\r
1426 ASSERT_EFI_ERROR (Status);\r
1427\r
1428 //\r
1429 // Post our Boot Maint VFR binary to the HII database.\r
1430 //\r
1431 mBmmCallbackInfo->BmmHiiHandle = HiiAddPackages (\r
1432 &mBootMaintGuid,\r
1433 mBmmCallbackInfo->BmmDriverHandle,\r
1434 BootMaintenanceManagerBin,\r
13c4e864 1435 BootMaintenanceManagerUiLibStrings,\r
4af04335
DB
1436 NULL\r
1437 );\r
1438 ASSERT (mBmmCallbackInfo->BmmHiiHandle != NULL);\r
1439\r
1440 //\r
1441 // Locate Formbrowser2 protocol\r
1442 //\r
1443 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2);\r
1444 ASSERT_EFI_ERROR (Status);\r
1445\r
1446 EfiBootManagerRefreshAllBootOption ();\r
1447\r
1448 //\r
1449 // Create LoadOption in BmmCallbackInfo for Driver Callback\r
1450 //\r
1451 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
1452 ASSERT (Ptr != NULL);\r
1453\r
1454 //\r
1455 // Initialize Bmm callback data.\r
1456 //\r
1457 mBmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
1458 Ptr += sizeof (BM_LOAD_CONTEXT);\r
1459\r
1460 mBmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
1461 Ptr += sizeof (BM_FILE_CONTEXT);\r
1462\r
1463 mBmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
1464 Ptr += sizeof (BM_HANDLE_CONTEXT);\r
1465\r
1466 mBmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;\r
1467\r
1468 mBmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;\r
1469 mBmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;\r
1470\r
1471 InitAllMenu (mBmmCallbackInfo);\r
1472\r
1473 CreateUpdateData();\r
1474 //\r
1475 // Update boot maintenance manager page \r
1476 //\r
1477 InitializeBmmConfig(mBmmCallbackInfo);\r
1478\r
1479 return EFI_SUCCESS;\r
1480}\r
1481\r
1482/**\r
1483 Unloads the application and its installed protocol.\r
1484\r
1485 @param ImageHandle Handle that identifies the image to be unloaded.\r
1486 @param SystemTable The system table.\r
1487\r
1488 @retval EFI_SUCCESS The image has been unloaded.\r
1489\r
1490**/\r
1491EFI_STATUS\r
1492EFIAPI\r
13c4e864 1493BootMaintenanceManagerUiLibDestructor (\r
4af04335
DB
1494 IN EFI_HANDLE ImageHandle,\r
1495 IN EFI_SYSTEM_TABLE *SystemTable\r
1496 )\r
1497\r
1498{\r
1499 if (mStartOpCodeHandle != NULL) {\r
1500 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
1501 }\r
1502\r
1503 if (mEndOpCodeHandle != NULL) {\r
1504 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
1505 }\r
1506\r
1507 FreeAllMenu ();\r
1508\r
1509 //\r
1510 // Remove our IFR data from HII database\r
1511 //\r
1512 HiiRemovePackages (mBmmCallbackInfo->BmmHiiHandle);\r
1513\r
1514 gBS->UninstallMultipleProtocolInterfaces (\r
1515 mBmmCallbackInfo->BmmDriverHandle,\r
1516 &gEfiDevicePathProtocolGuid,\r
1517 &mBmmHiiVendorDevicePath,\r
1518 &gEfiHiiConfigAccessProtocolGuid,\r
1519 &mBmmCallbackInfo->BmmConfigAccess,\r
1520 NULL\r
1521 );\r
1522\r
1523 FreePool (mBmmCallbackInfo->LoadContext);\r
1524\r
1525 return EFI_SUCCESS;\r
1526}\r
1527\r