]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformDxe/Platform.c
OvmfPkg: PlatformDxe: add form widgets for video modes
[mirror_edk2.git] / OvmfPkg / PlatformDxe / Platform.c
index 16066a0f0e238b161d6bbe8a27b049c1c284b57b..4b141629c9aed195a264164a0d2de75536318775 100644 (file)
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 **/\r
 \r
+#include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/HiiLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiHiiServicesLib.h>\r
 #include <Protocol/DevicePath.h>\r
 #include <Protocol/HiiConfigAccess.h>\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Guid/OvmfPlatformConfig.h>\r
 \r
+#include "Platform.h"\r
 #include "PlatformConfig.h"\r
 \r
 //\r
@@ -94,6 +99,26 @@ extern UINT8 PlatformDxeStrings[];
 extern UINT8 PlatformFormsBin[];\r
 \r
 \r
+/**\r
+  This function is called by the HII machinery when it fetches the form state.\r
+\r
+  See the precise documentation in the UEFI spec.\r
+\r
+  @param[in]  This      The Config Access Protocol instance.\r
+\r
+  @param[in]  Request   A <ConfigRequest> format UCS-2 string describing the\r
+                        query.\r
+\r
+  @param[out] Progress  A pointer into Request on output, identifying the query\r
+                        element where processing failed.\r
+\r
+  @param[out] Results   A <MultiConfigAltResp> format UCS-2 string that has\r
+                        all values filled in for the names in the Request\r
+                        string.\r
+\r
+  @return  Status codes from gHiiConfigRouting->BlockToConfig().\r
+\r
+**/\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
@@ -104,7 +129,24 @@ ExtractConfig (
   OUT       EFI_STRING                      *Results\r
 )\r
 {\r
-  return EFI_SUCCESS;\r
+  MAIN_FORM_STATE MainFormState;\r
+  EFI_STATUS      Status;\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));\r
+\r
+  StrnCpy ((CHAR16 *) MainFormState.CurrentPreferredResolution,\r
+           L"Unset", MAXSIZE_RES_CUR);\r
+  MainFormState.NextPreferredResolution = 0;\r
+  Status = gHiiConfigRouting->BlockToConfig (gHiiConfigRouting, Request,\r
+                                (VOID *) &MainFormState, sizeof MainFormState,\r
+                                Results, Progress);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "%a: BlockToConfig(): %r, Progress=\"%s\"\n",\r
+      __FUNCTION__, Status, (Status == EFI_DEVICE_ERROR) ? NULL : *Progress));\r
+  } else {\r
+    DEBUG ((EFI_D_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));\r
+  }\r
+  return Status;\r
 }\r
 \r
 \r
@@ -137,6 +179,168 @@ Callback (
 }\r
 \r
 \r
