c030d1319ee02ea46ebe9ef4d6bd09aeef955519
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / BdsDxe / DeviceMngr / DeviceManager.c
1 /** @file\r
2   The platform device manager reference implement\r
3 \r
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "DeviceManager.h"\r
16 \r
17 DEVICE_MANAGER_CALLBACK_DATA  gDeviceManagerPrivate = {\r
18   DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
19   NULL,\r
20   NULL,\r
21   {\r
22     FakeExtractConfig,\r
23     FakeRouteConfig,\r
24     DeviceManagerCallback\r
25   }\r
26 };\r
27 \r
28 EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
29 \r
30 DEVICE_MANAGER_MENU_ITEM  mDeviceManagerMenuItemTable[] = {\r
31   { STRING_TOKEN (STR_DISK_DEVICE),     EFI_DISK_DEVICE_CLASS },\r
32   { STRING_TOKEN (STR_VIDEO_DEVICE),    EFI_VIDEO_DEVICE_CLASS },\r
33   { STRING_TOKEN (STR_NETWORK_DEVICE),  EFI_NETWORK_DEVICE_CLASS },\r
34   { STRING_TOKEN (STR_INPUT_DEVICE),    EFI_INPUT_DEVICE_CLASS },\r
35   { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
36   { STRING_TOKEN (STR_OTHER_DEVICE),    EFI_OTHER_DEVICE_CLASS }\r
37 };\r
38 \r
39 #define MENU_ITEM_NUM  \\r
40   (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))\r
41 \r
42 /**\r
43   This function is invoked if user selected a iteractive opcode from Device Manager's\r
44   Formset. The decision by user is saved to gCallbackKey for later processing. If\r
45   user set VBIOS, the new value is saved to EFI variable.\r
46 \r
47 \r
48   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
49   @param Action          Specifies the type of action taken by the browser.\r
50   @param QuestionId      A unique value which is sent to the original exporting driver\r
51                          so that it can identify the type of data to expect.\r
52   @param Type            The type of value for the question.\r
53   @param Value           A pointer to the data being sent to the original exporting driver.\r
54   @param ActionRequest   On return, points to the action requested by the callback function.\r
55 \r
56   @retval  EFI_SUCCESS           The callback successfully handled the action.\r
57   @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
58 \r
59 **/\r
60 EFI_STATUS\r
61 EFIAPI\r
62 DeviceManagerCallback (\r
63   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
64   IN  EFI_BROWSER_ACTION                     Action,\r
65   IN  EFI_QUESTION_ID                        QuestionId,\r
66   IN  UINT8                                  Type,\r
67   IN  EFI_IFR_TYPE_VALUE                     *Value,\r
68   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
69   )\r
70 {\r
71   DEVICE_MANAGER_CALLBACK_DATA *PrivateData;\r
72 \r
73   if ((Value == NULL) || (ActionRequest == NULL)) {\r
74     return EFI_INVALID_PARAMETER;\r
75   }\r
76 \r
77   PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);\r
78 \r
79   switch (QuestionId) {\r
80   case DEVICE_MANAGER_KEY_VBIOS:\r
81     PrivateData->VideoBios = Value->u8;\r
82     gRT->SetVariable (\r
83            L"VBIOS",\r
84            &gEfiGenericPlatformVariableGuid,\r
85            EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
86            sizeof (UINT8),\r
87            &PrivateData->VideoBios\r
88            );\r
89 \r
90     //\r
91     // Tell browser not to ask for confirmation of changes,\r
92     // since we have already applied.\r
93     //\r
94     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
95     break;\r
96 \r
97   default:\r
98     //\r
99     // The key corresponds the Handle Index which was requested to be displayed\r
100     //\r
101     gCallbackKey = QuestionId;\r
102 \r
103     //\r
104     // Request to exit SendForm(), so as to switch to selected form\r
105     //\r
106     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
107     break;\r
108   }\r
109 \r
110   return EFI_SUCCESS;\r
111 }\r
112 \r
113 /**\r
114 \r
115   This function registers HII packages to HII database.\r
116 \r
117   @retval EFI_SUCCESS This function complete successfully.\r
118   @return Other value if failed to register HII packages.\r
119 \r
120 **/\r
121 EFI_STATUS\r
122 InitializeDeviceManager (\r
123   VOID\r
124   )\r
125 {\r
126   EFI_STATUS                  Status;\r
127   EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
128 \r
129   //\r
130   // Create driver handle used by HII database\r
131   //\r
132   Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);\r
133   if (EFI_ERROR (Status)) {\r
134     return Status;\r
135   }\r
136 \r
137   //\r
138   // Install Config Access protocol to driver handle\r
139   //\r
140   Status = gBS->InstallProtocolInterface (\r
141                   &gDeviceManagerPrivate.DriverHandle,\r
142                   &gEfiHiiConfigAccessProtocolGuid,\r
143                   EFI_NATIVE_INTERFACE,\r
144                   &gDeviceManagerPrivate.ConfigAccess\r
145                   );\r
146   ASSERT_EFI_ERROR (Status);\r
147 \r
148   //\r
149   // Publish our HII data\r
150   //\r
151   PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
152   ASSERT (PackageList != NULL);\r
153 \r
154   Status = gHiiDatabase->NewPackageList (\r
155                            gHiiDatabase,\r
156                            PackageList,\r
157                            gDeviceManagerPrivate.DriverHandle,\r
158                            &gDeviceManagerPrivate.HiiHandle\r
159                            );\r
160   FreePool (PackageList);\r
161 \r
162   return Status;\r
163 }\r
164 \r
165 /**\r
166 \r
167   Call the browser and display the device manager to allow user\r
168   to configure the platform.\r
169 \r
170   This function create the dynamic content for device manager. It includes\r
171   section header for all class of devices, one-of opcode to set VBIOS.\r
172   \r
173   @retval  EFI_SUCCESS             Operation is successful.\r
174   @retval  Other values if failed to clean up the dynamic content from HII\r
175            database.\r
176 \r
177 **/\r
178 EFI_STATUS\r
179 CallDeviceManager (\r
180   VOID\r
181   )\r
182 {\r
183   EFI_STATUS                  Status;\r
184   UINTN                       Count;\r
185   UINTN                       Index;\r
186   CHAR16                      *String;\r
187   UINTN                       StringLength;\r
188   EFI_HII_UPDATE_DATA         UpdateData[MENU_ITEM_NUM];\r
189   EFI_STRING_ID               Token;\r
190   EFI_STRING_ID               TokenHelp;\r
191   IFR_OPTION                  *IfrOptionList;\r
192   UINT8                       *VideoOption;\r
193   UINTN                       VideoOptionSize;\r
194   EFI_HII_HANDLE              *HiiHandles;\r
195   UINTN                       HandleBufferLength;\r
196   UINTN                       NumberOfHiiHandles;\r
197   EFI_HII_HANDLE              HiiHandle;\r
198   UINT16                      FormSetClass;\r
199   EFI_STRING_ID               FormSetTitle;\r
200   EFI_STRING_ID               FormSetHelp;\r
201   EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
202   EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
203 \r
204   IfrOptionList       = NULL;\r
205   VideoOption         = NULL;\r
206   HiiHandles          = NULL;\r
207   HandleBufferLength  = 0;\r
208 \r
209   Status        = EFI_SUCCESS;\r
210   gCallbackKey  = 0;\r
211 \r
212   //\r
213   // Connect all prior to entering the platform setup menu.\r
214   //\r
215   if (!gConnectAllHappened) {\r
216     BdsLibConnectAllDriversToAllControllers ();\r
217     gConnectAllHappened = TRUE;\r
218   }\r
219 \r
220   //\r
221   // Create Subtitle OpCodes\r
222   //\r
223   for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
224     //\r
225     // Allocate space for creation of UpdateData Buffer\r
226     //\r
227     UpdateData[Index].BufferSize = 0x1000;\r
228     UpdateData[Index].Offset = 0;\r
229     UpdateData[Index].Data = AllocatePool (0x1000);\r
230     ASSERT (UpdateData[Index].Data != NULL);\r
231 \r
232     CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1,  &UpdateData[Index]);\r
233   }\r
234 \r
235   //\r
236   // Get all the Hii handles\r
237   //\r
238   Status = HiiLibGetHiiHandles (&HandleBufferLength, &HiiHandles);\r
239   ASSERT_EFI_ERROR (Status);\r
240 \r
241   HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
242 \r
243   StringLength  = 0x1000;\r
244   String        = AllocateZeroPool (StringLength);\r
245   ASSERT (String != NULL);\r
246 \r
247   //\r
248   // Search for formset of each class type\r
249   //\r
250   NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
251   for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
252     IfrLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);\r
253 \r
254     if (FormSetClass == EFI_NON_DEVICE_CLASS) {\r
255       continue;\r
256     }\r
257 \r
258     Token = 0;\r
259     *String = 0;\r
260     StringLength = 0x1000;\r
261     HiiLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);\r
262     HiiLibNewString (HiiHandle, &Token, String);\r
263 \r
264     TokenHelp = 0;\r
265     *String = 0;\r
266     StringLength = 0x1000;\r
267     HiiLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);\r
268     HiiLibNewString (HiiHandle, &TokenHelp, String);\r
269 \r
270     for (Count = 0; Count < MENU_ITEM_NUM; Count++) {\r
271       if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {\r
272         CreateActionOpCode (\r
273           (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),\r
274           Token,\r
275           TokenHelp,\r
276           EFI_IFR_FLAG_CALLBACK,\r
277           0,\r
278           &UpdateData[Count]\r
279           );\r
280       }\r
281     }\r
282   }\r
283   FreePool (String);\r
284 \r
285   for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
286     //\r
287     // Add End Opcode for Subtitle\r
288     //\r
289     CreateEndOpCode (&UpdateData[Index]);\r
290 \r
291     IfrLibUpdateForm (\r
292       HiiHandle,\r
293       &mDeviceManagerGuid,\r
294       DEVICE_MANAGER_FORM_ID,\r
295       mDeviceManagerMenuItemTable[Index].Class,\r
296       FALSE,\r
297       &UpdateData[Index]\r
298       );\r
299   }\r
300 \r
301   //\r
302   // Add oneof for video BIOS selection\r
303   //\r
304   VideoOption = BdsLibGetVariableAndSize (\r
305                   L"VBIOS",\r
306                   &gEfiGenericPlatformVariableGuid,\r
307                   &VideoOptionSize\r
308                   );\r
309   if (NULL == VideoOption) {\r
310     gDeviceManagerPrivate.VideoBios = 0;\r
311   } else {\r
312     gDeviceManagerPrivate.VideoBios = VideoOption[0];\r
313     FreePool (VideoOption);\r
314   }\r
315 \r
316   ASSERT (gDeviceManagerPrivate.VideoBios <= 1);\r
317 \r
318   IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
319   ASSERT (IfrOptionList != NULL);\r
320   IfrOptionList[0].Flags        = 0;\r
321   IfrOptionList[0].StringToken  = STRING_TOKEN (STR_ONE_OF_PCI);\r
322   IfrOptionList[0].Value.u8     = 0;\r
323   IfrOptionList[1].Flags        = 0;\r
324   IfrOptionList[1].StringToken  = STRING_TOKEN (STR_ONE_OF_AGP);\r
325   IfrOptionList[1].Value.u8     = 1;\r
326   IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;\r
327 \r
328   UpdateData[0].Offset = 0;\r
329   CreateOneOfOpCode (\r
330     DEVICE_MANAGER_KEY_VBIOS,\r
331     0,\r
332     0,\r
333     STRING_TOKEN (STR_ONE_OF_VBIOS),\r
334     STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
335     EFI_IFR_FLAG_CALLBACK,\r
336     EFI_IFR_NUMERIC_SIZE_1,\r
337     IfrOptionList,\r
338     2,\r
339     &UpdateData[0]\r
340     );\r
341 \r
342   IfrLibUpdateForm (\r
343     HiiHandle,\r
344     &mDeviceManagerGuid,\r
345     DEVICE_MANAGER_FORM_ID,\r
346     LABEL_VBIOS,\r
347     FALSE,\r
348     &UpdateData[0]\r
349     );\r
350 \r
351   //\r
352   // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
353   //\r
354   gBS->RestoreTPL (TPL_APPLICATION);\r
355 \r
356   ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
357   Status = gFormBrowser2->SendForm (\r
358                            gFormBrowser2,\r
359                            &HiiHandle,\r
360                            1,\r
361                            NULL,\r
362                            0,\r
363                            NULL,\r
364                            &ActionRequest\r
365                            );\r
366   if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
367     EnableResetRequired ();\r
368   }\r
369 \r
370   //\r
371   // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
372   // a target to display\r
373   //\r
374   if (gCallbackKey != 0) {\r
375     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
376     Status = gFormBrowser2->SendForm (\r
377                              gFormBrowser2,\r
378                              &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
379                              1,\r
380                              NULL,\r
381                              0,\r
382                              NULL,\r
383                              &ActionRequest\r
384                              );\r
385 \r
386     if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
387       EnableResetRequired ();\r
388     }\r
389 \r
390     //\r
391     // Force return to Device Manager\r
392     //\r
393     gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
394   }\r
395 \r
396   //\r
397   // Cleanup dynamic created strings in HII database by reinstall the packagelist\r
398   //\r
399   gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
400   PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
401   ASSERT (PackageList != NULL);\r
402   Status = gHiiDatabase->NewPackageList (\r
403                            gHiiDatabase,\r
404                            PackageList,\r
405                            gDeviceManagerPrivate.DriverHandle,\r
406                            &gDeviceManagerPrivate.HiiHandle\r
407                            );\r
408   FreePool (PackageList);\r
409 \r
410   for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
411     FreePool (UpdateData[Index].Data);\r
412   }\r
413   FreePool (HiiHandles);\r
414 \r
415   gBS->RaiseTPL (TPL_APPLICATION);\r
416 \r
417   return Status;\r
418 }\r