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