]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PlatformDxe/Platform.c
OvmfPkg: PlatformDxe: add form widgets for video modes
[mirror_edk2.git] / OvmfPkg / PlatformDxe / Platform.c
CommitLineData
d945a8ba
LE
1/** @file\r
2 This driver effectuates OVMF's platform configuration settings and exposes\r
3 them via HII.\r
4\r
5 Copyright (C) 2014, Red Hat, Inc.\r
6 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
7\r
8 This program and the accompanying materials are licensed and made available\r
9 under the terms and conditions of the BSD License which accompanies this\r
10 distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15**/\r
16\r
92e74550 17#include <Library/BaseLib.h>\r
d945a8ba 18#include <Library/DebugLib.h>\r
877a4dbb
LE
19#include <Library/DevicePathLib.h>\r
20#include <Library/HiiLib.h>\r
d945a8ba 21#include <Library/UefiBootServicesTableLib.h>\r
92e74550 22#include <Library/UefiHiiServicesLib.h>\r
877a4dbb
LE
23#include <Protocol/DevicePath.h>\r
24#include <Protocol/HiiConfigAccess.h>\r
92e74550
LE
25#include <Guid/MdeModuleHii.h>\r
26#include <Guid/OvmfPlatformConfig.h>\r
d945a8ba 27\r
92e74550 28#include "Platform.h"\r
bdaf30e4
LE
29#include "PlatformConfig.h"\r
30\r
877a4dbb
LE
31//\r
32// The HiiAddPackages() library function requires that any controller (or\r
33// image) handle, to be associated with the HII packages under installation, be\r
34// "decorated" with a device path. The tradition seems to be a vendor device\r
35// path.\r
36//\r
37// We'd like to associate our HII packages with the driver's image handle. The\r
38// first idea is to use the driver image's device path. Unfortunately, loaded\r
39// images only come with an EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL (not the\r
40// usual EFI_DEVICE_PATH_PROTOCOL), ie. a different GUID. In addition, even the\r
41// EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL interface may be NULL, if the image\r
42// has been loaded from an "unnamed" memory source buffer.\r
43//\r
44// Hence let's just stick with the tradition -- use a dedicated vendor device\r
45// path, with the driver's FILE_GUID.\r
46//\r
47#pragma pack(1)\r
48typedef struct {\r
49 VENDOR_DEVICE_PATH VendorDevicePath;\r
50 EFI_DEVICE_PATH_PROTOCOL End;\r
51} PKG_DEVICE_PATH;\r
52#pragma pack()\r
53\r
54STATIC PKG_DEVICE_PATH mPkgDevicePath = {\r
55 {\r
56 {\r
57 HARDWARE_DEVICE_PATH,\r
58 HW_VENDOR_DP,\r
59 {\r
60 (UINT8) (sizeof (VENDOR_DEVICE_PATH) ),\r
61 (UINT8) (sizeof (VENDOR_DEVICE_PATH) >> 8)\r
62 }\r
63 },\r
64 EFI_CALLER_ID_GUID\r
65 },\r
66 {\r
67 END_DEVICE_PATH_TYPE,\r
68 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
69 {\r
70 (UINT8) (END_DEVICE_PATH_LENGTH ),\r
71 (UINT8) (END_DEVICE_PATH_LENGTH >> 8)\r
72 }\r
73 }\r
74};\r
75\r
76//\r
77// The configuration interface between the HII engine (form display etc) and\r
78// this driver.\r
79//\r
80STATIC EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess;\r
81\r
82//\r
83// The handle representing our list of packages after installation.\r
84//\r
85STATIC EFI_HII_HANDLE mInstalledPackages;\r
86\r
87//\r
88// The arrays below constitute our HII package list. They are auto-generated by\r
89// the VFR compiler and linked into the driver image during the build.\r
90//\r
91// - The strings package receives its C identifier from the driver's BASE_NAME,\r
92// plus "Strings".\r
93//\r
94// - The forms package receives its C identifier from the VFR file's basename,\r
95// plus "Bin".\r
96//\r
97//\r
98extern UINT8 PlatformDxeStrings[];\r
99extern UINT8 PlatformFormsBin[];\r
100\r
101\r
92e74550
LE
102/**\r
103 This function is called by the HII machinery when it fetches the form state.\r
104\r
105 See the precise documentation in the UEFI spec.\r
106\r
107 @param[in] This The Config Access Protocol instance.\r
108\r
109 @param[in] Request A <ConfigRequest> format UCS-2 string describing the\r
110 query.\r
111\r
112 @param[out] Progress A pointer into Request on output, identifying the query\r
113 element where processing failed.\r
114\r
115 @param[out] Results A <MultiConfigAltResp> format UCS-2 string that has\r
116 all values filled in for the names in the Request\r
117 string.\r
118\r
119 @return Status codes from gHiiConfigRouting->BlockToConfig().\r
120\r
121**/\r
877a4dbb
LE
122STATIC\r
123EFI_STATUS\r
124EFIAPI\r
125ExtractConfig (\r
126 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
127 IN CONST EFI_STRING Request,\r
128 OUT EFI_STRING *Progress,\r
129 OUT EFI_STRING *Results\r
130)\r
131{\r
92e74550
LE
132 MAIN_FORM_STATE MainFormState;\r
133 EFI_STATUS Status;\r
134\r
135 DEBUG ((EFI_D_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));\r
136\r
137 StrnCpy ((CHAR16 *) MainFormState.CurrentPreferredResolution,\r
138 L"Unset", MAXSIZE_RES_CUR);\r
139 MainFormState.NextPreferredResolution = 0;\r
140 Status = gHiiConfigRouting->BlockToConfig (gHiiConfigRouting, Request,\r
141 (VOID *) &MainFormState, sizeof MainFormState,\r
142 Results, Progress);\r
143 if (EFI_ERROR (Status)) {\r
144 DEBUG ((EFI_D_ERROR, "%a: BlockToConfig(): %r, Progress=\"%s\"\n",\r
145 __FUNCTION__, Status, (Status == EFI_DEVICE_ERROR) ? NULL : *Progress));\r
146 } else {\r
147 DEBUG ((EFI_D_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));\r
148 }\r
149 return Status;\r
877a4dbb
LE
150}\r
151\r
152\r
153STATIC\r
154EFI_STATUS\r
155EFIAPI\r
156RouteConfig (\r
157 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
158 IN CONST EFI_STRING Configuration,\r
159 OUT EFI_STRING *Progress\r
160)\r
161{\r
162 return EFI_SUCCESS;\r
163}\r
164\r
165\r
166STATIC\r
167EFI_STATUS\r
168EFIAPI\r
169Callback (\r
170 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
171 IN EFI_BROWSER_ACTION Action,\r
172 IN EFI_QUESTION_ID QuestionId,\r
173 IN UINT8 Type,\r
174 IN OUT EFI_IFR_TYPE_VALUE *Value,\r
175 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
176 )\r
177{\r
178 return EFI_SUCCESS;\r
179}\r
180\r
181\r
92e74550
LE
182/**\r
183 Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,\r
184 based on available GOP resolutions, to be placed under a "one-of-many" (ie.\r
185 "drop down list") opcode.\r
186\r
187 @param[in] PackageList The package list with the formset and form for\r
188 which the drop down options are produced. Option\r
189 names are added as new strings to PackageList.\r
190\r
191 @param[out] OpCodeBuffer On output, a dynamically allocated opcode buffer\r
192 with drop down list options corresponding to GOP\r
193 resolutions. The caller is responsible for freeing\r
194 OpCodeBuffer with HiiFreeOpCodeHandle() after use.\r
195\r
196 @retval EFI_SUCESS Opcodes have been successfully produced.\r
197\r
198 @return Status codes from underlying functions. PackageList may\r
199 have been extended with new strings. OpCodeBuffer is\r
200 unchanged.\r
201**/\r
202STATIC\r
203EFI_STATUS\r
204EFIAPI\r
205CreateResolutionOptions (\r
206 IN EFI_HII_HANDLE *PackageList,\r
207 OUT VOID **OpCodeBuffer\r
208 )\r
209{\r
210 EFI_STATUS Status;\r
211 VOID *OutputBuffer;\r
212 EFI_STRING_ID NewString;\r
213 VOID *OpCode;\r
214\r
215 OutputBuffer = HiiAllocateOpCodeHandle ();\r
216 if (OutputBuffer == NULL) {\r
217 return EFI_OUT_OF_RESOURCES;\r
218 }\r
219\r
220 NewString = HiiSetString (PackageList, 0 /* new string */, L"800x600",\r
221 NULL /* for all languages */);\r
222 if (NewString == 0) {\r
223 Status = EFI_OUT_OF_RESOURCES;\r
224 goto FreeOutputBuffer;\r
225 }\r
226 OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,\r
227 0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, 0 /* Value */);\r
228 if (OpCode == NULL) {\r
229 Status = EFI_OUT_OF_RESOURCES;\r
230 goto FreeOutputBuffer;\r
231 }\r
232\r
233 *OpCodeBuffer = OutputBuffer;\r
234 return EFI_SUCCESS;\r
235\r
236FreeOutputBuffer:\r
237 HiiFreeOpCodeHandle (OutputBuffer);\r
238\r
239 return Status;\r
240}\r
241\r
242\r
243/**\r
244 Populate the form identified by the (PackageList, FormSetGuid, FormId)\r
245 triplet.\r
246\r
247 @retval EFI_SUCESS Form successfully updated.\r
248 @return Status codes from underlying functions.\r
249\r
250**/\r
251STATIC\r
252EFI_STATUS\r
253EFIAPI\r
254PopulateForm (\r
255 IN EFI_HII_HANDLE *PackageList,\r
256 IN EFI_GUID *FormSetGuid,\r
257 IN EFI_FORM_ID FormId\r
258 )\r
259{\r
260 EFI_STATUS Status;\r
261 VOID *OpCodeBuffer;\r
262 VOID *OpCode;\r
263 EFI_IFR_GUID_LABEL *Anchor;\r
264 VOID *OpCodeBuffer2;\r
265\r
266 //\r
267 // 1. Allocate an empty opcode buffer.\r
268 //\r
269 OpCodeBuffer = HiiAllocateOpCodeHandle ();\r
270 if (OpCodeBuffer == NULL) {\r
271 return EFI_OUT_OF_RESOURCES;\r
272 }\r
273\r
274 //\r
275 // 2. Create a label opcode (which is a Tiano extension) inside the buffer.\r
276 // The label's number must match the "anchor" label in the form.\r
277 //\r
278 OpCode = HiiCreateGuidOpCode (OpCodeBuffer, &gEfiIfrTianoGuid,\r
279 NULL /* optional copy origin */, sizeof *Anchor);\r
280 if (OpCode == NULL) {\r
281 Status = EFI_OUT_OF_RESOURCES;\r
282 goto FreeOpCodeBuffer;\r
283 }\r
284 Anchor = OpCode;\r
285 Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
286 Anchor->Number = LABEL_RES_NEXT;\r
287\r
288 //\r
289 // 3. Create the opcodes inside the buffer that are to be inserted into the\r
290 // form.\r
291 //\r
292 // 3.1. Get a list of resolutions.\r
293 //\r
294 Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2);\r
295 if (EFI_ERROR (Status)) {\r
296 goto FreeOpCodeBuffer;\r
297 }\r
298\r
299 //\r
300 // 3.2. Create a one-of-many question with the above options.\r
301 //\r
302 OpCode = HiiCreateOneOfOpCode (\r
303 OpCodeBuffer, // create opcode inside this\r
304 // opcode buffer,\r
305 QUESTION_RES_NEXT, // ID of question,\r
306 FORMSTATEID_MAIN_FORM, // identifies form state\r
307 // storage,\r
308 (UINT16) OFFSET_OF (MAIN_FORM_STATE, // value of question stored\r
309 NextPreferredResolution), // at this offset,\r
310 STRING_TOKEN (STR_RES_NEXT), // Prompt,\r
311 STRING_TOKEN (STR_RES_NEXT_HELP), // Help,\r
312 0, // QuestionFlags,\r
313 EFI_IFR_NUMERIC_SIZE_4, // see sizeof\r
314 // NextPreferredResolution,\r
315 OpCodeBuffer2, // buffer with possible\r
316 // choices,\r
317 NULL // DEFAULT opcodes\r
318 );\r
319 if (OpCode == NULL) {\r
320 Status = EFI_OUT_OF_RESOURCES;\r
321 goto FreeOpCodeBuffer2;\r
322 }\r
323\r
324 //\r
325 // 4. Update the form with the opcode buffer.\r
326 //\r
327 Status = HiiUpdateForm (PackageList, FormSetGuid, FormId,\r
328 OpCodeBuffer, // buffer with head anchor, and new contents to be\r
329 // inserted at it\r
330 NULL // buffer with tail anchor, for deleting old\r
331 // contents up to it\r
332 );\r
333\r
334FreeOpCodeBuffer2:\r
335 HiiFreeOpCodeHandle (OpCodeBuffer2);\r
336\r
337FreeOpCodeBuffer:\r
338 HiiFreeOpCodeHandle (OpCodeBuffer);\r
339\r
340 return Status;\r
341}\r
342\r
343\r
bdaf30e4
LE
344/**\r
345 Load and execute the platform configuration.\r
346\r
347 @retval EFI_SUCCESS Configuration loaded and executed.\r
348 @return Status codes from PlatformConfigLoad().\r
349**/\r
350STATIC\r
351EFI_STATUS\r
352EFIAPI\r
353ExecutePlatformConfig (\r
354 VOID\r
355 )\r
356{\r
357 EFI_STATUS Status;\r
358 PLATFORM_CONFIG PlatformConfig;\r
359 UINT64 OptionalElements;\r
360\r
361 Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);\r
362 if (EFI_ERROR (Status)) {\r
363 DEBUG (((Status == EFI_NOT_FOUND) ? EFI_D_VERBOSE : EFI_D_ERROR,\r
364 "%a: failed to load platform config: %r\n", __FUNCTION__, Status));\r
365 return Status;\r
366 }\r
367\r
368 if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {\r
369 //\r
370 // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.\r
371 //\r
372 PcdSet32 (PcdVideoHorizontalResolution,\r
373 PlatformConfig.HorizontalResolution);\r
374 PcdSet32 (PcdVideoVerticalResolution,\r
375 PlatformConfig.VerticalResolution);\r
376 }\r
377\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381\r
d945a8ba
LE
382/**\r
383 Entry point for this driver.\r
384\r
385 @param[in] ImageHandle Image handle of this driver.\r
386 @param[in] SystemTable Pointer to SystemTable.\r
387\r
388 @retval EFI_SUCESS Driver has loaded successfully.\r
877a4dbb
LE
389 @retval EFI_OUT_OF_RESOURCES Failed to install HII packages.\r
390 @return Error codes from lower level functions.\r
d945a8ba
LE
391\r
392**/\r
393EFI_STATUS\r
394EFIAPI\r
395PlatformInit (\r
396 IN EFI_HANDLE ImageHandle,\r
397 IN EFI_SYSTEM_TABLE *SystemTable\r
398 )\r
399{\r
877a4dbb
LE
400 EFI_STATUS Status;\r
401\r
bdaf30e4 402 ExecutePlatformConfig ();\r
877a4dbb
LE
403\r
404 mConfigAccess.ExtractConfig = &ExtractConfig;\r
405 mConfigAccess.RouteConfig = &RouteConfig;\r
406 mConfigAccess.Callback = &Callback;\r
407\r
408 //\r
409 // Declare ourselves suitable for HII communication.\r
410 //\r
411 Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,\r
412 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
413 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
414 NULL);\r
415 if (EFI_ERROR (Status)) {\r
416 return Status;\r
417 }\r
418\r
419 //\r
420 // Publish the HII package list to HII Database.\r
421 //\r
422 mInstalledPackages = HiiAddPackages (\r
423 &gEfiCallerIdGuid, // PackageListGuid\r
424 ImageHandle, // associated DeviceHandle\r
425 PlatformDxeStrings, // 1st package\r
426 PlatformFormsBin, // 2nd package\r
427 NULL // terminator\r
428 );\r
429 if (mInstalledPackages == NULL) {\r
430 Status = EFI_OUT_OF_RESOURCES;\r
431 goto UninstallProtocols;\r
432 }\r
433\r
92e74550
LE
434 Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid,\r
435 FORMID_MAIN_FORM);\r
436 if (EFI_ERROR (Status)) {\r
437 goto RemovePackages;\r
438 }\r
439\r
d945a8ba 440 return EFI_SUCCESS;\r
877a4dbb 441\r
92e74550
LE
442RemovePackages:\r
443 HiiRemovePackages (mInstalledPackages);\r
444\r
877a4dbb
LE
445UninstallProtocols:\r
446 gBS->UninstallMultipleProtocolInterfaces (ImageHandle,\r
447 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
448 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
449 NULL);\r
450 return Status;\r
d945a8ba
LE
451}\r
452\r
453/**\r
454 Unload the driver.\r
455\r
456 @param[in] ImageHandle Handle that identifies the image to evict.\r
457\r
458 @retval EFI_SUCCESS The image has been unloaded.\r
459**/\r
460EFI_STATUS\r
461EFIAPI\r
462PlatformUnload (\r
463 IN EFI_HANDLE ImageHandle\r
464 )\r
465{\r
877a4dbb
LE
466 HiiRemovePackages (mInstalledPackages);\r
467 gBS->UninstallMultipleProtocolInterfaces (ImageHandle,\r
468 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
469 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
470 NULL);\r
d945a8ba
LE
471 return EFI_SUCCESS;\r
472}\r