]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c
Add in code to support the deletion of opcode from a form.
[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 EFI_STATUS
21 EFIAPI
22 HiiExportDatabase (
23 IN EFI_HII_PROTOCOL *This,
24 IN FRAMEWORK_EFI_HII_HANDLE Handle,
25 IN OUT UINTN *BufferSize,
26 OUT VOID *Buffer
27 )
28 /*++
29
30 Routine Description:
31
32 This function allows a program to extract a form or form package that has
33 previously been registered with the EFI HII database.
34
35 Arguments:
36
37 Returns:
38
39 --*/
40 {
41 ASSERT (FALSE);
42 return EFI_UNSUPPORTED;
43 }
44
45 EFI_STATUS
46 EFIAPI
47 HiiGetForms (
48 IN EFI_HII_PROTOCOL *This,
49 IN FRAMEWORK_EFI_HII_HANDLE Handle,
50 IN EFI_FORM_ID FormId,
51 IN OUT UINTN *BufferLengthTemp,
52 OUT UINT8 *Buffer
53 )
54 /*++
55
56 Routine Description:
57
58 This function allows a program to extract a form or form package that has
59 previously been registered with the EFI HII database.
60
61 Arguments:
62 This - A pointer to the EFI_HII_PROTOCOL instance.
63
64 Handle - Handle on which the form resides. Type FRAMEWORK_EFI_HII_HANDLE is defined in
65 EFI_HII_PROTOCOL.NewPack() in the Packages section.
66
67 FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.
68 Type EFI_FORM_ID is defined in "Related Definitions" below.
69
70 BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
71 the length was sufficient and, if it was not, the length that is required to fit the
72 requested form(s).
73
74 Buffer - The buffer designed to receive the form(s).
75
76 Returns:
77
78 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength
79 was updated.
80
81 EFI_INVALID_PARAMETER - The handle is unknown.
82
83 EFI_NOT_FOUND - A form on the requested handle cannot be found with the
84 requested FormId.
85
86 EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.
87
88 --*/
89 {
90 ASSERT (FALSE);
91 return EFI_UNSUPPORTED;
92 }
93
94
95 EFI_STATUS
96 EFIAPI
97 HiiGetDefaultImage (
98 IN EFI_HII_PROTOCOL *This,
99 IN FRAMEWORK_EFI_HII_HANDLE Handle,
100 IN UINTN DefaultMask,
101 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
102 )
103 /*++
104
105 Routine Description:
106
107 This function allows a program to extract the NV Image
108 that represents the default storage image
109
110 Arguments:
111 This - A pointer to the EFI_HII_PROTOCOL instance.
112 Handle - The HII handle from which will have default data retrieved.
113 UINTN - Mask used to retrieve the default image.
114 VariablePackList - Callee allocated, tightly-packed, link list data
115 structure that contain all default varaible packs
116 from the Hii Database.
117
118 Returns:
119 EFI_NOT_FOUND - If Hii database does not contain any default images.
120 EFI_INVALID_PARAMETER - Invalid input parameter.
121 EFI_SUCCESS - Operation successful.
122
123 --*/
124 {
125 LIST_ENTRY *UefiDefaults;
126 EFI_HII_HANDLE UefiHiiHandle;
127 EFI_STATUS Status;
128 EFI_HII_THUNK_PRIVATE_DATA *Private;
129
130 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
131
132 UefiHiiHandle = FrameworkHiiHandleToUefiHiiHandle (Private, Handle);
133 if (UefiHiiHandle == NULL) {
134 ASSERT (FALSE);
135 return EFI_INVALID_PARAMETER;
136 }
137
138 UefiDefaults = NULL;
139 Status = UefiIfrGetBufferTypeDefaults (UefiHiiHandle, &UefiDefaults);
140 if (EFI_ERROR (Status)) {
141 goto Done;
142 }
143
144 Status = UefiDefaultsToFrameworkDefaults (UefiDefaults, DefaultMask, VariablePackList);
145
146 Done:
147 FreeDefaultList (UefiDefaults);
148
149 return Status;
150 }
151
152 EFI_STATUS
153 ThunkUpdateFormCallBack (
154 IN EFI_HANDLE CallbackHandle,
155 IN CONST HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry
156 )
157 {
158 EFI_STATUS Status;
159 EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallbackProtocol;
160 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccessProtocol;
161 EFI_HANDLE UefiDriverHandle;
162 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigAccessProtocolInstance;
163
164 Status = gBS->HandleProtocol (
165 CallbackHandle,
166 &gEfiFormCallbackProtocolGuid,
167 (VOID **) &FrameworkFormCallbackProtocol
168 );
169 if (EFI_ERROR (Status)) {
170 return EFI_INVALID_PARAMETER;
171 }
172
173 Status = mHiiDatabase->GetPackageListHandle (
174 mHiiDatabase,
175 HandleMapEntry->UefiHiiHandle,
176 &UefiDriverHandle
177 );
178 ASSERT_EFI_ERROR (Status);
179 Status = gBS->HandleProtocol (
180 UefiDriverHandle,
181 &gEfiHiiConfigAccessProtocolGuid,
182 (VOID **) &ConfigAccessProtocol
183 );
184 ASSERT_EFI_ERROR (Status);
185
186 ConfigAccessProtocolInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (ConfigAccessProtocol);
187
188 ConfigAccessProtocolInstance->FrameworkFormCallbackProtocol = FrameworkFormCallbackProtocol;
189
190 return EFI_SUCCESS;
191 }
192
193
194 STATIC
195 EFI_STATUS
196 GetPackageDataFromPackageList (
197 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
198 IN UINT32 PackageIndex,
199 OUT UINT32 *BufferLen,
200 OUT EFI_HII_PACKAGE_HEADER **Buffer
201 )
202 {
203 UINT32 Index;
204 EFI_HII_PACKAGE_HEADER *Package;
205 UINT32 Offset;
206 UINT32 PackageListLength;
207 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
208
209 ASSERT(HiiPackageList != NULL);
210
211 if ((BufferLen == NULL) || (Buffer == NULL)) {
212 return EFI_INVALID_PARAMETER;
213 }
214
215 Package = NULL;
216 Index = 0;
217 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
218 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
219 while (Offset < PackageListLength) {
220 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
221 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
222 if (Index == PackageIndex) {
223 break;
224 }
225 Offset += PackageHeader.Length;
226 Index++;
227 }
228 if (Offset >= PackageListLength) {
229 //
230 // no package found in this Package List
231 //
232 return EFI_NOT_FOUND;
233 }
234
235 *BufferLen = PackageHeader.Length;
236 *Buffer = Package;
237 return EFI_SUCCESS;
238 }
239
240 /**
241 Check if Label exist in the IFR form package.
242
243 @param
244
245 **/
246 EFI_STATUS
247 LocateLabel (
248 IN CONST EFI_HII_PACKAGE_HEADER *Package,
249 IN EFI_FORM_LABEL Label,
250 OUT EFI_GUID *FormsetGuid,
251 OUT EFI_FORM_ID *FormId
252 )
253 {
254 UINTN Offset;
255 EFI_IFR_OP_HEADER *IfrOpHdr;
256 UINT8 ExtendOpCode;
257 UINT16 LabelNumber;
258 EFI_GUID InternalFormSetGuid;
259 EFI_FORM_ID InternalFormId;
260 BOOLEAN GetFormSet;
261 BOOLEAN GetForm;
262
263 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
264 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
265
266 InternalFormId= 0;
267 ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID));
268 GetFormSet = FALSE;
269 GetForm = FALSE;
270
271 while (Offset < Package->Length) {
272 switch (IfrOpHdr->OpCode) {
273 case EFI_IFR_FORM_SET_OP :
274 CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID));
275 GetFormSet = TRUE;
276 break;
277
278 case EFI_IFR_FORM_OP:
279 CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID));
280 GetForm = TRUE;
281 break;
282
283 case EFI_IFR_GUID_OP :
284 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
285
286 if (ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) {
287 //
288 // Go to the next Op-Code
289 //
290 Offset += IfrOpHdr->Length;
291 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
292 continue;
293 }
294
295 CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
296 if (LabelNumber == Label) {
297 ASSERT (GetForm && GetFormSet);
298 CopyGuid (FormsetGuid, &InternalFormSetGuid);
299 *FormId = InternalFormId;
300 return EFI_SUCCESS;
301 }
302
303
304 break;
305 default :
306 break;
307 }
308
309 //
310 // Go to the next Op-Code
311 //
312 Offset += IfrOpHdr->Length;
313 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
314 }
315
316 return EFI_NOT_FOUND;
317 }
318
319 /**
320 Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
321
322 EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
323 does not restrict labels with same label value to be duplicated in either FormSet
324 scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
325 with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
326 and Form ID is returned if such Label is found.
327
328
329 @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
330 @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
331 There is no Form ID with value Label found in all Form Sets in the pacakge
332 list.
333
334 @retval EFI_SUCCESS The first found Form ID is returned in FormId.
335 **/
336 EFI_STATUS
337 ThunkLocateFormId (
338 IN EFI_HII_HANDLE Handle,
339 IN EFI_FORM_LABEL Label,
340 OUT EFI_GUID *FormsetGuid,
341 OUT EFI_FORM_ID *FormId
342 )
343 {
344 EFI_STATUS Status;
345 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
346 UINT32 Index;
347 UINTN BufferSize;
348 EFI_HII_PACKAGE_HEADER PackageHeader;
349 EFI_HII_PACKAGE_HEADER *Package;
350 UINT32 PackageLength;
351
352 BufferSize = 0;
353 HiiPackageList = NULL;
354 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
355 if (Status == EFI_BUFFER_TOO_SMALL) {
356 HiiPackageList = AllocatePool (BufferSize);
357 ASSERT (HiiPackageList != NULL);
358
359 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
360 if (EFI_ERROR (Status)) {
361 goto Done;
362 }
363 }
364
365 for (Index = 0; ; Index++) {
366 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
367 if (!EFI_ERROR (Status)) {
368 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
369 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
370 Status = LocateLabel (Package, Label, FormsetGuid, FormId);
371 if (!EFI_ERROR(Status)) {
372 break;
373 }
374 }
375 } else {
376 break;
377 }
378 }
379
380
381 Done:
382 FreePool (HiiPackageList);
383
384 return Status;
385 }
386 EFI_STATUS
387 EFIAPI
388 HiiUpdateForm (
389 IN EFI_HII_PROTOCOL *This,
390 IN FRAMEWORK_EFI_HII_HANDLE Handle,
391 IN EFI_FORM_LABEL Label,
392 IN BOOLEAN AddData,
393 IN FRAMEWORK_EFI_HII_UPDATE_DATA *Data
394 )
395 /*++
396
397 Routine Description:
398 This function allows the caller to update a form that has
399 previously been registered with the EFI HII database.
400
401 Arguments:
402 Handle - Hii Handle associated with the Formset to modify
403 Label - Update information starting immediately after this label in the IFR
404 AddData - If TRUE, add data. If FALSE, remove data
405 Data - If adding data, this is the pointer to the data to add
406
407 Returns:
408 EFI_SUCCESS - Update success.
409 Other - Update fail.
410
411 --*/
412 {
413 EFI_STATUS Status;
414 EFI_HII_THUNK_PRIVATE_DATA *Private;
415 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
416 EFI_HII_UPDATE_DATA *UefiHiiUpdateData;
417 EFI_HII_HANDLE UefiHiiHandle;
418 EFI_GUID FormsetGuid;
419 EFI_FORM_ID FormId;
420
421 Status = EFI_SUCCESS;
422
423 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
424
425 HandleMapEntry = FrameworkHiiHandleToMapDatabaseEntry (Private, Handle);
426
427 if (HandleMapEntry == NULL) {
428 return EFI_NOT_FOUND;
429 }
430
431 if (Data->FormSetUpdate) {
432 Status = ThunkUpdateFormCallBack ((EFI_HANDLE) (UINTN) Data->FormCallbackHandle, HandleMapEntry);
433 if (EFI_ERROR (Status)) {
434 return Status;
435 }
436 }
437
438 if (HandleMapEntry->IsPackageListWithOnlyStringPackages) {
439 UefiHiiHandle = TagGuidToUefiIfrHiiHandle (Private, &HandleMapEntry->TagGuid);
440
441 if (UefiHiiHandle == NULL) {
442 return EFI_INVALID_PARAMETER;
443 }
444 } else {
445 UefiHiiHandle = HandleMapEntry->UefiHiiHandle;
446 }
447
448 UefiHiiUpdateData = NULL;
449
450 if (AddData) {
451 if (Data->DataCount != 0) {
452
453 Status = ThunkFrameworkUpdateDataToUefiUpdateData (Data, AddData, &UefiHiiUpdateData);
454 ASSERT_EFI_ERROR (Status);
455
456 Status = ThunkLocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId);
457 ASSERT_EFI_ERROR (Status);
458
459 Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, AddData, UefiHiiUpdateData);
460 ASSERT_EFI_ERROR (Status);
461
462 } else {
463 ASSERT (FALSE);
464 return EFI_INVALID_PARAMETER;
465 }
466
467 } else {
468 Status = ThunkLocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId);
469 ASSERT_EFI_ERROR (Status);
470
471 //
472 // Delete Opcode starting from Labe in FormId found
473 //
474
475 Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, FALSE, NULL);
476 ASSERT_EFI_ERROR (Status);
477 }
478
479 if (UefiHiiUpdateData != NULL) {
480 SafeFreePool (UefiHiiUpdateData->Data);
481 SafeFreePool (UefiHiiUpdateData);
482 }
483
484 return Status;
485 }