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