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