]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Forms.c
d39001f981bb1eb353ea02a7d8c53e17559e0ac7
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / 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
19 //
20 // This structure is only intended to be used in this file.
21 //
22 #pragma pack(1)
23 typedef struct {
24 EFI_HII_PACK_HEADER PackageHeader;
25 FRAMEWORK_EFI_IFR_FORM_SET FormSet;
26 FRAMEWORK_EFI_IFR_END_FORM_SET EndFormSet;
27 } FW_HII_FORMSET_TEMPLATE;
28 #pragma pack()
29
30 FW_HII_FORMSET_TEMPLATE FormSetTemplate = {
31 {
32 sizeof (FW_HII_FORMSET_TEMPLATE),
33 EFI_HII_IFR
34 },
35 {
36 {
37 FRAMEWORK_EFI_IFR_FORM_SET_OP,
38 sizeof (FRAMEWORK_EFI_IFR_FORM_SET)
39 },
40 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}, //Guid
41 0,
42 0,
43 0,
44 0,
45 0,
46 0
47 },
48 {
49 {
50 FRAMEWORK_EFI_IFR_END_FORM_SET_OP,
51 sizeof (FRAMEWORK_EFI_IFR_END_FORM_SET)
52 }
53 }
54 };
55
56
57 EFI_GUID mTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
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 if (ThunkContext->FormSet != NULL) {
149 OutputFormSet->FormSet.Class = ThunkContext->FormSet->Class;
150 OutputFormSet->FormSet.SubClass = ThunkContext->FormSet->SubClass;
151 OutputFormSet->FormSet.Help = ThunkContext->FormSet->Help;
152 OutputFormSet->FormSet.FormSetTitle = ThunkContext->FormSet->FormSetTitle;
153 }
154
155 return EFI_SUCCESS;
156 }
157
158
159 /**
160
161 This function allows a program to extract the NV Image
162 that represents the default storage image
163
164
165 @param This A pointer to the EFI_HII_PROTOCOL instance.
166 @param Handle The HII handle from which will have default data retrieved.
167 UINTN - Mask used to retrieve the default image.
168 @param DefaultMask EDES_TODO: Add parameter description
169 @param VariablePackList Callee allocated, tightly-packed, link list data
170 structure that contain all default varaible packs
171 from the Hii Database.
172
173 @retval EFI_NOT_FOUND If Hii database does not contain any default images.
174 @retval EFI_INVALID_PARAMETER Invalid input parameter.
175 @retval EFI_SUCCESS Operation successful.
176
177 **/
178 EFI_STATUS
179 EFIAPI
180 HiiGetDefaultImage (
181 IN EFI_HII_PROTOCOL *This,
182 IN FRAMEWORK_EFI_HII_HANDLE Handle,
183 IN UINTN DefaultMask,
184 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
185 )
186 {
187 LIST_ENTRY *UefiDefaults;
188 EFI_STATUS Status;
189 HII_THUNK_PRIVATE_DATA *Private;
190 HII_THUNK_CONTEXT *ThunkContext;
191
192 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
193
194 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
195 if (ThunkContext == NULL) {
196 ASSERT (FALSE);
197 return EFI_INVALID_PARAMETER;
198 }
199
200 UefiDefaults = NULL;
201 Status = UefiIfrGetBufferTypeDefaults (ThunkContext, &UefiDefaults);
202 if (EFI_ERROR (Status)) {
203 goto Done;
204 }
205
206 Status = UefiDefaultsToFwDefaults (UefiDefaults, DefaultMask, ThunkContext->FormSet->DefaultVarStoreId, VariablePackList);
207
208 Done:
209 FreeDefaultList (UefiDefaults);
210
211 return Status;
212 }
213
214 /**
215 This function update the FormCallbackProtocol cached in Config Access
216 private context data.
217
218 @param CallbackHandle The EFI Handle on which the Framework FormCallbackProtocol is
219 installed.
220 @param ThunkContext The Thunk Context.
221
222 @retval EFI_SUCCESS The update is successful.
223 @retval EFI_INVALID_PARAMETER If no Framework FormCallbackProtocol is located on CallbackHandle.
224
225 **/
226 EFI_STATUS
227 UpdateFormCallBack (
228 IN EFI_HANDLE CallbackHandle,
229 IN CONST HII_THUNK_CONTEXT *ThunkContext
230 )
231 {
232 EFI_STATUS Status;
233 EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;
234 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccessProtocol;
235 EFI_HANDLE UefiDriverHandle;
236 CONFIG_ACCESS_PRIVATE *ConfigAccessPrivate;
237
238 Status = gBS->HandleProtocol (
239 CallbackHandle,
240 &gEfiFormCallbackProtocolGuid,
241 (VOID **) &FormCallbackProtocol
242 );
243 if (EFI_ERROR (Status)) {
244 return EFI_INVALID_PARAMETER;
245 }
246
247 Status = mHiiDatabase->GetPackageListHandle (
248 mHiiDatabase,
249 ThunkContext->UefiHiiHandle,
250 &UefiDriverHandle
251 );
252 ASSERT_EFI_ERROR (Status);
253 Status = gBS->HandleProtocol (
254 UefiDriverHandle,
255 &gEfiHiiConfigAccessProtocolGuid,
256 (VOID **) &ConfigAccessProtocol
257 );
258 ASSERT_EFI_ERROR (Status);
259
260 ConfigAccessPrivate = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (ConfigAccessProtocol);
261
262 ConfigAccessPrivate->FormCallbackProtocol = FormCallbackProtocol;
263
264 return EFI_SUCCESS;
265 }
266
267
268 /**
269 Get the package data from the Package List.
270
271 @param HiiPackageList Package List.
272 @param PackageIndex The index of the Package in the Package List.
273 @param BufferLen The Length of the Pacage data.
274 @param Buffer On output, the Package data.
275
276 @return EFI_NOT_FOUND No Package is found for PackageIndex.
277 @return EFI_SUCCESS The package data is returned.
278
279 **/
280 EFI_STATUS
281 GetPackageData (
282 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
283 IN UINT32 PackageIndex,
284 OUT UINT32 *BufferLen,
285 OUT EFI_HII_PACKAGE_HEADER **Buffer
286 )
287 {
288 UINT32 Index;
289 EFI_HII_PACKAGE_HEADER *Package;
290 UINT32 Offset;
291 UINT32 PackageListLength;
292 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
293
294 ASSERT(HiiPackageList != NULL);
295
296 if ((BufferLen == NULL) || (Buffer == NULL)) {
297 return EFI_INVALID_PARAMETER;
298 }
299
300 Package = NULL;
301 Index = 0;
302 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
303 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
304 while (Offset < PackageListLength) {
305 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
306 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
307 if (Index == PackageIndex) {
308 break;
309 }
310 Offset += PackageHeader.Length;
311 Index++;
312 }
313 if (Offset >= PackageListLength) {
314 //
315 // no package found in this Package List
316 //
317 return EFI_NOT_FOUND;
318 }
319
320 *BufferLen = PackageHeader.Length;
321 *Buffer = Package;
322 return EFI_SUCCESS;
323 }
324
325 /**
326 Check if Label exist in the IFR form package and return the FormSet GUID
327 and Form ID.
328
329 @param Package The Package Header.
330 @param Label The Label ID.
331 @param FormsetGuid Returns the FormSet GUID.
332 @param FormId Returns the Form ID.
333
334 @retval EFI_SUCCESS The FORM ID is found.
335 @retval EFI_NOT_FOUND The FORM ID is not found.
336 **/
337 EFI_STATUS
338 LocateLabel (
339 IN CONST EFI_HII_PACKAGE_HEADER *Package,
340 IN EFI_FORM_LABEL Label,
341 OUT EFI_GUID *FormsetGuid,
342 OUT EFI_FORM_ID *FormId
343 )
344 {
345 UINTN Offset;
346 EFI_IFR_OP_HEADER *IfrOpHdr;
347 EFI_GUID InternalFormSetGuid;
348 EFI_FORM_ID InternalFormId;
349 BOOLEAN GetFormSet;
350 BOOLEAN GetForm;
351 EFI_IFR_GUID_LABEL *LabelOpcode;
352
353 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
354 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
355
356 InternalFormId= 0;
357 ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID));
358 GetFormSet = FALSE;
359 GetForm = FALSE;
360
361 while (Offset < Package->Length) {
362 switch (IfrOpHdr->OpCode) {
363 case EFI_IFR_FORM_SET_OP :
364 CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID));
365 GetFormSet = TRUE;
366 break;
367
368 case EFI_IFR_FORM_OP:
369 CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID));
370 GetForm = TRUE;
371 break;
372
373 case EFI_IFR_GUID_OP :
374 LabelOpcode = (EFI_IFR_GUID_LABEL *) IfrOpHdr;
375 //
376 // If it is an Label opcode.
377 //
378 if ((LabelOpcode->ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) && (CompareMem (&LabelOpcode->Guid, &mTianoHiiIfrGuid, sizeof (EFI_GUID)) == 0)) {
379 if (CompareMem (&Label, &LabelOpcode->Number, sizeof (UINT16)) == 0) {
380 ASSERT (GetForm && GetFormSet);
381 CopyGuid (FormsetGuid, &InternalFormSetGuid);
382 *FormId = InternalFormId;
383 return EFI_SUCCESS;
384 }
385 }
386 break;
387 default :
388 break;
389 }
390
391 //
392 // Go to the next Op-Code
393 //
394 Offset += IfrOpHdr->Length;
395 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
396 }
397
398 return EFI_NOT_FOUND;
399 }
400
401 /**
402 Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
403
404 EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
405 does not restrict labels with same label value to be duplicated in either FormSet
406 scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
407 with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
408 and Form ID is returned if such Label is found.
409
410
411 @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
412 @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
413 There is no Form ID with value Label found in all Form Sets in the pacakge
414 list.
415
416 @retval EFI_SUCCESS The first found Form ID is returned in FormId.
417 **/
418 EFI_STATUS
419 LocateFormId (
420 IN EFI_HII_HANDLE Handle,
421 IN EFI_FORM_LABEL Label,
422 OUT EFI_GUID *FormsetGuid,
423 OUT EFI_FORM_ID *FormId
424 )
425 {
426 EFI_STATUS Status;
427 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
428 UINT32 Index;
429 UINTN BufferSize;
430 EFI_HII_PACKAGE_HEADER PackageHeader;
431 EFI_HII_PACKAGE_HEADER *Package;
432 UINT32 PackageLength;
433
434 BufferSize = 0;
435 HiiPackageList = NULL;
436 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
437 if (Status == EFI_BUFFER_TOO_SMALL) {
438 HiiPackageList = AllocatePool (BufferSize);
439 ASSERT (HiiPackageList != NULL);
440
441 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
442 if (EFI_ERROR (Status)) {
443 goto Done;
444 }
445 }
446
447 for (Index = 0; ; Index++) {
448 Status = GetPackageData (HiiPackageList, Index, &PackageLength, &Package);
449 if (!EFI_ERROR (Status)) {
450 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
451 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
452 Status = LocateLabel (Package, Label, FormsetGuid, FormId);
453 if (!EFI_ERROR(Status)) {
454 break;
455 }
456 }
457 } else {
458 break;
459 }
460 }
461
462
463 Done:
464 FreePool (HiiPackageList);
465
466 return Status;
467 }
468
469 /**
470 This function allows the caller to update a form that has
471 previously been registered with the EFI HII database.
472
473
474 @param This EDES_TODO: Add parameter description
475 @param Handle Hii Handle associated with the Formset to modify
476 @param Label Update information starting immediately after this label in the IFR
477 @param AddData If TRUE, add data. If FALSE, remove data
478 @param Data If adding data, this is the pointer to the data to add
479
480 @retval EFI_SUCCESS Update success.
481 @retval Other Update fail.
482
483 **/
484 EFI_STATUS
485 EFIAPI
486 HiiThunkUpdateForm (
487 IN EFI_HII_PROTOCOL *This,
488 IN FRAMEWORK_EFI_HII_HANDLE Handle,
489 IN EFI_FORM_LABEL Label,
490 IN BOOLEAN AddData,
491 IN EFI_HII_UPDATE_DATA *Data
492 )
493 {
494 EFI_STATUS Status;
495 HII_THUNK_PRIVATE_DATA *Private;
496 HII_THUNK_CONTEXT *ThunkContext;
497 EFI_HII_HANDLE UefiHiiHandle;
498 EFI_GUID FormsetGuid;
499 EFI_FORM_ID FormId;
500 EFI_TPL OldTpl;
501 VOID *StartOpCodeHandle;
502 VOID *EndOpCodeHandle;
503 EFI_IFR_GUID_LABEL *StartLabel;
504 EFI_IFR_GUID_LABEL *EndLabel;
505
506 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
507
508 mInFrameworkUpdatePakcage = TRUE;
509 Status = EFI_SUCCESS;
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 //
544 // Init OpCode Handle
545 //
546 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
547 ASSERT (StartOpCodeHandle != NULL);
548
549 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
550 ASSERT (EndOpCodeHandle != NULL);
551
552 //
553 // Create Hii Extend Label OpCode as the start opcode
554 //
555 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
556 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
557 StartLabel->Number = Label;
558
559 //
560 // Create Hii Extend Label OpCode as the end opcode
561 //
562 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
563 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
564 EndLabel->Number = 0xffff;
565
566 if (AddData) {
567 if (Data->DataCount != 0) {
568
569 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
570 Status = FwUpdateDataToUefiUpdateData (ThunkContext, Data, StartOpCodeHandle);
571 ASSERT_EFI_ERROR (Status);
572
573 Status = HiiUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, StartOpCodeHandle, NULL);
574 ASSERT_EFI_ERROR (Status);
575 }
576 } else {
577 //
578 // Delete Opcode starting from Labe in FormId found
579 //
580 Status = HiiUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, StartOpCodeHandle, EndOpCodeHandle);
581 ASSERT_EFI_ERROR (Status);
582 }
583
584 HiiFreeOpCodeHandle (StartOpCodeHandle);
585 HiiFreeOpCodeHandle (EndOpCodeHandle);
586
587 Done:
588
589 mInFrameworkUpdatePakcage = FALSE;
590
591 gBS->RestoreTPL (OldTpl);
592
593 return Status;
594 }