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