3 Copyright (c) 2006, 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
21 #include "DeviceManager.h"
23 STATIC UINT16 mTokenCount
;
24 EFI_FRONTPAGE_CALLBACK_INFO FPCallbackInfo
;
25 extern UINTN gCallbackKey
;
26 extern EFI_FORM_BROWSER_PROTOCOL
*gBrowser
;
27 extern EFI_GUID gBdsStringPackGuid
;
28 extern BOOLEAN gConnectAllHappened
;
30 STRING_REF gStringTokenTable
[] = {
42 DeviceManagerCallbackRoutine (
43 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
45 IN EFI_IFR_DATA_ARRAY
*DataArray
,
46 OUT EFI_HII_CALLBACK_PACKET
**Packet
52 This is the function that is called to provide results data to the driver. This data
53 consists of a unique key which is used to identify what data is either being passed back
58 KeyValue - A unique value which is sent to the original exporting driver so that it
59 can identify the type of data to expect. The format of the data tends to
60 vary based on the op-code that geerated the callback.
62 Data - A pointer to the data being sent to the original exporting driver.
69 // The KeyValue corresponds in this case to the handle which was requested to be displayed
71 EFI_FRONTPAGE_CALLBACK_INFO
*CallbackInfo
;
73 CallbackInfo
= EFI_FP_CALLBACK_DATA_FROM_THIS (This
);
76 CallbackInfo
->Data
.VideoBIOS
= (UINT8
) (UINTN
) (((EFI_IFR_DATA_ENTRY
*)(DataArray
+ 1))->Data
);
79 &gEfiGlobalVariableGuid
,
80 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
82 &CallbackInfo
->Data
.VideoBIOS
90 gCallbackKey
= KeyValue
;
95 InitializeDeviceManager (
102 Initialize HII information for the FrontPage
112 EFI_HII_PACKAGES
*PackageList
;
113 EFI_HII_UPDATE_DATA
*UpdateData
;
116 // Allocate space for creation of UpdateData Buffer
118 UpdateData
= AllocateZeroPool (0x1000);
119 ASSERT (UpdateData
!= NULL
);
121 PackageList
= PreparePackages (1, &gBdsStringPackGuid
, DeviceManagerVfrBin
);
122 Status
= Hii
->NewPack (Hii
, PackageList
, &FPCallbackInfo
.DevMgrHiiHandle
);
123 gBS
->FreePool (PackageList
);
126 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
128 FPCallbackInfo
.Signature
= EFI_FP_CALLBACK_DATA_SIGNATURE
;
129 FPCallbackInfo
.DevMgrCallback
.NvRead
= NULL
;
130 FPCallbackInfo
.DevMgrCallback
.NvWrite
= NULL
;
131 FPCallbackInfo
.DevMgrCallback
.Callback
= DeviceManagerCallbackRoutine
;
134 // Install protocol interface
136 FPCallbackInfo
.CallbackHandle
= NULL
;
138 Status
= gBS
->InstallProtocolInterface (
139 &FPCallbackInfo
.CallbackHandle
,
140 &gEfiFormCallbackProtocolGuid
,
141 EFI_NATIVE_INTERFACE
,
142 &FPCallbackInfo
.DevMgrCallback
145 ASSERT_EFI_ERROR (Status
);
148 // Flag update pending in FormSet
150 UpdateData
->FormSetUpdate
= TRUE
;
152 // Register CallbackHandle data for FormSet
154 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) FPCallbackInfo
.CallbackHandle
;
156 // Simply registering the callback handle
158 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) 0x0000, TRUE
, UpdateData
);
160 gBS
->FreePool (UpdateData
);
172 Call the browser and display the device manager
179 EFI_SUCCESS - Operation is successful.
180 EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.
187 EFI_HII_HANDLE Index
;
189 EFI_IFR_FORM_SET
*FormSetData
;
192 EFI_HII_UPDATE_DATA
*UpdateData
;
194 STRING_REF TokenHelp
;
195 IFR_OPTION
*IfrOptionList
;
197 UINTN VideoOptionSize
;
198 EFI_HII_HANDLE
*HiiHandles
;
199 UINT16 HandleBufferLength
;
201 IfrOptionList
= NULL
;
203 HandleBufferLength
= 0;
206 // Connect all prior to entering the platform setup menu.
208 if (!gConnectAllHappened
) {
209 BdsLibConnectAllDriversToAllControllers ();
210 gConnectAllHappened
= TRUE
;
213 // Allocate space for creation of UpdateData Buffer
215 UpdateData
= AllocateZeroPool (0x1000);
216 ASSERT (UpdateData
!= NULL
);
218 Status
= EFI_SUCCESS
;
222 if (mTokenCount
== 0) {
223 Hii
->NewString (Hii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &mTokenCount
, L
" ");
227 TokenHelp
= (UINT16
) (Token
+ 1);
232 for (Index
= 0, Count
= 1; Count
< 0x10000; Count
<<= 1, Index
++) {
234 // We will strip off all previous menu entries
236 UpdateData
->DataCount
= 0xFF;
239 // Erase entries on this label
241 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, FALSE
, UpdateData
);
244 // Did we reach the end of the Token Table?
246 if (gStringTokenTable
[Index
] == 0xFFFF) {
250 CreateSubTitleOpCode (gStringTokenTable
[Index
], &UpdateData
->Data
);
252 // Add a single menu item - in this case a subtitle for the device type
254 UpdateData
->DataCount
= 1;
257 // Add default title for this label
259 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, TRUE
, UpdateData
);
262 // Add a space and an exit string. Remember since we add things at the label and push other things beyond the
263 // label down, we add this in reverse order
265 CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING
), &UpdateData
->Data
);
266 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, TRUE
, UpdateData
);
267 CreateSubTitleOpCode (STR_EMPTY_STRING
, &UpdateData
->Data
);
268 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) Count
, TRUE
, UpdateData
);
270 HiiHandles
= AllocateZeroPool (HandleBufferLength
);
271 Hii
->FindHandles (Hii
, &HandleBufferLength
, HiiHandles
);
273 for (Index
= 1, BufferSize
= 0; Index
< HandleBufferLength
; Index
++) {
275 // Am not initializing Buffer since the first thing checked is the size
276 // this way I can get the real buffersize in the smallest code size
278 Status
= Hii
->GetForms (Hii
, Index
, 0, &BufferSize
, Buffer
);
280 if (Status
!= EFI_NOT_FOUND
) {
282 // BufferSize should have the real size of the forms now
284 Buffer
= AllocateZeroPool (BufferSize
);
285 ASSERT (Buffer
!= NULL
);
288 // Am not initializing Buffer since the first thing checked is the size
289 // this way I can get the real buffersize in the smallest code size
291 Status
= Hii
->GetForms (Hii
, Index
, 0, &BufferSize
, Buffer
);
294 // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.
296 FormSetData
= (EFI_IFR_FORM_SET
*) (Buffer
+ sizeof (EFI_HII_PACK_HEADER
));
299 // If this formset belongs in the device manager, add it to the menu
301 if (FormSetData
->Class
!= EFI_NON_DEVICE_CLASS
) {
303 StringLength
= 0x1000;
304 String
= AllocateZeroPool (StringLength
);
305 ASSERT (String
!= NULL
);
307 Status
= Hii
->GetString (Hii
, Index
, FormSetData
->FormSetTitle
, TRUE
, NULL
, &StringLength
, String
);
308 Status
= Hii
->NewString (Hii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &Token
, String
);
311 // If token value exceeded real token value - we need to add a new token values
313 if (Status
== EFI_INVALID_PARAMETER
) {
316 Status
= Hii
->NewString (Hii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &Token
, String
);
319 StringLength
= 0x1000;
320 if (FormSetData
->Help
== 0) {
323 Status
= Hii
->GetString (Hii
, Index
, FormSetData
->Help
, TRUE
, NULL
, &StringLength
, String
);
324 if (StringLength
== 0x02) {
327 Status
= Hii
->NewString (Hii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &TokenHelp
, String
);
328 if (Status
== EFI_INVALID_PARAMETER
) {
330 Status
= Hii
->NewString (Hii
, NULL
, FPCallbackInfo
.DevMgrHiiHandle
, &TokenHelp
, String
);
335 gBS
->FreePool (String
);
338 0x1000, // Device Manager Page
339 Token
, // Description String Token
340 TokenHelp
, // Description Help String Token
341 EFI_IFR_FLAG_INTERACTIVE
| EFI_IFR_FLAG_NV_ACCESS
, // Flag designating callback is active
342 (UINT16
) Index
, // Callback key value
343 &UpdateData
->Data
// Buffer to fill with op-code
347 // In the off-chance that we have lots of extra tokens allocated to the DeviceManager
348 // this ensures we are fairly re-using the tokens instead of constantly growing the token
349 // storage for this one handle. If we incremented the token value beyond what it normally
350 // would use, we will fall back into the error path which seeds the token value with a 0
351 // so that we can correctly add a token value.
353 if (TokenHelp
== 0) {
355 // Since we didn't add help, only advance Token by 1
359 Token
= (UINT16
) (Token
+ 2);
360 TokenHelp
= (UINT16
) (TokenHelp
+ 2);
363 // This for loop basically will take the Class value which is a bitmask and
364 // update the form for every active bit. There will be a label at each bit
365 // location. So if someone had a device which a class of EFI_DISK_DEVICE_CLASS |
366 // EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry
367 // on each corresponding label.
369 for (Count
= 1; Count
< 0x10000; Count
<<= 1) {
371 // This is an active bit, so update the form
373 if (FormSetData
->Class
& Count
) {
376 FPCallbackInfo
.DevMgrHiiHandle
,
377 (EFI_FORM_LABEL
) (FormSetData
->Class
& Count
),
387 // Reset Buffer pointer to original location
389 gBS
->FreePool (Buffer
);
393 // Add oneof for video BIOS selection
395 VideoOption
= BdsLibGetVariableAndSize (
397 &gEfiGlobalVariableGuid
,
400 if (NULL
== VideoOption
) {
401 FPCallbackInfo
.Data
.VideoBIOS
= 0;
403 FPCallbackInfo
.Data
.VideoBIOS
= VideoOption
[0];
404 gBS
->FreePool (VideoOption
);
407 ASSERT (FPCallbackInfo
.Data
.VideoBIOS
<= 1);
409 Status
= gBS
->AllocatePool (EfiBootServicesData
, 2 * sizeof (IFR_OPTION
), &IfrOptionList
);
410 if (IfrOptionList
!= NULL
) {
411 IfrOptionList
[0].Flags
= EFI_IFR_FLAG_INTERACTIVE
;
412 IfrOptionList
[0].Key
= SET_VIDEO_BIOS_TYPE_QUESTION_ID
+ 0x2000;
413 IfrOptionList
[0].StringToken
= STRING_TOKEN (STR_ONE_OF_PCI
);
414 IfrOptionList
[0].Value
= 0;
415 IfrOptionList
[0].OptionString
= NULL
;
416 IfrOptionList
[1].Flags
= EFI_IFR_FLAG_INTERACTIVE
;
417 IfrOptionList
[1].Key
= SET_VIDEO_BIOS_TYPE_QUESTION_ID
+ 0x2000;
418 IfrOptionList
[1].StringToken
= STRING_TOKEN (STR_ONE_OF_AGP
);
419 IfrOptionList
[1].Value
= 1;
420 IfrOptionList
[1].OptionString
= NULL
;
421 IfrOptionList
[FPCallbackInfo
.Data
.VideoBIOS
].Flags
|= EFI_IFR_FLAG_DEFAULT
;
424 SET_VIDEO_BIOS_TYPE_QUESTION_ID
,
426 STRING_TOKEN (STR_ONE_OF_VBIOS
),
427 STRING_TOKEN (STR_ONE_OF_VBIOS_HELP
),
433 UpdateData
->DataCount
= 4;
434 Hii
->UpdateForm (Hii
, FPCallbackInfo
.DevMgrHiiHandle
, (EFI_FORM_LABEL
) EFI_VBIOS_CLASS
, TRUE
, UpdateData
);
435 gBS
->FreePool (IfrOptionList
);
438 Status
= gBrowser
->SendForm (
440 TRUE
, // Use the database
441 &FPCallbackInfo
.DevMgrHiiHandle
, // The HII Handle
444 FPCallbackInfo
.CallbackHandle
,
445 (UINT8
*) &FPCallbackInfo
.Data
,
450 Hii
->ResetStrings (Hii
, FPCallbackInfo
.DevMgrHiiHandle
);
453 // We will have returned from processing a callback - user either hit ESC to exit, or selected
454 // a target to display
456 if (gCallbackKey
!= 0 && gCallbackKey
< 0x2000) {
457 Status
= gBrowser
->SendForm (
459 TRUE
, // Use the database
460 (EFI_HII_HANDLE
*) &gCallbackKey
, // The HII Handle
463 NULL
, // This is the handle that the interface to the callback was installed on
470 // Force return to Device Manager
475 if (gCallbackKey
>= 0x2000) {
479 gBS
->FreePool (UpdateData
);