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