]> git.proxmox.com Git - mirror_edk2.git/blame - EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.c
Bug fix for "Tiano BIOS needs to implement an automatic reboot when BIOS settings...
[mirror_edk2.git] / EdkNt32Pkg / Dxe / PlatformBds / Generic / DeviceMngr / DeviceManager.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name: \r
13\r
14 DeviceManager.c\r
15\r
16Abstract:\r
17\r
18 The platform device manager reference implement\r
19\r
20--*/\r
21#include "DeviceManager.h"\r
22\r
23STATIC UINT16 mTokenCount;\r
24EFI_FRONTPAGE_CALLBACK_INFO FPCallbackInfo;\r
25extern UINTN gCallbackKey;\r
26extern EFI_FORM_BROWSER_PROTOCOL *gBrowser;\r
27extern EFI_GUID gBdsStringPackGuid;\r
28extern BOOLEAN gConnectAllHappened;\r
29\r
30STRING_REF gStringTokenTable[] = {\r
31 STR_VIDEO_DEVICE,\r
32 STR_NETWORK_DEVICE,\r
33 STR_INPUT_DEVICE,\r
34 STR_ON_BOARD_DEVICE,\r
35 STR_OTHER_DEVICE,\r
36 STR_EMPTY_STRING,\r
37 0xFFFF\r
38};\r
39\r
40EFI_STATUS\r
41EFIAPI\r
42DeviceManagerCallbackRoutine (\r
43 IN EFI_FORM_CALLBACK_PROTOCOL *This,\r
44 IN UINT16 KeyValue,\r
45 IN EFI_IFR_DATA_ARRAY *DataArray,\r
46 OUT EFI_HII_CALLBACK_PACKET **Packet\r
47 )\r
48/*++\r
49\r
50Routine Description:\r
51\r
52 This is the function that is called to provide results data to the driver. This data\r
53 consists of a unique key which is used to identify what data is either being passed back\r
54 or being asked for. \r
55\r
56Arguments:\r
57\r
58 KeyValue - A unique value which is sent to the original exporting driver so that it\r
59 can identify the type of data to expect. The format of the data tends to\r
60 vary based on the op-code that geerated the callback.\r
61\r
62 Data - A pointer to the data being sent to the original exporting driver.\r
63\r
64Returns: \r
65\r
66--*/\r
67{\r
68 //\r
69 // The KeyValue corresponds in this case to the handle which was requested to be displayed\r
70 //\r
71 EFI_FRONTPAGE_CALLBACK_INFO *CallbackInfo;\r
72\r
73 CallbackInfo = EFI_FP_CALLBACK_DATA_FROM_THIS (This);\r
74 switch (KeyValue) {\r
75 case 0x2000:\r
76 CallbackInfo->Data.VideoBIOS = (UINT8) (UINTN) (((EFI_IFR_DATA_ENTRY *)(DataArray + 1))->Data);\r
77 gRT->SetVariable (\r
78 L"VBIOS",\r
79 &gEfiGlobalVariableGuid,\r
80 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
81 sizeof (UINT8),\r
82 &CallbackInfo->Data.VideoBIOS\r
83 );\r
84 break;\r
85\r
86 default:\r
87 break;\r
88 }\r
89\r
90 gCallbackKey = KeyValue;\r
91 return EFI_SUCCESS;\r
92}\r
93\r
94EFI_STATUS\r
95InitializeDeviceManager (\r
96 VOID\r
97 )\r
98/*++\r
99\r
100Routine Description:\r
101\r
102 Initialize HII information for the FrontPage\r
103\r
104Arguments:\r
105 None\r
106 \r
107Returns:\r
108\r
109--*/\r
110{\r
111 EFI_STATUS Status;\r
112 EFI_HII_PACKAGES *PackageList;\r
113 EFI_HII_UPDATE_DATA *UpdateData;\r
114\r
115 //\r
116 // Allocate space for creation of UpdateData Buffer\r
117 //\r
118 UpdateData = AllocateZeroPool (0x1000);\r
119 ASSERT (UpdateData != NULL);\r
120\r
121 PackageList = PreparePackages (1, &gBdsStringPackGuid, DeviceManagerVfrBin);\r
122 Status = Hii->NewPack (Hii, PackageList, &FPCallbackInfo.DevMgrHiiHandle);\r
123 gBS->FreePool (PackageList);\r
124\r
125 //\r
126 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator\r
127 //\r
128 FPCallbackInfo.Signature = EFI_FP_CALLBACK_DATA_SIGNATURE;\r
129 FPCallbackInfo.DevMgrCallback.NvRead = NULL;\r
130 FPCallbackInfo.DevMgrCallback.NvWrite = NULL;\r
131 FPCallbackInfo.DevMgrCallback.Callback = DeviceManagerCallbackRoutine;\r
132\r
133 //\r
134 // Install protocol interface\r
135 //\r
136 FPCallbackInfo.CallbackHandle = NULL;\r
137\r
138 Status = gBS->InstallProtocolInterface (\r
139 &FPCallbackInfo.CallbackHandle,\r
140 &gEfiFormCallbackProtocolGuid,\r
141 EFI_NATIVE_INTERFACE,\r
142 &FPCallbackInfo.DevMgrCallback\r
143 );\r
144\r
145 ASSERT_EFI_ERROR (Status);\r
146\r
147 //\r
148 // Flag update pending in FormSet\r
149 //\r
150 UpdateData->FormSetUpdate = TRUE;\r
151 //\r
152 // Register CallbackHandle data for FormSet\r
153 //\r
154 UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FPCallbackInfo.CallbackHandle;\r
155 //\r
156 // Simply registering the callback handle\r
157 //\r
158 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
159\r
160 gBS->FreePool (UpdateData);\r
161 return Status;\r
162}\r
163\r
164EFI_STATUS\r
165CallDeviceManager (\r
166 VOID\r
167 )\r
168/*++\r
169\r
170Routine Description:\r
171 \r
172 Call the browser and display the device manager\r
173\r
174Arguments:\r
175 \r
176 None\r
177 \r
178Returns:\r
179 EFI_SUCCESS - Operation is successful.\r
180 EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.\r
181 \r
182--*/\r
183{\r
184 EFI_STATUS Status;\r
185 UINTN BufferSize;\r
186 UINTN Count;\r
187 EFI_HII_HANDLE Index;\r
188 UINT8 *Buffer;\r
189 EFI_IFR_FORM_SET *FormSetData;\r
190 CHAR16 *String;\r
191 UINTN StringLength;\r
192 EFI_HII_UPDATE_DATA *UpdateData;\r
193 STRING_REF Token;\r
194 STRING_REF TokenHelp;\r
195 IFR_OPTION *IfrOptionList;\r
196 UINT8 *VideoOption;\r
197 UINTN VideoOptionSize;\r
198 EFI_HII_HANDLE *HiiHandles;\r
199 UINT16 HandleBufferLength;\r
9e0e49fc 200 BOOLEAN BootDeviceMngrMenuResetRequired;\r
878ddf1f 201\r
202 IfrOptionList = NULL;\r
203 VideoOption = NULL;\r
204 HandleBufferLength = 0;\r
205\r
206 //\r
207 // Connect all prior to entering the platform setup menu.\r
208 //\r
209 if (!gConnectAllHappened) {\r
210 BdsLibConnectAllDriversToAllControllers ();\r
211 gConnectAllHappened = TRUE;\r
212 }\r
213 //\r
214 // Allocate space for creation of UpdateData Buffer\r
215 //\r
216 UpdateData = AllocateZeroPool (0x1000);\r
217 ASSERT (UpdateData != NULL);\r
218\r
219 Status = EFI_SUCCESS;\r
220 Buffer = NULL;\r
221 FormSetData = NULL;\r
222 gCallbackKey = 0;\r
223 if (mTokenCount == 0) {\r
224 Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &mTokenCount, L" ");\r
225 }\r
226\r
227 Token = mTokenCount;\r
228 TokenHelp = (UINT16) (Token + 1);\r
229\r
230 //\r
231 // Reset the menu\r
232 //\r
233 for (Index = 0, Count = 1; Count < 0x10000; Count <<= 1, Index++) {\r
234 //\r
235 // We will strip off all previous menu entries\r
236 //\r
237 UpdateData->DataCount = 0xFF;\r
238\r
239 //\r
240 // Erase entries on this label\r
241 //\r
242 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, FALSE, UpdateData);\r
243\r
244 //\r
245 // Did we reach the end of the Token Table?\r
246 //\r
247 if (gStringTokenTable[Index] == 0xFFFF) {\r
248 break;\r
249 }\r
250\r
251 CreateSubTitleOpCode (gStringTokenTable[Index], &UpdateData->Data);\r
252 //\r
253 // Add a single menu item - in this case a subtitle for the device type\r
254 //\r
255 UpdateData->DataCount = 1;\r
256\r
257 //\r
258 // Add default title for this label\r
259 //\r
260 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
261 }\r
262 //\r
263 // Add a space and an exit string. Remember since we add things at the label and push other things beyond the\r
264 // label down, we add this in reverse order\r
265 //\r
266 CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING), &UpdateData->Data);\r
267 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
268 CreateSubTitleOpCode (STR_EMPTY_STRING, &UpdateData->Data);\r
269 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
270\r
271 HiiHandles = AllocateZeroPool (HandleBufferLength);\r
272 Hii->FindHandles (Hii, &HandleBufferLength, HiiHandles);\r
273\r
274 for (Index = 1, BufferSize = 0; Index < HandleBufferLength; Index++) {\r
275 //\r
276 // Am not initializing Buffer since the first thing checked is the size\r
277 // this way I can get the real buffersize in the smallest code size\r
278 //\r
279 Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);\r
280\r
281 if (Status != EFI_NOT_FOUND) {\r
282 //\r
283 // BufferSize should have the real size of the forms now\r
284 //\r
285 Buffer = AllocateZeroPool (BufferSize);\r
286 ASSERT (Buffer != NULL);\r
287\r
288 //\r
289 // Am not initializing Buffer since the first thing checked is the size\r
290 // this way I can get the real buffersize in the smallest code size\r
291 //\r
292 Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);\r
293\r
294 //\r
295 // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.\r
296 //\r
297 FormSetData = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACK_HEADER));\r
298\r
299 //\r
300 // If this formset belongs in the device manager, add it to the menu\r
301 //\r
302 if (FormSetData->Class != EFI_NON_DEVICE_CLASS) {\r
303\r
304 StringLength = 0x1000;\r
305 String = AllocateZeroPool (StringLength);\r
306 ASSERT (String != NULL);\r
307\r
308 Status = Hii->GetString (Hii, Index, FormSetData->FormSetTitle, TRUE, NULL, &StringLength, String);\r
309 Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);\r
310\r
311 //\r
312 // If token value exceeded real token value - we need to add a new token values\r
313 //\r
314 if (Status == EFI_INVALID_PARAMETER) {\r
315 Token = 0;\r
316 TokenHelp = 0;\r
317 Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);\r
318 }\r
319\r
320 StringLength = 0x1000;\r
321 if (FormSetData->Help == 0) {\r
322 TokenHelp = 0;\r
323 } else {\r
324 Status = Hii->GetString (Hii, Index, FormSetData->Help, TRUE, NULL, &StringLength, String);\r
325 if (StringLength == 0x02) {\r
326 TokenHelp = 0;\r
327 } else {\r
328 Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);\r
329 if (Status == EFI_INVALID_PARAMETER) {\r
330 TokenHelp = 0;\r
331 Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);\r
332 }\r
333 }\r
334 }\r
335\r
336 gBS->FreePool (String);\r
337\r
338 CreateGotoOpCode (\r
339 0x1000, // Device Manager Page\r
340 Token, // Description String Token\r
341 TokenHelp, // Description Help String Token\r
342 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // Flag designating callback is active\r
343 (UINT16) Index, // Callback key value\r
344 &UpdateData->Data // Buffer to fill with op-code\r
345 );\r
346\r
347 //\r
348 // In the off-chance that we have lots of extra tokens allocated to the DeviceManager\r
349 // this ensures we are fairly re-using the tokens instead of constantly growing the token\r
350 // storage for this one handle. If we incremented the token value beyond what it normally\r
351 // would use, we will fall back into the error path which seeds the token value with a 0\r
352 // so that we can correctly add a token value.\r
353 //\r
354 if (TokenHelp == 0) {\r
355 //\r
356 // Since we didn't add help, only advance Token by 1\r
357 //\r
358 Token++;\r
359 } else {\r
360 Token = (UINT16) (Token + 2);\r
361 TokenHelp = (UINT16) (TokenHelp + 2);\r
362 }\r
363 //\r
364 // This for loop basically will take the Class value which is a bitmask and\r
365 // update the form for every active bit. There will be a label at each bit\r
366 // location. So if someone had a device which a class of EFI_DISK_DEVICE_CLASS |\r
367 // EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry\r
368 // on each corresponding label.\r
369 //\r
370 for (Count = 1; Count < 0x10000; Count <<= 1) {\r
371 //\r
372 // This is an active bit, so update the form\r
373 //\r
374 if (FormSetData->Class & Count) {\r
375 Hii->UpdateForm (\r
376 Hii,\r
377 FPCallbackInfo.DevMgrHiiHandle,\r
378 (EFI_FORM_LABEL) (FormSetData->Class & Count),\r
379 TRUE,\r
380 UpdateData\r
381 );\r
382 }\r
383 }\r
384 }\r
385\r
386 BufferSize = 0;\r
387 //\r
388 // Reset Buffer pointer to original location\r
389 //\r
390 gBS->FreePool (Buffer);\r
391 }\r
392 }\r
393 //\r
394 // Add oneof for video BIOS selection\r
395 //\r
396 VideoOption = BdsLibGetVariableAndSize (\r
397 L"VBIOS",\r
398 &gEfiGlobalVariableGuid,\r
399 &VideoOptionSize\r
400 );\r
401 if (NULL == VideoOption) {\r
402 FPCallbackInfo.Data.VideoBIOS = 0;\r
403 } else {\r
404 FPCallbackInfo.Data.VideoBIOS = VideoOption[0];\r
405 gBS->FreePool (VideoOption);\r
406 }\r
407\r
408 ASSERT (FPCallbackInfo.Data.VideoBIOS <= 1);\r
409\r
410 Status = gBS->AllocatePool (EfiBootServicesData, 2 * sizeof (IFR_OPTION), &IfrOptionList);\r
411 if (IfrOptionList != NULL) {\r
412 IfrOptionList[0].Flags = EFI_IFR_FLAG_INTERACTIVE;\r
413 IfrOptionList[0].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;\r
414 IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);\r
415 IfrOptionList[0].Value = 0;\r
416 IfrOptionList[0].OptionString = NULL;\r
417 IfrOptionList[1].Flags = EFI_IFR_FLAG_INTERACTIVE;\r
418 IfrOptionList[1].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;\r
419 IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);\r
420 IfrOptionList[1].Value = 1;\r
421 IfrOptionList[1].OptionString = NULL;\r
422 IfrOptionList[FPCallbackInfo.Data.VideoBIOS].Flags |= EFI_IFR_FLAG_DEFAULT;\r
423\r
424 CreateOneOfOpCode (\r
425 SET_VIDEO_BIOS_TYPE_QUESTION_ID,\r
426 (UINT8) 1,\r
427 STRING_TOKEN (STR_ONE_OF_VBIOS),\r
428 STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
429 IfrOptionList,\r
430 2,\r
431 &UpdateData->Data\r
432 );\r
433\r
434 UpdateData->DataCount = 4;\r
435 Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) EFI_VBIOS_CLASS, TRUE, UpdateData);\r
436 gBS->FreePool (IfrOptionList);\r
437 }\r
438\r
9e0e49fc 439 BootDeviceMngrMenuResetRequired = FALSE;\r
878ddf1f 440 Status = gBrowser->SendForm (\r
441 gBrowser,\r
442 TRUE, // Use the database\r
443 &FPCallbackInfo.DevMgrHiiHandle, // The HII Handle\r
444 1,\r
445 NULL,\r
446 FPCallbackInfo.CallbackHandle,\r
447 (UINT8 *) &FPCallbackInfo.Data,\r
448 NULL,\r
9e0e49fc 449 &BootDeviceMngrMenuResetRequired\r
878ddf1f 450 );\r
451\r
9e0e49fc 452 if (BootDeviceMngrMenuResetRequired) {\r
453 EnableResetRequired ();\r
454 }\r
455\r
878ddf1f 456 Hii->ResetStrings (Hii, FPCallbackInfo.DevMgrHiiHandle);\r
457\r
458 //\r
459 // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
460 // a target to display\r
461 //\r
462 if (gCallbackKey != 0 && gCallbackKey < 0x2000) {\r
9e0e49fc 463 BootDeviceMngrMenuResetRequired = FALSE;\r
878ddf1f 464 Status = gBrowser->SendForm (\r
465 gBrowser,\r
466 TRUE, // Use the database\r
467 (EFI_HII_HANDLE *) &gCallbackKey, // The HII Handle\r
468 1,\r
469 NULL,\r
470 NULL, // This is the handle that the interface to the callback was installed on\r
471 NULL,\r
472 NULL,\r
9e0e49fc 473 &BootDeviceMngrMenuResetRequired\r
878ddf1f 474 );\r
475\r
9e0e49fc 476 if (BootDeviceMngrMenuResetRequired) {\r
477 EnableResetRequired ();\r
478 }\r
878ddf1f 479 //\r
480 // Force return to Device Manager\r
481 //\r
482 gCallbackKey = 4;\r
483 }\r
484\r
485 if (gCallbackKey >= 0x2000) {\r
486 gCallbackKey = 4;\r
487 }\r
488\r
489 gBS->FreePool (UpdateData);\r
490\r
491 return Status;\r
492}\r