+/**\r
+  Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,\r
+  based on available GOP resolutions, to be placed under a "one-of-many" (ie.\r
+  "drop down list") opcode.\r
+\r
+  @param[in]  PackageList   The package list with the formset and form for\r
+                            which the drop down options are produced. Option\r
+                            names are added as new strings to PackageList.\r
+\r
+  @param[out] OpCodeBuffer  On output, a dynamically allocated opcode buffer\r
+                            with drop down list options corresponding to GOP\r
+                            resolutions. The caller is responsible for freeing\r
+                            OpCodeBuffer with HiiFreeOpCodeHandle() after use.\r
+\r
+  @retval EFI_SUCESS  Opcodes have been successfully produced.\r
+\r
+  @return             Status codes from underlying functions. PackageList may\r
+                      have been extended with new strings. OpCodeBuffer is\r
+                      unchanged.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+CreateResolutionOptions (\r
+  IN  EFI_HII_HANDLE  *PackageList,\r
+  OUT VOID            **OpCodeBuffer\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  VOID                         *OutputBuffer;\r
+  EFI_STRING_ID                NewString;\r
+  VOID                         *OpCode;\r
+\r
+  OutputBuffer = HiiAllocateOpCodeHandle ();\r
+  if (OutputBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewString = HiiSetString (PackageList, 0 /* new string */, L"800x600",\r
+                NULL /* for all languages */);\r
+  if (NewString == 0) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeOutputBuffer;\r
+  }\r
+  OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,\r
+             0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, 0 /* Value */);\r
+  if (OpCode == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeOutputBuffer;\r
+  }\r
+\r
+  *OpCodeBuffer = OutputBuffer;\r
+  return EFI_SUCCESS;\r
+\r
+FreeOutputBuffer:\r
+  HiiFreeOpCodeHandle (OutputBuffer);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Populate the form identified by the (PackageList, FormSetGuid, FormId)\r
+  triplet.\r
+\r
+  @retval EFI_SUCESS  Form successfully updated.\r
+  @return             Status codes from underlying functions.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PopulateForm (\r
+  IN  EFI_HII_HANDLE  *PackageList,\r
+  IN  EFI_GUID        *FormSetGuid,\r
+  IN  EFI_FORM_ID     FormId\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  VOID               *OpCodeBuffer;\r
+  VOID               *OpCode;\r
+  EFI_IFR_GUID_LABEL *Anchor;\r
+  VOID               *OpCodeBuffer2;\r
+\r
+  //\r
+  // 1. Allocate an empty opcode buffer.\r
+  //\r
+  OpCodeBuffer = HiiAllocateOpCodeHandle ();\r
+  if (OpCodeBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // 2. Create a label opcode (which is a Tiano extension) inside the buffer.\r
+  // The label's number must match the "anchor" label in the form.\r
+  //\r
+  OpCode = HiiCreateGuidOpCode (OpCodeBuffer, &gEfiIfrTianoGuid,\r
+             NULL /* optional copy origin */, sizeof *Anchor);\r
+  if (OpCode == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeOpCodeBuffer;\r
+  }\r
+  Anchor               = OpCode;\r
+  Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  Anchor->Number       = LABEL_RES_NEXT;\r
+\r
+  //\r
+  // 3. Create the opcodes inside the buffer that are to be inserted into the\r
+  // form.\r
+  //\r
+  // 3.1. Get a list of resolutions.\r
+  //\r
+  Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeOpCodeBuffer;\r
+  }\r
+\r
+  //\r
+  // 3.2. Create a one-of-many question with the above options.\r
+  //\r
+  OpCode = HiiCreateOneOfOpCode (\r
+             OpCodeBuffer,                        // create opcode inside this\r
+                                                  //   opcode buffer,\r
+             QUESTION_RES_NEXT,                   // ID of question,\r
+             FORMSTATEID_MAIN_FORM,               // identifies form state\r
+                                                  //   storage,\r
+             (UINT16) OFFSET_OF (MAIN_FORM_STATE, // value of question stored\r
+                        NextPreferredResolution), //   at this offset,\r
+             STRING_TOKEN (STR_RES_NEXT),         // Prompt,\r
+             STRING_TOKEN (STR_RES_NEXT_HELP),    // Help,\r
+             0,                                   // QuestionFlags,\r
+             EFI_IFR_NUMERIC_SIZE_4,              // see sizeof\r
+                                                  //   NextPreferredResolution,\r
+             OpCodeBuffer2,                       // buffer with possible\r
+                                                  //   choices,\r
+             NULL                                 // DEFAULT opcodes\r
+             );\r
+  if (OpCode == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeOpCodeBuffer2;\r
+  }\r
+\r
+  //\r
+  // 4. Update the form with the opcode buffer.\r
+  //\r
+  Status = HiiUpdateForm (PackageList, FormSetGuid, FormId,\r
+             OpCodeBuffer, // buffer with head anchor, and new contents to be\r
+                           // inserted at it\r
+             NULL          // buffer with tail anchor, for deleting old\r
+                           // contents up to it\r
+             );\r
+\r
+FreeOpCodeBuffer2:\r
+  HiiFreeOpCodeHandle (OpCodeBuffer2);\r
+\r
+FreeOpCodeBuffer:\r
+  HiiFreeOpCodeHandle (OpCodeBuffer);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Load and execute the platform configuration.\r
 \r
@@ -227,8 +431,17 @@ PlatformInit (
     goto UninstallProtocols;\r
   }\r
 \r
+  Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid,\r
+             FORMID_MAIN_FORM);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RemovePackages;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 \r
+RemovePackages:\r
+  HiiRemovePackages (mInstalledPackages);\r
+\r
 UninstallProtocols:\r
   gBS->UninstallMultipleProtocolInterfaces (ImageHandle,\r
          &gEfiDevicePathProtocolGuid,      &mPkgDevicePath,\r