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 
16 #include "BootMaintenanceManager.h"
17 #include "BootMaintenanceManagerCustomizedUiSupport.h"
18 
19 #define UI_HII_DRIVER_LIST_SIZE               0x8
20 
21 typedef struct {
22   EFI_STRING_ID   PromptId;
23   EFI_STRING_ID   HelpId;
24   EFI_STRING_ID   DevicePathId;
25   EFI_GUID        FormSetGuid;
26   BOOLEAN         EmptyLineAfter;
27 } UI_HII_DRIVER_INSTANCE;
28 
29 STATIC UI_HII_DRIVER_INSTANCE       *gHiiDriverList;
30 
31 
32 /**
33   Create the dynamic item to allow user to set the "BootNext" vaule.
34 
35   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
36   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
37 
38 **/
39 VOID
BmmCreateBootNextMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)40 BmmCreateBootNextMenu(
41   IN EFI_HII_HANDLE              HiiHandle,
42   IN VOID                        *StartOpCodeHandle
43   )
44 {
45   BM_MENU_ENTRY   *NewMenuEntry;
46   BM_LOAD_CONTEXT *NewLoadContext;
47   UINT16          Index;
48   VOID            *OptionsOpCodeHandle;
49   UINT32          BootNextIndex;
50 
51   if (BootOptionMenu.MenuNumber == 0) {
52     return;
53   }
54 
55   BootNextIndex = NONE_BOOTNEXT_VALUE;
56 
57   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
58   ASSERT (OptionsOpCodeHandle != NULL);
59 
60   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
61     NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
62     NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
63 
64     if (NewLoadContext->IsBootNext) {
65       HiiCreateOneOfOptionOpCode (
66         OptionsOpCodeHandle,
67         NewMenuEntry->DisplayStringToken,
68         EFI_IFR_OPTION_DEFAULT,
69         EFI_IFR_TYPE_NUM_SIZE_32,
70         Index
71         );
72       BootNextIndex = Index;
73     } else {
74       HiiCreateOneOfOptionOpCode (
75         OptionsOpCodeHandle,
76         NewMenuEntry->DisplayStringToken,
77         0,
78         EFI_IFR_TYPE_NUM_SIZE_32,
79         Index
80         );
81     }
82   }
83 
84   if (BootNextIndex == NONE_BOOTNEXT_VALUE) {
85     HiiCreateOneOfOptionOpCode (
86       OptionsOpCodeHandle,
87       STRING_TOKEN (STR_NONE),
88       EFI_IFR_OPTION_DEFAULT,
89       EFI_IFR_TYPE_NUM_SIZE_32,
90       NONE_BOOTNEXT_VALUE
91       );
92   } else {
93     HiiCreateOneOfOptionOpCode (
94       OptionsOpCodeHandle,
95       STRING_TOKEN (STR_NONE),
96       0,
97       EFI_IFR_TYPE_NUM_SIZE_32,
98       NONE_BOOTNEXT_VALUE
99       );
100   }
101 
102   HiiCreateOneOfOpCode (
103     StartOpCodeHandle,
104     (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,
105     VARSTORE_ID_BOOT_MAINT,
106     BOOT_NEXT_VAR_OFFSET,
107     STRING_TOKEN (STR_BOOT_NEXT),
108     STRING_TOKEN (STR_BOOT_NEXT_HELP),
109     0,
110     EFI_IFR_NUMERIC_SIZE_4,
111     OptionsOpCodeHandle,
112     NULL
113     );
114 
115   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
116 
117 }
118 
119 /**
120   Create Time Out Menu in the page.
121 
122   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
123   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
124 
125 **/
126 VOID
BmmCreateTimeOutMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)127 BmmCreateTimeOutMenu (
128   IN EFI_HII_HANDLE              HiiHandle,
129   IN VOID                        *StartOpCodeHandle
130   )
131 {
132   HiiCreateNumericOpCode (
133     StartOpCodeHandle,
134     (EFI_QUESTION_ID) FORM_TIME_OUT_ID,
135     VARSTORE_ID_BOOT_MAINT,
136     BOOT_TIME_OUT_VAR_OFFSET,
137     STRING_TOKEN(STR_NUM_AUTO_BOOT),
138     STRING_TOKEN(STR_HLP_AUTO_BOOT),
139     EFI_IFR_FLAG_CALLBACK,
140     EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,
141     0,
142     65535,
143     0,
144     NULL
145     );
146 }
147 
148 /**
149   Create Boot Option menu in the page.
150 
151   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
152   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
153 
154 **/
155 VOID
BmmCreateBootOptionMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)156 BmmCreateBootOptionMenu (
157   IN EFI_HII_HANDLE              HiiHandle,
158   IN VOID                        *StartOpCodeHandle
159   )
160 {
161   HiiCreateGotoOpCode (
162     StartOpCodeHandle,
163     FORM_BOOT_SETUP_ID,
164     STRING_TOKEN (STR_FORM_BOOT_SETUP_TITLE),
165     STRING_TOKEN (STR_FORM_BOOT_SETUP_HELP),
166     EFI_IFR_FLAG_CALLBACK,
167     FORM_BOOT_SETUP_ID
168     );
169 }
170 
171 /**
172   Create Driver Option menu in the page.
173 
174   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
175   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
176 
177 **/
178 VOID
BmmCreateDriverOptionMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)179 BmmCreateDriverOptionMenu (
180   IN EFI_HII_HANDLE              HiiHandle,
181   IN VOID                        *StartOpCodeHandle
182   )
183 {
184   HiiCreateGotoOpCode (
185     StartOpCodeHandle,
186     FORM_DRIVER_SETUP_ID,
187     STRING_TOKEN (STR_FORM_DRIVER_SETUP_TITLE),
188     STRING_TOKEN (STR_FORM_DRIVER_SETUP_HELP),
189     EFI_IFR_FLAG_CALLBACK,
190     FORM_DRIVER_SETUP_ID
191     );
192 }
193 
194 /**
195   Create Com Option menu in the page.
196 
197   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
198   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
199 
200 **/
201 VOID
BmmCreateComOptionMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)202 BmmCreateComOptionMenu (
203   IN EFI_HII_HANDLE              HiiHandle,
204   IN VOID                        *StartOpCodeHandle
205   )
206 {
207   HiiCreateGotoOpCode (
208     StartOpCodeHandle,
209     FORM_CON_MAIN_ID,
210     STRING_TOKEN (STR_FORM_CON_MAIN_TITLE),
211     STRING_TOKEN (STR_FORM_CON_MAIN_HELP),
212     EFI_IFR_FLAG_CALLBACK,
213     FORM_CON_MAIN_ID
214     );
215 }
216 
217 /**
218   Create Com Option menu in the page.
219 
220   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
221   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
222 
223 **/
224 VOID
BmmCreateBootFromFileMenu(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)225 BmmCreateBootFromFileMenu (
226   IN EFI_HII_HANDLE              HiiHandle,
227   IN VOID                        *StartOpCodeHandle
228   )
229 {
230   HiiCreateGotoOpCode (
231     StartOpCodeHandle,
232     FORM_MAIN_ID,
233     STRING_TOKEN (STR_BOOT_FROM_FILE),
234     STRING_TOKEN (STR_BOOT_FROM_FILE_HELP),
235     EFI_IFR_FLAG_CALLBACK,
236     KEY_VALUE_BOOT_FROM_FILE
237     );
238 }
239 
240 /**
241   Create empty line menu in the front page.
242 
243   @param    HiiHandle           The hii handle for the Uiapp driver.
244   @param    StartOpCodeHandle   The opcode handle to save the new opcode.
245 
246 **/
247 VOID
BmmCreateEmptyLine(IN EFI_HII_HANDLE HiiHandle,IN VOID * StartOpCodeHandle)248 BmmCreateEmptyLine (
249   IN EFI_HII_HANDLE              HiiHandle,
250   IN VOID                        *StartOpCodeHandle
251   )
252 {
253   HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_NULL_STRING), 0, 0, 0);
254 }
255 
256 /**
257   Extract device path for given HII handle and class guid.
258 
259   @param Handle          The HII handle.
260 
261   @retval  NULL          Fail to get the device path string.
262   @return  PathString    Get the device path string.
263 
264 **/
265 CHAR16 *
ExtractDevicePathFromHandle(IN EFI_HII_HANDLE Handle)266 ExtractDevicePathFromHandle (
267   IN      EFI_HII_HANDLE      Handle
268   )
269 {
270   EFI_STATUS                       Status;
271   EFI_HANDLE                       DriverHandle;
272 
273   ASSERT (Handle != NULL);
274 
275   if (Handle == NULL) {
276     return NULL;
277   }
278 
279   Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);
280   if (EFI_ERROR (Status)) {
281     return NULL;
282   }
283 
284   return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE);
285 }
286 
287 /**
288   Check whether this driver need to be shown in the front page.
289 
290   @param    HiiHandle           The hii handle for the driver.
291   @param    Guid                The special guid for the driver which is the target.
292   @param    PromptId            Return the prompt string id.
293   @param    HelpId              Return the help string id.
294   @param    FormsetGuid         Return the formset guid info.
295 
296   @retval   EFI_SUCCESS         Search the driver success
297 
298 **/
299 BOOLEAN
IsRequiredDriver(IN EFI_HII_HANDLE HiiHandle,IN EFI_GUID * Guid,OUT EFI_STRING_ID * PromptId,OUT EFI_STRING_ID * HelpId,OUT VOID * FormsetGuid)300 IsRequiredDriver (
301   IN  EFI_HII_HANDLE              HiiHandle,
302   IN  EFI_GUID                    *Guid,
303   OUT EFI_STRING_ID               *PromptId,
304   OUT EFI_STRING_ID               *HelpId,
305   OUT VOID                        *FormsetGuid
306   )
307 {
308   EFI_STATUS                  Status;
309   UINT8                       ClassGuidNum;
310   EFI_GUID                    *ClassGuid;
311   EFI_IFR_FORM_SET            *Buffer;
312   UINTN                       BufferSize;
313   UINT8                       *Ptr;
314   UINTN                       TempSize;
315   BOOLEAN                     RetVal;
316 
317   Status = HiiGetFormSetFromHiiHandle(HiiHandle, &Buffer,&BufferSize);
318   if (EFI_ERROR (Status)) {
319     return FALSE;
320   }
321 
322   RetVal = FALSE;
323   TempSize = 0;
324   Ptr = (UINT8 *) Buffer;
325   while(TempSize < BufferSize)  {
326     TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
327 
328     if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){
329       Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
330       continue;
331     }
332 
333     ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);
334     ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));
335     while (ClassGuidNum-- > 0) {
336       if (!CompareGuid (Guid, ClassGuid)){
337         ClassGuid ++;
338         continue;
339       }
340 
341       *PromptId = ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle;
342       *HelpId = ((EFI_IFR_FORM_SET *)Ptr)->Help;
343       CopyMem (FormsetGuid, &((EFI_IFR_FORM_SET *) Ptr)->Guid, sizeof (EFI_GUID));
344       RetVal = TRUE;
345     }
346   }
347 
348   FreePool (Buffer);
349 
350   return RetVal;
351 }
352 
353 /**
354   Search the drivers in the system which need to show in the front page
355   and insert the menu to the front page.
356 
357   @param    HiiHandle           The hii handle for the Uiapp driver.
358   @param    ClassGuid           The class guid for the driver which is the target.
359   @param    SpecialHandlerFn    The pointer to the specail handler function, if any.
360   @param    StartOpCodeHandle   The opcode handle to save the new opcode.
361 
362   @retval   EFI_SUCCESS         Search the driver success
363 
364 **/
365 EFI_STATUS
BmmListThirdPartyDrivers(IN EFI_HII_HANDLE HiiHandle,IN EFI_GUID * ClassGuid,IN DRIVER_SPECIAL_HANDLER SpecialHandlerFn,IN VOID * StartOpCodeHandle)366 BmmListThirdPartyDrivers (
367   IN EFI_HII_HANDLE              HiiHandle,
368   IN EFI_GUID                    *ClassGuid,
369   IN DRIVER_SPECIAL_HANDLER      SpecialHandlerFn,
370   IN VOID                        *StartOpCodeHandle
371   )
372 {
373   UINTN                       Index;
374   EFI_STRING                  String;
375   EFI_STRING_ID               Token;
376   EFI_STRING_ID               TokenHelp;
377   EFI_HII_HANDLE              *HiiHandles;
378   CHAR16                      *DevicePathStr;
379   UINTN                       Count;
380   UINTN                       CurrentSize;
381   UI_HII_DRIVER_INSTANCE      *DriverListPtr;
382   EFI_STRING                  NewName;
383   BOOLEAN                     EmptyLineAfter;
384 
385   if (gHiiDriverList != NULL) {
386     FreePool (gHiiDriverList);
387   }
388 
389   HiiHandles = HiiGetHiiHandles (NULL);
390   ASSERT (HiiHandles != NULL);
391 
392   gHiiDriverList = AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE * sizeof (UI_HII_DRIVER_INSTANCE));
393   ASSERT (gHiiDriverList != NULL);
394   DriverListPtr = gHiiDriverList;
395   CurrentSize = UI_HII_DRIVER_LIST_SIZE;
396 
397   for (Index = 0, Count = 0; HiiHandles[Index] != NULL; Index++) {
398     if (!IsRequiredDriver (HiiHandles[Index], ClassGuid, &Token, &TokenHelp, &gHiiDriverList[Count].FormSetGuid)) {
399       continue;
400     }
401 
402     String = HiiGetString (HiiHandles[Index], Token, NULL);
403     if (String == NULL) {
404       String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
405       ASSERT (String != NULL);
406     } else if (SpecialHandlerFn != NULL) {
407       //
408       // Check whether need to rename the driver name.
409       //
410       EmptyLineAfter = FALSE;
411       if (SpecialHandlerFn (String, &NewName, &EmptyLineAfter)) {
412         FreePool (String);
413         String = NewName;
414         DriverListPtr[Count].EmptyLineAfter = EmptyLineAfter;
415       }
416     }
417     DriverListPtr[Count].PromptId = HiiSetString (HiiHandle, 0, String, NULL);
418     FreePool (String);
419 
420     String = HiiGetString (HiiHandles[Index], TokenHelp, NULL);
421     if (String == NULL) {
422       String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
423       ASSERT (String != NULL);
424     }
425     DriverListPtr[Count].HelpId = HiiSetString (HiiHandle, 0, String, NULL);
426     FreePool (String);
427 
428     DevicePathStr = ExtractDevicePathFromHandle(HiiHandles[Index]);
429     if (DevicePathStr != NULL){
430       DriverListPtr[Count].DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);
431       FreePool (DevicePathStr);
432     } else {
433       DriverListPtr[Count].DevicePathId = 0;
434     }
435 
436     Count++;
437     if (Count >= CurrentSize) {
438       DriverListPtr = AllocateCopyPool ((Count + UI_HII_DRIVER_LIST_SIZE) * sizeof (UI_HII_DRIVER_INSTANCE), gHiiDriverList);
439       ASSERT (DriverListPtr != NULL);
440       FreePool (gHiiDriverList);
441       gHiiDriverList = DriverListPtr;
442       CurrentSize += UI_HII_DRIVER_LIST_SIZE;
443     }
444   }
445 
446   FreePool (HiiHandles);
447 
448   Index = 0;
449   while (gHiiDriverList[Index].PromptId != 0) {
450     HiiCreateGotoExOpCode (
451       StartOpCodeHandle,
452       0,
453       gHiiDriverList[Index].PromptId,
454       gHiiDriverList[Index].HelpId,
455       0,
456       0,
457       0,
458       &gHiiDriverList[Index].FormSetGuid,
459       gHiiDriverList[Index].DevicePathId
460     );
461 
462     if (gHiiDriverList[Index].EmptyLineAfter) {
463       BmmCreateEmptyLine (HiiHandle, StartOpCodeHandle);
464     }
465 
466     Index ++;
467   }
468 
469   return EFI_SUCCESS;
470 }
471 
472