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