]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PlatformDxe/Platform.c
OvmfPkg: QemuVideoDxe: serialize Start() against callbacks
[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
bc4c5366 6 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
d945a8ba
LE
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
bc4c5366
JJ
266 OpCodeBuffer2 = NULL;\r
267\r
92e74550
LE
268 //\r
269 // 1. Allocate an empty opcode buffer.\r
270 //\r
271 OpCodeBuffer = HiiAllocateOpCodeHandle ();\r
272 if (OpCodeBuffer == NULL) {\r
273 return EFI_OUT_OF_RESOURCES;\r
274 }\r
275\r
276 //\r
277 // 2. Create a label opcode (which is a Tiano extension) inside the buffer.\r
278 // The label's number must match the "anchor" label in the form.\r
279 //\r
280 OpCode = HiiCreateGuidOpCode (OpCodeBuffer, &gEfiIfrTianoGuid,\r
281 NULL /* optional copy origin */, sizeof *Anchor);\r
282 if (OpCode == NULL) {\r
283 Status = EFI_OUT_OF_RESOURCES;\r
284 goto FreeOpCodeBuffer;\r
285 }\r
286 Anchor = OpCode;\r
287 Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
288 Anchor->Number = LABEL_RES_NEXT;\r
289\r
290 //\r
291 // 3. Create the opcodes inside the buffer that are to be inserted into the\r
292 // form.\r
293 //\r
294 // 3.1. Get a list of resolutions.\r
295 //\r
296 Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2);\r
297 if (EFI_ERROR (Status)) {\r
298 goto FreeOpCodeBuffer;\r
299 }\r
300\r
301 //\r
302 // 3.2. Create a one-of-many question with the above options.\r
303 //\r
304 OpCode = HiiCreateOneOfOpCode (\r
305 OpCodeBuffer, // create opcode inside this\r
306 // opcode buffer,\r
307 QUESTION_RES_NEXT, // ID of question,\r
308 FORMSTATEID_MAIN_FORM, // identifies form state\r
309 // storage,\r
310 (UINT16) OFFSET_OF (MAIN_FORM_STATE, // value of question stored\r
311 NextPreferredResolution), // at this offset,\r
312 STRING_TOKEN (STR_RES_NEXT), // Prompt,\r
313 STRING_TOKEN (STR_RES_NEXT_HELP), // Help,\r
314 0, // QuestionFlags,\r
315 EFI_IFR_NUMERIC_SIZE_4, // see sizeof\r
316 // NextPreferredResolution,\r
317 OpCodeBuffer2, // buffer with possible\r
318 // choices,\r
319 NULL // DEFAULT opcodes\r
320 );\r
321 if (OpCode == NULL) {\r
322 Status = EFI_OUT_OF_RESOURCES;\r
323 goto FreeOpCodeBuffer2;\r
324 }\r
325\r
326 //\r
327 // 4. Update the form with the opcode buffer.\r
328 //\r
329 Status = HiiUpdateForm (PackageList, FormSetGuid, FormId,\r
330 OpCodeBuffer, // buffer with head anchor, and new contents to be\r
331 // inserted at it\r
332 NULL // buffer with tail anchor, for deleting old\r
333 // contents up to it\r
334 );\r
335\r
336FreeOpCodeBuffer2:\r
337 HiiFreeOpCodeHandle (OpCodeBuffer2);\r
338\r
339FreeOpCodeBuffer:\r
340 HiiFreeOpCodeHandle (OpCodeBuffer);\r
341\r
342 return Status;\r
343}\r
344\r
345\r
bdaf30e4
LE
346/**\r
347 Load and execute the platform configuration.\r
348\r
349 @retval EFI_SUCCESS Configuration loaded and executed.\r
350 @return Status codes from PlatformConfigLoad().\r
351**/\r
352STATIC\r
353EFI_STATUS\r
354EFIAPI\r
355ExecutePlatformConfig (\r
356 VOID\r
357 )\r
358{\r
359 EFI_STATUS Status;\r
360 PLATFORM_CONFIG PlatformConfig;\r
361 UINT64 OptionalElements;\r
362\r
363 Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);\r
364 if (EFI_ERROR (Status)) {\r
365 DEBUG (((Status == EFI_NOT_FOUND) ? EFI_D_VERBOSE : EFI_D_ERROR,\r
366 "%a: failed to load platform config: %r\n", __FUNCTION__, Status));\r
367 return Status;\r
368 }\r
369\r
370 if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {\r
371 //\r
372 // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.\r
373 //\r
374 PcdSet32 (PcdVideoHorizontalResolution,\r
375 PlatformConfig.HorizontalResolution);\r
376 PcdSet32 (PcdVideoVerticalResolution,\r
377 PlatformConfig.VerticalResolution);\r
378 }\r
379\r
380 return EFI_SUCCESS;\r
381}\r
382\r
383\r
d945a8ba
LE
384/**\r
385 Entry point for this driver.\r
386\r
387 @param[in] ImageHandle Image handle of this driver.\r
388 @param[in] SystemTable Pointer to SystemTable.\r
389\r
390 @retval EFI_SUCESS Driver has loaded successfully.\r
877a4dbb
LE
391 @retval EFI_OUT_OF_RESOURCES Failed to install HII packages.\r
392 @return Error codes from lower level functions.\r
d945a8ba
LE
393\r
394**/\r
395EFI_STATUS\r
396EFIAPI\r
397PlatformInit (\r
398 IN EFI_HANDLE ImageHandle,\r
399 IN EFI_SYSTEM_TABLE *SystemTable\r
400 )\r
401{\r
877a4dbb
LE
402 EFI_STATUS Status;\r
403\r
bdaf30e4 404 ExecutePlatformConfig ();\r
877a4dbb
LE
405\r
406 mConfigAccess.ExtractConfig = &ExtractConfig;\r
407 mConfigAccess.RouteConfig = &RouteConfig;\r
408 mConfigAccess.Callback = &Callback;\r
409\r
410 //\r
411 // Declare ourselves suitable for HII communication.\r
412 //\r
413 Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,\r
414 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
415 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
416 NULL);\r
417 if (EFI_ERROR (Status)) {\r
418 return Status;\r
419 }\r
420\r
421 //\r
422 // Publish the HII package list to HII Database.\r
423 //\r
424 mInstalledPackages = HiiAddPackages (\r
425 &gEfiCallerIdGuid, // PackageListGuid\r
426 ImageHandle, // associated DeviceHandle\r
427 PlatformDxeStrings, // 1st package\r
428 PlatformFormsBin, // 2nd package\r
429 NULL // terminator\r
430 );\r
431 if (mInstalledPackages == NULL) {\r
432 Status = EFI_OUT_OF_RESOURCES;\r
433 goto UninstallProtocols;\r
434 }\r
435\r
92e74550
LE
436 Status = PopulateForm (mInstalledPackages, &gOvmfPlatformConfigGuid,\r
437 FORMID_MAIN_FORM);\r
438 if (EFI_ERROR (Status)) {\r
439 goto RemovePackages;\r
440 }\r
441\r
d945a8ba 442 return EFI_SUCCESS;\r
877a4dbb 443\r
92e74550
LE
444RemovePackages:\r
445 HiiRemovePackages (mInstalledPackages);\r
446\r
877a4dbb
LE
447UninstallProtocols:\r
448 gBS->UninstallMultipleProtocolInterfaces (ImageHandle,\r
449 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
450 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
451 NULL);\r
452 return Status;\r
d945a8ba
LE
453}\r
454\r
455/**\r
456 Unload the driver.\r
457\r
458 @param[in] ImageHandle Handle that identifies the image to evict.\r
459\r
460 @retval EFI_SUCCESS The image has been unloaded.\r
461**/\r
462EFI_STATUS\r
463EFIAPI\r
464PlatformUnload (\r
465 IN EFI_HANDLE ImageHandle\r
466 )\r
467{\r
877a4dbb
LE
468 HiiRemovePackages (mInstalledPackages);\r
469 gBS->UninstallMultipleProtocolInterfaces (ImageHandle,\r
470 &gEfiDevicePathProtocolGuid, &mPkgDevicePath,\r
471 &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,\r
472 NULL);\r
d945a8ba
LE
473 return EFI_SUCCESS;\r
474}\r