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