]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / BootMaint.c
1 /** @file
2 The functions for Boot Maintainence Main menu.
3
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "BootMaint.h"
10 #include "FormGuid.h"
11 #include "Bds.h"
12 #include "FrontPage.h"
13
14 EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
15 {
16 END_DEVICE_PATH_TYPE,
17 END_ENTIRE_DEVICE_PATH_SUBTYPE,
18 {
19 END_DEVICE_PATH_LENGTH,
20 0
21 }
22 }
23 };
24
25 HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = {
26 {
27 {
28 HARDWARE_DEVICE_PATH,
29 HW_VENDOR_DP,
30 {
31 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
32 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
33 }
34 },
35 BOOT_MAINT_FORMSET_GUID
36 },
37 {
38 END_DEVICE_PATH_TYPE,
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,
40 {
41 (UINT8) (END_DEVICE_PATH_LENGTH),
42 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
43 }
44 }
45 };
46
47 HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = {
48 {
49 {
50 HARDWARE_DEVICE_PATH,
51 HW_VENDOR_DP,
52 {
53 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
54 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
55 }
56 },
57 FILE_EXPLORE_FORMSET_GUID
58 },
59 {
60 END_DEVICE_PATH_TYPE,
61 END_ENTIRE_DEVICE_PATH_SUBTYPE,
62 {
63 (UINT8) (END_DEVICE_PATH_LENGTH),
64 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
65 }
66 }
67 };
68
69 CHAR16 mBootMaintStorageName[] = L"BmmData";
70 CHAR16 mFileExplorerStorageName[] = L"FeData";
71 BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL;
72
73 /**
74 Init all memu.
75
76 @param CallbackData The BMM context data.
77
78 **/
79 VOID
80 InitAllMenu (
81 IN BMM_CALLBACK_DATA *CallbackData
82 );
83
84 /**
85 Free up all Menu Option list.
86
87 **/
88 VOID
89 FreeAllMenu (
90 VOID
91 );
92
93 /**
94 Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member
95 in BMM context data and create all of dynamic OP code for BMM.
96
97 @param CallbackData The BMM context data.
98
99 **/
100 VOID
101 InitializeBmmConfig (
102 IN BMM_CALLBACK_DATA *CallbackData
103 )
104 {
105 BM_MENU_ENTRY *NewMenuEntry;
106 BM_LOAD_CONTEXT *NewLoadContext;
107 UINT16 Index;
108
109 ASSERT (CallbackData != NULL);
110
111 //
112 // Initialize data which located in BMM main page
113 //
114 CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
115 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
116 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
117 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
118
119 if (NewLoadContext->IsBootNext) {
120 CallbackData->BmmFakeNvData.BootNext = Index;
121 break;
122 }
123 }
124
125 CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
126
127 //
128 // Initialize data which located in Boot Options Menu
129 //
130 GetBootOrder (CallbackData);
131 GetLegacyDeviceOrder (CallbackData);
132
133 //
134 // Initialize data which located in Driver Options Menu
135 //
136 GetDriverOrder (CallbackData);
137
138 //
139 // Initialize data which located in Console Options Menu
140 //
141 GetConsoleOutMode (CallbackData);
142 GetConsoleInCheck (CallbackData);
143 GetConsoleOutCheck (CallbackData);
144 GetConsoleErrCheck (CallbackData);
145 GetTerminalAttribute (CallbackData);
146
147 //
148 // Backup Initialize BMM configuartion data to BmmOldFakeNVData
149 //
150 CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));
151 }
152
153 /**
154 Create string tokens for a menu from its help strings and display strings
155
156 @param CallbackData The BMM context data.
157 @param HiiHandle Hii Handle of the package to be updated.
158 @param MenuOption The Menu whose string tokens need to be created
159
160 @retval EFI_SUCCESS String tokens created successfully
161 @retval others contain some errors
162 **/
163 EFI_STATUS
164 CreateMenuStringToken (
165 IN BMM_CALLBACK_DATA *CallbackData,
166 IN EFI_HII_HANDLE HiiHandle,
167 IN BM_MENU_OPTION *MenuOption
168 )
169 {
170 BM_MENU_ENTRY *NewMenuEntry;
171 UINTN Index;
172
173 for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
174 NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
175
176 NewMenuEntry->DisplayStringToken = HiiSetString (
177 HiiHandle,
178 0,
179 NewMenuEntry->DisplayString,
180 NULL
181 );
182
183 if (NULL == NewMenuEntry->HelpString) {
184 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
185 } else {
186 NewMenuEntry->HelpStringToken = HiiSetString (
187 HiiHandle,
188 0,
189 NewMenuEntry->HelpString,
190 NULL
191 );
192 }
193 }
194
195 return EFI_SUCCESS;
196 }
197
198 /**
199 This function allows a caller to extract the current configuration for one
200 or more named elements from the target driver.
201
202
203 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
204 @param Request A null-terminated Unicode string in <ConfigRequest> format.
205 @param Progress On return, points to a character in the Request string.
206 Points to the string's null terminator if request was successful.
207 Points to the most recent '&' before the first failing name/value
208 pair (or the beginning of the string if the failure is in the
209 first name/value pair) if the request was not successful.
210 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
211 has all values filled in for the names in the Request string.
212 String to be allocated by the called function.
213
214 @retval EFI_SUCCESS The Results is filled with the requested values.
215 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
216 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
217 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 BootMaintExtractConfig (
223 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
224 IN CONST EFI_STRING Request,
225 OUT EFI_STRING *Progress,
226 OUT EFI_STRING *Results
227 )
228 {
229 EFI_STATUS Status;
230 UINTN BufferSize;
231 BMM_CALLBACK_DATA *Private;
232 EFI_STRING ConfigRequestHdr;
233 EFI_STRING ConfigRequest;
234 BOOLEAN AllocatedRequest;
235 UINTN Size;
236
237 if (Progress == NULL || Results == NULL) {
238 return EFI_INVALID_PARAMETER;
239 }
240
241 *Progress = Request;
242 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) {
243 return EFI_NOT_FOUND;
244 }
245
246 ConfigRequestHdr = NULL;
247 ConfigRequest = NULL;
248 AllocatedRequest = FALSE;
249 Size = 0;
250
251 Private = BMM_CALLBACK_DATA_FROM_THIS (This);
252 //
253 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
254 //
255 BufferSize = sizeof (BMM_FAKE_NV_DATA);
256 ConfigRequest = Request;
257 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
258 //
259 // Request has no request element, construct full request string.
260 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
261 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
262 //
263 ConfigRequestHdr = HiiConstructConfigHdr (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle);
264 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
265 ConfigRequest = AllocateZeroPool (Size);
266 ASSERT (ConfigRequest != NULL);
267 AllocatedRequest = TRUE;
268 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
269 FreePool (ConfigRequestHdr);
270 }
271
272 Status = gHiiConfigRouting->BlockToConfig (
273 gHiiConfigRouting,
274 ConfigRequest,
275 (UINT8 *) &Private->BmmFakeNvData,
276 BufferSize,
277 Results,
278 Progress
279 );
280 //
281 // Free the allocated config request string.
282 //
283 if (AllocatedRequest) {
284 FreePool (ConfigRequest);
285 ConfigRequest = NULL;
286 }
287 //
288 // Set Progress string to the original request string.
289 //
290 if (Request == NULL) {
291 *Progress = NULL;
292 } else if (StrStr (Request, L"OFFSET") == NULL) {
293 *Progress = Request + StrLen (Request);
294 }
295
296 return Status;
297 }
298
299 /**
300 This function applies changes in a driver's configuration.
301 Input is a Configuration, which has the routing data for this
302 driver followed by name / value configuration pairs. The driver
303 must apply those pairs to its configurable storage. If the
304 driver's configuration is stored in a linear block of data
305 and the driver's name / value pairs are in <BlockConfig>
306 format, it may use the ConfigToBlock helper function (above) to
307 simplify the job. Currently not implemented.
308
309 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
310 @param[in] Configuration A null-terminated Unicode string in
311 <ConfigString> format.
312 @param[out] Progress A pointer to a string filled in with the
313 offset of the most recent '&' before the
314 first failing name / value pair (or the
315 beginn ing of the string if the failure
316 is in the first name / value pair) or
317 the terminating NULL if all was
318 successful.
319
320 @retval EFI_SUCCESS The results have been distributed or are
321 awaiting distribution.
322 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
323 parts of the results that must be
324 stored awaiting possible future
325 protocols.
326 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
327 Results parameter would result
328 in this type of error.
329 @retval EFI_NOT_FOUND Target for the specified routing data
330 was not found.
331 **/
332 EFI_STATUS
333 EFIAPI
334 BootMaintRouteConfig (
335 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
336 IN CONST EFI_STRING Configuration,
337 OUT EFI_STRING *Progress
338 )
339 {
340 EFI_STATUS Status;
341 UINTN BufferSize;
342 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
343 BMM_FAKE_NV_DATA *NewBmmData;
344 BMM_FAKE_NV_DATA *OldBmmData;
345 BM_CONSOLE_CONTEXT *NewConsoleContext;
346 BM_TERMINAL_CONTEXT *NewTerminalContext;
347 BM_MENU_ENTRY *NewMenuEntry;
348 BM_LOAD_CONTEXT *NewLoadContext;
349 UINT16 Index;
350 BOOLEAN TerminalAttChange;
351 BMM_CALLBACK_DATA *Private;
352
353 if (Progress == NULL) {
354 return EFI_INVALID_PARAMETER;
355 }
356 *Progress = Configuration;
357
358 if (Configuration == NULL) {
359 return EFI_INVALID_PARAMETER;
360 }
361
362 //
363 // Check routing data in <ConfigHdr>.
364 // Note: there is no name for Name/Value storage, only GUID will be checked
365 //
366 if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) {
367 return EFI_NOT_FOUND;
368 }
369
370 Status = gBS->LocateProtocol (
371 &gEfiHiiConfigRoutingProtocolGuid,
372 NULL,
373 (VOID**) &ConfigRouting
374 );
375 if (EFI_ERROR (Status)) {
376 return Status;
377 }
378
379 Private = BMM_CALLBACK_DATA_FROM_THIS (This);
380 //
381 // Get Buffer Storage data from EFI variable
382 //
383 BufferSize = sizeof (BMM_FAKE_NV_DATA);
384 OldBmmData = &Private->BmmOldFakeNVData;
385 NewBmmData = &Private->BmmFakeNvData;
386 //
387 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
388 //
389 Status = ConfigRouting->ConfigToBlock (
390 ConfigRouting,
391 Configuration,
392 (UINT8 *) NewBmmData,
393 &BufferSize,
394 Progress
395 );
396 ASSERT_EFI_ERROR (Status);
397 //
398 // Compare new and old BMM configuration data and only do action for modified item to
399 // avoid setting unnecessary non-volatile variable
400 //
401
402 //
403 // Check data which located in BMM main page and save the settings if need
404 //
405 if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) {
406 Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID);
407 }
408
409 if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) {
410 Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID);
411 }
412
413 if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) {
414 Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID);
415 }
416
417 if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) {
418 Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID);
419 }
420
421 if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) {
422 Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID);
423 }
424
425 //
426 // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process
427 // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel
428 //
429 if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {
430 Status = Var_UpdateBootOrder (Private);
431 }
432
433 //
434 // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process
435 // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel
436 //
437 if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {
438 Status = Var_UpdateDriverOrder (Private);
439 }
440
441 //
442 // Check data which located in Boot Options Menu and save the settings if need
443 //
444 if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) {
445 for (Index = 0;
446 ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0]))));
447 Index ++) {
448 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
449 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
450 NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index];
451 NewBmmData->BootOptionDel[Index] = FALSE;
452 NewBmmData->BootOptionDelMark[Index] = FALSE;
453 }
454
455 Var_DelBootOption ();
456 }
457
458 //
459 // Check data which located in Driver Options Menu and save the settings if need
460 //
461 if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) {
462 for (Index = 0;
463 ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0]))));
464 Index++) {
465 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
466 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
467 NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index];
468 NewBmmData->DriverOptionDel[Index] = FALSE;
469 NewBmmData->DriverOptionDelMark[Index] = FALSE;
470 }
471 Var_DelDriverOption ();
472 }
473
474 if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) {
475 Status = gRT->SetVariable (
476 L"Timeout",
477 &gEfiGlobalVariableGuid,
478 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
479 sizeof (UINT16),
480 &(NewBmmData->BootTimeOut)
481 );
482 ASSERT_EFI_ERROR(Status);
483
484 //
485 // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check.
486 //
487 Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut;
488 }
489
490 if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) {
491 Status = Var_UpdateBootNext (Private);
492 }
493
494 if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) {
495 Var_UpdateConMode (Private);
496 }
497
498 TerminalAttChange = FALSE;
499 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
500
501 //
502 // only need update modified items
503 //
504 if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 &&
505 CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 &&
506 CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 &&
507 CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 &&
508 CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 &&
509 CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) {
510 continue;
511 }
512
513 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
514 ASSERT (NewMenuEntry != NULL);
515 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
516 NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index];
517 ASSERT (NewBmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList)));
518 NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value;
519 NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index];
520 ASSERT (NewBmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList)));
521 NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value;
522 NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index];
523 ASSERT (NewBmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList)));
524 NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value;
525 NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index];
526 ASSERT (NewBmmData->COMParity[Index] < (ARRAY_SIZE (ParityList)));
527 NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value;
528 NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index];
529 NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index];
530 ChangeTerminalDevicePath (
531 &(NewTerminalContext->DevicePath),
532 FALSE
533 );
534 TerminalAttChange = TRUE;
535 }
536 if (TerminalAttChange) {
537 Var_UpdateConsoleInpOption ();
538 Var_UpdateConsoleOutOption ();
539 Var_UpdateErrorOutOption ();
540 }
541
542 //
543 // Check data which located in Console Options Menu and save the settings if need
544 //
545 if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) {
546 for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {
547 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
548 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
549 ASSERT (Index < MAX_MENU_NUMBER);
550 NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index];
551 }
552
553 Var_UpdateConsoleInpOption ();
554 }
555
556 if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) {
557 for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {
558 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
559 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
560 ASSERT (Index < MAX_MENU_NUMBER);
561 NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index];
562 }
563
564 Var_UpdateConsoleOutOption ();
565 }
566
567 if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) {
568 for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {
569 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
570 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
571 ASSERT (Index < MAX_MENU_NUMBER);
572 NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index];
573 }
574
575 Var_UpdateErrorOutOption ();
576 }
577
578 //
579 // After user do the save action, need to update OldBmmData.
580 //
581 CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));
582
583 return EFI_SUCCESS;
584 }
585
586 /**
587 Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option.
588
589 **/
590 EFI_STATUS
591 InitializeLegacyBootOption (
592 VOID
593 )
594 {
595 RefreshUpdateData ();
596 mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID;
597
598 //
599 // If LegacyBios Protocol is installed, add 3 tags about legacy boot option
600 // in BootOption form: legacy FD/HD/CD/NET/BEV
601 //
602 HiiCreateGotoOpCode (
603 mStartOpCodeHandle,
604 FORM_SET_FD_ORDER_ID,
605 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
606 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
607 EFI_IFR_FLAG_CALLBACK,
608 FORM_SET_FD_ORDER_ID
609 );
610
611 HiiCreateGotoOpCode (
612 mStartOpCodeHandle,
613 FORM_SET_HD_ORDER_ID,
614 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
615 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
616 EFI_IFR_FLAG_CALLBACK,
617 FORM_SET_HD_ORDER_ID
618 );
619
620 HiiCreateGotoOpCode (
621 mStartOpCodeHandle,
622 FORM_SET_CD_ORDER_ID,
623 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
624 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
625 EFI_IFR_FLAG_CALLBACK,
626 FORM_SET_CD_ORDER_ID
627 );
628
629 HiiCreateGotoOpCode (
630 mStartOpCodeHandle,
631 FORM_SET_NET_ORDER_ID,
632 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
633 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
634 EFI_IFR_FLAG_CALLBACK,
635 FORM_SET_NET_ORDER_ID
636 );
637
638 HiiCreateGotoOpCode (
639 mStartOpCodeHandle,
640 FORM_SET_BEV_ORDER_ID,
641 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
642 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
643 EFI_IFR_FLAG_CALLBACK,
644 FORM_SET_BEV_ORDER_ID
645 );
646
647 HiiUpdateForm (
648 mBmmCallbackInfo->BmmHiiHandle,
649 &gBootMaintFormSetGuid,
650 FORM_BOOT_SETUP_ID,
651 mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID
652 mEndOpCodeHandle // LABEL_END
653 );
654
655 return EFI_SUCCESS;
656 }
657
658 /**
659 This function processes the results of changes in configuration.
660
661
662 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
663 @param Action Specifies the type of action taken by the browser.
664 @param QuestionId A unique value which is sent to the original exporting driver
665 so that it can identify the type of data to expect.
666 @param Type The type of value for the question.
667 @param Value A pointer to the data being sent to the original exporting driver.
668 @param ActionRequest On return, points to the action requested by the callback function.
669
670 @retval EFI_SUCCESS The callback successfully handled the action.
671 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
672 @retval EFI_DEVICE_ERROR The variable could not be saved.
673 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
674 @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.
675 **/
676 EFI_STATUS
677 EFIAPI
678 BootMaintCallback (
679 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
680 IN EFI_BROWSER_ACTION Action,
681 IN EFI_QUESTION_ID QuestionId,
682 IN UINT8 Type,
683 IN EFI_IFR_TYPE_VALUE *Value,
684 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
685 )
686 {
687 BMM_CALLBACK_DATA *Private;
688 BM_MENU_ENTRY *NewMenuEntry;
689 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
690 EFI_STATUS Status;
691 UINTN OldValue;
692 UINTN NewValue;
693 UINTN Number;
694 UINTN Pos;
695 UINTN Bit;
696 UINT16 NewValuePos;
697 UINT16 Index3;
698 UINT16 Index2;
699 UINT16 Index;
700 UINT8 *OldLegacyDev;
701 UINT8 *NewLegacyDev;
702 UINT8 *DisMap;
703 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
704
705 Private = BMM_CALLBACK_DATA_FROM_THIS (This);
706 if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) {
707 //
708 // Initilize Form for legacy boot option.
709 //
710 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
711 if (!EFI_ERROR (Status)) {
712 InitializeLegacyBootOption ();
713 }
714
715 return EFI_SUCCESS;
716 }
717
718 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
719 //
720 // All other action return unsupported.
721 //
722 return EFI_UNSUPPORTED;
723 }
724
725 Status = EFI_SUCCESS;
726 OldValue = 0;
727 NewValue = 0;
728 Number = 0;
729 OldLegacyDev = NULL;
730 NewLegacyDev = NULL;
731 NewValuePos = 0;
732 DisMap = NULL;
733
734 Private = BMM_CALLBACK_DATA_FROM_THIS (This);
735 //
736 // Retrieve uncommitted data from Form Browser
737 //
738 CurrentFakeNVMap = &Private->BmmFakeNvData;
739 HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);
740 if (Action == EFI_BROWSER_ACTION_CHANGING) {
741 if (Value == NULL) {
742 return EFI_INVALID_PARAMETER;
743 }
744
745 UpdatePageId (Private, QuestionId);
746
747 if (QuestionId < FILE_OPTION_OFFSET) {
748 if (QuestionId < CONFIG_OPTION_OFFSET) {
749 switch (QuestionId) {
750 case KEY_VALUE_BOOT_FROM_FILE:
751 Private->FeCurrentState = FileExplorerStateBootFromFile;
752 break;
753
754 case FORM_BOOT_ADD_ID:
755 Private->FeCurrentState = FileExplorerStateAddBootOption;
756 break;
757
758 case FORM_DRV_ADD_FILE_ID:
759 Private->FeCurrentState = FileExplorerStateAddDriverOptionState;
760 break;
761
762 case FORM_DRV_ADD_HANDLE_ID:
763 CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);
764 UpdateDrvAddHandlePage (Private);
765 break;
766
767 case FORM_BOOT_DEL_ID:
768 CleanUpPage (FORM_BOOT_DEL_ID, Private);
769 UpdateBootDelPage (Private);
770 break;
771
772 case FORM_BOOT_CHG_ID:
773 case FORM_DRV_CHG_ID:
774 UpdatePageBody (QuestionId, Private);
775 break;
776
777 case FORM_DRV_DEL_ID:
778 CleanUpPage (FORM_DRV_DEL_ID, Private);
779 UpdateDrvDelPage (Private);
780 break;
781
782 case FORM_BOOT_NEXT_ID:
783 CleanUpPage (FORM_BOOT_NEXT_ID, Private);
784 UpdateBootNextPage (Private);
785 break;
786
787 case FORM_TIME_OUT_ID:
788 CleanUpPage (FORM_TIME_OUT_ID, Private);
789 UpdateTimeOutPage (Private);
790 break;
791
792 case FORM_CON_IN_ID:
793 case FORM_CON_OUT_ID:
794 case FORM_CON_ERR_ID:
795 UpdatePageBody (QuestionId, Private);
796 break;
797
798 case FORM_CON_MODE_ID:
799 CleanUpPage (FORM_CON_MODE_ID, Private);
800 UpdateConModePage (Private);
801 break;
802
803 case FORM_CON_COM_ID:
804 CleanUpPage (FORM_CON_COM_ID, Private);
805 UpdateConCOMPage (Private);
806 break;
807
808 case FORM_SET_FD_ORDER_ID:
809 case FORM_SET_HD_ORDER_ID:
810 case FORM_SET_CD_ORDER_ID:
811 case FORM_SET_NET_ORDER_ID:
812 case FORM_SET_BEV_ORDER_ID:
813 CleanUpPage (QuestionId, Private);
814 UpdateSetLegacyDeviceOrderPage (QuestionId, Private);
815 break;
816
817 default:
818 break;
819 }
820 } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {
821 Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);
822 Private->CurrentTerminal = Index2;
823
824 CleanUpPage (FORM_CON_COM_SETUP_ID, Private);
825 UpdateTerminalPage (Private);
826
827 } else if (QuestionId >= HANDLE_OPTION_OFFSET) {
828 Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);
829
830 NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2);
831 ASSERT (NewMenuEntry != NULL);
832 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
833
834 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);
835
836 Private->MenuEntry = NewMenuEntry;
837 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;
838
839 UpdateDriverAddHandleDescPage (Private);
840 }
841 }
842 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
843 if ((Value == NULL) || (ActionRequest == NULL)) {
844 return EFI_INVALID_PARAMETER;
845 }
846 if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
847 if (Value->b){
848 //
849 // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.
850 //
851 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE;
852 } else {
853 //
854 // Means user remove the old check status.
855 //
856 CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE;
857 }
858 } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
859 if (Value->b){
860 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE;
861 } else {
862 CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE;
863 }
864 } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) {
865 //
866 // Update Select FD/HD/CD/NET/BEV Order Form
867 //
868
869 DisMap = Private->BmmOldFakeNVData.DisableMap;
870
871 if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) {
872 Number = (UINT16) LegacyFDMenu.MenuNumber;
873 OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD;
874 NewLegacyDev = CurrentFakeNVMap->LegacyFD;
875 } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) {
876 Number = (UINT16) LegacyHDMenu.MenuNumber;
877 OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD;
878 NewLegacyDev = CurrentFakeNVMap->LegacyHD;
879 } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) {
880 Number = (UINT16) LegacyCDMenu.MenuNumber;
881 OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD;
882 NewLegacyDev = CurrentFakeNVMap->LegacyCD;
883 } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) {
884 Number = (UINT16) LegacyNETMenu.MenuNumber;
885 OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET;
886 NewLegacyDev = CurrentFakeNVMap->LegacyNET;
887 } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) {
888 Number = (UINT16) LegacyBEVMenu.MenuNumber;
889 OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV;
890 NewLegacyDev = CurrentFakeNVMap->LegacyBEV;
891 }
892 //
893 // First, find the different position
894 // if there is change, it should be only one
895 //
896 for (Index = 0; Index < Number; Index++) {
897 if (OldLegacyDev[Index] != NewLegacyDev[Index]) {
898 OldValue = OldLegacyDev[Index];
899 NewValue = NewLegacyDev[Index];
900 break;
901 }
902 }
903
904 if (Index != Number) {
905 //
906 // there is change, now process
907 //
908 if (0xFF == NewValue) {
909 //
910 // This item will be disable
911 // Just move the items behind this forward to overlap it
912 //
913 Pos = OldValue / 8;
914 Bit = 7 - (OldValue % 8);
915 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
916 for (Index2 = Index; Index2 < Number - 1; Index2++) {
917 NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];
918 }
919
920 NewLegacyDev[Index2] = 0xFF;
921 } else {
922 for (Index2 = 0; Index2 < Number; Index2++) {
923 if (Index2 == Index) {
924 continue;
925 }
926
927 if (OldLegacyDev[Index2] == NewValue) {
928 //
929 // If NewValue is in OldLegacyDev array
930 // remember its old position
931 //
932 NewValuePos = Index2;
933 break;
934 }
935 }
936
937 if (Index2 != Number) {
938 //
939 // We will change current item to an existing item
940 // (It's hard to describe here, please read code, it's like a cycle-moving)
941 //
942 for (Index2 = NewValuePos; Index2 != Index;) {
943 if (NewValuePos < Index) {
944 NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];
945 Index2++;
946 } else {
947 NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];
948 Index2--;
949 }
950 }
951 } else {
952 //
953 // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
954 // so we should modify DisMap to reflect the change
955 //
956 Pos = NewValue / 8;
957 Bit = 7 - (NewValue % 8);
958 DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
959 if (0xFF != OldValue) {
960 //
961 // Because NewValue is a item that was disabled before
962 // so after changing the OldValue should be disabled
963 // actually we are doing a swap of enable-disable states of two items
964 //
965 Pos = OldValue / 8;
966 Bit = 7 - (OldValue % 8);
967 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
968 }
969 }
970 }
971 //
972 // To prevent DISABLE appears in the middle of the list
973 // we should perform a re-ordering
974 //
975 Index3 = Index;
976 Index = 0;
977 while (Index < Number) {
978 if (0xFF != NewLegacyDev[Index]) {
979 Index++;
980 continue;
981 }
982
983 Index2 = Index;
984 Index2++;
985 while (Index2 < Number) {
986 if (0xFF != NewLegacyDev[Index2]) {
987 break;
988 }
989
990 Index2++;
991 }
992
993 if (Index2 < Number) {
994 NewLegacyDev[Index] = NewLegacyDev[Index2];
995 NewLegacyDev[Index2] = 0xFF;
996 }
997
998 Index++;
999 }
1000
1001 //
1002 // Return correct question value.
1003 //
1004 Value->u8 = NewLegacyDev[Index3];
1005 }
1006 } else {
1007 switch (QuestionId) {
1008 case KEY_VALUE_SAVE_AND_EXIT:
1009 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1010 break;
1011
1012 case KEY_VALUE_NO_SAVE_AND_EXIT:
1013 //
1014 // Restore local maintain data.
1015 //
1016 DiscardChangeHandler (Private, CurrentFakeNVMap);
1017 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1018 break;
1019
1020 case FORM_RESET:
1021 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1022 return EFI_UNSUPPORTED;
1023
1024 default:
1025 break;
1026 }
1027 }
1028 }
1029
1030 //
1031 // Pass changed uncommitted data back to Form Browser
1032 //
1033 HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL);
1034 return EFI_SUCCESS;
1035 }
1036
1037 /**
1038 Discard all changes done to the BMM pages such as Boot Order change,
1039 Driver order change.
1040
1041 @param Private The BMM context data.
1042 @param CurrentFakeNVMap The current Fack NV Map.
1043
1044 **/
1045 VOID
1046 DiscardChangeHandler (
1047 IN BMM_CALLBACK_DATA *Private,
1048 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap
1049 )
1050 {
1051 UINT16 Index;
1052
1053 switch (Private->BmmPreviousPageId) {
1054 case FORM_BOOT_CHG_ID:
1055 CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder));
1056 break;
1057
1058 case FORM_DRV_CHG_ID:
1059 CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder));
1060 break;
1061
1062 case FORM_BOOT_DEL_ID:
1063 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));
1064 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
1065 CurrentFakeNVMap->BootOptionDel[Index] = FALSE;
1066 CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE;
1067 }
1068 break;
1069
1070 case FORM_DRV_DEL_ID:
1071 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));
1072 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
1073 CurrentFakeNVMap->DriverOptionDel[Index] = FALSE;
1074 CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE;
1075 }
1076 break;
1077
1078 case FORM_BOOT_NEXT_ID:
1079 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;
1080 break;
1081
1082 case FORM_TIME_OUT_ID:
1083 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;
1084 break;
1085
1086 case FORM_DRV_ADD_HANDLE_DESC_ID:
1087 case FORM_DRV_ADD_FILE_ID:
1088 case FORM_DRV_ADD_HANDLE_ID:
1089 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;
1090 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;
1091 break;
1092
1093 default:
1094 break;
1095 }
1096 }
1097
1098 /**
1099 Initialize the Boot Maintenance Utitliy.
1100
1101
1102 @retval EFI_SUCCESS utility ended successfully
1103 @retval others contain some errors
1104
1105 **/
1106 EFI_STATUS
1107 InitializeBM (
1108 VOID
1109 )
1110 {
1111 BMM_CALLBACK_DATA *BmmCallbackInfo;
1112 EFI_STATUS Status;
1113 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
1114 UINT32 Length;
1115 UINT8 *Data;
1116
1117 Status = EFI_SUCCESS;
1118 BmmCallbackInfo = mBmmCallbackInfo;
1119
1120 BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;
1121 BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;
1122 BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive;
1123 BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown;
1124
1125 //
1126 // Reinstall String packages to include more new strings.
1127 //
1128
1129 //
1130 // String package size
1131 //
1132 Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32);
1133
1134 //
1135 // Add the length of the Package List Header and the terminating Package Header
1136 //
1137 Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);
1138
1139 //
1140 // Allocate the storage for the entire Package List
1141 //
1142 PackageListHeader = AllocateZeroPool (Length);
1143
1144 //
1145 // If the Package List can not be allocated, then return a NULL HII Handle
1146 //
1147 if (PackageListHeader == NULL) {
1148 return EFI_OUT_OF_RESOURCES;
1149 }
1150
1151 //
1152 // Fill in the GUID and Length of the Package List Header
1153 //
1154 PackageListHeader->PackageLength = Length;
1155
1156 //
1157 // Copy String Data into Package list.
1158 //
1159 Data = (UINT8 *)(PackageListHeader + 1);
1160 Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32);
1161 CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length);
1162
1163 //
1164 // Add End type HII package.
1165 //
1166 Data += Length;
1167 ((EFI_HII_PACKAGE_HEADER *) Data)->Type = EFI_HII_PACKAGE_END;
1168 ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER);
1169
1170 //
1171 // Update String package for BM
1172 //
1173 CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid);
1174 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader);
1175
1176 //
1177 // Update String package for FE.
1178 //
1179 CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid);
1180 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader);
1181
1182 FreePool (PackageListHeader);
1183
1184 //
1185 // Init OpCode Handle and Allocate space for creation of Buffer
1186 //
1187 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
1188 if (mStartOpCodeHandle == NULL) {
1189 Status = EFI_OUT_OF_RESOURCES;
1190 goto Exit;
1191 }
1192
1193 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
1194 if (mEndOpCodeHandle == NULL) {
1195 Status = EFI_OUT_OF_RESOURCES;
1196 goto Exit;
1197 }
1198
1199 //
1200 // Create Hii Extend Label OpCode as the start opcode
1201 //
1202 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1203 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1204
1205 //
1206 // Create Hii Extend Label OpCode as the end opcode
1207 //
1208 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1209 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1210 mEndLabel->Number = LABEL_END;
1211
1212 InitializeStringDepository ();
1213
1214 InitAllMenu (BmmCallbackInfo);
1215
1216 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);
1217 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);
1218 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);
1219 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);
1220 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);
1221 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);
1222 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);
1223
1224 InitializeBmmConfig (BmmCallbackInfo);
1225
1226 //
1227 // Dispatch BMM main formset and File Explorer formset.
1228 //
1229 FormSetDispatcher (BmmCallbackInfo);
1230
1231 //
1232 // Clean up.
1233 //
1234 CleanUpStringDepository ();
1235
1236 FreeAllMenu ();
1237
1238 Exit:
1239 if (mStartOpCodeHandle != NULL) {
1240 HiiFreeOpCodeHandle (mStartOpCodeHandle);
1241 }
1242
1243 if (mEndOpCodeHandle != NULL) {
1244 HiiFreeOpCodeHandle (mEndOpCodeHandle);
1245 }
1246
1247 return Status;
1248 }
1249
1250
1251 /**
1252 Initialized all Menu Option List.
1253
1254 @param CallbackData The BMM context data.
1255
1256 **/
1257 VOID
1258 InitAllMenu (
1259 IN BMM_CALLBACK_DATA *CallbackData
1260 )
1261 {
1262 InitializeListHead (&BootOptionMenu.Head);
1263 InitializeListHead (&DriverOptionMenu.Head);
1264 BOpt_GetBootOptions (CallbackData);
1265 BOpt_GetDriverOptions (CallbackData);
1266 BOpt_GetLegacyOptions ();
1267 InitializeListHead (&FsOptionMenu.Head);
1268 BOpt_FindDrivers ();
1269 InitializeListHead (&DirectoryMenu.Head);
1270 InitializeListHead (&ConsoleInpMenu.Head);
1271 InitializeListHead (&ConsoleOutMenu.Head);
1272 InitializeListHead (&ConsoleErrMenu.Head);
1273 InitializeListHead (&TerminalMenu.Head);
1274 LocateSerialIo ();
1275 GetAllConsoles ();
1276 }
1277
1278 /**
1279 Free up all Menu Option list.
1280
1281 **/
1282 VOID
1283 FreeAllMenu (
1284 VOID
1285 )
1286 {
1287 BOpt_FreeMenu (&DirectoryMenu);
1288 BOpt_FreeMenu (&FsOptionMenu);
1289 BOpt_FreeMenu (&BootOptionMenu);
1290 BOpt_FreeMenu (&DriverOptionMenu);
1291 BOpt_FreeMenu (&DriverMenu);
1292 BOpt_FreeLegacyOptions ();
1293 FreeAllConsoles ();
1294 }
1295
1296 /**
1297 Initialize all the string depositories.
1298
1299 **/
1300 VOID
1301 InitializeStringDepository (
1302 VOID
1303 )
1304 {
1305 STRING_DEPOSITORY *StringDepository;
1306 StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);
1307 FileOptionStrDepository = StringDepository++;
1308 ConsoleOptionStrDepository = StringDepository++;
1309 BootOptionStrDepository = StringDepository++;
1310 BootOptionHelpStrDepository = StringDepository++;
1311 DriverOptionStrDepository = StringDepository++;
1312 DriverOptionHelpStrDepository = StringDepository++;
1313 TerminalStrDepository = StringDepository;
1314 }
1315
1316 /**
1317 Fetch a usable string node from the string depository and return the string token.
1318
1319 @param CallbackData The BMM context data.
1320 @param StringDepository The string repository.
1321
1322 @retval EFI_STRING_ID String token.
1323
1324 **/
1325 EFI_STRING_ID
1326 GetStringTokenFromDepository (
1327 IN BMM_CALLBACK_DATA *CallbackData,
1328 IN STRING_DEPOSITORY *StringDepository
1329 )
1330 {
1331 STRING_LIST_NODE *CurrentListNode;
1332 STRING_LIST_NODE *NextListNode;
1333
1334 CurrentListNode = StringDepository->CurrentNode;
1335
1336 if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {
1337 //
1338 // Fetch one reclaimed node from the list.
1339 //
1340 NextListNode = StringDepository->CurrentNode->Next;
1341 } else {
1342 //
1343 // If there is no usable node in the list, update the list.
1344 //
1345 NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));
1346 ASSERT (NextListNode != NULL);
1347 NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL);
1348 ASSERT (NextListNode->StringToken != 0);
1349
1350 StringDepository->TotalNodeNumber++;
1351
1352 if (NULL == CurrentListNode) {
1353 StringDepository->ListHead = NextListNode;
1354 } else {
1355 CurrentListNode->Next = NextListNode;
1356 }
1357 }
1358
1359 StringDepository->CurrentNode = NextListNode;
1360
1361 return StringDepository->CurrentNode->StringToken;
1362 }
1363
1364 /**
1365 Reclaim string depositories by moving the current node pointer to list head..
1366
1367 **/
1368 VOID
1369 ReclaimStringDepository (
1370 VOID
1371 )
1372 {
1373 UINTN DepositoryIndex;
1374 STRING_DEPOSITORY *StringDepository;
1375
1376 StringDepository = FileOptionStrDepository;
1377 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
1378 StringDepository->CurrentNode = StringDepository->ListHead;
1379 StringDepository++;
1380 }
1381 }
1382
1383 /**
1384 Release resource for all the string depositories.
1385
1386 **/
1387 VOID
1388 CleanUpStringDepository (
1389 VOID
1390 )
1391 {
1392 UINTN NodeIndex;
1393 UINTN DepositoryIndex;
1394 STRING_LIST_NODE *CurrentListNode;
1395 STRING_LIST_NODE *NextListNode;
1396 STRING_DEPOSITORY *StringDepository;
1397
1398 //
1399 // Release string list nodes.
1400 //
1401 StringDepository = FileOptionStrDepository;
1402 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
1403 CurrentListNode = StringDepository->ListHead;
1404 for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {
1405 NextListNode = CurrentListNode->Next;
1406 FreePool (CurrentListNode);
1407 CurrentListNode = NextListNode;
1408 }
1409
1410 StringDepository++;
1411 }
1412 //
1413 // Release string depository.
1414 //
1415 FreePool (FileOptionStrDepository);
1416 }
1417
1418 /**
1419 Start boot maintenance manager
1420
1421 @retval EFI_SUCCESS If BMM is invoked successfully.
1422 @return Other value if BMM return unsuccessfully.
1423
1424 **/
1425 EFI_STATUS
1426 BdsStartBootMaint (
1427 VOID
1428 )
1429 {
1430 EFI_STATUS Status;
1431 LIST_ENTRY BdsBootOptionList;
1432
1433 InitializeListHead (&BdsBootOptionList);
1434
1435 //
1436 // Connect all prior to entering the platform setup menu.
1437 //
1438 if (!gConnectAllHappened) {
1439 BdsLibConnectAllDriversToAllControllers ();
1440 gConnectAllHappened = TRUE;
1441 }
1442 //
1443 // Have chance to enumerate boot device
1444 //
1445 BdsLibEnumerateAllBootOption (&BdsBootOptionList);
1446
1447 //
1448 // Group the legacy boot options for the same device type
1449 //
1450 GroupMultipleLegacyBootOption4SameType ();
1451
1452 //
1453 // Init the BMM
1454 //
1455 Status = InitializeBM ();
1456
1457 return Status;
1458 }
1459
1460 /**
1461 Dispatch BMM formset and FileExplorer formset.
1462
1463
1464 @param CallbackData The BMM context data.
1465
1466 @retval EFI_SUCCESS If function complete successfully.
1467 @return Other value if the Setup Browser process BMM's pages and
1468 return unsuccessfully.
1469
1470 **/
1471 EFI_STATUS
1472 FormSetDispatcher (
1473 IN BMM_CALLBACK_DATA *CallbackData
1474 )
1475 {
1476 EFI_STATUS Status;
1477 EFI_BROWSER_ACTION_REQUEST ActionRequest;
1478
1479 while (TRUE) {
1480 UpdatePageId (CallbackData, FORM_MAIN_ID);
1481
1482 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
1483 Status = gFormBrowser2->SendForm (
1484 gFormBrowser2,
1485 &CallbackData->BmmHiiHandle,
1486 1,
1487 &gBootMaintFormSetGuid,
1488 0,
1489 NULL,
1490 &ActionRequest
1491 );
1492 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
1493 EnableResetRequired ();
1494 }
1495
1496 ReclaimStringDepository ();
1497
1498 //
1499 // When this Formset returns, check if we are going to explore files.
1500 //
1501 if (FileExplorerStateInActive != CallbackData->FeCurrentState) {
1502 UpdateFileExplorer (CallbackData, 0);
1503
1504 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
1505 Status = gFormBrowser2->SendForm (
1506 gFormBrowser2,
1507 &CallbackData->FeHiiHandle,
1508 1,
1509 &gFileExploreFormSetGuid,
1510 0,
1511 NULL,
1512 &ActionRequest
1513 );
1514 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
1515 EnableResetRequired ();
1516 }
1517
1518 CallbackData->FeCurrentState = FileExplorerStateInActive;
1519 CallbackData->FeDisplayContext = FileExplorerDisplayUnknown;
1520 ReclaimStringDepository ();
1521 } else {
1522 break;
1523 }
1524 }
1525
1526 return Status;
1527 }
1528
1529 /**
1530 Intall BootMaint and FileExplorer HiiPackages.
1531
1532 **/
1533 EFI_STATUS
1534 InitBMPackage (
1535 VOID
1536 )
1537 {
1538 BMM_CALLBACK_DATA *BmmCallbackInfo;
1539 EFI_STATUS Status;
1540 UINT8 *Ptr;
1541
1542 //
1543 // Create CallbackData structures for Driver Callback
1544 //
1545 BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));
1546 if (BmmCallbackInfo == NULL) {
1547 return EFI_OUT_OF_RESOURCES;
1548 }
1549
1550 //
1551 // Create LoadOption in BmmCallbackInfo for Driver Callback
1552 //
1553 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));
1554 if (Ptr == NULL) {
1555 FreePool (BmmCallbackInfo);
1556 BmmCallbackInfo = NULL;
1557 return EFI_OUT_OF_RESOURCES;
1558 }
1559 //
1560 // Initialize Bmm callback data.
1561 //
1562 BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
1563 Ptr += sizeof (BM_LOAD_CONTEXT);
1564
1565 BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
1566 Ptr += sizeof (BM_FILE_CONTEXT);
1567
1568 BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
1569 Ptr += sizeof (BM_HANDLE_CONTEXT);
1570
1571 BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;
1572
1573 BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;
1574 BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;
1575 BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig;
1576 BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback;
1577 BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig;
1578 BmmCallbackInfo->FeConfigAccess.RouteConfig = FileExplorerRouteConfig;
1579 BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback;
1580
1581 //
1582 // Install Device Path Protocol and Config Access protocol to driver handle
1583 //
1584 Status = gBS->InstallMultipleProtocolInterfaces (
1585 &BmmCallbackInfo->BmmDriverHandle,
1586 &gEfiDevicePathProtocolGuid,
1587 &mBmmHiiVendorDevicePath,
1588 &gEfiHiiConfigAccessProtocolGuid,
1589 &BmmCallbackInfo->BmmConfigAccess,
1590 NULL
1591 );
1592 ASSERT_EFI_ERROR (Status);
1593
1594 //
1595 // Install Device Path Protocol and Config Access protocol to driver handle
1596 //
1597 Status = gBS->InstallMultipleProtocolInterfaces (
1598 &BmmCallbackInfo->FeDriverHandle,
1599 &gEfiDevicePathProtocolGuid,
1600 &mFeHiiVendorDevicePath,
1601 &gEfiHiiConfigAccessProtocolGuid,
1602 &BmmCallbackInfo->FeConfigAccess,
1603 NULL
1604 );
1605 ASSERT_EFI_ERROR (Status);
1606
1607 //
1608 // Post our Boot Maint VFR binary to the HII database.
1609 //
1610 BmmCallbackInfo->BmmHiiHandle = HiiAddPackages (
1611 &gBootMaintFormSetGuid,
1612 BmmCallbackInfo->BmmDriverHandle,
1613 BmBin,
1614 BdsDxeStrings,
1615 NULL
1616 );
1617 ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL);
1618
1619 //
1620 // Post our File Explorer VFR binary to the HII database.
1621 //
1622 BmmCallbackInfo->FeHiiHandle = HiiAddPackages (
1623 &gFileExploreFormSetGuid,
1624 BmmCallbackInfo->FeDriverHandle,
1625 FEBin,
1626 BdsDxeStrings,
1627 NULL
1628 );
1629 ASSERT (BmmCallbackInfo->FeHiiHandle != NULL);
1630
1631 mBmmCallbackInfo = BmmCallbackInfo;
1632
1633 return EFI_SUCCESS;
1634 }
1635
1636 /**
1637 Remvoe the intalled BootMaint and FileExplorer HiiPackages.
1638
1639 **/
1640 VOID
1641 FreeBMPackage (
1642 VOID
1643 )
1644 {
1645 BMM_CALLBACK_DATA *BmmCallbackInfo;
1646
1647 BmmCallbackInfo = mBmmCallbackInfo;
1648
1649 //
1650 // Remove our IFR data from HII database
1651 //
1652 HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle);
1653 HiiRemovePackages (BmmCallbackInfo->FeHiiHandle);
1654
1655 if (BmmCallbackInfo->FeDriverHandle != NULL) {
1656 gBS->UninstallMultipleProtocolInterfaces (
1657 BmmCallbackInfo->FeDriverHandle,
1658 &gEfiDevicePathProtocolGuid,
1659 &mFeHiiVendorDevicePath,
1660 &gEfiHiiConfigAccessProtocolGuid,
1661 &BmmCallbackInfo->FeConfigAccess,
1662 NULL
1663 );
1664 }
1665
1666 if (BmmCallbackInfo->BmmDriverHandle != NULL) {
1667 gBS->UninstallMultipleProtocolInterfaces (
1668 BmmCallbackInfo->BmmDriverHandle,
1669 &gEfiDevicePathProtocolGuid,
1670 &mBmmHiiVendorDevicePath,
1671 &gEfiHiiConfigAccessProtocolGuid,
1672 &BmmCallbackInfo->BmmConfigAccess,
1673 NULL
1674 );
1675 }
1676
1677 FreePool (BmmCallbackInfo->LoadContext);
1678 FreePool (BmmCallbackInfo);
1679
1680 mBmmCallbackInfo = NULL;
1681
1682 return;
1683 }
1684