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