OvmfPkg/PlatformDxe: Handle all requests in ExtractConfig and RouteConfig

Per the UEFI specification, if the Request argument in
EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig() is NULL or does not contain
any request elements, the implementation should return all of the settings
being abstracted for the particular ConfigHdr reference.

The current implementation returns EFI_INVALID_PARAMETER if Request is
NULL or does not contain any request elements. Instead, construct
a new ConfigRequest to handle these cases per the specification.

In addition, per the UEFI specification, if the Configuration argument in
EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig() has a ConfigHdr that
specifies a non-existing target, the implementation should return
EFI_NOT_FOUND.

The current implementation returns EFI_INVALID_PARAMETER if Configuration
has a non-existing target in ConfigHdr. Instead, perform a check and
return EFI_NOT_FOUND in this case.

Signed-off-by: Dimitrije Pavlov <Dimitrije.Pavlov@arm.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
Dimitrije Pavlov 2022-08-18 14:58:42 -05:00 committed by mergify[bot]
parent 165b5bcd68
commit aefcc91805
3 changed files with 116 additions and 3 deletions

View File

@ -108,6 +108,11 @@ STATIC EFI_EVENT mGopEvent;
// //
STATIC VOID *mGopTracker; STATIC VOID *mGopTracker;
//
// The driver image handle, used to obtain the device path for <ConfigHdr>.
//
STATIC EFI_HANDLE mImageHandle;
// //
// Cache the resolutions we get from the GOP. // Cache the resolutions we get from the GOP.
// //
@ -229,6 +234,10 @@ ExtractConfig (
{ {
MAIN_FORM_STATE MainFormState; MAIN_FORM_STATE MainFormState;
EFI_STATUS Status; EFI_STATUS Status;
EFI_STRING ConfigRequestHdr;
EFI_STRING ConfigRequest;
UINTN Size;
BOOLEAN AllocatedRequest;
DEBUG ((DEBUG_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request)); DEBUG ((DEBUG_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));
@ -236,18 +245,73 @@ ExtractConfig (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
ConfigRequestHdr = NULL;
ConfigRequest = NULL;
Size = 0;
AllocatedRequest = FALSE;
//
// Check if <ConfigHdr> matches the GUID and name
//
*Progress = Request;
if ((Request != NULL) &&
!HiiIsConfigHdrMatch (
Request,
&gOvmfPlatformConfigGuid,
mVariableName
)
)
{
return EFI_NOT_FOUND;
}
Status = PlatformConfigToFormState (&MainFormState); Status = PlatformConfigToFormState (&MainFormState);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
*Progress = Request;
return Status; return Status;
} }
if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
//
// Request has no <RequestElement>, so construct full request string.
// Allocate and fill a buffer large enough to hold <ConfigHdr>
// followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a
// null terminator.
//
ConfigRequestHdr = HiiConstructConfigHdr (
&gOvmfPlatformConfigGuid,
mVariableName,
mImageHandle
);
if (ConfigRequestHdr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
ConfigRequest = AllocateZeroPool (Size);
AllocatedRequest = TRUE;
if (ConfigRequest == NULL) {
FreePool (ConfigRequestHdr);
return EFI_OUT_OF_RESOURCES;
}
UnicodeSPrint (
ConfigRequest,
Size,
L"%s&OFFSET=0&WIDTH=%016LX",
ConfigRequestHdr,
sizeof MainFormState
);
FreePool (ConfigRequestHdr);
} else {
ConfigRequest = Request;
}
// //
// Answer the textual request keying off the binary form state. // Answer the textual request keying off the binary form state.
// //
Status = gHiiConfigRouting->BlockToConfig ( Status = gHiiConfigRouting->BlockToConfig (
gHiiConfigRouting, gHiiConfigRouting,
Request, ConfigRequest,
(VOID *)&MainFormState, (VOID *)&MainFormState,
sizeof MainFormState, sizeof MainFormState,
Results, Results,
@ -265,6 +329,33 @@ ExtractConfig (
DEBUG ((DEBUG_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results)); DEBUG ((DEBUG_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));
} }
//
// If we used a newly allocated ConfigRequest, update Progress to point to
// original Request instead of ConfigRequest.
//
if (Request == NULL) {
*Progress = NULL;
} else if (StrStr (Request, L"OFFSET") == NULL) {
if (EFI_ERROR (Status)) {
//
// Since we constructed ConfigRequest, failure can only occur if there
// is not enough memory. In this case, we point Progress to the first
// character of Request.
//
*Progress = Request;
} else {
//
// In case of success, we point Progress to the null terminator of
// Request.
//
*Progress = Request + StrLen (Request);
}
}
if (AllocatedRequest) {
FreePool (ConfigRequest);
}
return Status; return Status;
} }
@ -348,6 +439,21 @@ RouteConfig (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
//
// Check if <ConfigHdr> matches the GUID and name
//
*Progress = Configuration;
if ((Configuration != NULL) &&
!HiiIsConfigHdrMatch (
Configuration,
&gOvmfPlatformConfigGuid,
mVariableName
)
)
{
return EFI_NOT_FOUND;
}
// //
// the "read" step in RMW // the "read" step in RMW
// //
@ -866,6 +972,11 @@ PlatformInit (
return Status; return Status;
} }
//
// Save the driver image handle.
//
mImageHandle = ImageHandle;
// //
// Publish the HII package list to HII Database. // Publish the HII package list to HII Database.
// //

View File

@ -21,7 +21,7 @@
// //
// Name of the UEFI variable that we use for persistent storage. // Name of the UEFI variable that we use for persistent storage.
// //
STATIC CHAR16 mVariableName[] = L"PlatformConfig"; CHAR16 mVariableName[] = L"PlatformConfig";
/** /**
Serialize and persistently save platform configuration. Serialize and persistently save platform configuration.

View File

@ -50,4 +50,6 @@ PlatformConfigLoad (
#define PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION BIT0 #define PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION BIT0
#define PLATFORM_CONFIG_F_DOWNGRADE BIT63 #define PLATFORM_CONFIG_F_DOWNGRADE BIT63
extern CHAR16 mVariableName[];
#endif // _PLATFORM_CONFIG_H_ #endif // _PLATFORM_CONFIG_H_