]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.c
1) Add in support for Framework VFR file which specify all VAR Store correctly. This...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / UefiIfrDefault.c
1 /** @file
2 Function and Macro defintions for to extract default values from UEFI Form package.
3
4 Copyright (c) 2008, Intel Corporation
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 <FrameworkDxe.h>
17
18 #include <Protocol/FrameworkHii.h>
19 #include <Protocol/HiiDatabase.h>
20
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26
27 #include "HiiDatabase.h"
28 #include "UefiIfrParser.h"
29 #include "UefiIfrDefault.h"
30
31 //
32 // Extern Variables
33 //
34 extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
35 extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol;
36 extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol;
37 extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol;
38
39 /**
40 Set the data position at Offset with Width in Node->Buffer based
41 the value passed in.
42
43 @param Node The Buffer Storage Node.
44 @param Value The input value.
45 @param Offset The offset in Node->Buffer for the update.
46 @param Width The length of the Value.
47
48 @retval VOID
49
50 **/
51 VOID
52 SetNodeBuffer (
53 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node,
54 IN CONST EFI_HII_VALUE *Value,
55 IN UINTN Offset,
56 IN UINTN Width
57 )
58 {
59 ASSERT (Node->Signature == UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE);
60 ASSERT (Offset + Width <= Node->Size);
61
62 CopyMem (Node->Buffer + Offset, &Value->Value.u8, Width);
63 }
64
65
66 /**
67 Reset Question to its default value.
68
69 Note Framework 0.92's HII Implementation does not support for default value for these opcodes:
70 EFI_IFR_ORDERED_LIST_OP:
71 EFI_IFR_PASSWORD_OP:
72 EFI_IFR_STRING_OP:
73
74 @param FormSet FormSet data structure.
75 @param DefaultId The Class of the default.
76
77 @retval EFI_SUCCESS Question is reset to default value.
78
79 **/
80 EFI_STATUS
81 GetQuestionDefault (
82 IN FORM_BROWSER_FORMSET *FormSet,
83 IN FORM_BROWSER_FORM *Form,
84 IN FORM_BROWSER_STATEMENT *Question,
85 IN UINT16 DefaultId,
86 IN UINT16 VarStoreId,
87 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
88 )
89 {
90 EFI_STATUS Status;
91 LIST_ENTRY *Link;
92 QUESTION_DEFAULT *Default;
93 QUESTION_OPTION *Option;
94 EFI_HII_VALUE *HiiValue;
95
96 Status = EFI_SUCCESS;
97
98 //
99 // Statement don't have storage, skip them
100 //
101 if (Question->QuestionId == 0) {
102 return Status;
103 }
104
105 if (Question->VarStoreId != VarStoreId) {
106 return Status;
107 }
108
109 ASSERT (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER);
110
111 //
112 // There are three ways to specify default value for a Question:
113 // 1, use nested EFI_IFR_DEFAULT (highest priority)
114 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
115 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
116 //
117 HiiValue = &Question->HiiValue;
118
119 //
120 // EFI_IFR_DEFAULT has highest priority
121 //
122 if (!IsListEmpty (&Question->DefaultListHead)) {
123 Link = GetFirstNode (&Question->DefaultListHead);
124 while (!IsNull (&Question->DefaultListHead, Link)) {
125 Default = QUESTION_DEFAULT_FROM_LINK (Link);
126
127 if (Default->DefaultId == DefaultId) {
128 //
129 // Default value is embedded in EFI_IFR_DEFAULT
130 //
131 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
132
133 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
134 return EFI_SUCCESS;
135 }
136
137 Link = GetNextNode (&Question->DefaultListHead, Link);
138 }
139 }
140
141 //
142 // EFI_ONE_OF_OPTION
143 //
144 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
145 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
146 //
147 // OneOfOption could only provide Standard and Manufacturing default
148 //
149 Link = GetFirstNode (&Question->OptionListHead);
150 while (!IsNull (&Question->OptionListHead, Link)) {
151 Option = QUESTION_OPTION_FROM_LINK (Link);
152
153 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
154 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
155 ) {
156 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
157
158 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
159 return EFI_SUCCESS;
160 }
161
162 Link = GetNextNode (&Question->OptionListHead, Link);
163 }
164 }
165 }
166
167 //
168 // EFI_IFR_CHECKBOX - lowest priority
169 //
170 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
171 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
172 //
173 // Checkbox could only provide Standard and Manufacturing default
174 //
175 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
176 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
177 ) {
178 HiiValue->Value.b = TRUE;
179 } else {
180 HiiValue->Value.b = FALSE;
181 }
182
183 SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
184 return EFI_SUCCESS;
185 }
186 }
187
188 return Status;
189 }
190
191
192 /**
193 Reset Questions in a Form to their default value.
194
195 @param FormSet FormSet data structure.
196 @param Form The Form which to be reset.
197 @param DefaultId The Class of the default.
198
199 @retval EFI_SUCCESS The function completed successfully.
200
201 **/
202 EFI_STATUS
203 ExtractFormDefault (
204 IN FORM_BROWSER_FORMSET *FormSet,
205 IN FORM_BROWSER_FORM *Form,
206 IN UINT16 DefaultId,
207 IN UINT16 VarStoreId,
208 OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
209 )
210 {
211 EFI_STATUS Status;
212 LIST_ENTRY *Link;
213 FORM_BROWSER_STATEMENT *Question;
214
215 Link = GetFirstNode (&Form->StatementListHead);
216 while (!IsNull (&Form->StatementListHead, Link)) {
217 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
218 //
219 // Reset Question to its default value
220 //
221 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, VarStoreId, Node);
222 if (EFI_ERROR (Status)) {
223 continue;
224 }
225
226 Link = GetNextNode (&Form->StatementListHead, Link);
227 }
228 return EFI_SUCCESS;
229 }
230
231
232 /**
233 Destroy all the buffer allocated for the fileds of
234 UEFI_IFR_BUFFER_STORAGE_NODE. The Node itself
235 will be freed too.
236
237 @param FormSet FormSet data structure.
238 @param DefaultId The Class of the default.
239
240 @retval VOID
241
242 **/
243 VOID
244 DestroyDefaultNode (
245 IN UEFI_IFR_BUFFER_STORAGE_NODE *Node
246 )
247 {
248 FreePool (Node->Buffer);
249 FreePool (Node->Name);
250 FreePool (Node);
251 }
252
253
254 /**
255 Get the default value for Buffer Type storage named by
256 a Default Store and a Storage Store from a FormSet.
257 The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
258 allocated by this function. It is inserted to the link list.
259
260 @param DefaultStore The Default Store.
261 @param Storage The Storage.
262 @param FormSet The Form Set.
263 @param UefiDefaultsListHead The head of link list for the output.
264
265 @retval EFI_SUCCESS Successful.
266
267 **/
268 EFI_STATUS
269 GetBufferTypeDefaultIdAndStorageId (
270 IN FORMSET_DEFAULTSTORE *DefaultStore,
271 IN FORMSET_STORAGE *Storage,
272 IN FORM_BROWSER_FORMSET *FormSet,
273 OUT LIST_ENTRY *UefiDefaultsListHead
274 )
275 {
276 UEFI_IFR_BUFFER_STORAGE_NODE *Node;
277 LIST_ENTRY *Link;
278 FORM_BROWSER_FORM *Form;
279 EFI_STATUS Status;
280
281 Node = AllocateZeroPool (sizeof (UEFI_IFR_BUFFER_STORAGE_NODE));
282 ASSERT (Node != NULL);
283
284 Node->Signature = UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE;
285 Node->Name = AllocateCopyPool (StrSize (Storage->Name), Storage->Name);
286 Node->DefaultId = DefaultStore->DefaultId;
287 Node->StoreId = Storage->VarStoreId;
288 CopyGuid (&Node->Guid, &Storage->Guid);
289 Node->Size = Storage->Size;
290 Node->Buffer = AllocateZeroPool (Node->Size);
291 //
292 // Extract default from IFR binary
293 //
294 Link = GetFirstNode (&FormSet->FormListHead);
295 while (!IsNull (&FormSet->FormListHead, Link)) {
296 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
297
298 Status = ExtractFormDefault (FormSet, Form, DefaultStore->DefaultId, Storage->VarStoreId, Node);
299 ASSERT_EFI_ERROR (Status);
300
301 Link = GetNextNode (&FormSet->FormListHead, Link);
302 }
303
304 InsertTailList (UefiDefaultsListHead, &Node->List);
305
306 return EFI_SUCCESS;
307 }
308
309
310 /**
311 Get the default value for Buffer Type storage named by
312 a Default Store from a FormSet.
313 The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
314 allocated by this function. The output can be multiple instances
315 of UEFI_IFR_BUFFER_STORAGE_NODE. It is inserted to the link list.
316
317 @param DefaultStore The Default Store.
318 @param FormSet The Form Set.
319 @param UefiDefaultsListHead The head of link list for the output.
320
321 @retval EFI_SUCCESS Successful.
322
323 **/
324 EFI_STATUS
325 GetBufferTypeDefaultId (
326 IN FORMSET_DEFAULTSTORE *DefaultStore,
327 IN FORM_BROWSER_FORMSET *FormSet,
328 OUT LIST_ENTRY *UefiDefaultsListHead
329 )
330 {
331 LIST_ENTRY *StorageLink;
332 FORMSET_STORAGE *Storage;
333 EFI_STATUS Status;
334
335 StorageLink = GetFirstNode (&FormSet->StorageListHead);
336
337 while (!IsNull (&FormSet->StorageListHead, StorageLink)) {
338 Storage = FORMSET_STORAGE_FROM_LINK(StorageLink);
339
340 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
341 Status = GetBufferTypeDefaultIdAndStorageId (DefaultStore, Storage, FormSet, UefiDefaultsListHead);
342 }
343
344 StorageLink = GetNextNode (&FormSet->StorageListHead, StorageLink);
345 }
346
347 return EFI_SUCCESS;
348 }
349
350
351 /**
352 Get the default value for Buffer Type storage from the first FormSet
353 in the Package List specified by a EFI_HII_HANDLE.
354
355 The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE.
356 They are inserted to the link list.
357
358 @param UefiHiiHandle The handle for the package list.
359 @param UefiDefaultsListHead The head of link list for the output.
360
361 @retval EFI_SUCCESS Successful.
362
363 **/
364 EFI_STATUS
365 UefiIfrGetBufferTypeDefaults (
366 IN HII_THUNK_CONTEXT *ThunkContext,
367 OUT LIST_ENTRY **UefiDefaults
368 )
369 {
370 LIST_ENTRY *DefaultLink;
371 FORMSET_DEFAULTSTORE *DefaultStore;
372 EFI_STATUS Status;
373
374 ASSERT (UefiDefaults != NULL);
375
376 *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY));
377 ASSERT (UefiDefaults != NULL);
378 InitializeListHead (*UefiDefaults);
379
380 DefaultLink = GetFirstNode (&ThunkContext->FormSet->DefaultStoreListHead);
381 while (!IsNull (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink)) {
382 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
383
384 Status = GetBufferTypeDefaultId (DefaultStore, ThunkContext->FormSet, *UefiDefaults);
385 ASSERT_EFI_ERROR (Status);
386
387 DefaultLink = GetNextNode (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink);
388 }
389
390 return EFI_SUCCESS;
391 }
392
393
394 /**
395 Convert the UEFI Buffer Type default values to a Framework HII default
396 values specified by a EFI_HII_VARIABLE_PACK_LIST structure.
397
398 @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
399 which contains the default values retrived from
400 a UEFI form set.
401 @param DefaultMask The default mask.
402 The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT
403 and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
404 UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
405 from specification to valid default class.
406 @param VariablePackList The output default value in a format defined in Framework.
407
408
409 @retval EFI_SUCCESS Successful.
410 @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or
411 FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
412 **/
413 EFI_STATUS
414 UefiDefaultsToFwDefaults (
415 IN LIST_ENTRY *ListHead,
416 IN UINTN DefaultMask,
417 IN EFI_VARSTORE_ID UefiFormSetDefaultVarStoreId,
418 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
419 )
420 {
421 LIST_ENTRY *List;
422 UEFI_IFR_BUFFER_STORAGE_NODE *Node;
423 UINTN Size;
424 UINTN Count;
425 UINT16 DefaultId;
426 EFI_HII_VARIABLE_PACK *Pack;
427 EFI_HII_VARIABLE_PACK_LIST *PackList;
428 UINTN Index;
429
430 if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_DEFAULT) {
431 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
432 } else if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING) {
433 DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
434 } else {
435 //
436 // UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
437 // from specification to valid default class.
438 //
439 ASSERT (FALSE);
440 return EFI_INVALID_PARAMETER;
441 }
442
443 //
444 // Calculate the size of the output EFI_HII_VARIABLE_PACK_LIST structure
445 //
446 Size = 0;
447 Count = 0;
448 List = GetFirstNode (ListHead);
449 while (!IsNull (ListHead, List)) {
450 Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
451
452 if (Node->DefaultId == DefaultId) {
453 Size += Node->Size;
454 Size += StrSize (Node->Name);
455
456 Count++;
457 }
458
459 List = GetNextNode (ListHead, List);
460 }
461
462 if (Count == 0) {
463 *VariablePackList = NULL;
464 return EFI_NOT_FOUND;
465 }
466
467 Size = Size + Count * (sizeof (EFI_HII_VARIABLE_PACK_LIST) + sizeof (EFI_HII_VARIABLE_PACK));
468
469 *VariablePackList = AllocateZeroPool (Size);
470 ASSERT (*VariablePackList != NULL);
471
472 List = GetFirstNode (ListHead);
473
474 PackList = (EFI_HII_VARIABLE_PACK_LIST *) *VariablePackList;
475 Pack = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
476 Index = 0;
477 while (!IsNull (ListHead, List)) {
478 Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
479
480 Size = 0;
481 if (Node->DefaultId == DefaultId) {
482 Size += Node->Size;
483 Size += StrSize (Node->Name);
484 Size += sizeof (EFI_HII_VARIABLE_PACK);
485
486 //
487 // In UEFI, 0 is defined to be invalid for EFI_IFR_VARSTORE.VarStoreId.
488 // So the default storage of Var Store in VFR from a Framework module
489 // should be translated to 0x0001 (FRAMEWORK_RESERVED_VARSTORE_ID).
490 //
491 if (Node->StoreId == UefiFormSetDefaultVarStoreId) {
492 Pack->VariableId = 0;
493 } else {
494 Pack->VariableId = Node->StoreId;
495 }
496 //
497 // Initialize EFI_HII_VARIABLE_PACK
498 //
499 Pack->Header.Type = 0;
500 Pack->Header.Length = (UINT32) Size;
501 Pack->VariableNameLength = (UINT32) StrSize (Node->Name);
502 CopyMem (&Pack->VariableGuid, &Node->Guid, sizeof (EFI_GUID));
503
504 CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK), Node->Name, StrSize (Node->Name));
505 CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength, Node->Buffer, Node->Size);
506
507 Size += sizeof (EFI_HII_VARIABLE_PACK_LIST);
508
509 //
510 // Initialize EFI_HII_VARIABLE_PACK_LIST
511 //
512 PackList->VariablePack = Pack;
513 Index++;
514 if (Index < Count) {
515 PackList->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *)((UINT8 *) PackList + Size);
516 }
517
518 }
519
520 List = GetNextNode (ListHead, List);
521 }
522
523
524 return EFI_SUCCESS;
525 }
526
527
528 /**
529 Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE.
530
531 @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
532 which contains the default values retrived from
533 a UEFI form set.
534
535
536 @retval VOID
537 **/
538 VOID
539 FreeDefaultList (
540 IN LIST_ENTRY *ListHead
541 )
542 {
543 LIST_ENTRY *Link;
544 UEFI_IFR_BUFFER_STORAGE_NODE *Default;
545
546 while (!IsListEmpty (ListHead)) {
547 Link = GetFirstNode (ListHead);
548
549 Default = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(Link);
550
551 RemoveEntryList (Link);
552
553 DestroyDefaultNode (Default);
554 }
555
556 FreePool (ListHead);
557 }
558