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