]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/ExtendedIfrSupportLib/Form.c
Update all files to follow doxygen style file header.
[mirror_edk2.git] / MdeModulePkg / Library / ExtendedIfrSupportLib / Form.c
1 /** @file
2 Common Library Routines to assist handle HII elements.
3
4 Copyright (c) 2007 - 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 #include "LibraryInternal.h"
16
17 STATIC
18 EFI_STATUS
19 GetPackageDataFromPackageList (
20 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
21 IN UINT32 PackageIndex,
22 OUT UINT32 *BufferLen,
23 OUT EFI_HII_PACKAGE_HEADER **Buffer
24 )
25 {
26 UINT32 Index;
27 EFI_HII_PACKAGE_HEADER *Package;
28 UINT32 Offset;
29 UINT32 PackageListLength;
30 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
31
32 ASSERT(HiiPackageList != NULL);
33
34 if ((BufferLen == NULL) || (Buffer == NULL)) {
35 return EFI_INVALID_PARAMETER;
36 }
37
38 Package = NULL;
39 Index = 0;
40 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
41 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
42 while (Offset < PackageListLength) {
43 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
44 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
45 if (Index == PackageIndex) {
46 break;
47 }
48 Offset += PackageHeader.Length;
49 Index++;
50 }
51 if (Offset >= PackageListLength) {
52 //
53 // no package found in this Package List
54 //
55 return EFI_NOT_FOUND;
56 }
57
58 *BufferLen = PackageHeader.Length;
59 *Buffer = Package;
60 return EFI_SUCCESS;
61 }
62
63 STATIC
64 EFI_STATUS
65 EFIAPI
66 UpdateFormPackageData (
67 IN EFI_GUID *FormSetGuid,
68 IN EFI_FORM_ID FormId,
69 IN EFI_HII_PACKAGE_HEADER *Package,
70 IN UINT32 PackageLength,
71 IN UINT16 Label,
72 IN BOOLEAN Insert,
73 IN EFI_HII_UPDATE_DATA *Data,
74 OUT UINT8 **TempBuffer,
75 OUT UINT32 *TempBufferSize
76 )
77 {
78 UINTN AddSize;
79 UINT8 *BufferPos;
80 EFI_HII_PACKAGE_HEADER PackageHeader;
81 UINTN Offset;
82 EFI_IFR_OP_HEADER *IfrOpHdr;
83 BOOLEAN GetFormSet;
84 BOOLEAN GetForm;
85 UINT8 ExtendOpCode;
86 UINT16 LabelNumber;
87 BOOLEAN Updated;
88 EFI_IFR_OP_HEADER *AddOpCode;
89
90 if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {
91 return EFI_INVALID_PARAMETER;
92 }
93
94 *TempBufferSize = PackageLength;
95 if (Data != NULL) {
96 *TempBufferSize += Data->Offset;
97 }
98 *TempBuffer = AllocateZeroPool (*TempBufferSize);
99 if (*TempBuffer == NULL) {
100 return EFI_OUT_OF_RESOURCES;
101 }
102
103 CopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));
104 *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);
105 BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);
106
107 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
108 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
109 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
110 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
111 GetForm = FALSE;
112 Updated = FALSE;
113
114 while (Offset < PackageHeader.Length) {
115 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
116 BufferPos += IfrOpHdr->Length;
117 *TempBufferSize += IfrOpHdr->Length;
118
119 switch (IfrOpHdr->OpCode) {
120 case EFI_IFR_FORM_SET_OP :
121 if (FormSetGuid != NULL) {
122 if (CompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {
123 GetFormSet = TRUE;
124 }
125 }
126 break;
127
128 case EFI_IFR_FORM_OP:
129 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
130 GetForm = TRUE;
131 }
132 break;
133
134 case EFI_IFR_GUID_OP :
135 if (!GetFormSet || !GetForm || Updated) {
136 //
137 // Go to the next Op-Code
138 //
139 Offset += IfrOpHdr->Length;
140 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
141 continue;
142 }
143
144 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
145 CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
146 if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {
147 //
148 // Go to the next Op-Code
149 //
150 Offset += IfrOpHdr->Length;
151 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
152 continue;
153 }
154
155 if (Insert && (Data != NULL)) {
156 //
157 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
158 // DataCount amount of opcodes unless runing into a label.
159 //
160 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
161 AddSize = 0;
162 while (AddSize < Data->Offset) {
163 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
164 BufferPos += AddOpCode->Length;
165 *TempBufferSize += AddOpCode->Length;
166
167 AddSize += AddOpCode->Length;
168 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
169 }
170 } else {
171 //
172 // Search the next Label.
173 //
174 while (TRUE) {
175 Offset += IfrOpHdr->Length;
176 //
177 // Search the next label and Fail if not label found.
178 //
179 if (Offset >= PackageHeader.Length) {
180 goto Fail;
181 }
182 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
183 if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {
184 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
185 if (ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {
186 break;
187 }
188 }
189 }
190
191 if (Data != NULL) {
192 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
193 AddSize = 0;
194 while (AddSize < Data->Offset) {
195 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
196 BufferPos += AddOpCode->Length;
197 *TempBufferSize += AddOpCode->Length;
198
199 AddSize += AddOpCode->Length;
200 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
201 }
202 }
203
204 //
205 // copy the next label
206 //
207 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
208 BufferPos += IfrOpHdr->Length;
209 *TempBufferSize += IfrOpHdr->Length;
210 }
211
212 Updated = TRUE;
213 break;
214 default :
215 break;
216 }
217
218 //
219 // Go to the next Op-Code
220 //
221 Offset += IfrOpHdr->Length;
222 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
223 }
224
225 //
226 // Update the package length.
227 //
228 PackageHeader.Length = *TempBufferSize;
229 CopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
230
231 Fail:
232 if (!Updated) {
233 gBS->FreePool (*TempBuffer);
234 *TempBufferSize = 0;
235 return EFI_NOT_FOUND;
236 }
237
238 return EFI_SUCCESS;
239 }
240
241
242 /**
243 This function allows the caller to update a form that has
244 previously been registered with the EFI HII database.
245
246 @param Handle Hii Handle
247 @param FormSetGuid The formset should be updated.
248 @param FormId The form should be updated.
249 @param Label Update information starting immediately after this
250 label in the IFR
251 @param Insert If TRUE and Data is not NULL, insert data after
252 Label. If FALSE, replace opcodes between two
253 labels with Data
254 @param Data The adding data; If NULL, remove opcodes between
255 two Label.
256
257 @retval EFI_SUCCESS Update success.
258 @retval Other Update fail.
259
260 **/
261 EFI_STATUS
262 EFIAPI
263 IfrLibUpdateForm (
264 IN EFI_HII_HANDLE Handle,
265 IN EFI_GUID *FormSetGuid, OPTIONAL
266 IN EFI_FORM_ID FormId,
267 IN UINT16 Label,
268 IN BOOLEAN Insert,
269 IN EFI_HII_UPDATE_DATA *Data
270 )
271 {
272 EFI_STATUS Status;
273 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
274 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
275 UINT32 Index;
276 EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;
277 UINTN BufferSize;
278 UINT8 *UpdateBufferPos;
279 EFI_HII_PACKAGE_HEADER PackageHeader;
280 EFI_HII_PACKAGE_HEADER *Package;
281 UINT32 PackageLength;
282 EFI_HII_PACKAGE_HEADER *TempBuffer;
283 UINT32 TempBufferSize;
284 BOOLEAN Updated;
285
286 if (Data == NULL) {
287 return EFI_INVALID_PARAMETER;
288 }
289
290 HiiDatabase = gIfrLibHiiDatabase;
291
292 //
293 // Get the orginal package list
294 //
295 BufferSize = 0;
296 HiiPackageList = NULL;
297 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
298 if (Status == EFI_BUFFER_TOO_SMALL) {
299 HiiPackageList = AllocatePool (BufferSize);
300 ASSERT (HiiPackageList != NULL);
301
302 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
303 if (EFI_ERROR (Status)) {
304 gBS->FreePool (HiiPackageList);
305 return Status;
306 }
307 }
308
309 //
310 // Calculate and allocate space for retrieval of IFR data
311 //
312 BufferSize += Data->Offset;
313 UpdateBuffer = AllocateZeroPool (BufferSize);
314 if (UpdateBuffer == NULL) {
315 return EFI_OUT_OF_RESOURCES;
316 }
317
318 UpdateBufferPos = (UINT8 *) UpdateBuffer;
319
320 //
321 // copy the package list header
322 //
323 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
324 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
325
326 Updated = FALSE;
327 for (Index = 0; ; Index++) {
328 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
329 if (Status == EFI_SUCCESS) {
330 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
331 if ((PackageHeader.Type == EFI_HII_PACKAGE_FORM) && !Updated) {
332 Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);
333 if (!EFI_ERROR(Status)) {
334 if (FormSetGuid == NULL) {
335 Updated = TRUE;
336 }
337 CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);
338 UpdateBufferPos += TempBufferSize;
339 gBS->FreePool (TempBuffer);
340 continue;
341 }
342 }
343
344 CopyMem (UpdateBufferPos, Package, PackageLength);
345 UpdateBufferPos += PackageLength;
346 } else if (Status == EFI_NOT_FOUND) {
347 break;
348 } else {
349 gBS->FreePool (HiiPackageList);
350 return Status;
351 }
352 }
353
354 //
355 // Update package list length
356 //
357 BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;
358 CopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));
359
360 gBS->FreePool (HiiPackageList);
361
362 return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);
363 }
364
365
366 /**
367 Configure the buffer accrording to ConfigBody strings.
368
369 @param DefaultId the ID of default.
370 @param Buffer the start address of buffer.
371 @param BufferSize the size of buffer.
372 @param Number the number of the strings.
373
374 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
375 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
376 @retval EFI_SUCCESS Operation successful.
377
378 **/
379 EFI_STATUS
380 EFIAPI
381 IfrLibExtractDefault(
382 IN VOID *Buffer,
383 IN UINTN *BufferSize,
384 UINTN Number,
385 ...
386 )
387 {
388 VA_LIST Args;
389 UINTN Index;
390 UINT32 TotalLen;
391 UINT8 *BufCfgArray;
392 UINT8 *BufferPos;
393 UINT16 Offset;
394 UINT16 Width;
395 UINT8 *Value;
396
397 if ((Buffer == NULL) || (BufferSize == NULL)) {
398 return EFI_INVALID_PARAMETER;
399 }
400
401 Offset = 0;
402 Width = 0;
403 Value = NULL;
404
405 VA_START (Args, Number);
406 for (Index = 0; Index < Number; Index++) {
407 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
408 CopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));
409 BufferPos = BufCfgArray + sizeof (UINT32);
410
411 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
412 CopyMem (&Offset, BufferPos, sizeof (UINT16));
413 BufferPos += sizeof (UINT16);
414 CopyMem (&Width, BufferPos, sizeof (UINT16));
415 BufferPos += sizeof (UINT16);
416 Value = BufferPos;
417 BufferPos += Width;
418
419 if ((UINTN)(Offset + Width) > *BufferSize) {
420 return EFI_BUFFER_TOO_SMALL;
421 }
422
423 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
424 }
425 }
426 VA_END (Args);
427
428 *BufferSize = (UINTN)Offset;
429
430 return EFI_SUCCESS;
431 }
432
433