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