2 This driver effectuates OVMF's platform configuration settings and exposes
5 Copyright (C) 2014, Red Hat, Inc.
6 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DevicePathLib.h>
20 #include <Library/HiiLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiHiiServicesLib.h>
23 #include <Protocol/DevicePath.h>
24 #include <Protocol/HiiConfigAccess.h>
25 #include <Guid/MdeModuleHii.h>
26 #include <Guid/OvmfPlatformConfig.h>
29 #include "PlatformConfig.h"
32 // The HiiAddPackages() library function requires that any controller (or
33 // image) handle, to be associated with the HII packages under installation, be
34 // "decorated" with a device path. The tradition seems to be a vendor device
37 // We'd like to associate our HII packages with the driver's image handle. The
38 // first idea is to use the driver image's device path. Unfortunately, loaded
39 // images only come with an EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL (not the
40 // usual EFI_DEVICE_PATH_PROTOCOL), ie. a different GUID. In addition, even the
41 // EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL interface may be NULL, if the image
42 // has been loaded from an "unnamed" memory source buffer.
44 // Hence let's just stick with the tradition -- use a dedicated vendor device
45 // path, with the driver's FILE_GUID.
49 VENDOR_DEVICE_PATH VendorDevicePath
;
50 EFI_DEVICE_PATH_PROTOCOL End
;
54 STATIC PKG_DEVICE_PATH mPkgDevicePath
= {
60 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
) ),
61 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
) >> 8)
68 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
70 (UINT8
) (END_DEVICE_PATH_LENGTH
),
71 (UINT8
) (END_DEVICE_PATH_LENGTH
>> 8)
77 // The configuration interface between the HII engine (form display etc) and
80 STATIC EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess
;
83 // The handle representing our list of packages after installation.
85 STATIC EFI_HII_HANDLE mInstalledPackages
;
88 // The arrays below constitute our HII package list. They are auto-generated by
89 // the VFR compiler and linked into the driver image during the build.
91 // - The strings package receives its C identifier from the driver's BASE_NAME,
94 // - The forms package receives its C identifier from the VFR file's basename,
98 extern UINT8 PlatformDxeStrings
[];
99 extern UINT8 PlatformFormsBin
[];
103 This function is called by the HII machinery when it fetches the form state.
105 See the precise documentation in the UEFI spec.
107 @param[in] This The Config Access Protocol instance.
109 @param[in] Request A <ConfigRequest> format UCS-2 string describing the
112 @param[out] Progress A pointer into Request on output, identifying the query
113 element where processing failed.
115 @param[out] Results A <MultiConfigAltResp> format UCS-2 string that has
116 all values filled in for the names in the Request
119 @return Status codes from gHiiConfigRouting->BlockToConfig().
126 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
127 IN CONST EFI_STRING Request
,
128 OUT EFI_STRING
*Progress
,
129 OUT EFI_STRING
*Results
132 MAIN_FORM_STATE MainFormState
;
135 DEBUG ((EFI_D_VERBOSE
, "%a: Request=\"%s\"\n", __FUNCTION__
, Request
));
137 StrnCpy ((CHAR16
*) MainFormState
.CurrentPreferredResolution
,
138 L
"Unset", MAXSIZE_RES_CUR
);
139 MainFormState
.NextPreferredResolution
= 0;
140 Status
= gHiiConfigRouting
->BlockToConfig (gHiiConfigRouting
, Request
,
141 (VOID
*) &MainFormState
, sizeof MainFormState
,
143 if (EFI_ERROR (Status
)) {
144 DEBUG ((EFI_D_ERROR
, "%a: BlockToConfig(): %r, Progress=\"%s\"\n",
145 __FUNCTION__
, Status
, (Status
== EFI_DEVICE_ERROR
) ? NULL
: *Progress
));
147 DEBUG ((EFI_D_VERBOSE
, "%a: Results=\"%s\"\n", __FUNCTION__
, *Results
));
157 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
158 IN CONST EFI_STRING Configuration
,
159 OUT EFI_STRING
*Progress
170 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
171 IN EFI_BROWSER_ACTION Action
,
172 IN EFI_QUESTION_ID QuestionId
,
174 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
175 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
183 Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,
184 based on available GOP resolutions, to be placed under a "one-of-many" (ie.
185 "drop down list") opcode.
187 @param[in] PackageList The package list with the formset and form for
188 which the drop down options are produced. Option
189 names are added as new strings to PackageList.
191 @param[out] OpCodeBuffer On output, a dynamically allocated opcode buffer
192 with drop down list options corresponding to GOP
193 resolutions. The caller is responsible for freeing
194 OpCodeBuffer with HiiFreeOpCodeHandle() after use.
196 @retval EFI_SUCESS Opcodes have been successfully produced.
198 @return Status codes from underlying functions. PackageList may
199 have been extended with new strings. OpCodeBuffer is
205 CreateResolutionOptions (
206 IN EFI_HII_HANDLE
*PackageList
,
207 OUT VOID
**OpCodeBuffer
212 EFI_STRING_ID NewString
;
215 OutputBuffer
= HiiAllocateOpCodeHandle ();
216 if (OutputBuffer
== NULL
) {
217 return EFI_OUT_OF_RESOURCES
;
220 NewString
= HiiSetString (PackageList
, 0 /* new string */, L
"800x600",
221 NULL
/* for all languages */);
222 if (NewString
== 0) {
223 Status
= EFI_OUT_OF_RESOURCES
;
224 goto FreeOutputBuffer
;
226 OpCode
= HiiCreateOneOfOptionOpCode (OutputBuffer
, NewString
,
227 0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4
, 0 /* Value */);
228 if (OpCode
== NULL
) {
229 Status
= EFI_OUT_OF_RESOURCES
;
230 goto FreeOutputBuffer
;
233 *OpCodeBuffer
= OutputBuffer
;
237 HiiFreeOpCodeHandle (OutputBuffer
);
244 Populate the form identified by the (PackageList, FormSetGuid, FormId)
247 @retval EFI_SUCESS Form successfully updated.
248 @return Status codes from underlying functions.
255 IN EFI_HII_HANDLE
*PackageList
,
256 IN EFI_GUID
*FormSetGuid
,
257 IN EFI_FORM_ID FormId
263 EFI_IFR_GUID_LABEL
*Anchor
;
266 OpCodeBuffer2
= NULL
;
269 // 1. Allocate an empty opcode buffer.
271 OpCodeBuffer
= HiiAllocateOpCodeHandle ();
272 if (OpCodeBuffer
== NULL
) {
273 return EFI_OUT_OF_RESOURCES
;
277 // 2. Create a label opcode (which is a Tiano extension) inside the buffer.
278 // The label's number must match the "anchor" label in the form.
280 OpCode
= HiiCreateGuidOpCode (OpCodeBuffer
, &gEfiIfrTianoGuid
,
281 NULL
/* optional copy origin */, sizeof *Anchor
);
282 if (OpCode
== NULL
) {
283 Status
= EFI_OUT_OF_RESOURCES
;
284 goto FreeOpCodeBuffer
;
287 Anchor
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
288 Anchor
->Number
= LABEL_RES_NEXT
;
291 // 3. Create the opcodes inside the buffer that are to be inserted into the
294 // 3.1. Get a list of resolutions.
296 Status
= CreateResolutionOptions (PackageList
, &OpCodeBuffer2
);
297 if (EFI_ERROR (Status
)) {
298 goto FreeOpCodeBuffer
;
302 // 3.2. Create a one-of-many question with the above options.
304 OpCode
= HiiCreateOneOfOpCode (
305 OpCodeBuffer
, // create opcode inside this
307 QUESTION_RES_NEXT
, // ID of question,
308 FORMSTATEID_MAIN_FORM
, // identifies form state
310 (UINT16
) OFFSET_OF (MAIN_FORM_STATE
, // value of question stored
311 NextPreferredResolution
), // at this offset,
312 STRING_TOKEN (STR_RES_NEXT
), // Prompt,
313 STRING_TOKEN (STR_RES_NEXT_HELP
), // Help,
315 EFI_IFR_NUMERIC_SIZE_4
, // see sizeof
316 // NextPreferredResolution,
317 OpCodeBuffer2
, // buffer with possible
319 NULL
// DEFAULT opcodes
321 if (OpCode
== NULL
) {
322 Status
= EFI_OUT_OF_RESOURCES
;
323 goto FreeOpCodeBuffer2
;
327 // 4. Update the form with the opcode buffer.
329 Status
= HiiUpdateForm (PackageList
, FormSetGuid
, FormId
,
330 OpCodeBuffer
, // buffer with head anchor, and new contents to be
332 NULL
// buffer with tail anchor, for deleting old
337 HiiFreeOpCodeHandle (OpCodeBuffer2
);
340 HiiFreeOpCodeHandle (OpCodeBuffer
);
347 Load and execute the platform configuration.
349 @retval EFI_SUCCESS Configuration loaded and executed.
350 @return Status codes from PlatformConfigLoad().
355 ExecutePlatformConfig (
360 PLATFORM_CONFIG PlatformConfig
;
361 UINT64 OptionalElements
;
363 Status
= PlatformConfigLoad (&PlatformConfig
, &OptionalElements
);
364 if (EFI_ERROR (Status
)) {
365 DEBUG (((Status
== EFI_NOT_FOUND
) ? EFI_D_VERBOSE
: EFI_D_ERROR
,
366 "%a: failed to load platform config: %r\n", __FUNCTION__
, Status
));
370 if (OptionalElements
& PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION
) {
372 // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.
374 PcdSet32 (PcdVideoHorizontalResolution
,
375 PlatformConfig
.HorizontalResolution
);
376 PcdSet32 (PcdVideoVerticalResolution
,
377 PlatformConfig
.VerticalResolution
);
385 Entry point for this driver.
387 @param[in] ImageHandle Image handle of this driver.
388 @param[in] SystemTable Pointer to SystemTable.
390 @retval EFI_SUCESS Driver has loaded successfully.
391 @retval EFI_OUT_OF_RESOURCES Failed to install HII packages.
392 @return Error codes from lower level functions.
398 IN EFI_HANDLE ImageHandle
,
399 IN EFI_SYSTEM_TABLE
*SystemTable
404 ExecutePlatformConfig ();
406 mConfigAccess
.ExtractConfig
= &ExtractConfig
;
407 mConfigAccess
.RouteConfig
= &RouteConfig
;
408 mConfigAccess
.Callback
= &Callback
;
411 // Declare ourselves suitable for HII communication.
413 Status
= gBS
->InstallMultipleProtocolInterfaces (&ImageHandle
,
414 &gEfiDevicePathProtocolGuid
, &mPkgDevicePath
,
415 &gEfiHiiConfigAccessProtocolGuid
, &mConfigAccess
,
417 if (EFI_ERROR (Status
)) {
422 // Publish the HII package list to HII Database.
424 mInstalledPackages
= HiiAddPackages (
425 &gEfiCallerIdGuid
, // PackageListGuid
426 ImageHandle
, // associated DeviceHandle
427 PlatformDxeStrings
, // 1st package
428 PlatformFormsBin
, // 2nd package
431 if (mInstalledPackages
== NULL
) {
432 Status
= EFI_OUT_OF_RESOURCES
;
433 goto UninstallProtocols
;
436 Status
= PopulateForm (mInstalledPackages
, &gOvmfPlatformConfigGuid
,
438 if (EFI_ERROR (Status
)) {
445 HiiRemovePackages (mInstalledPackages
);
448 gBS
->UninstallMultipleProtocolInterfaces (ImageHandle
,
449 &gEfiDevicePathProtocolGuid
, &mPkgDevicePath
,
450 &gEfiHiiConfigAccessProtocolGuid
, &mConfigAccess
,
458 @param[in] ImageHandle Handle that identifies the image to evict.
460 @retval EFI_SUCCESS The image has been unloaded.
465 IN EFI_HANDLE ImageHandle
468 HiiRemovePackages (mInstalledPackages
);
469 gBS
->UninstallMultipleProtocolInterfaces (ImageHandle
,
470 &gEfiDevicePathProtocolGuid
, &mPkgDevicePath
,
471 &gEfiHiiConfigAccessProtocolGuid
, &mConfigAccess
,