]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
MdeModulePkg BootManagerUiLib: Save mode info for later use.
[mirror_edk2.git] / MdeModulePkg / Library / BootMaintenanceManagerUiLib / BootMaintenance.c
... / ...
CommitLineData
1/** @file\r
2The functions for Boot Maintainence Main menu.\r
3\r
4Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
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
240 Status = PcdSet32S (PcdConOutColumn, mBmmSetupTextModeColumn);\r
241 ASSERT_EFI_ERROR (Status);\r
242 Status = PcdSet32S (PcdConOutRow, mBmmSetupTextModeRow);\r
243 ASSERT_EFI_ERROR (Status);\r
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
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
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
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
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 Index;\r
871 EFI_DEVICE_PATH_PROTOCOL * File;\r
872\r
873 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
874 //\r
875 // Do nothing for other UEFI Action. Only do call back when data is changed.\r
876 //\r
877 return EFI_UNSUPPORTED;\r
878 }\r
879\r
880 Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
881 //\r
882 // Retrive uncommitted data from Form Browser\r
883 //\r
884 CurrentFakeNVMap = &Private->BmmFakeNvData;\r
885 HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);\r
886\r
887 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
888 if (Value == NULL) {\r
889 return EFI_INVALID_PARAMETER;\r
890 }\r
891 \r
892 UpdatePageId (Private, QuestionId);\r
893\r
894 if (QuestionId < FILE_OPTION_OFFSET) {\r
895 if (QuestionId < CONFIG_OPTION_OFFSET) {\r
896 switch (QuestionId) {\r
897 case FORM_BOOT_ADD_ID:\r
898 // Leave BMM and enter FileExplorer. \r
899 ChooseFile (NULL, L".efi", CreateBootOptionFromFile, &File);\r
900 break;\r
901\r
902 case FORM_DRV_ADD_FILE_ID:\r
903 // Leave BMM and enter FileExplorer.\r
904 ChooseFile (NULL, L".efi", CreateDriverOptionFromFile, &File);\r
905 break;\r
906\r
907 case FORM_DRV_ADD_HANDLE_ID:\r
908 CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
909 UpdateDrvAddHandlePage (Private);\r
910 break;\r
911\r
912 case FORM_BOOT_DEL_ID:\r
913 CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
914 UpdateBootDelPage (Private);\r
915 break;\r
916\r
917 case FORM_BOOT_CHG_ID:\r
918 case FORM_DRV_CHG_ID:\r
919 UpdatePageBody (QuestionId, Private);\r
920 break;\r
921\r
922 case FORM_DRV_DEL_ID:\r
923 CleanUpPage (FORM_DRV_DEL_ID, Private);\r
924 UpdateDrvDelPage (Private);\r
925 break;\r
926\r
927 case FORM_CON_IN_ID:\r
928 case FORM_CON_OUT_ID:\r
929 case FORM_CON_ERR_ID:\r
930 UpdatePageBody (QuestionId, Private);\r
931 break;\r
932\r
933 case FORM_CON_MODE_ID:\r
934 CleanUpPage (FORM_CON_MODE_ID, Private);\r
935 UpdateConModePage (Private);\r
936 break;\r
937\r
938 case FORM_CON_COM_ID:\r
939 CleanUpPage (FORM_CON_COM_ID, Private);\r
940 UpdateConCOMPage (Private);\r
941 break;\r
942\r
943 default:\r
944 break;\r
945 }\r
946 } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
947 Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
948 Private->CurrentTerminal = Index;\r
949\r
950 CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
951 UpdateTerminalPage (Private);\r
952\r
953 } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
954 Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
955\r
956 NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
957 ASSERT (NewMenuEntry != NULL);\r
958 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
959\r
960 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
961\r
962 Private->MenuEntry = NewMenuEntry;\r
963 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;\r
964\r
965 UpdateDriverAddHandleDescPage (Private);\r
966 }\r
967 }\r
968 if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){\r
969 // Leave BMM and enter FileExplorer.\r
970 ChooseFile (NULL, L".efi", BootFromFile, &File);\r
971 }\r
972 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
973 if ((Value == NULL) || (ActionRequest == NULL)) {\r
974 return EFI_INVALID_PARAMETER;\r
975 }\r
976 \r
977 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) {\r
978 CurrentFakeNVMap->BootOptionChanged = FALSE;\r
979 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
980 } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
981 CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
982 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
983 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
984 //\r
985 // Discard changes and exit formset\r
986 //\r
987 CurrentFakeNVMap->DriverOptionalData[0] = 0x0000;\r
988 CurrentFakeNVMap->DriverDescriptionData[0] = 0x0000;\r
989 CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
990 CurrentFakeNVMap->ForceReconnect = TRUE;\r
991 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
992 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) {\r
993 //\r
994 // Discard changes and exit formset\r
995 //\r
996 CurrentFakeNVMap->BootOptionalData[0] = 0x0000;\r
997 CurrentFakeNVMap->BootDescriptionData[0] = 0x0000;\r
998 CurrentFakeNVMap->BootOptionChanged = FALSE;\r
999 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1000 } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) {\r
1001 CurrentFakeNVMap->BootOptionChanged = TRUE;\r
1002 } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) {\r
1003 CurrentFakeNVMap->DriverOptionChanged = TRUE;\r
1004 } \r
1005\r
1006 if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {\r
1007 if (Value->b){\r
1008 //\r
1009 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.\r
1010 //\r
1011 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE;\r
1012 } else {\r
1013 //\r
1014 // Means user remove the old check status.\r
1015 //\r
1016 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE;\r
1017 }\r
1018 } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {\r
1019 if (Value->b){\r
1020 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE;\r
1021 } else {\r
1022 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE;\r
1023 }\r
1024 } else {\r
1025 switch (QuestionId) {\r
1026 case KEY_VALUE_SAVE_AND_EXIT:\r
1027 case KEY_VALUE_NO_SAVE_AND_EXIT:\r
1028 if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
1029 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
1030 } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
1031 DiscardChangeHandler (Private, CurrentFakeNVMap);\r
1032 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
1033 }\r
1034\r
1035 break;\r
1036\r
1037 case FORM_RESET:\r
1038 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
1039 return EFI_UNSUPPORTED;\r
1040\r
1041 default:\r
1042 break;\r
1043 }\r
1044 }\r
1045 }\r
1046\r
1047 //\r
1048 // Pass changed uncommitted data back to Form Browser\r
1049 //\r
1050 HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL);\r
1051\r
1052 return EFI_SUCCESS;\r
1053}\r
1054\r
1055/**\r
1056 Discard all changes done to the BMM pages such as Boot Order change,\r
1057 Driver order change.\r
1058\r
1059 @param Private The BMM context data.\r
1060 @param CurrentFakeNVMap The current Fack NV Map.\r
1061\r
1062**/\r
1063VOID\r
1064DiscardChangeHandler (\r
1065 IN BMM_CALLBACK_DATA *Private,\r
1066 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
1067 )\r
1068{\r
1069 UINT16 Index;\r
1070\r
1071 switch (Private->BmmPreviousPageId) {\r
1072 case FORM_BOOT_CHG_ID:\r
1073 CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder));\r
1074 break;\r
1075\r
1076 case FORM_DRV_CHG_ID:\r
1077 CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder));\r
1078 break;\r
1079\r
1080 case FORM_BOOT_DEL_ID:\r
1081 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));\r
1082 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
1083 CurrentFakeNVMap->BootOptionDel[Index] = FALSE;\r
1084 }\r
1085 break;\r
1086\r
1087 case FORM_DRV_DEL_ID:\r
1088 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));\r
1089 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
1090 CurrentFakeNVMap->DriverOptionDel[Index] = FALSE;\r
1091 }\r
1092 break;\r
1093\r
1094 case FORM_BOOT_NEXT_ID:\r
1095 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
1096 break;\r
1097\r
1098 case FORM_TIME_OUT_ID:\r
1099 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
1100 break;\r
1101\r
1102 case FORM_DRV_ADD_HANDLE_DESC_ID:\r
1103 case FORM_DRV_ADD_FILE_ID:\r
1104 case FORM_DRV_ADD_HANDLE_ID:\r
1105 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;\r
1106 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;\r
1107 break;\r
1108\r
1109 default:\r
1110 break;\r
1111 }\r
1112}\r
1113\r
1114/**\r
1115\r
1116 Update the menus in the BMM page.\r
1117\r
1118**/\r
1119VOID\r
1120CustomizeMenus (\r
1121 VOID\r
1122 )\r
1123{\r
1124 VOID *StartOpCodeHandle;\r
1125 VOID *EndOpCodeHandle;\r
1126 EFI_IFR_GUID_LABEL *StartGuidLabel;\r
1127 EFI_IFR_GUID_LABEL *EndGuidLabel;\r
1128\r
1129 //\r
1130 // Allocate space for creation of UpdateData Buffer\r
1131 //\r
1132 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1133 ASSERT (StartOpCodeHandle != NULL);\r
1134\r
1135 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1136 ASSERT (EndOpCodeHandle != NULL);\r
1137 //\r
1138 // Create Hii Extend Label OpCode as the start opcode\r
1139 //\r
1140 StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1141 StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1142 StartGuidLabel->Number = LABEL_FORM_MAIN_START;\r
1143 //\r
1144 // Create Hii Extend Label OpCode as the end opcode\r
1145 //\r
1146 EndGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1147 EndGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1148 EndGuidLabel->Number = LABEL_FORM_MAIN_END;\r
1149\r
1150 //\r
1151 //Updata Front Page form\r
1152 //\r
1153 UiCustomizeBMMPage (\r
1154 mBmmCallbackInfo->BmmHiiHandle,\r
1155 StartOpCodeHandle\r
1156 );\r
1157\r
1158 HiiUpdateForm (\r
1159 mBmmCallbackInfo->BmmHiiHandle,\r
1160 &mBootMaintGuid,\r
1161 FORM_MAIN_ID,\r
1162 StartOpCodeHandle,\r
1163 EndOpCodeHandle\r
1164 );\r
1165\r
1166 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1167 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1168}\r
1169\r
1170/**\r
1171 Create dynamic code for BMM and initialize all of BMM configuration data in BmmFakeNvData and\r
1172 BmmOldFakeNVData member in BMM context data.\r
1173\r
1174 @param CallbackData The BMM context data.\r
1175\r
1176**/\r
1177VOID\r
1178InitializeBmmConfig (\r
1179 IN BMM_CALLBACK_DATA *CallbackData\r
1180 )\r
1181{\r
1182 BM_MENU_ENTRY *NewMenuEntry;\r
1183 BM_LOAD_CONTEXT *NewLoadContext;\r
1184 UINT16 Index;\r
1185\r
1186 ASSERT (CallbackData != NULL);\r
1187\r
1188 //\r
1189 // Initialize data which located in BMM main page\r
1190 //\r
1191 CallbackData->BmmFakeNvData.BootNext = NONE_BOOTNEXT_VALUE;\r
1192 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
1193 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
1194 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1195\r
1196 if (NewLoadContext->IsBootNext) {\r
1197 CallbackData->BmmFakeNvData.BootNext = Index;\r
1198 break;\r
1199 }\r
1200 }\r
1201\r
1202 CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);\r
1203\r
1204 //\r
1205 // Initialize data which located in Boot Options Menu\r
1206 //\r
1207 GetBootOrder (CallbackData);\r
1208\r
1209 //\r
1210 // Initialize data which located in Driver Options Menu\r
1211 //\r
1212 GetDriverOrder (CallbackData);\r
1213\r
1214 //\r
1215 // Initialize data which located in Console Options Menu\r
1216 //\r
1217 GetConsoleOutMode (CallbackData);\r
1218 GetConsoleInCheck (CallbackData);\r
1219 GetConsoleOutCheck (CallbackData);\r
1220 GetConsoleErrCheck (CallbackData);\r
1221 GetTerminalAttribute (CallbackData);\r
1222\r
1223 CallbackData->BmmFakeNvData.ForceReconnect = TRUE;\r
1224\r
1225 //\r
1226 // Update the menus.\r
1227 //\r
1228 CustomizeMenus ();\r
1229\r
1230 //\r
1231 // Backup Initialize BMM configuartion data to BmmOldFakeNVData\r
1232 //\r
1233 CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));\r
1234}\r
1235\r
1236/**\r
1237 Initialized all Menu Option List.\r
1238\r
1239 @param CallbackData The BMM context data.\r
1240\r
1241**/\r
1242VOID\r
1243InitAllMenu (\r
1244 IN BMM_CALLBACK_DATA *CallbackData\r
1245 )\r
1246{\r
1247 InitializeListHead (&BootOptionMenu.Head);\r
1248 InitializeListHead (&DriverOptionMenu.Head);\r
1249 BOpt_GetBootOptions (CallbackData);\r
1250 BOpt_GetDriverOptions (CallbackData);\r
1251 BOpt_FindDrivers ();\r
1252 InitializeListHead (&ConsoleInpMenu.Head);\r
1253 InitializeListHead (&ConsoleOutMenu.Head);\r
1254 InitializeListHead (&ConsoleErrMenu.Head);\r
1255 InitializeListHead (&TerminalMenu.Head);\r
1256 LocateSerialIo ();\r
1257 GetAllConsoles ();\r
1258 mAllMenuInit = TRUE;\r
1259}\r
1260\r
1261/**\r
1262 Free up all Menu Option list.\r
1263\r
1264**/\r
1265VOID\r
1266FreeAllMenu (\r
1267 VOID\r
1268 )\r
1269{\r
1270 if (!mAllMenuInit){\r
1271 return;\r
1272 }\r
1273 BOpt_FreeMenu (&BootOptionMenu);\r
1274 BOpt_FreeMenu (&DriverOptionMenu);\r
1275 BOpt_FreeMenu (&DriverMenu);\r
1276 FreeAllConsoles ();\r
1277 mAllMenuInit = FALSE;\r
1278}\r
1279\r
1280/**\r
1281\r
1282 Install Boot Maintenance Manager Menu driver.\r
1283\r
1284 @param ImageHandle The image handle.\r
1285 @param SystemTable The system table.\r
1286\r
1287 @retval EFI_SUCEESS Install Boot manager menu success.\r
1288 @retval Other Return error status.\r
1289\r
1290**/\r
1291EFI_STATUS\r
1292EFIAPI\r
1293BootMaintenanceManagerUiLibConstructor (\r
1294 IN EFI_HANDLE ImageHandle,\r
1295 IN EFI_SYSTEM_TABLE *SystemTable\r
1296 )\r
1297\r
1298{\r
1299 EFI_STATUS Status;\r
1300 UINT8 *Ptr;\r
1301\r
1302 Status = EFI_SUCCESS;\r
1303\r
1304 //\r
1305 // Install Device Path Protocol and Config Access protocol to driver handle\r
1306 //\r
1307 Status = gBS->InstallMultipleProtocolInterfaces (\r
1308 &mBmmCallbackInfo->BmmDriverHandle,\r
1309 &gEfiDevicePathProtocolGuid,\r
1310 &mBmmHiiVendorDevicePath,\r
1311 &gEfiHiiConfigAccessProtocolGuid,\r
1312 &mBmmCallbackInfo->BmmConfigAccess,\r
1313 NULL\r
1314 );\r
1315 ASSERT_EFI_ERROR (Status);\r
1316\r
1317 //\r
1318 // Post our Boot Maint VFR binary to the HII database.\r
1319 //\r
1320 mBmmCallbackInfo->BmmHiiHandle = HiiAddPackages (\r
1321 &mBootMaintGuid,\r
1322 mBmmCallbackInfo->BmmDriverHandle,\r
1323 BootMaintenanceManagerBin,\r
1324 BootMaintenanceManagerUiLibStrings,\r
1325 NULL\r
1326 );\r
1327 ASSERT (mBmmCallbackInfo->BmmHiiHandle != NULL);\r
1328\r
1329 //\r
1330 // Locate Formbrowser2 protocol\r
1331 //\r
1332 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2);\r
1333 ASSERT_EFI_ERROR (Status);\r
1334\r
1335 EfiBootManagerRefreshAllBootOption ();\r
1336\r
1337 //\r
1338 // Create LoadOption in BmmCallbackInfo for Driver Callback\r
1339 //\r
1340 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
1341 ASSERT (Ptr != NULL);\r
1342\r
1343 //\r
1344 // Initialize Bmm callback data.\r
1345 //\r
1346 mBmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
1347 Ptr += sizeof (BM_LOAD_CONTEXT);\r
1348\r
1349 mBmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
1350 Ptr += sizeof (BM_FILE_CONTEXT);\r
1351\r
1352 mBmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
1353 Ptr += sizeof (BM_HANDLE_CONTEXT);\r
1354\r
1355 mBmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;\r
1356\r
1357 mBmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;\r
1358 mBmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;\r
1359\r
1360 InitAllMenu (mBmmCallbackInfo);\r
1361\r
1362 CreateUpdateData();\r
1363 //\r
1364 // Update boot maintenance manager page \r
1365 //\r
1366 InitializeBmmConfig(mBmmCallbackInfo);\r
1367\r
1368 return EFI_SUCCESS;\r
1369}\r
1370\r
1371/**\r
1372 Unloads the application and its installed protocol.\r
1373\r
1374 @param ImageHandle Handle that identifies the image to be unloaded.\r
1375 @param SystemTable The system table.\r
1376\r
1377 @retval EFI_SUCCESS The image has been unloaded.\r
1378\r
1379**/\r
1380EFI_STATUS\r
1381EFIAPI\r
1382BootMaintenanceManagerUiLibDestructor (\r
1383 IN EFI_HANDLE ImageHandle,\r
1384 IN EFI_SYSTEM_TABLE *SystemTable\r
1385 )\r
1386\r
1387{\r
1388 if (mStartOpCodeHandle != NULL) {\r
1389 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
1390 }\r
1391\r
1392 if (mEndOpCodeHandle != NULL) {\r
1393 HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
1394 }\r
1395\r
1396 FreeAllMenu ();\r
1397\r
1398 //\r
1399 // Remove our IFR data from HII database\r
1400 //\r
1401 HiiRemovePackages (mBmmCallbackInfo->BmmHiiHandle);\r
1402\r
1403 gBS->UninstallMultipleProtocolInterfaces (\r
1404 mBmmCallbackInfo->BmmDriverHandle,\r
1405 &gEfiDevicePathProtocolGuid,\r
1406 &mBmmHiiVendorDevicePath,\r
1407 &gEfiHiiConfigAccessProtocolGuid,\r
1408 &mBmmCallbackInfo->BmmConfigAccess,\r
1409 NULL\r
1410 );\r
1411\r
1412 FreePool (mBmmCallbackInfo->LoadContext);\r
1413\r
1414 return EFI_SUCCESS;\r
1415}\r
1416\r