X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FPlatformDxe%2FPlatform.c;h=126d8e73823b408e1980581b3ce5f3b9f4ad6c08;hb=3f20f9cf4febf0683b0d54a48aaff93eec41b0e5;hp=b95326e2b5fe5d5eb6a1783fb3d7ab56da6964a1;hpb=1df57ba3e66ad72f6ac67008aa9a99d4648e0200;p=mirror_edk2.git diff --git a/OvmfPkg/PlatformDxe/Platform.c b/OvmfPkg/PlatformDxe/Platform.c index b95326e2b5..126d8e7382 100644 --- a/OvmfPkg/PlatformDxe/Platform.c +++ b/OvmfPkg/PlatformDxe/Platform.c @@ -15,6 +15,7 @@ **/ #include +#include #include #include #include @@ -125,6 +126,79 @@ STATIC UINTN mNumGopModes; STATIC GOP_MODE *mGopModes; +/** + Load the persistent platform configuration and translate it to binary form + state. + + If the platform configuration is missing, then the function fills in a + default state. + + @param[out] MainFormState Binary form/widget state after translation. + + @retval EFI_SUCCESS Form/widget state ready. + @return Error codes from underlying functions. +**/ +STATIC +EFI_STATUS +EFIAPI +PlatformConfigToFormState ( + OUT MAIN_FORM_STATE *MainFormState + ) +{ + EFI_STATUS Status; + PLATFORM_CONFIG PlatformConfig; + UINT64 OptionalElements; + UINTN ModeNumber; + + ZeroMem (MainFormState, sizeof *MainFormState); + + Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements); + switch (Status) { + case EFI_SUCCESS: + if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) { + // + // Format the preferred resolution as text. + // + UnicodeSPrintAsciiFormat ( + (CHAR16 *) MainFormState->CurrentPreferredResolution, + sizeof MainFormState->CurrentPreferredResolution, + "%Ldx%Ld", + (INT64) PlatformConfig.HorizontalResolution, + (INT64) PlatformConfig.VerticalResolution); + + // + // Try to locate it in the drop-down list too. This may not succeed, but + // that's fine. + // + for (ModeNumber = 0; ModeNumber < mNumGopModes; ++ModeNumber) { + if (mGopModes[ModeNumber].X == PlatformConfig.HorizontalResolution && + mGopModes[ModeNumber].Y == PlatformConfig.VerticalResolution) { + MainFormState->NextPreferredResolution = (UINT32) ModeNumber; + break; + } + } + + break; + } + // + // fall through otherwise + // + + case EFI_NOT_FOUND: + UnicodeSPrintAsciiFormat ( + (CHAR16 *) MainFormState->CurrentPreferredResolution, + sizeof MainFormState->CurrentPreferredResolution, + "Unset"); + break; + + default: + return Status; + } + + return EFI_SUCCESS; +} + + /** This function is called by the HII machinery when it fetches the form state. @@ -142,7 +216,9 @@ STATIC GOP_MODE *mGopModes; all values filled in for the names in the Request string. - @return Status codes from gHiiConfigRouting->BlockToConfig(). + @retval EFI_SUCCESS Extraction of form state in + encoding successful. + @return Status codes from underlying functions. **/ STATIC @@ -160,9 +236,15 @@ ExtractConfig ( DEBUG ((EFI_D_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request)); - StrnCpy ((CHAR16 *) MainFormState.CurrentPreferredResolution, - L"Unset", MAXSIZE_RES_CUR); - MainFormState.NextPreferredResolution = 0; + Status = PlatformConfigToFormState (&MainFormState); + if (EFI_ERROR (Status)) { + *Progress = Request; + return Status; + } + + // + // Answer the textual request keying off the binary form state. + // Status = gHiiConfigRouting->BlockToConfig (gHiiConfigRouting, Request, (VOID *) &MainFormState, sizeof MainFormState, Results, Progress); @@ -176,6 +258,62 @@ ExtractConfig ( } +/** + Interpret the binary form state and save it as persistent platform + configuration. + + @param[in] MainFormState Binary form/widget state to verify and save. + + @retval EFI_SUCCESS Platform configuration saved. + @return Error codes from underlying functions. +**/ +STATIC +EFI_STATUS +EFIAPI +FormStateToPlatformConfig ( + IN CONST MAIN_FORM_STATE *MainFormState + ) +{ + EFI_STATUS Status; + PLATFORM_CONFIG PlatformConfig; + CONST GOP_MODE *GopMode; + + // + // There's nothing to do with the textual CurrentPreferredResolution field. + // We verify and translate the selection in the drop-down list. + // + if (MainFormState->NextPreferredResolution >= mNumGopModes) { + return EFI_INVALID_PARAMETER; + } + GopMode = mGopModes + MainFormState->NextPreferredResolution; + + ZeroMem (&PlatformConfig, sizeof PlatformConfig); + PlatformConfig.HorizontalResolution = GopMode->X; + PlatformConfig.VerticalResolution = GopMode->Y; + + Status = PlatformConfigSave (&PlatformConfig); + return Status; +} + + +/** + This function is called by the HII machinery when it wants the driver to + interpret and persist the form state. + + See the precise documentation in the UEFI spec. + + @param[in] This The Config Access Protocol instance. + + @param[in] Configuration A format UCS-2 string describing the + form state. + + @param[out] Progress A pointer into Configuration on output, + identifying the element where processing failed. + + @retval EFI_SUCCESS Configuration verified, state permanent. + + @return Status codes from underlying functions. +**/ STATIC EFI_STATUS EFIAPI @@ -185,9 +323,46 @@ RouteConfig ( OUT EFI_STRING *Progress ) { + MAIN_FORM_STATE MainFormState; + UINTN BlockSize; + EFI_STATUS Status; + DEBUG ((EFI_D_VERBOSE, "%a: Configuration=\"%s\"\n", __FUNCTION__, Configuration)); - return EFI_SUCCESS; + + // + // the "read" step in RMW + // + Status = PlatformConfigToFormState (&MainFormState); + if (EFI_ERROR (Status)) { + *Progress = Configuration; + return Status; + } + + // + // the "modify" step in RMW + // + // (Update the binary form state. This update may be partial, which is why in + // general we must pre-load the form state from the platform config.) + // + BlockSize = sizeof MainFormState; + Status = gHiiConfigRouting->ConfigToBlock (gHiiConfigRouting, Configuration, + (VOID *) &MainFormState, &BlockSize, Progress); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: ConfigToBlock(): %r, Progress=\"%s\"\n", + __FUNCTION__, Status, + (Status == EFI_BUFFER_TOO_SMALL) ? NULL : *Progress)); + return Status; + } + + // + // the "write" step in RMW + // + Status = FormStateToPlatformConfig (&MainFormState); + if (EFI_ERROR (Status)) { + *Progress = Configuration; + } + return Status; } @@ -488,6 +663,7 @@ ExecutePlatformConfig ( EFI_STATUS Status; PLATFORM_CONFIG PlatformConfig; UINT64 OptionalElements; + RETURN_STATUS PcdStatus; Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements); if (EFI_ERROR (Status)) { @@ -500,10 +676,13 @@ ExecutePlatformConfig ( // // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs. // - PcdSet32 (PcdVideoHorizontalResolution, + PcdStatus = PcdSet32S (PcdVideoHorizontalResolution, PlatformConfig.HorizontalResolution); - PcdSet32 (PcdVideoVerticalResolution, + ASSERT_RETURN_ERROR (PcdStatus); + + PcdStatus = PcdSet32S (PcdVideoVerticalResolution, PlatformConfig.VerticalResolution); + ASSERT_RETURN_ERROR (PcdStatus); } return EFI_SUCCESS;