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
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.
18 The platform device manager reference implement
22 // Include common header file for this module.
24 #include "CommonHeader.h"
25 #include "DeviceManager.h"
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
;
33 STRING_REF gStringTokenTable
[] = {
45 DeviceManagerCallbackRoutine (
46 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
48 IN EFI_IFR_DATA_ARRAY
*DataArray
,
49 OUT EFI_HII_CALLBACK_PACKET
**Packet
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
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.
65 Data - A pointer to the data being sent to the original exporting driver.
72 // The KeyValue corresponds in this case to the handle which was requested to be displayed
74 EFI_FRONTPAGE_CALLBACK_INFO
*CallbackInfo
;
76 CallbackInfo
= EFI_FP_CALLBACK_DATA_FROM_THIS (This
);
79 CallbackInfo
->Data
.VideoBIOS
= (UINT8
) (UINTN
) (((EFI_IFR_DATA_ENTRY
*)(DataArray
+ 1))->Data
);
82 &gEfiGenericPlatformVariableGuid
,
83 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
85 &CallbackInfo
->Data
.VideoBIOS
93 gCallbackKey
= KeyValue
;
98 InitializeDeviceManager (
105 Initialize HII information for the FrontPage
115 EFI_HII_PACKAGES
*PackageList
;
116 EFI_HII_UPDATE_DATA
*UpdateData
;
119 // Allocate space for creation of UpdateData Buffer
121 UpdateData
= AllocateZeroPool (0x1000);
122 ASSERT (UpdateData
!= NULL
);
124 PackageList
= PreparePackages (1, &gEfiCallerIdGuid
, DeviceManagerVfrBin
);
125 Status
= gHii
->NewPack (gHii
, PackageList
, &FPCallbackInfo
.DevMgrHiiHandle
);
126 FreePool (PackageList
);
129 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
131 FPCallbackInfo
.Signature
= EFI_FP_CALLBACK_DATA_SIGNATURE
;
132 FPCallbackInfo
.DevMgrCallback
.NvRead
= NULL
;
133 FPCallbackInfo
.DevMgrCallback
.NvWrite
= NULL
;
134 FPCallbackInfo
.DevMgrCallback
.Callback
= DeviceManagerCallbackRoutine
;
137 // Install protocol interface
139 FPCallbackInfo
.CallbackHandle
= NULL
;
141 Status
= gBS
->InstallProtocolInterface (
142 &FPCallbackInfo
.CallbackHandle
,
143 &gEfiFormCallbackProtocolGuid
,
144 EFI_NATIVE_INTERFACE
,
145 &FPCallbackInfo
.DevMgrCallback
148 ASSERT_EFI_ERROR (Status
);
151 // Flag update pending in FormSet
153 UpdateData
->FormSetUpdate
= TRUE
;
155 // Register CallbackHandle data for FormSet
157 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) FPCallbackInfo
.CallbackHandle
;
159 // Simply registering the callback handle
161 gHii
->UpdateForm (gHii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) 0x0000, TRUE
, UpdateData
);
163 FreePool (UpdateData
);
175 Call the browser and display the device manager
182 EFI_SUCCESS - Operation is successful.
183 EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.
190 EFI_HII_HANDLE Index
;
192 EFI_IFR_FORM_SET
*FormSetData
;
195 EFI_HII_UPDATE_DATA
*UpdateData
;
197 STRING_REF TokenHelp
;
198 IFR_OPTION
*IfrOptionList
;
200 UINTN VideoOptionSize
;
201 EFI_HII_HANDLE
*HiiHandles
;
202 UINT16 HandleBufferLength
;
203 BOOLEAN BootDeviceMngrMenuResetRequired
;
205 IfrOptionList
= NULL
;
208 HandleBufferLength
= 0;
211 // Connect all prior to entering the platform setup menu.
213 if (!gConnectAllHappened
) {
214 BdsLibConnectAllDriversToAllControllers ();
215 gConnectAllHappened
= TRUE
;
218 // Allocate space for creation of UpdateData Buffer
220 UpdateData
= AllocateZeroPool (0x1000);
221 ASSERT (UpdateData
!= NULL
);
223 Status
= EFI_SUCCESS
;
227 if (mTokenCount
== 0) {
228 gHii
->NewString (gHii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &mTokenCount
, L
" ");
232 TokenHelp
= (UINT16
) (Token
+ 1);
237 for (Index
= 0, Count
= 1; Count
< 0x10000; Count
<<= 1, Index
++) {
239 // We will strip off all previous menu entries
241 UpdateData
->DataCount
= 0xFF;
244 // Erase entries on this label
246 gHii
->UpdateForm (gHii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, FALSE
, UpdateData
);
249 // Did we reach the end of the Token Table?
251 if (gStringTokenTable
[Index
] == 0xFFFF) {
255 CreateSubTitleOpCode (gStringTokenTable
[Index
], &UpdateData
->Data
);
257 // Add a single menu item - in this case a subtitle for the device type
259 UpdateData
->DataCount
= 1;
262 // Add default title for this label
264 gHii
->UpdateForm (gHii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, TRUE
, UpdateData
);
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
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
);
276 // Get all the gHii handles
278 Status
= BdsLibGetHiiHandles (gHii
, &HandleBufferLength
, &HiiHandles
);
279 ASSERT_EFI_ERROR (Status
);
281 for (Index
= 1, BufferSize
= 0; Index
< HandleBufferLength
; Index
++) {
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
286 Status
= gHii
->GetForms (gHii
, Index
, 0, &BufferSize
, Buffer
);
288 if (Status
!= EFI_NOT_FOUND
) {
290 // BufferSize should have the real size of the forms now
292 Buffer
= AllocateZeroPool (BufferSize
);
293 ASSERT (Buffer
!= NULL
);
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
299 Status
= gHii
->GetForms (gHii
, Index
, 0, &BufferSize
, Buffer
);
302 // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.
304 FormSetData
= (EFI_IFR_FORM_SET
*) (Buffer
+ sizeof (EFI_HII_PACK_HEADER
));
307 // If this formset belongs in the device manager, add it to the menu
309 if (FormSetData
->Class
!= EFI_NON_DEVICE_CLASS
) {
311 StringLength
= 0x1000;
312 String
= AllocateZeroPool (StringLength
);
313 ASSERT (String
!= NULL
);
315 Status
= gHii
->GetString (gHii
, Index
, FormSetData
->FormSetTitle
, TRUE
, NULL
, &StringLength
, String
);
316 Status
= gHii
->NewString (gHii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &Token
, String
);
319 // If token value exceeded real token value - we need to add a new token values
321 if (Status
== EFI_INVALID_PARAMETER
) {
324 Status
= gHii
->NewString (gHii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &Token
, String
);
327 StringLength
= 0x1000;
328 if (FormSetData
->Help
== 0) {
331 Status
= gHii
->GetString (gHii
, Index
, FormSetData
->Help
, TRUE
, NULL
, &StringLength
, String
);
332 if (StringLength
== 0x02) {
335 Status
= gHii
->NewString (gHii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &TokenHelp
, String
);
336 if (Status
== EFI_INVALID_PARAMETER
) {
338 Status
= gHii
->NewString (gHii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &TokenHelp
, String
);
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
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.
361 if (TokenHelp
== 0) {
363 // Since we didn't add help, only advance Token by 1
367 Token
= (UINT16
) (Token
+ 2);
368 TokenHelp
= (UINT16
) (TokenHelp
+ 2);
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.
377 for (Count
= 1; Count
< 0x10000; Count
<<= 1) {
379 // This is an active bit, so update the form
381 if (FormSetData
->Class
& Count
) {
384 FPCallbackInfo
.DevMgrHiiHandle
,
385 (EFI_FORM_LABEL
) (FormSetData
->Class
& Count
),
395 // Reset Buffer pointer to original location
401 // Add oneof for video BIOS selection
403 VideoOption
= BdsLibGetVariableAndSize (
405 &gEfiGenericPlatformVariableGuid
,
408 if (NULL
== VideoOption
) {
409 FPCallbackInfo
.Data
.VideoBIOS
= 0;
411 FPCallbackInfo
.Data
.VideoBIOS
= VideoOption
[0];
412 FreePool (VideoOption
);
415 ASSERT (FPCallbackInfo
.Data
.VideoBIOS
<= 1);
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
;
432 SET_VIDEO_BIOS_TYPE_QUESTION_ID
,
434 STRING_TOKEN (STR_ONE_OF_VBIOS
),
435 STRING_TOKEN (STR_ONE_OF_VBIOS_HELP
),
441 UpdateData
->DataCount
= 4;
442 gHii
->UpdateForm (gHii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) EFI_VBIOS_CLASS
, TRUE
, UpdateData
);
443 FreePool (IfrOptionList
);
446 BootDeviceMngrMenuResetRequired
= FALSE
;
447 Status
= gBrowser
->SendForm (
449 TRUE
, // Use the database
450 &FPCallbackInfo
.DevMgrHiiHandle
, // The HII Handle
453 FPCallbackInfo
.CallbackHandle
,
454 (UINT8
*) &FPCallbackInfo
.Data
,
456 &BootDeviceMngrMenuResetRequired
459 if (BootDeviceMngrMenuResetRequired
) {
460 EnableResetRequired ();
463 gHii
->ResetStrings (gHii
, FPCallbackInfo
.DevMgrHiiHandle
);
466 // We will have returned from processing a callback - user either hit ESC to exit, or selected
467 // a target to display
469 if (gCallbackKey
!= 0 && gCallbackKey
< 0x2000) {
470 BootDeviceMngrMenuResetRequired
= FALSE
;
471 Status
= gBrowser
->SendForm (
473 TRUE
, // Use the database
474 (EFI_HII_HANDLE
*) &gCallbackKey
, // The HII Handle
477 NULL
, // This is the handle that the interface to the callback was installed on
480 &BootDeviceMngrMenuResetRequired
483 if (BootDeviceMngrMenuResetRequired
) {
484 EnableResetRequired ();
487 // Force return to Device Manager
492 if (gCallbackKey
>= 0x2000) {
496 FreePool (UpdateData
);
497 FreePool (HiiHandles
);