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