]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Forms.c
1 /**@file
2 This file contains the form processing code to the HII database.
3
4 Copyright (c) 2006 - 2008 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17 #include "UefiIfrDefault.h"
18 #include "OpcodeCreation.h"
19
20 //
21 // This structure is only intended to be used in this file.
22 //
23 #pragma pack(push, 1)
24 typedef struct {
25 EFI_HII_PACK_HEADER PackageHeader;
26 FRAMEWORK_EFI_IFR_FORM_SET FormSet;
27 FRAMEWORK_EFI_IFR_END_FORM_SET EndFormSet;
28 } FW_HII_FORMSET_TEMPLATE;
29 #pragma pack(pop)
30
31 FW_HII_FORMSET_TEMPLATE FormSetTemplate = {
32 {
33 sizeof (FW_HII_FORMSET_TEMPLATE),
34 EFI_HII_IFR
35 },
36 {
37 {
38 FRAMEWORK_EFI_IFR_FORM_SET_OP,
39 sizeof (FRAMEWORK_EFI_IFR_FORM_SET)
40 },
41 //Guid
42 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}},
43 0,
44 0,
45 0,
46 0,
47 0,
48 0
49 },
50 {
51 {
52 FRAMEWORK_EFI_IFR_END_FORM_SET_OP,
53 sizeof (FRAMEWORK_EFI_IFR_END_FORM_SET)
54 }
55 }
56 };
57
58
59 /**
60
61 This thunk module only handles UEFI HII packages. The caller of this function
62 won¡¯t be able to parse the content. Therefore, it is not supported.
63
64 This function will ASSERT and return EFI_UNSUPPORTED.
65
66 @param This N.A.
67 @param Handle N.A.
68 @param BufferSize N.A.
69 @param Buffer N.A.
70
71 @retval EFI_UNSUPPORTED
72
73 **/
74 EFI_STATUS
75 EFIAPI
76 HiiExportDatabase (
77 IN EFI_HII_PROTOCOL *This,
78 IN FRAMEWORK_EFI_HII_HANDLE Handle,
79 IN OUT UINTN *BufferSize,
80 OUT VOID *Buffer
81 )
82 {
83 ASSERT (FALSE);
84 return EFI_UNSUPPORTED;
85 }
86
87
88 /**
89 This function allows a program to extract a form or form package that has
90 previously been registered with the EFI HII database.
91
92 In this thunk module, this function will create a IFR Package with only
93 one Formset. Effectively, only the GUID of the Formset is updated and return
94 in this IFR package to caller. This is enable the Framework modules which call
95 a API named GetStringFromToken. GetStringFromToken retieves a String based on
96 a String Token from a Package List known only by the Formset GUID.
97
98
99
100 @param This A pointer to the EFI_HII_PROTOCOL instance.
101 @param Handle Handle on which the form resides. Type FRAMEWORK_EFI_HII_HANDLE is defined in
102 EFI_HII_PROTOCOL.NewPack() in the Packages section.
103 @param FormId Ignored by this implementation.
104 @param BufferLengthTemp On input, the size of input buffer. On output, it
105 is the size of FW_HII_FORMSET_TEMPLATE.
106 @param Buffer The buffer designed to receive the form(s).
107
108 @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength
109 was updated.
110 @retval EFI_INVALID_PARAMETER The handle is unknown.
111 @retval EFI_NOT_FOUND A form on the requested handle cannot be found with the
112 requested FormId.
113 @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to allow the form to be stored.
114
115 **/
116 EFI_STATUS
117 EFIAPI
118 HiiGetForms (
119 IN EFI_HII_PROTOCOL *This,
120 IN FRAMEWORK_EFI_HII_HANDLE Handle,
121 IN EFI_FORM_ID FormId,
122 IN OUT UINTN *BufferLengthTemp,
123 OUT UINT8 *Buffer
124 )
125 {
126 HII_THUNK_PRIVATE_DATA *Private;
127 HII_THUNK_CONTEXT *ThunkContext;
128 FW_HII_FORMSET_TEMPLATE *OutputFormSet;
129
130 if (*BufferLengthTemp < sizeof(FW_HII_FORMSET_TEMPLATE)) {
131 *BufferLengthTemp = sizeof(FW_HII_FORMSET_TEMPLATE);
132 return EFI_BUFFER_TOO_SMALL;
133 }
134
135 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
136
137 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
138
139 if (ThunkContext == NULL) {
140 return EFI_NOT_FOUND;
141 }
142
143 OutputFormSet = (FW_HII_FORMSET_TEMPLATE *) Buffer;
144
145 CopyMem (OutputFormSet, &FormSetTemplate, sizeof (FW_HII_FORMSET_TEMPLATE));
146 CopyMem (&OutputFormSet->FormSet.Guid, &ThunkContext->TagGuid, sizeof (EFI_GUID));
147
148 OutputFormSet->FormSet.Class = ThunkContext->FormSetClass;
149 OutputFormSet->FormSet.SubClass = ThunkContext->FormSetSubClass;
150 OutputFormSet->FormSet.Help = ThunkContext->FormSetHelp;
151 OutputFormSet->FormSet.FormSetTitle = ThunkContext->FormSetTitle;
152
153 return EFI_SUCCESS;
154 }
155
156
157 /**
158
159 This function allows a program to extract the NV Image
160 that represents the default storage image
161
162
163 @param This A pointer to the EFI_HII_PROTOCOL instance.
164 @param Handle The HII handle from which will have default data retrieved.
165 UINTN - Mask used to retrieve the default image.
166 @param DefaultMask EDES_TODO: Add parameter description
167 @param VariablePackList Callee allocated, tightly-packed, link list data
168 structure that contain all default varaible packs
169 from the Hii Database.
170
171 @retval EFI_NOT_FOUND If Hii database does not contain any default images.
172 @retval EFI_INVALID_PARAMETER Invalid input parameter.
173 @retval EFI_SUCCESS Operation successful.
174
175 **/
176 EFI_STATUS
177 EFIAPI
178 HiiGetDefaultImage (
179 IN EFI_HII_PROTOCOL *This,
180 IN FRAMEWORK_EFI_HII_HANDLE Handle,
181 IN UINTN DefaultMask,
182 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
183 )
184 {
185 LIST_ENTRY *UefiDefaults;
186 EFI_HII_HANDLE UefiHiiHandle;
187 EFI_STATUS Status;
188 HII_THUNK_PRIVATE_DATA *Private;
189
190 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
191
192 UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
193 if (UefiHiiHandle == NULL) {
194 ASSERT (FALSE);
195 return EFI_INVALID_PARAMETER;
196 }
197
198 UefiDefaults = NULL;
199 Status = UefiIfrGetBufferTypeDefaults (UefiHiiHandle, &UefiDefaults);
200 if (EFI_ERROR (Status)) {
201 goto Done;
202 }
203
204 Status = UefiDefaultsToFwDefaults (UefiDefaults, DefaultMask, VariablePackList);
205
206 Done:
207 FreeDefaultList (UefiDefaults);
208
209 return Status;
210 }
211
212 /**
213 EDES_TODO: Add function description.
214
215 @param CallbackHandle EDES_TODO: Add parameter description
216 @param ThunkContext EDES_TODO: Add parameter description
217
218 @return EDES_TODO: Add description for return value
219
220 **/
221 EFI_STATUS
222 UpdateFormCallBack (
223 IN EFI_HANDLE CallbackHandle,
224 IN CONST HII_THUNK_CONTEXT *ThunkContext
225 )
226 {
227 EFI_STATUS Status;
228 EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;
229 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccessProtocol;
230 EFI_HANDLE UefiDriverHandle;
231 CONFIG_ACCESS_PRIVATE *ConfigAccessPrivate;
232
233 Status = gBS->HandleProtocol (
234 CallbackHandle,
235 &gEfiFormCallbackProtocolGuid,
236 (VOID **) &FormCallbackProtocol
237 );
238 if (EFI_ERROR (Status)) {
239 return EFI_INVALID_PARAMETER;
240 }
241
242 Status = mHiiDatabase->GetPackageListHandle (
243 mHiiDatabase,
244 ThunkContext->UefiHiiHandle,
245 &UefiDriverHandle
246 );
247 ASSERT_EFI_ERROR (Status);
248 Status = gBS->HandleProtocol (
249 UefiDriverHandle,
250 &gEfiHiiConfigAccessProtocolGuid,
251 (VOID **) &ConfigAccessProtocol
252 );
253 ASSERT_EFI_ERROR (Status);
254
255 ConfigAccessPrivate = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (ConfigAccessProtocol);
256
257 ConfigAccessPrivate->FormCallbackProtocol = FormCallbackProtocol;
258
259 return EFI_SUCCESS;
260 }
261
262
263 /**
264 EDES_TODO: Add function description.
265
266 @param HiiPackageList EDES_TODO: Add parameter description
267 @param PackageIndex EDES_TODO: Add parameter description
268 @param BufferLen EDES_TODO: Add parameter description
269 @param Buffer EDES_TODO: Add parameter description
270
271 @return EDES_TODO: Add description for return value
272
273 **/
274 STATIC
275 EFI_STATUS
276 GetPackageData (
277 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
278 IN UINT32 PackageIndex,
279 OUT UINT32 *BufferLen,
280 OUT EFI_HII_PACKAGE_HEADER **Buffer
281 )
282 {
283 UINT32 Index;
284 EFI_HII_PACKAGE_HEADER *Package;
285 UINT32 Offset;
286 UINT32 PackageListLength;
287 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
288
289 ASSERT(HiiPackageList != NULL);
290
291 if ((BufferLen == NULL) || (Buffer == NULL)) {
292 return EFI_INVALID_PARAMETER;
293 }
294
295 Package = NULL;
296 Index = 0;
297 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
298 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
299 while (Offset < PackageListLength) {
300 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
301 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
302 if (Index == PackageIndex) {
303 break;
304 }
305 Offset += PackageHeader.Length;
306 Index++;
307 }
308 if (Offset >= PackageListLength) {
309 //
310 // no package found in this Package List
311 //
312 return EFI_NOT_FOUND;
313 }
314
315 *BufferLen = PackageHeader.Length;
316 *Buffer = Package;
317 return EFI_SUCCESS;
318 }
319
320 /**
321 Check if Label exist in the IFR form package.
322
323 @param
324
325 **/
326 EFI_STATUS
327 LocateLabel (
328 IN CONST EFI_HII_PACKAGE_HEADER *Package,
329 IN EFI_FORM_LABEL Label,
330 OUT EFI_GUID *FormsetGuid,
331 OUT EFI_FORM_ID *FormId
332 )
333 {
334 UINTN Offset;
335 EFI_IFR_OP_HEADER *IfrOpHdr;
336 UINT8 ExtendOpCode;
337 UINT16 LabelNumber;
338 EFI_GUID InternalFormSetGuid;
339 EFI_FORM_ID InternalFormId;
340 BOOLEAN GetFormSet;
341 BOOLEAN GetForm;
342
343 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
344 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
345
346 InternalFormId= 0;
347 ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID));
348 GetFormSet = FALSE;
349 GetForm = FALSE;
350
351 while (Offset < Package->Length) {
352 switch (IfrOpHdr->OpCode) {
353 case EFI_IFR_FORM_SET_OP :
354 CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID));
355 GetFormSet = TRUE;
356 break;
357
358 case EFI_IFR_FORM_OP:
359 CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID));
360 GetForm = TRUE;
361 break;
362
363 case EFI_IFR_GUID_OP :
364 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
365
366 if (ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) {
367 //
368 // Go to the next Op-Code
369 //
370 Offset += IfrOpHdr->Length;
371 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
372 continue;
373 }
374
375 CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
376 if (LabelNumber == Label) {
377 ASSERT (GetForm && GetFormSet);
378 CopyGuid (FormsetGuid, &InternalFormSetGuid);
379 *FormId = InternalFormId;
380 return EFI_SUCCESS;
381 }
382
383
384 break;
385 default :
386 break;
387 }
388
389 //
390 // Go to the next Op-Code
391 //
392 Offset += IfrOpHdr->Length;
393 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
394 }
395
396 return EFI_NOT_FOUND;
397 }
398
399 /**
400 Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
401
402 EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
403 does not restrict labels with same label value to be duplicated in either FormSet
404 scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
405 with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
406 and Form ID is returned if such Label is found.
407
408
409 @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
410 @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
411 There is no Form ID with value Label found in all Form Sets in the pacakge
412 list.
413
414 @retval EFI_SUCCESS The first found Form ID is returned in FormId.
415 **/
416 EFI_STATUS
417 LocateFormId (
418 IN EFI_HII_HANDLE Handle,
419 IN EFI_FORM_LABEL Label,
420 OUT EFI_GUID *FormsetGuid,
421 OUT EFI_FORM_ID *FormId
422 )
423 {
424 EFI_STATUS Status;
425 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
426 UINT32 Index;
427 UINTN BufferSize;
428 EFI_HII_PACKAGE_HEADER PackageHeader;
429 EFI_HII_PACKAGE_HEADER *Package;
430 UINT32 PackageLength;
431
432 BufferSize = 0;
433 HiiPackageList = NULL;
434 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
435 if (Status == EFI_BUFFER_TOO_SMALL) {
436 HiiPackageList = AllocatePool (BufferSize);
437 ASSERT (HiiPackageList != NULL);
438
439 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
440 if (EFI_ERROR (Status)) {
441 goto Done;
442 }
443 }
444
445 for (Index = 0; ; Index++) {
446 Status = GetPackageData (HiiPackageList, Index, &PackageLength, &Package);
447 if (!EFI_ERROR (Status)) {
448 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
449 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
450 Status = LocateLabel (Package, Label, FormsetGuid, FormId);
451 if (!EFI_ERROR(Status)) {
452 break;
453 }
454 }
455 } else {
456 break;
457 }
458 }
459
460
461 Done:
462 FreePool (HiiPackageList);
463
464 return Status;
465 }
466 /**
467 This function allows the caller to update a form that has
468 previously been registered with the EFI HII database.
469
470
471 @param This EDES_TODO: Add parameter description
472 @param Handle Hii Handle associated with the Formset to modify
473 @param Label Update information starting immediately after this label in the IFR
474 @param AddData If TRUE, add data. If FALSE, remove data
475 @param Data If adding data, this is the pointer to the data to add
476
477 @retval EFI_SUCCESS Update success.
478 @retval Other Update fail.
479
480 **/
481 EFI_STATUS
482 EFIAPI
483 HiiUpdateForm (
484 IN EFI_HII_PROTOCOL *This,
485 IN FRAMEWORK_EFI_HII_HANDLE Handle,
486 IN EFI_FORM_LABEL Label,
487 IN BOOLEAN AddData,
488 IN FRAMEWORK_EFI_HII_UPDATE_DATA *Data
489 )
490 {
491 EFI_STATUS Status;
492 HII_THUNK_PRIVATE_DATA *Private;
493 HII_THUNK_CONTEXT *ThunkContext;
494 EFI_HII_UPDATE_DATA *UefiHiiUpdateData;
495 EFI_HII_HANDLE UefiHiiHandle;
496 EFI_GUID FormsetGuid;
497 EFI_FORM_ID FormId;
498 EFI_TPL OldTpl;
499
500 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
501
502 mInFrameworkUpdatePakcage = TRUE;
503 Status = EFI_SUCCESS;
504 UefiHiiUpdateData = NULL;
505
506
507 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
508
509 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
510
511 if (ThunkContext == NULL) {
512 Status = EFI_NOT_FOUND;
513 goto Done;
514 }
515
516 if (Data->FormSetUpdate) {
517 Status = UpdateFormCallBack ((EFI_HANDLE) (UINTN) Data->FormCallbackHandle, ThunkContext);
518 if (EFI_ERROR (Status)) {
519 goto Done;
520 }
521 }
522
523 if ((ThunkContext->IfrPackageCount == 0) && (ThunkContext->StringPackageCount != 0)) {
524 UefiHiiHandle = TagGuidToUefiHiiHandle (Private, &ThunkContext->TagGuid);
525
526 if (UefiHiiHandle == NULL) {
527 Status = EFI_INVALID_PARAMETER;
528 goto Done;
529 }
530 } else {
531 UefiHiiHandle = ThunkContext->UefiHiiHandle;
532 }
533
534 Status = LocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId);
535 if (EFI_ERROR (Status)) {
536 //
537 // Can't find the label.
538 //
539 goto Done;
540 }
541
542 if (AddData) {
543 if (Data->DataCount != 0) {
544
545 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
546 Status = FwUpdateDataToUefiUpdateData (ThunkContext, Data, AddData, &UefiHiiUpdateData);
547 ASSERT_EFI_ERROR (Status);
548
549 Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, AddData, UefiHiiUpdateData);
550 ASSERT_EFI_ERROR (Status);
551
552 }
553 } else {
554 //
555 // Delete Opcode starting from Labe in FormId found
556 //
557 UefiHiiUpdateData = AllocateZeroPool (sizeof (*UefiHiiUpdateData));
558
559 Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, FALSE, UefiHiiUpdateData);
560 ASSERT_EFI_ERROR (Status);
561 }
562
563 Done:
564 if (UefiHiiUpdateData != NULL) {
565 SafeFreePool (UefiHiiUpdateData->Data);
566 SafeFreePool (UefiHiiUpdateData);
567 }
568
569 mInFrameworkUpdatePakcage = FALSE;
570
571 gBS->RestoreTPL (OldTpl);
572
573 return Status;
574 }