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