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