]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg/HiiDatabaseDxe: Correct the ReallocatePool size
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / ConfigRouting.c
1 /** @file
2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
3
4 Copyright (c) 2007 - 2016, 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
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate;
18
19 /**
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
22
23 This is a internal function.
24
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
27
28 @return The number of Unicode characters.
29
30 **/
31 UINTN
32 CalculateConfigStringLen (
33 IN EFI_STRING String
34 )
35 {
36 EFI_STRING TmpPtr;
37
38 //
39 // "GUID=" should be the first element of incoming string.
40 //
41 ASSERT (String != NULL);
42 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
43
44 //
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
47 //
48 TmpPtr = StrStr (String, L"&GUID=");
49 if (TmpPtr == NULL) {
50 return StrLen (String);
51 }
52
53 return (TmpPtr - String);
54 }
55
56
57 /**
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
60
61 This is a internal function.
62
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
65
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
70 binary format.
71
72 **/
73 EFI_STATUS
74 GetDevicePath (
75 IN EFI_STRING String,
76 OUT UINT8 **DevicePathData
77 )
78 {
79 UINTN Length;
80 EFI_STRING PathHdr;
81 UINT8 *DevicePathBuffer;
82 CHAR16 TemStr[2];
83 UINTN Index;
84 UINT8 DigitUint8;
85 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
86
87
88 if (String == NULL || DevicePathData == NULL) {
89 return EFI_INVALID_PARAMETER;
90 }
91
92 //
93 // Find the 'PATH=' of <PathHdr> and skip it.
94 //
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
96 if (*String == 0) {
97 return EFI_INVALID_PARAMETER;
98 }
99 //
100 // Check whether path data does exist.
101 //
102 String += StrLen (L"PATH=");
103 if (*String == 0) {
104 return EFI_INVALID_PARAMETER;
105 }
106 PathHdr = String;
107
108 //
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
112 //
113 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
114 //
115 // Check DevicePath Length
116 //
117 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
118 return EFI_NOT_FOUND;
119 }
120
121 //
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
125 //
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
127 if (DevicePathBuffer == NULL) {
128 return EFI_OUT_OF_RESOURCES;
129 }
130
131 //
132 // Convert DevicePath
133 //
134 ZeroMem (TemStr, sizeof (TemStr));
135 for (Index = 0; Index < Length; Index ++) {
136 TemStr[0] = PathHdr[Index];
137 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
138 if ((Index & 1) == 0) {
139 DevicePathBuffer [Index/2] = DigitUint8;
140 } else {
141 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
142 }
143 }
144
145 //
146 // Validate DevicePath
147 //
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;
149 while (!IsDevicePathEnd (DevicePath)) {
150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
151 //
152 // Invalid device path
153 //
154 FreePool (DevicePathBuffer);
155 return EFI_NOT_FOUND;
156 }
157 DevicePath = NextDevicePathNode (DevicePath);
158 }
159
160 //
161 // return the device path
162 //
163 *DevicePathData = DevicePathBuffer;
164 return EFI_SUCCESS;
165 }
166
167 /**
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
170
171 @param ConfigString String to be converted
172
173 **/
174 VOID
175 EFIAPI
176 HiiToLower (
177 IN EFI_STRING ConfigString
178 )
179 {
180 EFI_STRING String;
181 BOOLEAN Lower;
182
183 ASSERT (ConfigString != NULL);
184
185 //
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
187 //
188 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
189 if (*String == L'=') {
190 Lower = TRUE;
191 } else if (*String == L'&') {
192 Lower = FALSE;
193 } else if (Lower && *String >= L'A' && *String <= L'F') {
194 *String = (CHAR16) (*String - L'A' + L'a');
195 }
196 }
197
198 return;
199 }
200
201 /**
202 Generate a sub string then output it.
203
204 This is a internal function.
205
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
208
209 @param BufferLen The length of the Buffer in bytes.
210
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
213
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
217
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
220
221
222 **/
223 VOID
224 GenerateSubStr (
225 IN CONST EFI_STRING String,
226 IN UINTN BufferLen,
227 IN VOID *Buffer,
228 IN UINT8 Flag,
229 OUT EFI_STRING *SubStr
230 )
231 {
232 UINTN Length;
233 EFI_STRING Str;
234 EFI_STRING StringHeader;
235 CHAR16 *TemString;
236 CHAR16 *TemName;
237 UINT8 *TemBuffer;
238 UINTN Index;
239
240 ASSERT (String != NULL && SubStr != NULL);
241
242 if (Buffer == NULL) {
243 *SubStr = AllocateCopyPool (StrSize (String), String);
244 ASSERT (*SubStr != NULL);
245 return;
246 }
247
248 //
249 // Header + Data + '&' + '\0'
250 //
251 Length = StrLen (String) + BufferLen * 2 + 1 + 1;
252 Str = AllocateZeroPool (Length * sizeof (CHAR16));
253 ASSERT (Str != NULL);
254
255 StrCpyS (Str, Length, String);
256
257 StringHeader = Str + StrLen (String);
258 TemString = (CHAR16 *) StringHeader;
259
260 switch (Flag) {
261 case 1:
262 //
263 // Convert Buffer to Hex String in reverse order
264 //
265 TemBuffer = ((UINT8 *) Buffer);
266 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
267 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
268 }
269 break;
270 case 2:
271 //
272 // Check buffer is enough
273 //
274 TemName = (CHAR16 *) Buffer;
275 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
276 //
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
278 //
279 for (; *TemName != L'\0'; TemName++) {
280 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
281 }
282 break;
283 case 3:
284 //
285 // Convert Buffer to Hex String
286 //
287 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
288 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
289 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
290 }
291 break;
292 default:
293 break;
294 }
295
296 //
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
298 //
299 StrCatS (Str, Length, L"&");
300 HiiToLower (Str);
301
302 *SubStr = Str;
303 }
304
305
306 /**
307 Retrieve the <ConfigBody> from String then output it.
308
309 This is a internal function.
310
311 @param String A sub string of a configuration string in
312 <MultiConfigAltResp> format.
313 @param ConfigBody Points to the output string. It's caller's
314 responsibility to free this buffer.
315
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
318 @retval EFI_SUCCESS All existing storage is exported.
319
320 **/
321 EFI_STATUS
322 OutputConfigBody (
323 IN EFI_STRING String,
324 OUT EFI_STRING *ConfigBody
325 )
326 {
327 EFI_STRING TmpPtr;
328 EFI_STRING Result;
329 UINTN Length;
330
331 if (String == NULL || ConfigBody == NULL) {
332 return EFI_INVALID_PARAMETER;
333 }
334
335 //
336 // The setting information should start OFFSET, not ALTCFG.
337 //
338 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER;
340 }
341
342 TmpPtr = StrStr (String, L"GUID=");
343 if (TmpPtr == NULL) {
344 //
345 // It is the last <ConfigResp> of the incoming configuration string.
346 //
347 Result = AllocateCopyPool (StrSize (String), String);
348 if (Result == NULL) {
349 return EFI_OUT_OF_RESOURCES;
350 } else {
351 *ConfigBody = Result;
352 return EFI_SUCCESS;
353 }
354 }
355
356 Length = TmpPtr - String;
357 if (Length == 0) {
358 return EFI_NOT_FOUND;
359 }
360 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
361 if (Result == NULL) {
362 return EFI_OUT_OF_RESOURCES;
363 }
364
365 *(Result + Length - 1) = 0;
366 *ConfigBody = Result;
367 return EFI_SUCCESS;
368 }
369
370 /**
371 Append a string to a multi-string format.
372
373 This is a internal function.
374
375 @param MultiString String in <MultiConfigRequest>,
376 <MultiConfigAltResp>, or <MultiConfigResp>. On
377 input, the buffer length of this string is
378 MAX_STRING_LENGTH. On output, the buffer length
379 might be updated.
380 @param AppendString NULL-terminated Unicode string.
381
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
384
385 **/
386 EFI_STATUS
387 AppendToMultiString (
388 IN OUT EFI_STRING *MultiString,
389 IN EFI_STRING AppendString
390 )
391 {
392 UINTN AppendStringSize;
393 UINTN MultiStringSize;
394 UINTN MaxLen;
395
396 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
397 return EFI_INVALID_PARAMETER;
398 }
399
400 AppendStringSize = StrSize (AppendString);
401 MultiStringSize = StrSize (*MultiString);
402 MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
403
404 //
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
406 //
407 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
408 MultiStringSize > MAX_STRING_LENGTH) {
409 *MultiString = (EFI_STRING) ReallocatePool (
410 MultiStringSize,
411 MultiStringSize + AppendStringSize,
412 (VOID *) (*MultiString)
413 );
414 MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
415 ASSERT (*MultiString != NULL);
416 }
417 //
418 // Append the incoming string
419 //
420 StrCatS (*MultiString, MaxLen, AppendString);
421
422 return EFI_SUCCESS;
423 }
424
425
426 /**
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
428 or WIDTH or VALUE.
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
430
431 This is a internal function.
432
433 @param StringPtr String in <BlockConfig> format and points to the
434 first character of <Number>.
435 @param Number The output value. Caller takes the responsibility
436 to free memory.
437 @param Len Length of the <Number>, in characters.
438
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
440 structures.
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 successfully.
443
444 **/
445 EFI_STATUS
446 GetValueOfNumber (
447 IN EFI_STRING StringPtr,
448 OUT UINT8 **Number,
449 OUT UINTN *Len
450 )
451 {
452 EFI_STRING TmpPtr;
453 UINTN Length;
454 EFI_STRING Str;
455 UINT8 *Buf;
456 EFI_STATUS Status;
457 UINT8 DigitUint8;
458 UINTN Index;
459 CHAR16 TemStr[2];
460
461 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
462 return EFI_INVALID_PARAMETER;
463 }
464
465 Buf = NULL;
466
467 TmpPtr = StringPtr;
468 while (*StringPtr != L'\0' && *StringPtr != L'&') {
469 StringPtr++;
470 }
471 *Len = StringPtr - TmpPtr;
472 Length = *Len + 1;
473
474 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
475 if (Str == NULL) {
476 Status = EFI_OUT_OF_RESOURCES;
477 goto Exit;
478 }
479 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
480 *(Str + *Len) = L'\0';
481
482 Length = (Length + 1) / 2;
483 Buf = (UINT8 *) AllocateZeroPool (Length);
484 if (Buf == NULL) {
485 Status = EFI_OUT_OF_RESOURCES;
486 goto Exit;
487 }
488
489 Length = *Len;
490 ZeroMem (TemStr, sizeof (TemStr));
491 for (Index = 0; Index < Length; Index ++) {
492 TemStr[0] = Str[Length - Index - 1];
493 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
494 if ((Index & 1) == 0) {
495 Buf [Index/2] = DigitUint8;
496 } else {
497 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
498 }
499 }
500
501 *Number = Buf;
502 Status = EFI_SUCCESS;
503
504 Exit:
505 if (Str != NULL) {
506 FreePool (Str);
507 }
508
509 return Status;
510 }
511
512 /**
513 This function merges DefaultAltCfgResp string into AltCfgResp string for
514 the missing AltCfgId in AltCfgResq.
515
516 @param AltCfgResp Pointer to a null-terminated Unicode string in
517 <ConfigAltResp> format. The default value string
518 will be merged into it.
519 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
520 <MultiConfigAltResp> format. The default value
521 string may contain more than one ConfigAltResp
522 string for the different varstore buffer.
523
524 @retval EFI_SUCCESS The merged string returns.
525 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
526 **/
527 EFI_STATUS
528 EFIAPI
529 MergeDefaultString (
530 IN OUT EFI_STRING *AltCfgResp,
531 IN EFI_STRING DefaultAltCfgResp
532 )
533 {
534 EFI_STRING StringPtrDefault;
535 EFI_STRING StringPtrEnd;
536 CHAR16 TempChar;
537 EFI_STRING StringPtr;
538 EFI_STRING AltConfigHdr;
539 UINTN HeaderLength;
540 UINTN SizeAltCfgResp;
541 UINTN MaxLen;
542 UINTN TotalSize;
543
544 if (*AltCfgResp == NULL) {
545 return EFI_INVALID_PARAMETER;
546 }
547
548 //
549 // Get the requestr ConfigHdr
550 //
551 SizeAltCfgResp = 0;
552 StringPtr = *AltCfgResp;
553
554 //
555 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
556 //
557 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
558 return EFI_INVALID_PARAMETER;
559 }
560 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
561 StringPtr++;
562 }
563 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
564 StringPtr++;
565 }
566 if (*StringPtr == L'\0') {
567 return EFI_INVALID_PARAMETER;
568 }
569 StringPtr += StrLen (L"&PATH=");
570 while (*StringPtr != L'\0' && *StringPtr != L'&') {
571 StringPtr ++;
572 }
573 HeaderLength = StringPtr - *AltCfgResp;
574
575 //
576 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
577 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
578 //
579 MaxLen = 1 + HeaderLength + 8 + 4 + 1;
580 AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
581 if (AltConfigHdr == NULL) {
582 return EFI_OUT_OF_RESOURCES;
583 }
584 StrCpyS (AltConfigHdr, MaxLen, L"&");
585 StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
586 StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
587 HeaderLength = StrLen (AltConfigHdr);
588
589 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
590 while (StringPtrDefault != NULL) {
591 //
592 // Get AltCfg Name
593 //
594 StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
595 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
596
597 //
598 // Append the found default value string to the input AltCfgResp
599 //
600 if (StringPtr == NULL) {
601 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
602 SizeAltCfgResp = StrSize (*AltCfgResp);
603 if (StringPtrEnd == NULL) {
604 //
605 // No more default string is found.
606 //
607 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
608 *AltCfgResp = (EFI_STRING) ReallocatePool (
609 SizeAltCfgResp,
610 TotalSize,
611 (VOID *) (*AltCfgResp)
612 );
613 if (*AltCfgResp == NULL) {
614 FreePool (AltConfigHdr);
615 return EFI_OUT_OF_RESOURCES;
616 }
617 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
618 break;
619 } else {
620 TempChar = *StringPtrEnd;
621 *StringPtrEnd = L'\0';
622 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
623 *AltCfgResp = (EFI_STRING) ReallocatePool (
624 SizeAltCfgResp,
625 TotalSize,
626 (VOID *) (*AltCfgResp)
627 );
628 if (*AltCfgResp == NULL) {
629 FreePool (AltConfigHdr);
630 return EFI_OUT_OF_RESOURCES;
631 }
632 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
633 *StringPtrEnd = TempChar;
634 }
635 }
636
637 //
638 // Find next AltCfg String
639 //
640 *(AltConfigHdr + HeaderLength) = L'\0';
641 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
642 }
643
644 FreePool (AltConfigHdr);
645 return EFI_SUCCESS;
646 }
647
648 /**
649 This function inserts new DefaultValueData into the BlockData DefaultValue array.
650
651 @param BlockData The BlockData is updated to add new default value.
652 @param DefaultValueData The DefaultValue is added.
653
654 **/
655 VOID
656 InsertDefaultValue (
657 IN IFR_BLOCK_DATA *BlockData,
658 IN IFR_DEFAULT_DATA *DefaultValueData
659 )
660 {
661 LIST_ENTRY *Link;
662 IFR_DEFAULT_DATA *DefaultValueArray;
663 LIST_ENTRY *DefaultLink;
664
665 DefaultLink = &BlockData->DefaultValueEntry;
666
667 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
668 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
669 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
670 //
671 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
672 //
673 if (DefaultValueData->Type > DefaultValueArray->Type) {
674 //
675 // Update the default value array in BlockData.
676 //
677 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
678 DefaultValueArray->Type = DefaultValueData->Type;
679 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
680 }
681 return;
682 }
683 }
684
685 //
686 // Insert new default value data in tail.
687 //
688 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
689 ASSERT (DefaultValueArray != NULL);
690 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
691 InsertTailList (Link, &DefaultValueArray->Entry);
692 }
693
694 /**
695 This function inserts new BlockData into the block link
696
697 @param BlockLink The list entry points to block array.
698 @param BlockData The point to BlockData is added.
699
700 **/
701 VOID
702 InsertBlockData (
703 IN LIST_ENTRY *BlockLink,
704 IN IFR_BLOCK_DATA **BlockData
705 )
706 {
707 LIST_ENTRY *Link;
708 IFR_BLOCK_DATA *BlockArray;
709 IFR_BLOCK_DATA *BlockSingleData;
710
711 BlockSingleData = *BlockData;
712
713 if (BlockSingleData->Name != NULL) {
714 InsertTailList (BlockLink, &BlockSingleData->Entry);
715 return;
716 }
717
718 //
719 // Insert block data in its Offset and Width order.
720 //
721 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
722 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
723 if (BlockArray->Offset == BlockSingleData->Offset) {
724 if (BlockArray->Width > BlockSingleData->Width) {
725 //
726 // Insert this block data in the front of block array
727 //
728 InsertTailList (Link, &BlockSingleData->Entry);
729 return;
730 }
731
732 if (BlockArray->Width == BlockSingleData->Width) {
733 //
734 // The same block array has been added.
735 //
736 if (BlockSingleData != BlockArray) {
737 FreePool (BlockSingleData);
738 *BlockData = BlockArray;
739 }
740 return;
741 }
742 } else if (BlockArray->Offset > BlockSingleData->Offset) {
743 //
744 // Insert new block data in the front of block array
745 //
746 InsertTailList (Link, &BlockSingleData->Entry);
747 return;
748 }
749 }
750
751 //
752 // Add new block data into the tail.
753 //
754 InsertTailList (Link, &BlockSingleData->Entry);
755 }
756
757 /**
758 Retrieves a pointer to the a Null-terminated ASCII string containing the list
759 of languages that an HII handle in the HII Database supports. The returned
760 string is allocated using AllocatePool(). The caller is responsible for freeing
761 the returned string using FreePool(). The format of the returned string follows
762 the language format assumed the HII Database.
763
764 If HiiHandle is NULL, then ASSERT().
765
766 @param[in] HiiHandle A handle that was previously registered in the HII Database.
767
768 @retval NULL HiiHandle is not registered in the HII database
769 @retval NULL There are not enough resources available to retrieve the suported
770 languages.
771 @retval NULL The list of suported languages could not be retrieved.
772 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
773
774 **/
775 CHAR8 *
776 GetSupportedLanguages (
777 IN EFI_HII_HANDLE HiiHandle
778 )
779 {
780 EFI_STATUS Status;
781 UINTN LanguageSize;
782 CHAR8 TempSupportedLanguages;
783 CHAR8 *SupportedLanguages;
784
785 ASSERT (HiiHandle != NULL);
786
787 //
788 // Retrieve the size required for the supported languages buffer.
789 //
790 LanguageSize = 0;
791 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
792
793 //
794 // If GetLanguages() returns EFI_SUCCESS for a zero size,
795 // then there are no supported languages registered for HiiHandle. If GetLanguages()
796 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
797 // in the HII Database
798 //
799 if (Status != EFI_BUFFER_TOO_SMALL) {
800 //
801 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
802 //
803 return NULL;
804 }
805
806 //
807 // Allocate the supported languages buffer.
808 //
809 SupportedLanguages = AllocateZeroPool (LanguageSize);
810 if (SupportedLanguages == NULL) {
811 //
812 // Return NULL if allocation fails.
813 //
814 return NULL;
815 }
816
817 //
818 // Retrieve the supported languages string
819 //
820 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
821 if (EFI_ERROR (Status)) {
822 //
823 // Free the buffer and return NULL if the supported languages can not be retrieved.
824 //
825 FreePool (SupportedLanguages);
826 return NULL;
827 }
828
829 //
830 // Return the Null-terminated ASCII string of supported languages
831 //
832 return SupportedLanguages;
833 }
834
835 /**
836 Retrieves a string from a string package.
837
838 If HiiHandle is NULL, then ASSERT().
839 If StringId is 0, then ASSET.
840
841 @param[in] HiiHandle A handle that was previously registered in the HII Database.
842 @param[in] StringId The identifier of the string to retrieved from the string
843 package associated with HiiHandle.
844
845 @retval NULL The string specified by StringId is not present in the string package.
846 @retval Other The string was returned.
847
848 **/
849 EFI_STRING
850 InternalGetString (
851 IN EFI_HII_HANDLE HiiHandle,
852 IN EFI_STRING_ID StringId
853 )
854 {
855 EFI_STATUS Status;
856 UINTN StringSize;
857 CHAR16 TempString;
858 EFI_STRING String;
859 CHAR8 *SupportedLanguages;
860 CHAR8 *PlatformLanguage;
861 CHAR8 *BestLanguage;
862 CHAR8 *Language;
863
864 ASSERT (HiiHandle != NULL);
865 ASSERT (StringId != 0);
866
867 //
868 // Initialize all allocated buffers to NULL
869 //
870 SupportedLanguages = NULL;
871 PlatformLanguage = NULL;
872 BestLanguage = NULL;
873 String = NULL;
874 Language = "";
875
876 //
877 // Get the languages that the package specified by HiiHandle supports
878 //
879 SupportedLanguages = GetSupportedLanguages (HiiHandle);
880 if (SupportedLanguages == NULL) {
881 goto Error;
882 }
883
884 //
885 // Get the current platform language setting
886 //
887 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
888
889 //
890 // Get the best matching language from SupportedLanguages
891 //
892 BestLanguage = GetBestLanguage (
893 SupportedLanguages,
894 FALSE, // RFC 4646 mode
895 Language, // Highest priority
896 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
897 SupportedLanguages, // Lowest priority
898 NULL
899 );
900 if (BestLanguage == NULL) {
901 goto Error;
902 }
903
904 //
905 // Retrieve the size of the string in the string package for the BestLanguage
906 //
907 StringSize = 0;
908 Status = mPrivate.HiiString.GetString (
909 &mPrivate.HiiString,
910 BestLanguage,
911 HiiHandle,
912 StringId,
913 &TempString,
914 &StringSize,
915 NULL
916 );
917 //
918 // If GetString() returns EFI_SUCCESS for a zero size,
919 // then there are no supported languages registered for HiiHandle. If GetString()
920 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
921 // in the HII Database
922 //
923 if (Status != EFI_BUFFER_TOO_SMALL) {
924 goto Error;
925 }
926
927 //
928 // Allocate a buffer for the return string
929 //
930 String = AllocateZeroPool (StringSize);
931 if (String == NULL) {
932 goto Error;
933 }
934
935 //
936 // Retrieve the string from the string package
937 //
938 Status = mPrivate.HiiString.GetString (
939 &mPrivate.HiiString,
940 BestLanguage,
941 HiiHandle,
942 StringId,
943 String,
944 &StringSize,
945 NULL
946 );
947 if (EFI_ERROR (Status)) {
948 //
949 // Free the buffer and return NULL if the supported languages can not be retrieved.
950 //
951 FreePool (String);
952 String = NULL;
953 }
954
955 Error:
956 //
957 // Free allocated buffers
958 //
959 if (SupportedLanguages != NULL) {
960 FreePool (SupportedLanguages);
961 }
962 if (PlatformLanguage != NULL) {
963 FreePool (PlatformLanguage);
964 }
965 if (BestLanguage != NULL) {
966 FreePool (BestLanguage);
967 }
968
969 //
970 // Return the Null-terminated Unicode string
971 //
972 return String;
973 }
974
975 /**
976 This function checks VarOffset and VarWidth is in the block range.
977
978 @param RequestBlockArray The block array is to be checked.
979 @param VarOffset Offset of var to the structure
980 @param VarWidth Width of var.
981 @param IsNameValueType Whether this varstore is name/value varstore or not.
982 @param HiiHandle Hii handle for this hii package.
983
984 @retval TRUE This Var is in the block range.
985 @retval FALSE This Var is not in the block range.
986 **/
987 BOOLEAN
988 BlockArrayCheck (
989 IN IFR_BLOCK_DATA *RequestBlockArray,
990 IN UINT16 VarOffset,
991 IN UINT16 VarWidth,
992 IN BOOLEAN IsNameValueType,
993 IN EFI_HII_HANDLE HiiHandle
994 )
995 {
996 LIST_ENTRY *Link;
997 IFR_BLOCK_DATA *BlockData;
998 EFI_STRING Name;
999
1000 //
1001 // No Request Block array, all vars are got.
1002 //
1003 if (RequestBlockArray == NULL) {
1004 return TRUE;
1005 }
1006
1007 //
1008 // Check the input var is in the request block range.
1009 //
1010 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
1011 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1012
1013 if (IsNameValueType) {
1014 Name = InternalGetString (HiiHandle, VarOffset);
1015 ASSERT (Name != NULL);
1016
1017 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
1018 FreePool (Name);
1019 return TRUE;
1020 }
1021 FreePool (Name);
1022 } else {
1023 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
1024 return TRUE;
1025 }
1026 }
1027 }
1028
1029 return FALSE;
1030 }
1031
1032 /**
1033 Get form package data from data base.
1034
1035 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1036 @param HiiFormPackage The buffer saves the package data.
1037 @param PackageSize The buffer size of the package data.
1038
1039 **/
1040 EFI_STATUS
1041 GetFormPackageData (
1042 IN HII_DATABASE_RECORD *DataBaseRecord,
1043 IN OUT UINT8 **HiiFormPackage,
1044 OUT UINTN *PackageSize
1045 )
1046 {
1047 EFI_STATUS Status;
1048 UINTN Size;
1049 UINTN ResultSize;
1050
1051 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
1052 return EFI_INVALID_PARAMETER;
1053 }
1054
1055 Size = 0;
1056 ResultSize = 0;
1057 //
1058 // 0. Get Hii Form Package by HiiHandle
1059 //
1060 Status = ExportFormPackages (
1061 &mPrivate,
1062 DataBaseRecord->Handle,
1063 DataBaseRecord->PackageList,
1064 0,
1065 Size,
1066 HiiFormPackage,
1067 &ResultSize
1068 );
1069 if (EFI_ERROR (Status)) {
1070 return Status;
1071 }
1072
1073 (*HiiFormPackage) = AllocatePool (ResultSize);
1074 if (*HiiFormPackage == NULL) {
1075 Status = EFI_OUT_OF_RESOURCES;
1076 return Status;
1077 }
1078
1079 //
1080 // Get HiiFormPackage by HiiHandle
1081 //
1082 Size = ResultSize;
1083 ResultSize = 0;
1084 Status = ExportFormPackages (
1085 &mPrivate,
1086 DataBaseRecord->Handle,
1087 DataBaseRecord->PackageList,
1088 0,
1089 Size,
1090 *HiiFormPackage,
1091 &ResultSize
1092 );
1093 if (EFI_ERROR (Status)) {
1094 FreePool (*HiiFormPackage);
1095 }
1096
1097 *PackageSize = Size;
1098
1099 return Status;
1100 }
1101
1102
1103 /**
1104 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1105
1106 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1107 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1108 the first found varstore will be as ConfigHdr.
1109 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1110 @param EfiVarStore The efi varstore info which will return.
1111 **/
1112 EFI_STATUS
1113 GetVarStoreType (
1114 IN HII_DATABASE_RECORD *DataBaseRecord,
1115 IN EFI_STRING ConfigHdr,
1116 OUT BOOLEAN *IsEfiVarstore,
1117 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
1118 )
1119 {
1120 EFI_STATUS Status;
1121 UINTN IfrOffset;
1122 UINTN PackageOffset;
1123 EFI_IFR_OP_HEADER *IfrOpHdr;
1124 CHAR16 *VarStoreName;
1125 EFI_STRING GuidStr;
1126 EFI_STRING NameStr;
1127 EFI_STRING TempStr;
1128 UINTN LengthString;
1129 UINT8 *HiiFormPackage;
1130 UINTN PackageSize;
1131 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1132 EFI_HII_PACKAGE_HEADER *PackageHeader;
1133
1134 HiiFormPackage = NULL;
1135 LengthString = 0;
1136 Status = EFI_SUCCESS;
1137 GuidStr = NULL;
1138 NameStr = NULL;
1139 TempStr = NULL;
1140 *IsEfiVarstore = FALSE;
1141
1142 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1143 if (EFI_ERROR (Status)) {
1144 return Status;
1145 }
1146
1147 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1148 PackageOffset = IfrOffset;
1149 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1150
1151 while (IfrOffset < PackageSize) {
1152 //
1153 // More than one form packages exist.
1154 //
1155 if (PackageOffset >= PackageHeader->Length) {
1156 //
1157 // Process the new form package.
1158 //
1159 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1160 IfrOffset += PackageOffset;
1161 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1162 }
1163
1164 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1165 IfrOffset += IfrOpHdr->Length;
1166 PackageOffset += IfrOpHdr->Length;
1167
1168 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1169 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1170 //
1171 // If the length is small than the structure, this is from old efi
1172 // varstore definition. Old efi varstore get config directly from
1173 // GetVariable function.
1174 //
1175 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1176 continue;
1177 }
1178
1179 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1180 if (VarStoreName == NULL) {
1181 Status = EFI_OUT_OF_RESOURCES;
1182 goto Done;
1183 }
1184 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
1185
1186 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1187 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1188 LengthString = StrLen (GuidStr);
1189 LengthString = LengthString + StrLen (NameStr) + 1;
1190 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1191 if (TempStr == NULL) {
1192 FreePool (GuidStr);
1193 FreePool (NameStr);
1194 FreePool (VarStoreName);
1195 Status = EFI_OUT_OF_RESOURCES;
1196 goto Done;
1197 }
1198 StrCpyS (TempStr, LengthString, GuidStr);
1199 StrCatS (TempStr, LengthString, NameStr);
1200 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1201 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
1202 if (*EfiVarStore == NULL) {
1203 FreePool (VarStoreName);
1204 FreePool (GuidStr);
1205 FreePool (NameStr);
1206 FreePool (TempStr);
1207 Status = EFI_OUT_OF_RESOURCES;
1208 goto Done;
1209 }
1210 *IsEfiVarstore = TRUE;
1211 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1212 }
1213
1214 //
1215 // Free alllocated temp string.
1216 //
1217 FreePool (VarStoreName);
1218 FreePool (GuidStr);
1219 FreePool (NameStr);
1220 FreePool (TempStr);
1221
1222 //
1223 // Already found the varstore, break;
1224 //
1225 if (*IsEfiVarstore) {
1226 break;
1227 }
1228 }
1229 }
1230 Done:
1231 if (HiiFormPackage != NULL) {
1232 FreePool (HiiFormPackage);
1233 }
1234
1235 return Status;
1236 }
1237
1238 /**
1239 Check whether the ConfigRequest string has the request elements.
1240 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1241 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1242
1243 @param ConfigRequest The input config request string.
1244
1245 @retval TRUE The input include config request elements.
1246 @retval FALSE The input string not includes.
1247
1248 **/
1249 BOOLEAN
1250 GetElementsFromRequest (
1251 IN EFI_STRING ConfigRequest
1252 )
1253 {
1254 EFI_STRING TmpRequest;
1255
1256 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1257 ASSERT (TmpRequest != NULL);
1258
1259 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1260 return TRUE;
1261 }
1262
1263 return FALSE;
1264 }
1265
1266 /**
1267 Check whether the this varstore is the request varstore.
1268
1269 @param VarstoreGuid Varstore guid.
1270 @param Name Varstore name.
1271 @param ConfigHdr Current configRequest info.
1272
1273 @retval TRUE This varstore is the requst one.
1274 @retval FALSE This varstore is not the requst one.
1275
1276 **/
1277 BOOLEAN
1278 IsThisVarstore (
1279 IN EFI_GUID *VarstoreGuid,
1280 IN CHAR16 *Name,
1281 IN CHAR16 *ConfigHdr
1282 )
1283 {
1284 EFI_STRING GuidStr;
1285 EFI_STRING NameStr;
1286 EFI_STRING TempStr;
1287 UINTN LengthString;
1288 BOOLEAN RetVal;
1289
1290 RetVal = FALSE;
1291 GuidStr = NULL;
1292 TempStr = NULL;
1293
1294 //
1295 // If ConfigHdr has name field and varstore not has name, return FALSE.
1296 //
1297 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
1298 return FALSE;
1299 }
1300
1301 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1302 if (Name != NULL) {
1303 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
1304 } else {
1305 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1306 }
1307 LengthString = StrLen (GuidStr);
1308 LengthString = LengthString + StrLen (NameStr) + 1;
1309 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1310 if (TempStr == NULL) {
1311 goto Done;
1312 }
1313
1314 StrCpyS (TempStr, LengthString, GuidStr);
1315 StrCatS (TempStr, LengthString, NameStr);
1316
1317 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1318 RetVal = TRUE;
1319 }
1320
1321 Done:
1322 if (GuidStr != NULL) {
1323 FreePool (GuidStr);
1324 }
1325
1326 if (NameStr != NULL) {
1327 FreePool (NameStr);
1328 }
1329
1330 if (TempStr != NULL) {
1331 FreePool (TempStr);
1332 }
1333
1334 return RetVal;
1335 }
1336
1337 /**
1338 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1339
1340 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1341 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1342 the first found varstore will be as ConfigHdr.
1343 @retval TRUE This hii package is the reqeust one.
1344 @retval FALSE This hii package is not the reqeust one.
1345 **/
1346 BOOLEAN
1347 IsThisPackageList (
1348 IN HII_DATABASE_RECORD *DataBaseRecord,
1349 IN EFI_STRING ConfigHdr
1350 )
1351 {
1352 EFI_STATUS Status;
1353 UINTN IfrOffset;
1354 UINTN PackageOffset;
1355 EFI_IFR_OP_HEADER *IfrOpHdr;
1356 CHAR16 *VarStoreName;
1357 UINT8 *HiiFormPackage;
1358 UINTN PackageSize;
1359 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1360 EFI_HII_PACKAGE_HEADER *PackageHeader;
1361 EFI_IFR_VARSTORE *IfrVarStore;
1362 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1363 BOOLEAN FindVarstore;
1364
1365 HiiFormPackage = NULL;
1366 VarStoreName = NULL;
1367 Status = EFI_SUCCESS;
1368 FindVarstore = FALSE;
1369
1370 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1371 if (EFI_ERROR (Status)) {
1372 return FALSE;
1373 }
1374
1375 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1376 PackageOffset = IfrOffset;
1377 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1378
1379 while (IfrOffset < PackageSize) {
1380 //
1381 // More than one form packages exist.
1382 //
1383 if (PackageOffset >= PackageHeader->Length) {
1384 //
1385 // Process the new form package.
1386 //
1387 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1388 IfrOffset += PackageOffset;
1389 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1390 }
1391
1392 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1393 IfrOffset += IfrOpHdr->Length;
1394 PackageOffset += IfrOpHdr->Length;
1395
1396 switch (IfrOpHdr->OpCode) {
1397
1398 case EFI_IFR_VARSTORE_OP:
1399 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1400
1401 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
1402 if (VarStoreName == NULL) {
1403 goto Done;
1404 }
1405 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
1406
1407 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1408 FindVarstore = TRUE;
1409 goto Done;
1410 }
1411 break;
1412
1413 case EFI_IFR_VARSTORE_EFI_OP:
1414 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1415 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1416 if (VarStoreName == NULL) {
1417 goto Done;
1418 }
1419 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
1420
1421 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1422 FindVarstore = TRUE;
1423 goto Done;
1424 }
1425 break;
1426
1427 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1428 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1429
1430 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1431 FindVarstore = TRUE;
1432 goto Done;
1433 }
1434 break;
1435
1436 case EFI_IFR_FORM_OP:
1437 case EFI_IFR_FORM_MAP_OP:
1438 //
1439 // No matched varstore is found and directly return.
1440 //
1441 goto Done;
1442
1443 default:
1444 break;
1445 }
1446 }
1447 Done:
1448 if (HiiFormPackage != NULL) {
1449 FreePool (HiiFormPackage);
1450 }
1451
1452 if (VarStoreName != NULL) {
1453 FreePool (VarStoreName);
1454 }
1455
1456 return FindVarstore;
1457 }
1458
1459 /**
1460 Check whether the this op code is required.
1461
1462 @param RequestBlockArray The array includes all the request info or NULL.
1463 @param HiiHandle The hii handle for this form package.
1464 @param VarStorageData The varstore data strucure.
1465 @param IfrOpHdr Ifr opcode header for this opcode.
1466 @param VarWidth The buffer width for this opcode.
1467 @param ReturnData The data block added for this opcode.
1468
1469 @retval EFI_SUCCESS This opcode is required.
1470 @retval EFI_NOT_FOUND This opcode is not required.
1471 @retval Others Contain some error.
1472
1473 **/
1474 EFI_STATUS
1475 IsThisOpcodeRequired (
1476 IN IFR_BLOCK_DATA *RequestBlockArray,
1477 IN EFI_HII_HANDLE HiiHandle,
1478 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1479 IN EFI_IFR_OP_HEADER *IfrOpHdr,
1480 IN UINT16 VarWidth,
1481 OUT IFR_BLOCK_DATA **ReturnData
1482 )
1483 {
1484 IFR_BLOCK_DATA *BlockData;
1485 UINT16 VarOffset;
1486 EFI_STRING_ID NameId;
1487 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
1488
1489 NameId = 0;
1490 VarOffset = 0;
1491 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
1492
1493 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1494 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
1495
1496 //
1497 // Check whether this question is in requested block array.
1498 //
1499 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
1500 //
1501 // This question is not in the requested string. Skip it.
1502 //
1503 return EFI_NOT_FOUND;
1504 }
1505 } else {
1506 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
1507
1508 //
1509 // Check whether this question is in requested block array.
1510 //
1511 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
1512 //
1513 // This question is not in the requested string. Skip it.
1514 //
1515 return EFI_NOT_FOUND;
1516 }
1517
1518 //
1519 // Check this var question is in the var storage
1520 //
1521 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
1522 return EFI_INVALID_PARAMETER;
1523 }
1524 }
1525
1526 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1527 if (BlockData == NULL) {
1528 return EFI_OUT_OF_RESOURCES;
1529 }
1530
1531 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1532 BlockData->Name = InternalGetString(HiiHandle, NameId);
1533 } else {
1534 BlockData->Offset = VarOffset;
1535 }
1536
1537 BlockData->Width = VarWidth;
1538 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
1539 BlockData->OpCode = IfrOpHdr->OpCode;
1540 BlockData->Scope = IfrOpHdr->Scope;
1541 InitializeListHead (&BlockData->DefaultValueEntry);
1542 //
1543 // Add Block Data into VarStorageData BlockEntry
1544 //
1545 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1546 *ReturnData = BlockData;
1547
1548 return EFI_SUCCESS;
1549 }
1550
1551 /**
1552 This function parses Form Package to get the block array and the default
1553 value array according to the request ConfigHdr.
1554
1555 @param HiiHandle Hii Handle for this hii package.
1556 @param Package Pointer to the form package data.
1557 @param PackageLength Length of the pacakge.
1558 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1559 the first found varstore will be as ConfigHdr.
1560 @param RequestBlockArray The block array is retrieved from the request string.
1561 @param VarStorageData VarStorage structure contains the got block and default value.
1562 @param DefaultIdArray Point to the got default id and default name array.
1563
1564 @retval EFI_SUCCESS The block array and the default value array are got.
1565 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1566 are conflicted.
1567 @retval EFI_OUT_OF_RESOURCES No enough memory.
1568 **/
1569 EFI_STATUS
1570 EFIAPI
1571 ParseIfrData (
1572 IN EFI_HII_HANDLE HiiHandle,
1573 IN UINT8 *Package,
1574 IN UINT32 PackageLength,
1575 IN EFI_STRING ConfigHdr,
1576 IN IFR_BLOCK_DATA *RequestBlockArray,
1577 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1578 OUT IFR_DEFAULT_DATA *DefaultIdArray
1579 )
1580 {
1581 EFI_STATUS Status;
1582 UINTN IfrOffset;
1583 UINTN PackageOffset;
1584 EFI_IFR_VARSTORE *IfrVarStore;
1585 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1586 EFI_IFR_OP_HEADER *IfrOpHdr;
1587 EFI_IFR_ONE_OF *IfrOneOf;
1588 EFI_IFR_REF4 *IfrRef;
1589 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
1590 EFI_IFR_DEFAULT *IfrDefault;
1591 EFI_IFR_ORDERED_LIST *IfrOrderedList;
1592 EFI_IFR_CHECKBOX *IfrCheckBox;
1593 EFI_IFR_PASSWORD *IfrPassword;
1594 EFI_IFR_STRING *IfrString;
1595 EFI_IFR_DATE *IfrDate;
1596 EFI_IFR_TIME *IfrTime;
1597 IFR_DEFAULT_DATA DefaultData;
1598 IFR_DEFAULT_DATA *DefaultDataPtr;
1599 IFR_BLOCK_DATA *BlockData;
1600 CHAR16 *VarStoreName;
1601 UINT16 VarWidth;
1602 UINT16 VarDefaultId;
1603 BOOLEAN FirstOneOfOption;
1604 BOOLEAN FirstOrderedList;
1605 LIST_ENTRY *LinkData;
1606 LIST_ENTRY *LinkDefault;
1607 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1608 EFI_HII_PACKAGE_HEADER *PackageHeader;
1609 EFI_VARSTORE_ID VarStoreId;
1610
1611 Status = EFI_SUCCESS;
1612 BlockData = NULL;
1613 DefaultDataPtr = NULL;
1614 FirstOneOfOption = FALSE;
1615 VarStoreId = 0;
1616 FirstOrderedList = FALSE;
1617 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
1618
1619 //
1620 // Go through the form package to parse OpCode one by one.
1621 //
1622 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1623 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
1624 IfrOffset = PackageOffset;
1625 while (IfrOffset < PackageLength) {
1626
1627 //
1628 // More than one form package found.
1629 //
1630 if (PackageOffset >= PackageHeader->Length) {
1631 //
1632 // Already found varstore for this request, break;
1633 //
1634 if (VarStoreId != 0) {
1635 VarStoreId = 0;
1636 }
1637
1638 //
1639 // Get next package header info.
1640 //
1641 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
1642 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1643 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
1644 }
1645
1646 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
1647 switch (IfrOpHdr->OpCode) {
1648 case EFI_IFR_VARSTORE_OP:
1649 //
1650 // VarStore is found. Don't need to search any more.
1651 //
1652 if (VarStoreId != 0) {
1653 break;
1654 }
1655
1656 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1657
1658 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
1659 if (VarStoreName == NULL) {
1660 Status = EFI_OUT_OF_RESOURCES;
1661 goto Done;
1662 }
1663 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
1664
1665 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1666 //
1667 // Find the matched VarStore
1668 //
1669 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
1670 VarStorageData->Size = IfrVarStore->Size;
1671 VarStorageData->Name = VarStoreName;
1672 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
1673 VarStoreId = IfrVarStore->VarStoreId;
1674 }
1675 break;
1676
1677 case EFI_IFR_VARSTORE_EFI_OP:
1678 //
1679 // VarStore is found. Don't need to search any more.
1680 //
1681 if (VarStoreId != 0) {
1682 break;
1683 }
1684
1685 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1686
1687 //
1688 // If the length is small than the structure, this is from old efi
1689 // varstore definition. Old efi varstore get config directly from
1690 // GetVariable function.
1691 //
1692 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1693 break;
1694 }
1695
1696 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1697 if (VarStoreName == NULL) {
1698 Status = EFI_OUT_OF_RESOURCES;
1699 goto Done;
1700 }
1701 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
1702
1703 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1704 //
1705 // Find the matched VarStore
1706 //
1707 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
1708 VarStorageData->Size = IfrEfiVarStore->Size;
1709 VarStorageData->Name = VarStoreName;
1710 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
1711 VarStoreId = IfrEfiVarStore->VarStoreId;
1712 }
1713 break;
1714
1715 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1716 //
1717 // VarStore is found. Don't need to search any more.
1718 //
1719 if (VarStoreId != 0) {
1720 break;
1721 }
1722
1723 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1724
1725 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1726 //
1727 // Find the matched VarStore
1728 //
1729 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
1730 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
1731 VarStoreId = IfrNameValueVarStore->VarStoreId;
1732 }
1733 break;
1734
1735 case EFI_IFR_DEFAULTSTORE_OP:
1736 //
1737 // Add new the map between default id and default name.
1738 //
1739 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1740 if (DefaultDataPtr == NULL) {
1741 Status = EFI_OUT_OF_RESOURCES;
1742 goto Done;
1743 }
1744 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
1745 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
1746 DefaultDataPtr = NULL;
1747 break;
1748
1749 case EFI_IFR_FORM_OP:
1750 case EFI_IFR_FORM_MAP_OP:
1751 //
1752 // No matched varstore is found and directly return.
1753 //
1754 if ( VarStoreId == 0) {
1755 Status = EFI_SUCCESS;
1756 goto Done;
1757 }
1758 break;
1759
1760 case EFI_IFR_REF_OP:
1761 //
1762 // Ref question is not in IFR Form. This IFR form is not valid.
1763 //
1764 if ( VarStoreId == 0) {
1765 Status = EFI_INVALID_PARAMETER;
1766 goto Done;
1767 }
1768 //
1769 // Check whether this question is for the requested varstore.
1770 //
1771 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
1772 if (IfrRef->Question.VarStoreId != VarStoreId) {
1773 break;
1774 }
1775 VarWidth = (UINT16) (sizeof (EFI_HII_REF));
1776
1777 //
1778 // The BlockData may allocate by other opcode,need to clean.
1779 //
1780 if (BlockData != NULL){
1781 BlockData = NULL;
1782 }
1783
1784 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1785 if (EFI_ERROR (Status)) {
1786 if (Status == EFI_NOT_FOUND){
1787 //
1788 //The opcode is not required,exit and parse other opcode.
1789 //
1790 break;
1791 }
1792 goto Done;
1793 }
1794 break;
1795
1796 case EFI_IFR_ONE_OF_OP:
1797 case EFI_IFR_NUMERIC_OP:
1798 //
1799 // Numeric and OneOf has the same opcode structure.
1800 //
1801
1802 //
1803 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1804 //
1805 if (VarStoreId == 0) {
1806 Status = EFI_INVALID_PARAMETER;
1807 goto Done;
1808 }
1809 //
1810 // Check whether this question is for the requested varstore.
1811 //
1812 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
1813 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
1814 break;
1815 }
1816 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
1817
1818 //
1819 // The BlockData may allocate by other opcode,need to clean.
1820 //
1821 if (BlockData != NULL){
1822 BlockData = NULL;
1823 }
1824
1825 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1826 if (EFI_ERROR (Status)) {
1827 if (Status == EFI_NOT_FOUND){
1828 //
1829 //The opcode is not required,exit and parse other opcode.
1830 //
1831 break;
1832 }
1833 goto Done;
1834 }
1835
1836 //
1837 //when go to there,BlockData can't be NULLL.
1838 //
1839 ASSERT (BlockData != NULL);
1840
1841 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
1842 //
1843 // Set this flag to TRUE for the first oneof option.
1844 //
1845 FirstOneOfOption = TRUE;
1846 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
1847 //
1848 // Numeric minimum value will be used as default value when no default is specified.
1849 //
1850 DefaultData.Type = DefaultValueFromDefault;
1851 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
1852 case EFI_IFR_NUMERIC_SIZE_1:
1853 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
1854 break;
1855
1856 case EFI_IFR_NUMERIC_SIZE_2:
1857 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
1858 break;
1859
1860 case EFI_IFR_NUMERIC_SIZE_4:
1861 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
1862 break;
1863
1864 case EFI_IFR_NUMERIC_SIZE_8:
1865 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
1866 break;
1867
1868 default:
1869 Status = EFI_INVALID_PARAMETER;
1870 goto Done;
1871 }
1872 //
1873 // Set default value base on the DefaultId list get from IFR data.
1874 //
1875 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
1876 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
1877 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
1878 InsertDefaultValue (BlockData, &DefaultData);
1879 }
1880 }
1881 break;
1882
1883 case EFI_IFR_ORDERED_LIST_OP:
1884 //
1885 // offset by question header
1886 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1887 //
1888
1889 FirstOrderedList = TRUE;
1890 //
1891 // OrderedList question is not in IFR Form. This IFR form is not valid.
1892 //
1893 if (VarStoreId == 0) {
1894 Status = EFI_INVALID_PARAMETER;
1895 goto Done;
1896 }
1897 //
1898 // Check whether this question is for the requested varstore.
1899 //
1900 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
1901 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
1902 BlockData = NULL;
1903 break;
1904 }
1905 VarWidth = IfrOrderedList->MaxContainers;
1906
1907 //
1908 // The BlockData may allocate by other opcode,need to clean.
1909 //
1910 if (BlockData != NULL){
1911 BlockData = NULL;
1912 }
1913
1914 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1915 if (EFI_ERROR (Status)) {
1916 if (Status == EFI_NOT_FOUND){
1917 //
1918 //The opcode is not required,exit and parse other opcode.
1919 //
1920 break;
1921 }
1922 goto Done;
1923 }
1924 break;
1925
1926 case EFI_IFR_CHECKBOX_OP:
1927 //
1928 // EFI_IFR_DEFAULT_OP
1929 // offset by question header
1930 // width is 1 sizeof (BOOLEAN)
1931 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1932 // value by DefaultOption
1933 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1934 //
1935
1936 //
1937 // CheckBox question is not in IFR Form. This IFR form is not valid.
1938 //
1939 if (VarStoreId == 0) {
1940 Status = EFI_INVALID_PARAMETER;
1941 goto Done;
1942 }
1943 //
1944 // Check whether this question is for the requested varstore.
1945 //
1946 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
1947 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
1948 break;
1949 }
1950 VarWidth = (UINT16) sizeof (BOOLEAN);
1951
1952 //
1953 // The BlockData may allocate by other opcode,need to clean.
1954 //
1955 if (BlockData != NULL){
1956 BlockData = NULL;
1957 }
1958
1959 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1960 if (EFI_ERROR (Status)) {
1961 if (Status == EFI_NOT_FOUND){
1962 //
1963 //The opcode is not required,exit and parse other opcode.
1964 //
1965 break;
1966 }
1967 goto Done;
1968 }
1969
1970 //
1971 //when go to there,BlockData can't be NULLL.
1972 //
1973 ASSERT (BlockData != NULL);
1974
1975 //
1976 // Add default value for standard ID by CheckBox Flag
1977 //
1978 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1979 //
1980 // Prepare new DefaultValue
1981 //
1982 DefaultData.DefaultId = VarDefaultId;
1983 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
1984 //
1985 // When flag is set, defautl value is TRUE.
1986 //
1987 DefaultData.Type = DefaultValueFromFlag;
1988 DefaultData.Value.b = TRUE;
1989 } else {
1990 //
1991 // When flag is not set, defautl value is FASLE.
1992 //
1993 DefaultData.Type = DefaultValueFromDefault;
1994 DefaultData.Value.b = FALSE;
1995 }
1996 //
1997 // Add DefaultValue into current BlockData
1998 //
1999 InsertDefaultValue (BlockData, &DefaultData);
2000
2001 //
2002 // Add default value for Manufacture ID by CheckBox Flag
2003 //
2004 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2005 //
2006 // Prepare new DefaultValue
2007 //
2008 DefaultData.DefaultId = VarDefaultId;
2009 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
2010 //
2011 // When flag is set, defautl value is TRUE.
2012 //
2013 DefaultData.Type = DefaultValueFromFlag;
2014 DefaultData.Value.b = TRUE;
2015 } else {
2016 //
2017 // When flag is not set, defautl value is FASLE.
2018 //
2019 DefaultData.Type = DefaultValueFromDefault;
2020 DefaultData.Value.b = FALSE;
2021 }
2022 //
2023 // Add DefaultValue into current BlockData
2024 //
2025 InsertDefaultValue (BlockData, &DefaultData);
2026 break;
2027
2028 case EFI_IFR_DATE_OP:
2029 //
2030 // offset by question header
2031 // width MaxSize * sizeof (CHAR16)
2032 // no default value, only block array
2033 //
2034
2035 //
2036 // Date question is not in IFR Form. This IFR form is not valid.
2037 //
2038 if (VarStoreId == 0) {
2039 Status = EFI_INVALID_PARAMETER;
2040 goto Done;
2041 }
2042 //
2043 // Check whether this question is for the requested varstore.
2044 //
2045 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
2046 if (IfrDate->Question.VarStoreId != VarStoreId) {
2047 break;
2048 }
2049
2050 //
2051 // The BlockData may allocate by other opcode,need to clean.
2052 //
2053 if (BlockData != NULL){
2054 BlockData = NULL;
2055 }
2056
2057 VarWidth = (UINT16) sizeof (EFI_HII_DATE);
2058 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2059 if (EFI_ERROR (Status)) {
2060 if (Status == EFI_NOT_FOUND){
2061 //
2062 //The opcode is not required,exit and parse other opcode.
2063 //
2064 break;
2065 }
2066 goto Done;
2067 }
2068 break;
2069
2070 case EFI_IFR_TIME_OP:
2071 //
2072 // offset by question header
2073 // width MaxSize * sizeof (CHAR16)
2074 // no default value, only block array
2075 //
2076
2077 //
2078 // Time question is not in IFR Form. This IFR form is not valid.
2079 //
2080 if (VarStoreId == 0) {
2081 Status = EFI_INVALID_PARAMETER;
2082 goto Done;
2083 }
2084 //
2085 // Check whether this question is for the requested varstore.
2086 //
2087 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
2088 if (IfrTime->Question.VarStoreId != VarStoreId) {
2089 break;
2090 }
2091
2092 //
2093 // The BlockData may allocate by other opcode,need to clean.
2094 //
2095 if (BlockData != NULL){
2096 BlockData = NULL;
2097 }
2098
2099 VarWidth = (UINT16) sizeof (EFI_HII_TIME);
2100 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2101 if (EFI_ERROR (Status)) {
2102 if (Status == EFI_NOT_FOUND){
2103 //
2104 //The opcode is not required,exit and parse other opcode.
2105 //
2106 break;
2107 }
2108 goto Done;
2109 }
2110 break;
2111
2112 case EFI_IFR_STRING_OP:
2113 //
2114 // offset by question header
2115 // width MaxSize * sizeof (CHAR16)
2116 // no default value, only block array
2117 //
2118
2119 //
2120 // String question is not in IFR Form. This IFR form is not valid.
2121 //
2122 if (VarStoreId == 0) {
2123 Status = EFI_INVALID_PARAMETER;
2124 goto Done;
2125 }
2126 //
2127 // Check whether this question is for the requested varstore.
2128 //
2129 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
2130 if (IfrString->Question.VarStoreId != VarStoreId) {
2131 break;
2132 }
2133
2134 //
2135 // The BlockData may allocate by other opcode,need to clean.
2136 //
2137 if (BlockData != NULL){
2138 BlockData = NULL;
2139 }
2140
2141 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
2142 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2143 if (EFI_ERROR (Status)) {
2144 if (Status == EFI_NOT_FOUND){
2145 //
2146 //The opcode is not required,exit and parse other opcode.
2147 //
2148 break;
2149 }
2150 goto Done;
2151 }
2152 break;
2153
2154 case EFI_IFR_PASSWORD_OP:
2155 //
2156 // offset by question header
2157 // width MaxSize * sizeof (CHAR16)
2158 // no default value, only block array
2159 //
2160
2161 //
2162 // Password question is not in IFR Form. This IFR form is not valid.
2163 //
2164 if (VarStoreId == 0) {
2165 Status = EFI_INVALID_PARAMETER;
2166 goto Done;
2167 }
2168 //
2169 // Check whether this question is for the requested varstore.
2170 //
2171 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
2172 if (IfrPassword->Question.VarStoreId != VarStoreId) {
2173 break;
2174 }
2175
2176 //
2177 // The BlockData may allocate by other opcode,need to clean.
2178 //
2179 if (BlockData != NULL){
2180 BlockData = NULL;
2181 }
2182
2183 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
2184 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2185 if (EFI_ERROR (Status)) {
2186 if (Status == EFI_NOT_FOUND){
2187 //
2188 //The opcode is not required,exit and parse other opcode.
2189 //
2190 break;
2191 }
2192 goto Done;
2193 }
2194
2195 //
2196 // No default value for string.
2197 //
2198 BlockData = NULL;
2199 break;
2200
2201 case EFI_IFR_ONE_OF_OPTION_OP:
2202 //
2203 // No matched block data is ignored.
2204 //
2205 if (BlockData == NULL || BlockData->Scope == 0) {
2206 break;
2207 }
2208
2209 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
2210 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2211
2212 if (!FirstOrderedList){
2213 break;
2214 }
2215 //
2216 // Get ordered list option data type.
2217 //
2218 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
2219 VarWidth = 1;
2220 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
2221 VarWidth = 2;
2222 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
2223 VarWidth = 4;
2224 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
2225 VarWidth = 8;
2226 } else {
2227 //
2228 // Invalid ordered list option data type.
2229 //
2230 Status = EFI_INVALID_PARAMETER;
2231 if (BlockData->Name != NULL) {
2232 FreePool (BlockData->Name);
2233 }
2234 FreePool (BlockData);
2235 goto Done;
2236 }
2237
2238 //
2239 // Calculate Ordered list QuestionId width.
2240 //
2241 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
2242 //
2243 // Check whether this question is in requested block array.
2244 //
2245 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2246 //
2247 // This question is not in the requested string. Skip it.
2248 //
2249 if (BlockData->Name != NULL) {
2250 FreePool (BlockData->Name);
2251 }
2252 FreePool (BlockData);
2253 BlockData = NULL;
2254 break;
2255 }
2256 //
2257 // Check this var question is in the var storage
2258 //
2259 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2260 Status = EFI_INVALID_PARAMETER;
2261 if (BlockData->Name != NULL) {
2262 FreePool (BlockData->Name);
2263 }
2264 FreePool (BlockData);
2265 goto Done;
2266 }
2267 //
2268 // Add Block Data into VarStorageData BlockEntry
2269 //
2270 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2271
2272 FirstOrderedList = FALSE;
2273
2274 break;
2275 }
2276
2277 //
2278 // 1. Set default value for OneOf option when flag field has default attribute.
2279 //
2280 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2281 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
2282 //
2283 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2284 // The first oneof option value will be used as default value when no default value is specified.
2285 //
2286 FirstOneOfOption = FALSE;
2287
2288 // Prepare new DefaultValue
2289 //
2290 DefaultData.Type = DefaultValueFromFlag;
2291 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2292 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
2293 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2294 InsertDefaultValue (BlockData, &DefaultData);
2295 }
2296 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
2297 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2298 InsertDefaultValue (BlockData, &DefaultData);
2299 }
2300 }
2301
2302 //
2303 // 2. Set as the default value when this is the first option.
2304 // The first oneof option value will be used as default value when no default value is specified.
2305 //
2306 if (FirstOneOfOption) {
2307 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2308 FirstOneOfOption = FALSE;
2309
2310 //
2311 // Prepare new DefaultValue
2312 //
2313 DefaultData.Type = DefaultValueFromDefault;
2314 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2315 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2316 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2317 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2318 InsertDefaultValue (BlockData, &DefaultData);
2319 }
2320 }
2321 break;
2322
2323 case EFI_IFR_DEFAULT_OP:
2324 //
2325 // Update Current BlockData to the default value.
2326 //
2327 if (BlockData == NULL || BlockData->Scope == 0) {
2328 //
2329 // No matched block data is ignored.
2330 //
2331 break;
2332 }
2333
2334 //
2335 // Get the DefaultId
2336 //
2337 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
2338 VarDefaultId = IfrDefault->DefaultId;
2339 //
2340 // Prepare new DefaultValue
2341 //
2342 DefaultData.Type = DefaultValueFromOpcode;
2343 DefaultData.DefaultId = VarDefaultId;
2344 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2345
2346 // If the value field is expression, set the cleaned flag.
2347 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
2348 DefaultData.Cleaned = TRUE;
2349 }
2350 //
2351 // Add DefaultValue into current BlockData
2352 //
2353 InsertDefaultValue (BlockData, &DefaultData);
2354
2355 //
2356 // After insert the default value, reset the cleaned value for next
2357 // time used. If not set here, need to set the value before everytime
2358 // use it.
2359 //
2360 DefaultData.Cleaned = FALSE;
2361 break;
2362
2363 case EFI_IFR_END_OP:
2364 //
2365 // End Opcode is for Var question.
2366 //
2367 if (BlockData != NULL) {
2368 if (BlockData->Scope > 0) {
2369 BlockData->Scope--;
2370 }
2371 if (BlockData->Scope == 0) {
2372 BlockData = NULL;
2373 }
2374 }
2375
2376 break;
2377
2378 default:
2379 if (BlockData != NULL) {
2380 if (BlockData->Scope > 0) {
2381 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
2382 }
2383
2384 if (BlockData->Scope == 0) {
2385 BlockData = NULL;
2386 }
2387 }
2388 break;
2389 }
2390
2391 IfrOffset += IfrOpHdr->Length;
2392 PackageOffset += IfrOpHdr->Length;
2393 }
2394
2395 //
2396 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2397 //so set the Status to EFI_SUCCESS.
2398 //
2399 if (Status == EFI_NOT_FOUND){
2400 Status = EFI_SUCCESS;
2401 }
2402
2403 Done:
2404 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2405 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2406 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
2407 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2408 LinkDefault = LinkDefault->ForwardLink;
2409 if (DefaultDataPtr->Cleaned == TRUE) {
2410 RemoveEntryList (&DefaultDataPtr->Entry);
2411 FreePool (DefaultDataPtr);
2412 }
2413 }
2414 }
2415
2416 return Status;
2417 }
2418
2419 /**
2420 parse the configrequest string, get the elements.
2421
2422 @param ConfigRequest The input configrequest string.
2423 @param Progress Return the progress data.
2424
2425 @retval Block data pointer.
2426 **/
2427 IFR_BLOCK_DATA *
2428 GetBlockElement (
2429 IN EFI_STRING ConfigRequest,
2430 OUT EFI_STRING *Progress
2431 )
2432 {
2433 EFI_STRING StringPtr;
2434 IFR_BLOCK_DATA *BlockData;
2435 IFR_BLOCK_DATA *RequestBlockArray;
2436 EFI_STATUS Status;
2437 UINT8 *TmpBuffer;
2438 UINT16 Offset;
2439 UINT16 Width;
2440 LIST_ENTRY *Link;
2441 IFR_BLOCK_DATA *NextBlockData;
2442 UINTN Length;
2443
2444 TmpBuffer = NULL;
2445
2446 //
2447 // Init RequestBlockArray
2448 //
2449 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2450 if (RequestBlockArray == NULL) {
2451 goto Done;
2452 }
2453 InitializeListHead (&RequestBlockArray->Entry);
2454
2455 //
2456 // Get the request Block array from the request string
2457 // Offset and Width
2458 //
2459
2460 //
2461 // Parse each <RequestElement> if exists
2462 // Only <BlockName> format is supported by this help function.
2463 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2464 //
2465 StringPtr = ConfigRequest;
2466 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
2467 //
2468 // Skip the OFFSET string
2469 //
2470 *Progress = StringPtr;
2471 StringPtr += StrLen (L"&OFFSET=");
2472 //
2473 // Get Offset
2474 //
2475 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2476 if (EFI_ERROR (Status)) {
2477 goto Done;
2478 }
2479 Offset = 0;
2480 CopyMem (
2481 &Offset,
2482 TmpBuffer,
2483 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2484 );
2485 FreePool (TmpBuffer);
2486
2487 StringPtr += Length;
2488 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
2489 goto Done;
2490 }
2491 StringPtr += StrLen (L"&WIDTH=");
2492
2493 //
2494 // Get Width
2495 //
2496 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2497 if (EFI_ERROR (Status)) {
2498 goto Done;
2499 }
2500 Width = 0;
2501 CopyMem (
2502 &Width,
2503 TmpBuffer,
2504 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2505 );
2506 FreePool (TmpBuffer);
2507
2508 StringPtr += Length;
2509 if (*StringPtr != 0 && *StringPtr != L'&') {
2510 goto Done;
2511 }
2512
2513 //
2514 // Set Block Data
2515 //
2516 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2517 if (BlockData == NULL) {
2518 goto Done;
2519 }
2520 BlockData->Offset = Offset;
2521 BlockData->Width = Width;
2522 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
2523
2524 //
2525 // Skip &VALUE string if &VALUE does exists.
2526 //
2527 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
2528 StringPtr += StrLen (L"&VALUE=");
2529
2530 //
2531 // Get Value
2532 //
2533 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2534 if (EFI_ERROR (Status)) {
2535 goto Done;
2536 }
2537
2538 StringPtr += Length;
2539 if (*StringPtr != 0 && *StringPtr != L'&') {
2540 goto Done;
2541 }
2542 }
2543 //
2544 // If '\0', parsing is finished.
2545 //
2546 if (*StringPtr == 0) {
2547 break;
2548 }
2549 }
2550
2551 //
2552 // Merge the requested block data.
2553 //
2554 Link = RequestBlockArray->Entry.ForwardLink;
2555 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
2556 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2557 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
2558 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
2559 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
2560 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
2561 }
2562 RemoveEntryList (Link->ForwardLink);
2563 FreePool (NextBlockData);
2564 continue;
2565 }
2566 Link = Link->ForwardLink;
2567 }
2568
2569 return RequestBlockArray;
2570
2571 Done:
2572 if (RequestBlockArray != NULL) {
2573 //
2574 // Free Link Array RequestBlockArray
2575 //
2576 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2577 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2578 RemoveEntryList (&BlockData->Entry);
2579 FreePool (BlockData);
2580 }
2581
2582 FreePool (RequestBlockArray);
2583 }
2584
2585 return NULL;
2586 }
2587
2588 /**
2589 parse the configrequest string, get the elements.
2590
2591 @param ConfigRequest The input config request string.
2592 @param Progress Return the progress data.
2593
2594 @retval return data block array.
2595 **/
2596 IFR_BLOCK_DATA *
2597 GetNameElement (
2598 IN EFI_STRING ConfigRequest,
2599 OUT EFI_STRING *Progress
2600 )
2601 {
2602 EFI_STRING StringPtr;
2603 EFI_STRING NextTag;
2604 IFR_BLOCK_DATA *BlockData;
2605 IFR_BLOCK_DATA *RequestBlockArray;
2606 BOOLEAN HasValue;
2607
2608 StringPtr = ConfigRequest;
2609
2610 //
2611 // Init RequestBlockArray
2612 //
2613 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2614 if (RequestBlockArray == NULL) {
2615 goto Done;
2616 }
2617 InitializeListHead (&RequestBlockArray->Entry);
2618
2619 //
2620 // Get the request Block array from the request string
2621 //
2622
2623 //
2624 // Parse each <RequestElement> if exists
2625 // Only <BlockName> format is supported by this help function.
2626 // <BlockName> ::= &'Name***=***
2627 //
2628 while (StringPtr != NULL && *StringPtr == L'&') {
2629
2630 *Progress = StringPtr;
2631 //
2632 // Skip the L"&" string
2633 //
2634 StringPtr += 1;
2635
2636 HasValue = FALSE;
2637 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
2638 *NextTag = L'\0';
2639 HasValue = TRUE;
2640 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
2641 *NextTag = L'\0';
2642 }
2643
2644 //
2645 // Set Block Data
2646 //
2647 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2648 if (BlockData == NULL) {
2649 goto Done;
2650 }
2651
2652 //
2653 // Get Name
2654 //
2655 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
2656 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
2657
2658 if (HasValue) {
2659 //
2660 // If has value, skip the value.
2661 //
2662 StringPtr = NextTag + 1;
2663 *NextTag = L'=';
2664 StringPtr = StrStr (StringPtr, L"&");
2665 } else if (NextTag != NULL) {
2666 //
2667 // restore the '&' text.
2668 //
2669 StringPtr = NextTag;
2670 *NextTag = L'&';
2671 }
2672 }
2673
2674 return RequestBlockArray;
2675
2676 Done:
2677 if (RequestBlockArray != NULL) {
2678 //
2679 // Free Link Array RequestBlockArray
2680 //
2681 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2682 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2683 RemoveEntryList (&BlockData->Entry);
2684 if (BlockData->Name != NULL) {
2685 FreePool (BlockData->Name);
2686 }
2687 FreePool (BlockData);
2688 }
2689
2690 FreePool (RequestBlockArray);
2691 }
2692
2693 return NULL;
2694 }
2695
2696 /**
2697 Generate ConfigRequest string base on the varstore info.
2698
2699 @param ConfigHdr The config header for this varstore.
2700 @param VarStorageData The varstore info.
2701 @param Status Return Status.
2702 @param ConfigRequest The ConfigRequest info may be return.
2703
2704 @retval TRUE Need to continue
2705 @retval Others NO need to continue or error occur.
2706 **/
2707 BOOLEAN
2708 GenerateConfigRequest (
2709 IN CHAR16 *ConfigHdr,
2710 IN IFR_VARSTORAGE_DATA *VarStorageData,
2711 OUT EFI_STATUS *Status,
2712 IN OUT EFI_STRING *ConfigRequest
2713 )
2714 {
2715 BOOLEAN DataExist;
2716 UINTN Length;
2717 LIST_ENTRY *Link;
2718 CHAR16 *FullConfigRequest;
2719 CHAR16 *StringPtr;
2720 IFR_BLOCK_DATA *BlockData;
2721
2722 //
2723 // Append VarStorageData BlockEntry into *Request string
2724 // Now support only one varstore in a form package.
2725 //
2726
2727 //
2728 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2729 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2730 //
2731
2732 //
2733 // Compute the length of the entire request starting with <ConfigHdr> and a
2734 // Null-terminator
2735 //
2736 DataExist = FALSE;
2737 Length = StrLen (ConfigHdr) + 1;
2738
2739 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2740 DataExist = TRUE;
2741 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2742 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2743 //
2744 // Add <BlockName> length for each Name
2745 //
2746 // <BlockName> ::= &Name1&Name2&...
2747 // |1| StrLen(Name1)
2748 //
2749 Length = Length + (1 + StrLen (BlockData->Name));
2750 } else {
2751 //
2752 // Add <BlockName> length for each Offset/Width pair
2753 //
2754 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2755 // | 8 | 4 | 7 | 4 |
2756 //
2757 Length = Length + (8 + 4 + 7 + 4);
2758 }
2759 }
2760 //
2761 // No any request block data is found. The request string can't be constructed.
2762 //
2763 if (!DataExist) {
2764 *Status = EFI_SUCCESS;
2765 return FALSE;
2766 }
2767
2768 //
2769 // Allocate buffer for the entire <ConfigRequest>
2770 //
2771 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
2772 if (FullConfigRequest == NULL) {
2773 *Status = EFI_OUT_OF_RESOURCES;
2774 return FALSE;
2775 }
2776 StringPtr = FullConfigRequest;
2777
2778 //
2779 // Start with <ConfigHdr>
2780 //
2781 StrCpyS (StringPtr, Length, ConfigHdr);
2782 StringPtr += StrLen (StringPtr);
2783
2784 //
2785 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2786 //
2787 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2788 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2789 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2790 //
2791 // Append &Name1\0
2792 //
2793 UnicodeSPrint (
2794 StringPtr,
2795 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
2796 L"&%s",
2797 BlockData->Name
2798 );
2799 } else {
2800 //
2801 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2802 //
2803 UnicodeSPrint (
2804 StringPtr,
2805 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
2806 L"&OFFSET=%04X&WIDTH=%04X",
2807 BlockData->Offset,
2808 BlockData->Width
2809 );
2810 }
2811 StringPtr += StrLen (StringPtr);
2812 }
2813 //
2814 // Set to the got full request string.
2815 //
2816 HiiToLower (FullConfigRequest);
2817
2818 if (*ConfigRequest != NULL) {
2819 FreePool (*ConfigRequest);
2820 }
2821 *ConfigRequest = FullConfigRequest;
2822
2823 return TRUE;
2824 }
2825
2826 /**
2827 Generate ConfigRequest Header base on the varstore info.
2828
2829 @param VarStorageData The varstore info.
2830 @param DevicePath Device path for this varstore.
2831 @param ConfigHdr The config header for this varstore.
2832
2833 @retval EFI_SUCCESS Generate the header success.
2834 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2835 **/
2836 EFI_STATUS
2837 GenerateHdr (
2838 IN IFR_VARSTORAGE_DATA *VarStorageData,
2839 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2840 OUT EFI_STRING *ConfigHdr
2841 )
2842 {
2843 EFI_STRING GuidStr;
2844 EFI_STRING NameStr;
2845 EFI_STRING PathStr;
2846 UINTN Length;
2847 EFI_STATUS Status;
2848
2849 Status = EFI_SUCCESS;
2850 NameStr = NULL;
2851 GuidStr = NULL;
2852 PathStr = NULL;
2853
2854 //
2855 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2856 //
2857 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
2858 if (VarStorageData->Name != NULL) {
2859 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
2860 } else {
2861 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
2862 }
2863 GenerateSubStr (
2864 L"PATH=",
2865 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
2866 (VOID *) DevicePath,
2867 1,
2868 &PathStr
2869 );
2870 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
2871 if (VarStorageData->Name == NULL) {
2872 Length += 1;
2873 }
2874
2875 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
2876 if (*ConfigHdr == NULL) {
2877 Status = EFI_OUT_OF_RESOURCES;
2878 goto Done;
2879 }
2880 StrCpyS (*ConfigHdr, Length, GuidStr);
2881 StrCatS (*ConfigHdr, Length, NameStr);
2882 if (VarStorageData->Name == NULL) {
2883 StrCatS (*ConfigHdr, Length, L"&");
2884 }
2885 StrCatS (*ConfigHdr, Length, PathStr);
2886
2887 //
2888 // Remove the last character L'&'
2889 //
2890 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
2891
2892 Done:
2893 if (GuidStr != NULL) {
2894 FreePool (GuidStr);
2895 }
2896
2897 if (NameStr != NULL) {
2898 FreePool (NameStr);
2899 }
2900
2901 if (PathStr != NULL) {
2902 FreePool (PathStr);
2903 }
2904
2905 return Status;
2906 }
2907
2908 /**
2909 Get Data buffer size based on data type.
2910
2911 @param ValueType The input data type.
2912
2913 @retval The data buffer size for the input type.
2914 **/
2915 UINT16
2916 GetStorageWidth (
2917 IN UINT8 ValueType
2918 )
2919 {
2920 UINT16 StorageWidth;
2921
2922 switch (ValueType) {
2923 case EFI_IFR_NUMERIC_SIZE_1:
2924 case EFI_IFR_TYPE_BOOLEAN:
2925 StorageWidth = (UINT16) sizeof (UINT8);
2926 break;
2927
2928 case EFI_IFR_NUMERIC_SIZE_2:
2929 StorageWidth = (UINT16) sizeof (UINT16);
2930 break;
2931
2932 case EFI_IFR_NUMERIC_SIZE_4:
2933 StorageWidth = (UINT16) sizeof (UINT32);
2934 break;
2935
2936 case EFI_IFR_NUMERIC_SIZE_8:
2937 StorageWidth = (UINT16) sizeof (UINT64);
2938 break;
2939
2940 case EFI_IFR_TYPE_TIME:
2941 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
2942 break;
2943
2944 case EFI_IFR_TYPE_DATE:
2945 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
2946 break;
2947
2948 default:
2949 StorageWidth = 0;
2950 break;
2951 }
2952
2953 return StorageWidth;
2954 }
2955
2956 /**
2957 Generate ConfigAltResp string base on the varstore info.
2958
2959 @param HiiHandle Hii Handle for this hii package.
2960 @param ConfigHdr The config header for this varstore.
2961 @param VarStorageData The varstore info.
2962 @param DefaultIdArray The Default id array.
2963 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2964
2965 @retval TRUE Need to continue
2966 @retval Others NO need to continue or error occur.
2967 **/
2968 EFI_STATUS
2969 GenerateAltConfigResp (
2970 IN EFI_HII_HANDLE HiiHandle,
2971 IN CHAR16 *ConfigHdr,
2972 IN IFR_VARSTORAGE_DATA *VarStorageData,
2973 IN IFR_DEFAULT_DATA *DefaultIdArray,
2974 IN OUT EFI_STRING *DefaultAltCfgResp
2975 )
2976 {
2977 BOOLEAN DataExist;
2978 UINTN Length;
2979 LIST_ENTRY *Link;
2980 LIST_ENTRY *LinkData;
2981 LIST_ENTRY *LinkDefault;
2982 LIST_ENTRY *ListEntry;
2983 CHAR16 *StringPtr;
2984 IFR_BLOCK_DATA *BlockData;
2985 IFR_DEFAULT_DATA *DefaultId;
2986 IFR_DEFAULT_DATA *DefaultValueData;
2987 UINTN Width;
2988 UINT8 *TmpBuffer;
2989 CHAR16 *DefaultString;
2990
2991 BlockData = NULL;
2992 DataExist = FALSE;
2993 DefaultString = NULL;
2994 //
2995 // Add length for <ConfigHdr> + '\0'
2996 //
2997 Length = StrLen (ConfigHdr) + 1;
2998
2999 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3000 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3001 //
3002 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3003 // |1| StrLen (ConfigHdr) | 8 | 4 |
3004 //
3005 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
3006
3007 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3008 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3009 ListEntry = &BlockData->DefaultValueEntry;
3010 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3011 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3012 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3013 continue;
3014 }
3015 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3016 //
3017 // Add length for "&Name1=zzzzzzzzzzzz"
3018 // |1|Name|1|Value|
3019 //
3020 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
3021 } else {
3022 //
3023 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3024 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3025 //
3026 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
3027 }
3028 DataExist = TRUE;
3029 }
3030 }
3031 }
3032
3033 //
3034 // No default value is found. The default string doesn't exist.
3035 //
3036 if (!DataExist) {
3037 return EFI_SUCCESS;
3038 }
3039
3040 //
3041 // Allocate buffer for the entire <DefaultAltCfgResp>
3042 //
3043 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3044 if (*DefaultAltCfgResp == NULL) {
3045 return EFI_OUT_OF_RESOURCES;
3046 }
3047 StringPtr = *DefaultAltCfgResp;
3048
3049 //
3050 // Start with <ConfigHdr>
3051 //
3052 StrCpyS (StringPtr, Length, ConfigHdr);
3053 StringPtr += StrLen (StringPtr);
3054
3055 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3056 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3057 //
3058 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3059 // |1| StrLen (ConfigHdr) | 8 | 4 |
3060 //
3061 UnicodeSPrint (
3062 StringPtr,
3063 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
3064 L"&%s&ALTCFG=%04X",
3065 ConfigHdr,
3066 DefaultId->DefaultId
3067 );
3068 StringPtr += StrLen (StringPtr);
3069
3070 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3071 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3072 ListEntry = &BlockData->DefaultValueEntry;
3073 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3074 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3075 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3076 continue;
3077 }
3078 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3079 UnicodeSPrint (
3080 StringPtr,
3081 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
3082 L"&%s=",
3083 BlockData->Name
3084 );
3085 StringPtr += StrLen (StringPtr);
3086 } else {
3087 //
3088 // Add <BlockConfig>
3089 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3090 //
3091 UnicodeSPrint (
3092 StringPtr,
3093 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
3094 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3095 BlockData->Offset,
3096 BlockData->Width
3097 );
3098 StringPtr += StrLen (StringPtr);
3099 }
3100 Width = BlockData->Width;
3101 //
3102 // Convert Value to a hex string in "%x" format
3103 // NOTE: This is in the opposite byte that GUID and PATH use
3104 //
3105 if (BlockData->OpCode == EFI_IFR_STRING_OP){
3106 DefaultString = InternalGetString(HiiHandle, DefaultValueData->Value.string);
3107 TmpBuffer = (UINT8 *) DefaultString;
3108 } else {
3109 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
3110 }
3111 for (; Width > 0 && (TmpBuffer != NULL); Width--) {
3112 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
3113 }
3114 if (DefaultString != NULL){
3115 FreePool(DefaultString);
3116 DefaultString = NULL;
3117 }
3118 }
3119 }
3120 }
3121
3122 HiiToLower (*DefaultAltCfgResp);
3123
3124 return EFI_SUCCESS;
3125 }
3126
3127 /**
3128 This function gets the full request string and full default value string by
3129 parsing IFR data in HII form packages.
3130
3131 When Request points to NULL string, the request string and default value string
3132 for each varstore in form package will return.
3133
3134 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3135 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3136 @param Request Pointer to a null-terminated Unicode string in
3137 <ConfigRequest> format. When it doesn't contain
3138 any RequestElement, it will be updated to return
3139 the full RequestElement retrieved from IFR data.
3140 If it points to NULL, the request string for the first
3141 varstore in form package will be merged into a
3142 <MultiConfigRequest> format string and return.
3143 @param AltCfgResp Pointer to a null-terminated Unicode string in
3144 <ConfigAltResp> format. When the pointer is to NULL,
3145 the full default value string retrieved from IFR data
3146 will return. When the pinter is to a string, the
3147 full default value string retrieved from IFR data
3148 will be merged into the input string and return.
3149 When Request points to NULL, the default value string
3150 for each varstore in form package will be merged into
3151 a <MultiConfigAltResp> format string and return.
3152 @param PointerProgress Optional parameter, it can be be NULL.
3153 When it is not NULL, if Request is NULL, it returns NULL.
3154 On return, points to a character in the Request
3155 string. Points to the string's null terminator if
3156 request was successful. Points to the most recent
3157 & before the first failing name / value pair (or
3158 the beginning of the string if the failure is in
3159 the first name / value pair) if the request was
3160 not successful.
3161 @retval EFI_SUCCESS The Results string is set to the full request string.
3162 And AltCfgResp contains all default value string.
3163 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3164 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3165 can't be found in Form package.
3166 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3167 @retval EFI_INVALID_PARAMETER Request points to NULL.
3168
3169 **/
3170 EFI_STATUS
3171 EFIAPI
3172 GetFullStringFromHiiFormPackages (
3173 IN HII_DATABASE_RECORD *DataBaseRecord,
3174 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3175 IN OUT EFI_STRING *Request,
3176 IN OUT EFI_STRING *AltCfgResp,
3177 OUT EFI_STRING *PointerProgress OPTIONAL
3178 )
3179 {
3180 EFI_STATUS Status;
3181 UINT8 *HiiFormPackage;
3182 UINTN PackageSize;
3183 IFR_BLOCK_DATA *RequestBlockArray;
3184 IFR_BLOCK_DATA *BlockData;
3185 IFR_DEFAULT_DATA *DefaultValueData;
3186 IFR_DEFAULT_DATA *DefaultId;
3187 IFR_DEFAULT_DATA *DefaultIdArray;
3188 IFR_VARSTORAGE_DATA *VarStorageData;
3189 EFI_STRING DefaultAltCfgResp;
3190 EFI_STRING ConfigHdr;
3191 EFI_STRING StringPtr;
3192 EFI_STRING Progress;
3193
3194 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
3195 return EFI_INVALID_PARAMETER;
3196 }
3197
3198 //
3199 // Initialize the local variables.
3200 //
3201 RequestBlockArray = NULL;
3202 DefaultIdArray = NULL;
3203 VarStorageData = NULL;
3204 DefaultAltCfgResp = NULL;
3205 ConfigHdr = NULL;
3206 HiiFormPackage = NULL;
3207 PackageSize = 0;
3208 Progress = *Request;
3209
3210 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
3211 if (EFI_ERROR (Status)) {
3212 goto Done;
3213 }
3214
3215 //
3216 // 1. Get the request block array by Request String when Request string containts the block array.
3217 //
3218 StringPtr = NULL;
3219 if (*Request != NULL) {
3220 StringPtr = *Request;
3221 //
3222 // Jump <ConfigHdr>
3223 //
3224 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3225 Status = EFI_INVALID_PARAMETER;
3226 goto Done;
3227 }
3228 StringPtr += StrLen (L"GUID=");
3229 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3230 StringPtr++;
3231 }
3232 if (*StringPtr == L'\0') {
3233 Status = EFI_INVALID_PARAMETER;
3234 goto Done;
3235 }
3236 StringPtr += StrLen (L"&NAME=");
3237 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3238 StringPtr++;
3239 }
3240 if (*StringPtr == L'\0') {
3241 Status = EFI_INVALID_PARAMETER;
3242 goto Done;
3243 }
3244 StringPtr += StrLen (L"&PATH=");
3245 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3246 StringPtr ++;
3247 }
3248
3249 if (*StringPtr == L'\0') {
3250 //
3251 // No request block is found.
3252 //
3253 StringPtr = NULL;
3254 }
3255 }
3256
3257 //
3258 // If StringPtr != NULL, get the request elements.
3259 //
3260 if (StringPtr != NULL) {
3261 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
3262 RequestBlockArray = GetBlockElement(StringPtr, &Progress);
3263 } else {
3264 RequestBlockArray = GetNameElement(StringPtr, &Progress);
3265 }
3266
3267 if (RequestBlockArray == NULL) {
3268 Status = EFI_INVALID_PARAMETER;
3269 goto Done;
3270 }
3271 }
3272
3273 //
3274 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3275 //
3276 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
3277 if (DefaultIdArray == NULL) {
3278 Status = EFI_OUT_OF_RESOURCES;
3279 goto Done;
3280 }
3281 InitializeListHead (&DefaultIdArray->Entry);
3282
3283 //
3284 // Initialize VarStorageData to store the var store Block and Default value information.
3285 //
3286 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
3287 if (VarStorageData == NULL) {
3288 Status = EFI_OUT_OF_RESOURCES;
3289 goto Done;
3290 }
3291 InitializeListHead (&VarStorageData->Entry);
3292 InitializeListHead (&VarStorageData->BlockEntry);
3293
3294 //
3295 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3296 //
3297
3298 //
3299 // Parse the opcode in form pacakge to get the default setting.
3300 //
3301 Status = ParseIfrData (DataBaseRecord->Handle,
3302 HiiFormPackage,
3303 (UINT32) PackageSize,
3304 *Request,
3305 RequestBlockArray,
3306 VarStorageData,
3307 DefaultIdArray);
3308 if (EFI_ERROR (Status)) {
3309 goto Done;
3310 }
3311
3312 //
3313 // No requested varstore in IFR data and directly return
3314 //
3315 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
3316 Status = EFI_SUCCESS;
3317 goto Done;
3318 }
3319
3320 //
3321 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3322 //
3323 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
3324 if (EFI_ERROR (Status)) {
3325 goto Done;
3326 }
3327
3328 if (RequestBlockArray == NULL) {
3329 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
3330 goto Done;
3331 }
3332 }
3333
3334 //
3335 // 4. Construct Default Value string in AltResp according to request element.
3336 // Go through all VarStorageData Entry and get the DefaultId array for each one
3337 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3338 //
3339 Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
3340 if (EFI_ERROR (Status)) {
3341 goto Done;
3342 }
3343
3344 //
3345 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3346 //
3347 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
3348 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
3349 FreePool (DefaultAltCfgResp);
3350 } else if (*AltCfgResp == NULL) {
3351 *AltCfgResp = DefaultAltCfgResp;
3352 }
3353
3354 Done:
3355 if (RequestBlockArray != NULL) {
3356 //
3357 // Free Link Array RequestBlockArray
3358 //
3359 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3360 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3361 RemoveEntryList (&BlockData->Entry);
3362 if (BlockData->Name != NULL) {
3363 FreePool (BlockData->Name);
3364 }
3365 FreePool (BlockData);
3366 }
3367
3368 FreePool (RequestBlockArray);
3369 }
3370
3371 if (VarStorageData != NULL) {
3372 //
3373 // Free link array VarStorageData
3374 //
3375 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
3376 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
3377 RemoveEntryList (&BlockData->Entry);
3378 if (BlockData->Name != NULL) {
3379 FreePool (BlockData->Name);
3380 }
3381 //
3382 // Free default value link array
3383 //
3384 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
3385 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3386 RemoveEntryList (&DefaultValueData->Entry);
3387 FreePool (DefaultValueData);
3388 }
3389 FreePool (BlockData);
3390 }
3391 FreePool (VarStorageData);
3392 }
3393
3394 if (DefaultIdArray != NULL) {
3395 //
3396 // Free DefaultId Array
3397 //
3398 while (!IsListEmpty (&DefaultIdArray->Entry)) {
3399 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3400 RemoveEntryList (&DefaultId->Entry);
3401 FreePool (DefaultId);
3402 }
3403 FreePool (DefaultIdArray);
3404 }
3405
3406 //
3407 // Free the allocated string
3408 //
3409 if (ConfigHdr != NULL) {
3410 FreePool (ConfigHdr);
3411 }
3412
3413 //
3414 // Free Pacakge data
3415 //
3416 if (HiiFormPackage != NULL) {
3417 FreePool (HiiFormPackage);
3418 }
3419
3420 if (PointerProgress != NULL) {
3421 if (*Request == NULL) {
3422 *PointerProgress = NULL;
3423 } else if (EFI_ERROR (Status)) {
3424 *PointerProgress = *Request;
3425 } else {
3426 *PointerProgress = *Request + StrLen (*Request);
3427 }
3428 }
3429
3430 return Status;
3431 }
3432
3433 /**
3434 This function gets the full request resp string by
3435 parsing IFR data in HII form packages.
3436
3437 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3438 instance.
3439 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3440 varstore data structure.
3441 @param Request Pointer to a null-terminated Unicode string in
3442 <ConfigRequest> format.
3443 @param RequestResp Pointer to a null-terminated Unicode string in
3444 <ConfigResp> format.
3445 @param AccessProgress On return, points to a character in the Request
3446 string. Points to the string's null terminator if
3447 request was successful. Points to the most recent
3448 & before the first failing name / value pair (or
3449 the beginning of the string if the failure is in
3450 the first name / value pair) if the request was
3451 not successful.
3452
3453 @retval EFI_SUCCESS The Results string is set to the full request string.
3454 And AltCfgResp contains all default value string.
3455 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3456 @retval EFI_INVALID_PARAMETER Request points to NULL.
3457
3458 **/
3459 EFI_STATUS
3460 GetConfigRespFromEfiVarStore (
3461 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3462 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3463 IN EFI_STRING Request,
3464 OUT EFI_STRING *RequestResp,
3465 OUT EFI_STRING *AccessProgress
3466 )
3467 {
3468 EFI_STATUS Status;
3469 EFI_STRING VarStoreName;
3470 UINT8 *VarStore;
3471 UINTN BufferSize;
3472
3473 Status = EFI_SUCCESS;
3474 BufferSize = 0;
3475 VarStore = NULL;
3476 VarStoreName = NULL;
3477 *AccessProgress = Request;
3478
3479 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
3480 if (VarStoreName == NULL) {
3481 Status = EFI_OUT_OF_RESOURCES;
3482 goto Done;
3483 }
3484 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
3485
3486
3487 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3488 if (Status != EFI_BUFFER_TOO_SMALL) {
3489 goto Done;
3490 }
3491
3492 VarStore = AllocateZeroPool (BufferSize);
3493 ASSERT (VarStore != NULL);
3494 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
3495 if (EFI_ERROR (Status)) {
3496 goto Done;
3497 }
3498
3499 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
3500 if (EFI_ERROR (Status)) {
3501 goto Done;
3502 }
3503
3504 Done:
3505 if (VarStoreName != NULL) {
3506 FreePool (VarStoreName);
3507 }
3508
3509 if (VarStore != NULL) {
3510 FreePool (VarStore);
3511 }
3512
3513 return Status;
3514 }
3515
3516
3517 /**
3518 This function route the full request resp string for efi varstore.
3519
3520 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3521 instance.
3522 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3523 varstore data structure.
3524 @param RequestResp Pointer to a null-terminated Unicode string in
3525 <ConfigResp> format.
3526 @param Result Pointer to a null-terminated Unicode string in
3527 <ConfigResp> format.
3528
3529 @retval EFI_SUCCESS The Results string is set to the full request string.
3530 And AltCfgResp contains all default value string.
3531 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3532 @retval EFI_INVALID_PARAMETER Request points to NULL.
3533
3534 **/
3535 EFI_STATUS
3536 RouteConfigRespForEfiVarStore (
3537 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3538 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3539 IN EFI_STRING RequestResp,
3540 OUT EFI_STRING *Result
3541 )
3542 {
3543 EFI_STATUS Status;
3544 EFI_STRING VarStoreName;
3545 UINT8 *VarStore;
3546 UINTN BufferSize;
3547 UINTN BlockSize;
3548
3549 Status = EFI_SUCCESS;
3550 BufferSize = 0;
3551 VarStore = NULL;
3552 VarStoreName = NULL;
3553
3554 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
3555 if (VarStoreName == NULL) {
3556 Status = EFI_OUT_OF_RESOURCES;
3557 goto Done;
3558 }
3559 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
3560
3561 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3562 if (Status != EFI_BUFFER_TOO_SMALL) {
3563 goto Done;
3564 }
3565
3566 BlockSize = BufferSize;
3567 VarStore = AllocateZeroPool (BufferSize);
3568 ASSERT (VarStore != NULL);
3569 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
3570 if (EFI_ERROR (Status)) {
3571 goto Done;
3572 }
3573
3574 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
3575 if (EFI_ERROR (Status)) {
3576 goto Done;
3577 }
3578
3579 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
3580 if (EFI_ERROR (Status)) {
3581 goto Done;
3582 }
3583
3584 Done:
3585 if (VarStoreName != NULL) {
3586 FreePool (VarStoreName);
3587 }
3588
3589 if (VarStore != NULL) {
3590 FreePool (VarStore);
3591 }
3592
3593 return Status;
3594 }
3595
3596 /**
3597 Validate the config request elements.
3598
3599 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3600 without configHdr field.
3601
3602 @retval CHAR16 * THE first Name/value pair not correct.
3603 @retval NULL Success parse the name/value pair
3604 **/
3605 CHAR16 *
3606 OffsetWidthValidate (
3607 CHAR16 *ConfigElements
3608 )
3609 {
3610 CHAR16 *StringPtr;
3611 CHAR16 *RetVal;
3612
3613 StringPtr = ConfigElements;
3614
3615 while (1) {
3616 RetVal = StringPtr;
3617 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
3618 return RetVal;
3619 }
3620
3621 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3622 StringPtr++;
3623 }
3624 if (*StringPtr == L'\0') {
3625 return RetVal;
3626 }
3627
3628 StringPtr += StrLen (L"&WIDTH=");
3629 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
3630 StringPtr ++;
3631 }
3632
3633 if (*StringPtr == L'\0') {
3634 return NULL;
3635 }
3636 }
3637 }
3638
3639 /**
3640 Validate the config request elements.
3641
3642 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3643 without configHdr field.
3644
3645 @retval CHAR16 * THE first Name/value pair not correct.
3646 @retval NULL Success parse the name/value pair
3647
3648 **/
3649 CHAR16 *
3650 NameValueValidate (
3651 CHAR16 *ConfigElements
3652 )
3653 {
3654 CHAR16 *StringPtr;
3655 CHAR16 *RetVal;
3656
3657 StringPtr = ConfigElements;
3658
3659 while (1) {
3660 RetVal = StringPtr;
3661 if (*StringPtr != L'&') {
3662 return RetVal;
3663 }
3664 StringPtr += 1;
3665
3666 StringPtr = StrStr (StringPtr, L"&");
3667
3668 if (StringPtr == NULL) {
3669 return NULL;
3670 }
3671 }
3672 }
3673
3674 /**
3675 Validate the config request string.
3676
3677 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3678
3679 @retval CHAR16 * THE first element not correct.
3680 @retval NULL Success parse the name/value pair
3681
3682 **/
3683 CHAR16 *
3684 ConfigRequestValidate (
3685 CHAR16 *ConfigRequest
3686 )
3687 {
3688 BOOLEAN HasNameField;
3689 CHAR16 *StringPtr;
3690
3691 HasNameField = TRUE;
3692 StringPtr = ConfigRequest;
3693
3694 //
3695 // Check <ConfigHdr>
3696 //
3697 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3698 return ConfigRequest;
3699 }
3700 StringPtr += StrLen (L"GUID=");
3701 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3702 StringPtr++;
3703 }
3704 if (*StringPtr == L'\0') {
3705 return ConfigRequest;
3706 }
3707 StringPtr += StrLen (L"&NAME=");
3708 if (*StringPtr == L'&') {
3709 HasNameField = FALSE;
3710 }
3711 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3712 StringPtr++;
3713 }
3714 if (*StringPtr == L'\0') {
3715 return ConfigRequest;
3716 }
3717 StringPtr += StrLen (L"&PATH=");
3718 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3719 StringPtr ++;
3720 }
3721
3722 if (*StringPtr == L'\0') {
3723 return NULL;
3724 }
3725
3726 if (HasNameField) {
3727 //
3728 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3729 //
3730 return OffsetWidthValidate(StringPtr);
3731 } else {
3732 //
3733 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3734 //
3735 return NameValueValidate(StringPtr);
3736 }
3737 }
3738
3739 /**
3740 This function allows a caller to extract the current configuration
3741 for one or more named elements from one or more drivers.
3742
3743 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3744 instance.
3745 @param Request A null-terminated Unicode string in
3746 <MultiConfigRequest> format.
3747 @param Progress On return, points to a character in the Request
3748 string. Points to the string's null terminator if
3749 request was successful. Points to the most recent
3750 & before the first failing name / value pair (or
3751 the beginning of the string if the failure is in
3752 the first name / value pair) if the request was
3753 not successful.
3754 @param Results Null-terminated Unicode string in
3755 <MultiConfigAltResp> format which has all values
3756 filled in for the names in the Request string.
3757 String to be allocated by the called function.
3758
3759 @retval EFI_SUCCESS The Results string is filled with the values
3760 corresponding to all requested names.
3761 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3762 results that must be stored awaiting possible
3763 future protocols.
3764 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3765 Progress set to the "G" in "GUID" of the routing
3766 header that doesn't match. Note: There is no
3767 requirement that all routing data be validated
3768 before any configuration extraction.
3769 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3770 parameter would result in this type of error. The
3771 Progress parameter is set to NULL.
3772 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3773 before the error or the beginning of the string.
3774 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3775 Configuration Access Protocol returned
3776 EFI_INVALID_PARAMETER. Progress set to most recent
3777 & before the error or the beginning of the string.
3778
3779 **/
3780 EFI_STATUS
3781 EFIAPI
3782 HiiConfigRoutingExtractConfig (
3783 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3784 IN CONST EFI_STRING Request,
3785 OUT EFI_STRING *Progress,
3786 OUT EFI_STRING *Results
3787 )
3788 {
3789 HII_DATABASE_PRIVATE_DATA *Private;
3790 EFI_STRING StringPtr;
3791 EFI_STRING ConfigRequest;
3792 UINTN Length;
3793 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3794 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
3795 EFI_STATUS Status;
3796 LIST_ENTRY *Link;
3797 HII_DATABASE_RECORD *Database;
3798 UINT8 *DevicePathPkg;
3799 UINT8 *CurrentDevicePath;
3800 EFI_HANDLE DriverHandle;
3801 EFI_HII_HANDLE HiiHandle;
3802 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
3803 EFI_STRING AccessProgress;
3804 EFI_STRING AccessResults;
3805 EFI_STRING DefaultResults;
3806 BOOLEAN FirstElement;
3807 BOOLEAN IfrDataParsedFlag;
3808 BOOLEAN IsEfiVarStore;
3809 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
3810 EFI_STRING ErrorPtr;
3811 UINTN DevicePathSize;
3812
3813 if (This == NULL || Progress == NULL || Results == NULL) {
3814 return EFI_INVALID_PARAMETER;
3815 }
3816
3817 if (Request == NULL) {
3818 *Progress = NULL;
3819 return EFI_INVALID_PARAMETER;
3820 }
3821
3822 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3823 StringPtr = Request;
3824 *Progress = StringPtr;
3825 DefaultResults = NULL;
3826 ConfigRequest = NULL;
3827 Status = EFI_SUCCESS;
3828 AccessResults = NULL;
3829 AccessProgress = NULL;
3830 DevicePath = NULL;
3831 IfrDataParsedFlag = FALSE;
3832 IsEfiVarStore = FALSE;
3833 EfiVarStoreInfo = NULL;
3834
3835 //
3836 // The first element of <MultiConfigRequest> should be
3837 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3838 //
3839 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3840 return EFI_INVALID_PARAMETER;
3841 }
3842
3843 FirstElement = TRUE;
3844
3845 //
3846 // Allocate a fix length of memory to store Results. Reallocate memory for
3847 // Results if this fix length is insufficient.
3848 //
3849 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
3850 if (*Results == NULL) {
3851 return EFI_OUT_OF_RESOURCES;
3852 }
3853
3854 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
3855 //
3856 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3857 // or most recent & before the error.
3858 //
3859 if (StringPtr == Request) {
3860 *Progress = StringPtr;
3861 } else {
3862 *Progress = StringPtr - 1;
3863 }
3864
3865 //
3866 // Process each <ConfigRequest> of <MultiConfigRequest>
3867 //
3868 Length = CalculateConfigStringLen (StringPtr);
3869 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
3870 if (ConfigRequest == NULL) {
3871 Status = EFI_OUT_OF_RESOURCES;
3872 goto Done;
3873 }
3874 *(ConfigRequest + Length) = 0;
3875
3876 //
3877 // Get the UEFI device path
3878 //
3879 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
3880 if (EFI_ERROR (Status)) {
3881 goto Done;
3882 }
3883
3884 //
3885 // Find driver which matches the routing data.
3886 //
3887 DriverHandle = NULL;
3888 HiiHandle = NULL;
3889 Database = NULL;
3890 for (Link = Private->DatabaseList.ForwardLink;
3891 Link != &Private->DatabaseList;
3892 Link = Link->ForwardLink
3893 ) {
3894 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3895 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
3896 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
3897 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
3898 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
3899 DriverHandle = Database->DriverHandle;
3900 HiiHandle = Database->Handle;
3901 break;
3902 }
3903 }
3904 }
3905
3906 //
3907 // Try to find driver handle by device path.
3908 //
3909 if (DriverHandle == NULL) {
3910 TempDevicePath = DevicePath;
3911 Status = gBS->LocateDevicePath (
3912 &gEfiDevicePathProtocolGuid,
3913 &TempDevicePath,
3914 &DriverHandle
3915 );
3916 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
3917 //
3918 // Routing data does not match any known driver.
3919 // Set Progress to the 'G' in "GUID" of the routing header.
3920 //
3921 *Progress = StringPtr;
3922 Status = EFI_NOT_FOUND;
3923 goto Done;
3924 }
3925 }
3926
3927 //
3928 // Validate ConfigRequest String.
3929 //
3930 ErrorPtr = ConfigRequestValidate(ConfigRequest);
3931 if (ErrorPtr != NULL) {
3932 *Progress = StrStr (StringPtr, ErrorPtr);
3933 Status = EFI_INVALID_PARAMETER;
3934 goto Done;
3935 }
3936
3937 //
3938 // Check whether ConfigRequest contains request string.
3939 //
3940 IfrDataParsedFlag = FALSE;
3941 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
3942 //
3943 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3944 //
3945 IfrDataParsedFlag = TRUE;
3946 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
3947 if (EFI_ERROR (Status)) {
3948 //
3949 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3950 // Map it to the progress on <MultiConfigRequest> then return it.
3951 //
3952 ASSERT (AccessProgress != NULL);
3953 *Progress = StrStr (StringPtr, AccessProgress);
3954 goto Done;
3955 }
3956 //
3957 // Not any request block is found.
3958 //
3959 if (!GetElementsFromRequest(ConfigRequest)) {
3960 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
3961 goto NextConfigString;
3962 }
3963 }
3964
3965 //
3966 // Check whether this ConfigRequest is search from Efi varstore type storage.
3967 //
3968 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
3969 if (EFI_ERROR (Status)) {
3970 goto Done;
3971 }
3972
3973 if (IsEfiVarStore) {
3974 //
3975 // Call the GetVariable function to extract settings.
3976 //
3977 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
3978 FreePool (EfiVarStoreInfo);
3979 } else {
3980 //
3981 // Call corresponding ConfigAccess protocol to extract settings
3982 //
3983 Status = gBS->HandleProtocol (
3984 DriverHandle,
3985 &gEfiHiiConfigAccessProtocolGuid,
3986 (VOID **) &ConfigAccess
3987 );
3988 if (EFI_ERROR (Status)) {
3989 goto Done;
3990 }
3991
3992 Status = ConfigAccess->ExtractConfig (
3993 ConfigAccess,
3994 ConfigRequest,
3995 &AccessProgress,
3996 &AccessResults
3997 );
3998 }
3999 if (EFI_ERROR (Status)) {
4000 //
4001 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4002 // Map it to the progress on <MultiConfigRequest> then return it.
4003 //
4004 *Progress = StrStr (StringPtr, AccessProgress);
4005 goto Done;
4006 }
4007
4008 //
4009 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4010 // which seperates the first <ConfigAltResp> and the following ones.
4011 //
4012 ASSERT (*AccessProgress == 0);
4013
4014 //
4015 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4016 //
4017 if (!IfrDataParsedFlag && HiiHandle != NULL) {
4018 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4019 ASSERT_EFI_ERROR (Status);
4020 }
4021
4022 FreePool (DevicePath);
4023 DevicePath = NULL;
4024
4025 if (DefaultResults != NULL) {
4026 Status = MergeDefaultString (&AccessResults, DefaultResults);
4027 ASSERT_EFI_ERROR (Status);
4028 FreePool (DefaultResults);
4029 DefaultResults = NULL;
4030 }
4031
4032 NextConfigString:
4033 if (!FirstElement) {
4034 Status = AppendToMultiString (Results, L"&");
4035 ASSERT_EFI_ERROR (Status);
4036 }
4037
4038 Status = AppendToMultiString (Results, AccessResults);
4039 ASSERT_EFI_ERROR (Status);
4040
4041 FirstElement = FALSE;
4042
4043 FreePool (AccessResults);
4044 AccessResults = NULL;
4045 FreePool (ConfigRequest);
4046 ConfigRequest = NULL;
4047
4048 //
4049 // Go to next <ConfigRequest> (skip '&').
4050 //
4051 StringPtr += Length;
4052 if (*StringPtr == 0) {
4053 *Progress = StringPtr;
4054 break;
4055 }
4056
4057 StringPtr++;
4058 }
4059
4060 Done:
4061 if (EFI_ERROR (Status)) {
4062 FreePool (*Results);
4063 *Results = NULL;
4064 }
4065
4066 if (ConfigRequest != NULL) {
4067 FreePool (ConfigRequest);
4068 }
4069
4070 if (AccessResults != NULL) {
4071 FreePool (AccessResults);
4072 }
4073
4074 if (DefaultResults != NULL) {
4075 FreePool (DefaultResults);
4076 }
4077
4078 if (DevicePath != NULL) {
4079 FreePool (DevicePath);
4080 }
4081
4082 return Status;
4083 }
4084
4085
4086 /**
4087 This function allows the caller to request the current configuration for the
4088 entirety of the current HII database and returns the data in a
4089 null-terminated Unicode string.
4090
4091 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4092 instance.
4093 @param Results Null-terminated Unicode string in
4094 <MultiConfigAltResp> format which has all values
4095 filled in for the entirety of the current HII
4096 database. String to be allocated by the called
4097 function. De-allocation is up to the caller.
4098
4099 @retval EFI_SUCCESS The Results string is filled with the values
4100 corresponding to all requested names.
4101 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4102 results that must be stored awaiting possible
4103 future protocols.
4104 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4105 parameter would result in this type of error.
4106
4107 **/
4108 EFI_STATUS
4109 EFIAPI
4110 HiiConfigRoutingExportConfig (
4111 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4112 OUT EFI_STRING *Results
4113 )
4114 {
4115 EFI_STATUS Status;
4116 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4117 EFI_STRING AccessResults;
4118 EFI_STRING Progress;
4119 EFI_STRING StringPtr;
4120 EFI_STRING ConfigRequest;
4121 UINTN Index;
4122 EFI_HANDLE *ConfigAccessHandles;
4123 UINTN NumberConfigAccessHandles;
4124 BOOLEAN FirstElement;
4125 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4126 EFI_HII_HANDLE HiiHandle;
4127 EFI_STRING DefaultResults;
4128 HII_DATABASE_PRIVATE_DATA *Private;
4129 LIST_ENTRY *Link;
4130 HII_DATABASE_RECORD *Database;
4131 UINT8 *DevicePathPkg;
4132 UINT8 *CurrentDevicePath;
4133 BOOLEAN IfrDataParsedFlag;
4134
4135 if (This == NULL || Results == NULL) {
4136 return EFI_INVALID_PARAMETER;
4137 }
4138
4139 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4140
4141 //
4142 // Allocate a fix length of memory to store Results. Reallocate memory for
4143 // Results if this fix length is insufficient.
4144 //
4145 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4146 if (*Results == NULL) {
4147 return EFI_OUT_OF_RESOURCES;
4148 }
4149
4150 NumberConfigAccessHandles = 0;
4151 Status = gBS->LocateHandleBuffer (
4152 ByProtocol,
4153 &gEfiHiiConfigAccessProtocolGuid,
4154 NULL,
4155 &NumberConfigAccessHandles,
4156 &ConfigAccessHandles
4157 );
4158 if (EFI_ERROR (Status)) {
4159 return Status;
4160 }
4161
4162 FirstElement = TRUE;
4163
4164 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
4165 Status = gBS->HandleProtocol (
4166 ConfigAccessHandles[Index],
4167 &gEfiHiiConfigAccessProtocolGuid,
4168 (VOID **) &ConfigAccess
4169 );
4170 if (EFI_ERROR (Status)) {
4171 continue;
4172 }
4173
4174 //
4175 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4176 //
4177 IfrDataParsedFlag = FALSE;
4178 Progress = NULL;
4179 HiiHandle = NULL;
4180 DefaultResults = NULL;
4181 Database = NULL;
4182 ConfigRequest = NULL;
4183 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
4184 if (DevicePath != NULL) {
4185 for (Link = Private->DatabaseList.ForwardLink;
4186 Link != &Private->DatabaseList;
4187 Link = Link->ForwardLink
4188 ) {
4189 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4190 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4191 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4192 if (CompareMem (
4193 DevicePath,
4194 CurrentDevicePath,
4195 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
4196 ) == 0) {
4197 HiiHandle = Database->Handle;
4198 break;
4199 }
4200 }
4201 }
4202 }
4203
4204 Status = ConfigAccess->ExtractConfig (
4205 ConfigAccess,
4206 NULL,
4207 &Progress,
4208 &AccessResults
4209 );
4210 if (EFI_ERROR (Status)) {
4211 //
4212 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4213 //
4214 if (HiiHandle != NULL && DevicePath != NULL) {
4215 IfrDataParsedFlag = TRUE;
4216 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4217 //
4218 // Get the full request string to get the Current setting again.
4219 //
4220 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
4221 Status = ConfigAccess->ExtractConfig (
4222 ConfigAccess,
4223 ConfigRequest,
4224 &Progress,
4225 &AccessResults
4226 );
4227 FreePool (ConfigRequest);
4228 } else {
4229 Status = EFI_NOT_FOUND;
4230 }
4231 }
4232 }
4233
4234 if (!EFI_ERROR (Status)) {
4235 //
4236 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4237 //
4238 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
4239 StringPtr = StrStr (AccessResults, L"&GUID=");
4240 if (StringPtr != NULL) {
4241 *StringPtr = 0;
4242 }
4243 if (GetElementsFromRequest (AccessResults)) {
4244 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
4245 ASSERT_EFI_ERROR (Status);
4246 }
4247 if (StringPtr != NULL) {
4248 *StringPtr = L'&';
4249 }
4250 }
4251 //
4252 // Merge the default sting from IFR code into the got setting from driver.
4253 //
4254 if (DefaultResults != NULL) {
4255 Status = MergeDefaultString (&AccessResults, DefaultResults);
4256 ASSERT_EFI_ERROR (Status);
4257 FreePool (DefaultResults);
4258 DefaultResults = NULL;
4259 }
4260
4261 //
4262 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4263 // which seperates the first <ConfigAltResp> and the following ones.
4264 //
4265 if (!FirstElement) {
4266 Status = AppendToMultiString (Results, L"&");
4267 ASSERT_EFI_ERROR (Status);
4268 }
4269
4270 Status = AppendToMultiString (Results, AccessResults);
4271 ASSERT_EFI_ERROR (Status);
4272
4273 FirstElement = FALSE;
4274
4275 FreePool (AccessResults);
4276 AccessResults = NULL;
4277 }
4278 }
4279 FreePool (ConfigAccessHandles);
4280
4281 return EFI_SUCCESS;
4282 }
4283
4284
4285 /**
4286 This function processes the results of processing forms and routes it to the
4287 appropriate handlers or storage.
4288
4289 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4290 instance.
4291 @param Configuration A null-terminated Unicode string in
4292 <MulltiConfigResp> format.
4293 @param Progress A pointer to a string filled in with the offset of
4294 the most recent & before the first failing name /
4295 value pair (or the beginning of the string if the
4296 failure is in the first name / value pair) or the
4297 terminating NULL if all was successful.
4298
4299 @retval EFI_SUCCESS The results have been distributed or are awaiting
4300 distribution.
4301 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4302 results that must be stored awaiting possible
4303 future protocols.
4304 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4305 would result in this type of error.
4306 @retval EFI_NOT_FOUND Target for the specified routing data was not
4307 found.
4308
4309 **/
4310 EFI_STATUS
4311 EFIAPI
4312 HiiConfigRoutingRouteConfig (
4313 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4314 IN CONST EFI_STRING Configuration,
4315 OUT EFI_STRING *Progress
4316 )
4317 {
4318 HII_DATABASE_PRIVATE_DATA *Private;
4319 EFI_STRING StringPtr;
4320 EFI_STRING ConfigResp;
4321 UINTN Length;
4322 EFI_STATUS Status;
4323 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4324 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4325 LIST_ENTRY *Link;
4326 HII_DATABASE_RECORD *Database;
4327 UINT8 *DevicePathPkg;
4328 UINT8 *CurrentDevicePath;
4329 EFI_HANDLE DriverHandle;
4330 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4331 EFI_STRING AccessProgress;
4332 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4333 BOOLEAN IsEfiVarstore;
4334 UINTN DevicePathSize;
4335
4336 if (This == NULL || Progress == NULL) {
4337 return EFI_INVALID_PARAMETER;
4338 }
4339
4340 if (Configuration == NULL) {
4341 *Progress = NULL;
4342 return EFI_INVALID_PARAMETER;
4343 }
4344
4345 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4346 StringPtr = Configuration;
4347 *Progress = StringPtr;
4348 Database = NULL;
4349 AccessProgress = NULL;
4350 EfiVarStoreInfo= NULL;
4351 IsEfiVarstore = FALSE;
4352
4353 //
4354 // The first element of <MultiConfigResp> should be
4355 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4356 //
4357 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4358 return EFI_INVALID_PARAMETER;
4359 }
4360
4361 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4362 //
4363 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4364 // or most recent & before the error.
4365 //
4366 if (StringPtr == Configuration) {
4367 *Progress = StringPtr;
4368 } else {
4369 *Progress = StringPtr - 1;
4370 }
4371
4372 //
4373 // Process each <ConfigResp> of <MultiConfigResp>
4374 //
4375 Length = CalculateConfigStringLen (StringPtr);
4376 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4377 if (ConfigResp == NULL) {
4378 return EFI_OUT_OF_RESOURCES;
4379 }
4380 //
4381 // Append '\0' to the end of ConfigRequest
4382 //
4383 *(ConfigResp + Length) = 0;
4384
4385 //
4386 // Get the UEFI device path
4387 //
4388 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
4389 if (EFI_ERROR (Status)) {
4390 FreePool (ConfigResp);
4391 return Status;
4392 }
4393
4394 //
4395 // Find driver which matches the routing data.
4396 //
4397 DriverHandle = NULL;
4398 for (Link = Private->DatabaseList.ForwardLink;
4399 Link != &Private->DatabaseList;
4400 Link = Link->ForwardLink
4401 ) {
4402 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4403
4404 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4405 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4406 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4407 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
4408 DriverHandle = Database->DriverHandle;
4409 break;
4410 }
4411 }
4412 }
4413
4414 //
4415 // Try to find driver handle by device path.
4416 //
4417 if (DriverHandle == NULL) {
4418 TempDevicePath = DevicePath;
4419 Status = gBS->LocateDevicePath (
4420 &gEfiDevicePathProtocolGuid,
4421 &TempDevicePath,
4422 &DriverHandle
4423 );
4424 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4425 //
4426 // Routing data does not match any known driver.
4427 // Set Progress to the 'G' in "GUID" of the routing header.
4428 //
4429 FreePool (DevicePath);
4430 *Progress = StringPtr;
4431 FreePool (ConfigResp);
4432 return EFI_NOT_FOUND;
4433 }
4434 }
4435
4436 FreePool (DevicePath);
4437
4438 //
4439 // Check whether this ConfigRequest is search from Efi varstore type storage.
4440 //
4441 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
4442 if (EFI_ERROR (Status)) {
4443 return Status;
4444 }
4445
4446 if (IsEfiVarstore) {
4447 //
4448 // Call the SetVariable function to route settings.
4449 //
4450 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
4451 FreePool (EfiVarStoreInfo);
4452 } else {
4453 //
4454 // Call corresponding ConfigAccess protocol to route settings
4455 //
4456 Status = gBS->HandleProtocol (
4457 DriverHandle,
4458 &gEfiHiiConfigAccessProtocolGuid,
4459 (VOID **) &ConfigAccess
4460 );
4461 if (EFI_ERROR (Status)) {
4462 *Progress = StringPtr;
4463 FreePool (ConfigResp);
4464 return EFI_NOT_FOUND;
4465 }
4466
4467 Status = ConfigAccess->RouteConfig (
4468 ConfigAccess,
4469 ConfigResp,
4470 &AccessProgress
4471 );
4472 }
4473 if (EFI_ERROR (Status)) {
4474 ASSERT (AccessProgress != NULL);
4475 //
4476 // AccessProgress indicates the parsing progress on <ConfigResp>.
4477 // Map it to the progress on <MultiConfigResp> then return it.
4478 //
4479 *Progress = StrStr (StringPtr, AccessProgress);
4480
4481 FreePool (ConfigResp);
4482 return Status;
4483 }
4484
4485 FreePool (ConfigResp);
4486 ConfigResp = NULL;
4487
4488 //
4489 // Go to next <ConfigResp> (skip '&').
4490 //
4491 StringPtr += Length;
4492 if (*StringPtr == 0) {
4493 *Progress = StringPtr;
4494 break;
4495 }
4496
4497 StringPtr++;
4498
4499 }
4500
4501 return EFI_SUCCESS;
4502 }
4503
4504
4505 /**
4506 This helper function is to be called by drivers to map configuration data
4507 stored in byte array ("block") formats such as UEFI Variables into current
4508 configuration strings.
4509
4510 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4511 instance.
4512 @param ConfigRequest A null-terminated Unicode string in
4513 <ConfigRequest> format.
4514 @param Block Array of bytes defining the block's configuration.
4515 @param BlockSize Length in bytes of Block.
4516 @param Config Filled-in configuration string. String allocated
4517 by the function. Returned only if call is
4518 successful. It is <ConfigResp> string format.
4519 @param Progress A pointer to a string filled in with the offset of
4520 the most recent & before the first failing
4521 name/value pair (or the beginning of the string if
4522 the failure is in the first name / value pair) or
4523 the terminating NULL if all was successful.
4524
4525 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4526 terminator at the end of the ConfigRequest
4527 string.
4528 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4529 points to the first character of ConfigRequest.
4530 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4531 Block parameter would result in this type of
4532 error. Progress points to the first character of
4533 ConfigRequest.
4534 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4535 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4536 Block is left updated and Progress points at
4537 the "&" preceding the first non-<BlockName>.
4538
4539 **/
4540 EFI_STATUS
4541 EFIAPI
4542 HiiBlockToConfig (
4543 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4544 IN CONST EFI_STRING ConfigRequest,
4545 IN CONST UINT8 *Block,
4546 IN CONST UINTN BlockSize,
4547 OUT EFI_STRING *Config,
4548 OUT EFI_STRING *Progress
4549 )
4550 {
4551 HII_DATABASE_PRIVATE_DATA *Private;
4552 EFI_STRING StringPtr;
4553 UINTN Length;
4554 EFI_STATUS Status;
4555 EFI_STRING TmpPtr;
4556 UINT8 *TmpBuffer;
4557 UINTN Offset;
4558 UINTN Width;
4559 UINT8 *Value;
4560 EFI_STRING ValueStr;
4561 EFI_STRING ConfigElement;
4562 UINTN Index;
4563 UINT8 *TemBuffer;
4564 CHAR16 *TemString;
4565 CHAR16 TemChar;
4566
4567 TmpBuffer = NULL;
4568
4569 if (This == NULL || Progress == NULL || Config == NULL) {
4570 return EFI_INVALID_PARAMETER;
4571 }
4572
4573 if (Block == NULL || ConfigRequest == NULL) {
4574 *Progress = ConfigRequest;
4575 return EFI_INVALID_PARAMETER;
4576 }
4577
4578
4579 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4580 ASSERT (Private != NULL);
4581
4582 StringPtr = ConfigRequest;
4583 ValueStr = NULL;
4584 Value = NULL;
4585 ConfigElement = NULL;
4586
4587 //
4588 // Allocate a fix length of memory to store Results. Reallocate memory for
4589 // Results if this fix length is insufficient.
4590 //
4591 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4592 if (*Config == NULL) {
4593 return EFI_OUT_OF_RESOURCES;
4594 }
4595
4596 //
4597 // Jump <ConfigHdr>
4598 //
4599 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4600 *Progress = StringPtr;
4601 Status = EFI_INVALID_PARAMETER;
4602 goto Exit;
4603 }
4604 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
4605 StringPtr++;
4606 }
4607 if (*StringPtr == 0) {
4608 *Progress = StringPtr - 1;
4609 Status = EFI_INVALID_PARAMETER;
4610 goto Exit;
4611 }
4612
4613 while (*StringPtr != L'&' && *StringPtr != 0) {
4614 StringPtr++;
4615 }
4616 if (*StringPtr == 0) {
4617 *Progress = StringPtr;
4618
4619 AppendToMultiString(Config, ConfigRequest);
4620 HiiToLower (*Config);
4621
4622 return EFI_SUCCESS;
4623 }
4624 //
4625 // Skip '&'
4626 //
4627 StringPtr++;
4628
4629 //
4630 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4631 //
4632 TemChar = *StringPtr;
4633 *StringPtr = '\0';
4634 AppendToMultiString(Config, ConfigRequest);
4635 *StringPtr = TemChar;
4636
4637 //
4638 // Parse each <RequestElement> if exists
4639 // Only <BlockName> format is supported by this help function.
4640 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4641 //
4642 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
4643 //
4644 // Back up the header of one <BlockName>
4645 //
4646 TmpPtr = StringPtr;
4647
4648 StringPtr += StrLen (L"OFFSET=");
4649 //
4650 // Get Offset
4651 //
4652 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4653 if (EFI_ERROR (Status)) {
4654 *Progress = TmpPtr - 1;
4655 goto Exit;
4656 }
4657 Offset = 0;
4658 CopyMem (
4659 &Offset,
4660 TmpBuffer,
4661 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4662 );
4663 FreePool (TmpBuffer);
4664
4665 StringPtr += Length;
4666 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4667 *Progress = TmpPtr - 1;
4668 Status = EFI_INVALID_PARAMETER;
4669 goto Exit;
4670 }
4671 StringPtr += StrLen (L"&WIDTH=");
4672
4673 //
4674 // Get Width
4675 //
4676 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4677 if (EFI_ERROR (Status)) {
4678 *Progress = TmpPtr - 1;
4679 goto Exit;
4680 }
4681 Width = 0;
4682 CopyMem (
4683 &Width,
4684 TmpBuffer,
4685 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4686 );
4687 FreePool (TmpBuffer);
4688
4689 StringPtr += Length;
4690 if (*StringPtr != 0 && *StringPtr != L'&') {
4691 *Progress = TmpPtr - 1;
4692 Status = EFI_INVALID_PARAMETER;
4693 goto Exit;
4694 }
4695
4696 //
4697 // Calculate Value and convert it to hex string.
4698 //
4699 if (Offset + Width > BlockSize) {
4700 *Progress = StringPtr;
4701 Status = EFI_DEVICE_ERROR;
4702 goto Exit;
4703 }
4704
4705 Value = (UINT8 *) AllocateZeroPool (Width);
4706 if (Value == NULL) {
4707 *Progress = ConfigRequest;
4708 Status = EFI_OUT_OF_RESOURCES;
4709 goto Exit;
4710 }
4711
4712 CopyMem (Value, (UINT8 *) Block + Offset, Width);
4713
4714 Length = Width * 2 + 1;
4715 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
4716 if (ValueStr == NULL) {
4717 *Progress = ConfigRequest;
4718 Status = EFI_OUT_OF_RESOURCES;
4719 goto Exit;
4720 }
4721
4722 TemString = ValueStr;
4723 TemBuffer = Value + Width - 1;
4724 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
4725 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
4726 }
4727
4728 FreePool (Value);
4729 Value = NULL;
4730
4731 //
4732 // Build a ConfigElement
4733 //
4734 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
4735 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
4736 if (ConfigElement == NULL) {
4737 Status = EFI_OUT_OF_RESOURCES;
4738 goto Exit;
4739 }
4740 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
4741 if (*StringPtr == 0) {
4742 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
4743 }
4744 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
4745 StrCatS (ConfigElement, Length, L"VALUE=");
4746 StrCatS (ConfigElement, Length, ValueStr);
4747
4748 AppendToMultiString (Config, ConfigElement);
4749
4750 FreePool (ConfigElement);
4751 FreePool (ValueStr);
4752 ConfigElement = NULL;
4753 ValueStr = NULL;
4754
4755 //
4756 // If '\0', parsing is finished. Otherwise skip '&' to continue
4757 //
4758 if (*StringPtr == 0) {
4759 break;
4760 }
4761 AppendToMultiString (Config, L"&");
4762 StringPtr++;
4763
4764 }
4765
4766 if (*StringPtr != 0) {
4767 *Progress = StringPtr - 1;
4768 Status = EFI_INVALID_PARAMETER;
4769 goto Exit;
4770 }
4771
4772 HiiToLower (*Config);
4773 *Progress = StringPtr;
4774 return EFI_SUCCESS;
4775
4776 Exit:
4777 if (*Config != NULL) {
4778 FreePool (*Config);
4779 *Config = NULL;
4780 }
4781 if (ValueStr != NULL) {
4782 FreePool (ValueStr);
4783 }
4784 if (Value != NULL) {
4785 FreePool (Value);
4786 }
4787 if (ConfigElement != NULL) {
4788 FreePool (ConfigElement);
4789 }
4790
4791 return Status;
4792
4793 }
4794
4795
4796 /**
4797 This helper function is to be called by drivers to map configuration strings
4798 to configurations stored in byte array ("block") formats such as UEFI Variables.
4799
4800 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4801 instance.
4802 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4803 format.
4804 @param Block A possibly null array of bytes representing the
4805 current block. Only bytes referenced in the
4806 ConfigResp string in the block are modified. If
4807 this parameter is null or if the *BlockSize
4808 parameter is (on input) shorter than required by
4809 the Configuration string, only the BlockSize
4810 parameter is updated and an appropriate status
4811 (see below) is returned.
4812 @param BlockSize The length of the Block in units of UINT8. On
4813 input, this is the size of the Block. On output,
4814 if successful, contains the largest index of the
4815 modified byte in the Block, or the required buffer
4816 size if the Block is not large enough.
4817 @param Progress On return, points to an element of the ConfigResp
4818 string filled in with the offset of the most
4819 recent '&' before the first failing name / value
4820 pair (or the beginning of the string if the
4821 failure is in the first name / value pair) or the
4822 terminating NULL if all was successful.
4823
4824 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4825 terminator at the end of the ConfigResp string.
4826 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4827 points to the first character of ConfigResp.
4828 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4829 Block parameter would result in this type of
4830 error. Progress points to the first character of
4831 ConfigResp.
4832 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4833 value pair. Block is left updated and
4834 Progress points at the '&' preceding the first
4835 non-<BlockName>.
4836 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4837 BlockSize is updated with the required buffer size.
4838 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4839 Progress points to the "G" in "GUID" of the errant
4840 routing data.
4841
4842 **/
4843 EFI_STATUS
4844 EFIAPI
4845 HiiConfigToBlock (
4846 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4847 IN CONST EFI_STRING ConfigResp,
4848 IN OUT UINT8 *Block,
4849 IN OUT UINTN *BlockSize,
4850 OUT EFI_STRING *Progress
4851 )
4852 {
4853 HII_DATABASE_PRIVATE_DATA *Private;
4854 EFI_STRING StringPtr;
4855 EFI_STRING TmpPtr;
4856 UINTN Length;
4857 EFI_STATUS Status;
4858 UINT8 *TmpBuffer;
4859 UINTN Offset;
4860 UINTN Width;
4861 UINT8 *Value;
4862 UINTN BufferSize;
4863 UINTN MaxBlockSize;
4864
4865 TmpBuffer = NULL;
4866
4867 if (This == NULL || BlockSize == NULL || Progress == NULL) {
4868 return EFI_INVALID_PARAMETER;
4869 }
4870
4871 *Progress = ConfigResp;
4872 if (ConfigResp == NULL) {
4873 return EFI_INVALID_PARAMETER;
4874 }
4875
4876 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4877 ASSERT (Private != NULL);
4878
4879 StringPtr = ConfigResp;
4880 BufferSize = *BlockSize;
4881 Value = NULL;
4882 MaxBlockSize = 0;
4883
4884 //
4885 // Jump <ConfigHdr>
4886 //
4887 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4888 *Progress = StringPtr;
4889 Status = EFI_INVALID_PARAMETER;
4890 goto Exit;
4891 }
4892 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
4893 StringPtr++;
4894 }
4895 if (*StringPtr == 0) {
4896 *Progress = StringPtr;
4897 Status = EFI_INVALID_PARAMETER;
4898 goto Exit;
4899 }
4900
4901 while (*StringPtr != L'&' && *StringPtr != 0) {
4902 StringPtr++;
4903 }
4904 if (*StringPtr == 0) {
4905 *Progress = StringPtr;
4906 Status = EFI_INVALID_PARAMETER;
4907 goto Exit;
4908 }
4909
4910 //
4911 // Parse each <ConfigElement> if exists
4912 // Only '&'<BlockConfig> format is supported by this help function.
4913 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4914 //
4915 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
4916 TmpPtr = StringPtr;
4917 StringPtr += StrLen (L"&OFFSET=");
4918 //
4919 // Get Offset
4920 //
4921 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4922 if (EFI_ERROR (Status)) {
4923 *Progress = TmpPtr;
4924 goto Exit;
4925 }
4926 Offset = 0;
4927 CopyMem (
4928 &Offset,
4929 TmpBuffer,
4930 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4931 );
4932 FreePool (TmpBuffer);
4933
4934 StringPtr += Length;
4935 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4936 *Progress = TmpPtr;
4937 Status = EFI_INVALID_PARAMETER;
4938 goto Exit;
4939 }
4940 StringPtr += StrLen (L"&WIDTH=");
4941
4942 //
4943 // Get Width
4944 //
4945 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4946 if (EFI_ERROR (Status)) {
4947 *Progress = TmpPtr;
4948 goto Exit;
4949 }
4950 Width = 0;
4951 CopyMem (
4952 &Width,
4953 TmpBuffer,
4954 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4955 );
4956 FreePool (TmpBuffer);
4957
4958 StringPtr += Length;
4959 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
4960 *Progress = TmpPtr;
4961 Status = EFI_INVALID_PARAMETER;
4962 goto Exit;
4963 }
4964 StringPtr += StrLen (L"&VALUE=");
4965
4966 //
4967 // Get Value
4968 //
4969 Status = GetValueOfNumber (StringPtr, &Value, &Length);
4970 if (EFI_ERROR (Status)) {
4971 *Progress = TmpPtr;
4972 goto Exit;
4973 }
4974
4975 StringPtr += Length;
4976 if (*StringPtr != 0 && *StringPtr != L'&') {
4977 *Progress = TmpPtr;
4978 Status = EFI_INVALID_PARAMETER;
4979 goto Exit;
4980 }
4981
4982 //
4983 // Update the Block with configuration info
4984 //
4985 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
4986 CopyMem (Block + Offset, Value, Width);
4987 }
4988 if (Offset + Width > MaxBlockSize) {
4989 MaxBlockSize = Offset + Width;
4990 }
4991
4992 FreePool (Value);
4993 Value = NULL;
4994
4995 //
4996 // If '\0', parsing is finished.
4997 //
4998 if (*StringPtr == 0) {
4999 break;
5000 }
5001 }
5002
5003 //
5004 // The input string is not ConfigResp format, return error.
5005 //
5006 if (*StringPtr != 0) {
5007 *Progress = StringPtr;
5008 Status = EFI_INVALID_PARAMETER;
5009 goto Exit;
5010 }
5011
5012 *Progress = StringPtr + StrLen (StringPtr);
5013 *BlockSize = MaxBlockSize - 1;
5014
5015 if (MaxBlockSize > BufferSize) {
5016 *BlockSize = MaxBlockSize;
5017 if (Block != NULL) {
5018 return EFI_BUFFER_TOO_SMALL;
5019 }
5020 }
5021
5022 if (Block == NULL) {
5023 *Progress = ConfigResp;
5024 return EFI_INVALID_PARAMETER;
5025 }
5026
5027 return EFI_SUCCESS;
5028
5029 Exit:
5030
5031 if (Value != NULL) {
5032 FreePool (Value);
5033 }
5034 return Status;
5035 }
5036
5037
5038 /**
5039 This helper function is to be called by drivers to extract portions of
5040 a larger configuration string.
5041
5042 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5043 instance.
5044 @param Configuration A null-terminated Unicode string in
5045 <MultiConfigAltResp> format.
5046 @param Guid A pointer to the GUID value to search for in the
5047 routing portion of the ConfigResp string when
5048 retrieving the requested data. If Guid is NULL,
5049 then all GUID values will be searched for.
5050 @param Name A pointer to the NAME value to search for in the
5051 routing portion of the ConfigResp string when
5052 retrieving the requested data. If Name is NULL,
5053 then all Name values will be searched for.
5054 @param DevicePath A pointer to the PATH value to search for in the
5055 routing portion of the ConfigResp string when
5056 retrieving the requested data. If DevicePath is
5057 NULL, then all DevicePath values will be searched
5058 for.
5059 @param AltCfgId A pointer to the ALTCFG value to search for in the
5060 routing portion of the ConfigResp string when
5061 retrieving the requested data. If this parameter
5062 is NULL, then the current setting will be
5063 retrieved.
5064 @param AltCfgResp A pointer to a buffer which will be allocated by
5065 the function which contains the retrieved string
5066 as requested. This buffer is only allocated if
5067 the call was successful. It is <ConfigResp> format.
5068
5069 @retval EFI_SUCCESS The request succeeded. The requested data was
5070 extracted and placed in the newly allocated
5071 AltCfgResp buffer.
5072 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5073 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5074 @retval EFI_NOT_FOUND Target for the specified routing data was not
5075 found.
5076
5077 **/
5078 EFI_STATUS
5079 EFIAPI
5080 HiiGetAltCfg (
5081 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5082 IN CONST EFI_STRING Configuration,
5083 IN CONST EFI_GUID *Guid,
5084 IN CONST EFI_STRING Name,
5085 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
5086 IN CONST UINT16 *AltCfgId,
5087 OUT EFI_STRING *AltCfgResp
5088 )
5089 {
5090 EFI_STATUS Status;
5091 EFI_STRING StringPtr;
5092 EFI_STRING HdrStart;
5093 EFI_STRING HdrEnd;
5094 EFI_STRING TmpPtr;
5095 UINTN Length;
5096 EFI_STRING GuidStr;
5097 EFI_STRING NameStr;
5098 EFI_STRING PathStr;
5099 EFI_STRING AltIdStr;
5100 EFI_STRING Result;
5101 BOOLEAN GuidFlag;
5102 BOOLEAN NameFlag;
5103 BOOLEAN PathFlag;
5104
5105 HdrStart = NULL;
5106 HdrEnd = NULL;
5107 GuidStr = NULL;
5108 NameStr = NULL;
5109 PathStr = NULL;
5110 AltIdStr = NULL;
5111 Result = NULL;
5112 GuidFlag = FALSE;
5113 NameFlag = FALSE;
5114 PathFlag = FALSE;
5115
5116 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
5117 return EFI_INVALID_PARAMETER;
5118 }
5119
5120 StringPtr = Configuration;
5121 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5122 return EFI_INVALID_PARAMETER;
5123 }
5124
5125 //
5126 // Generate the sub string for later matching.
5127 //
5128 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
5129 GenerateSubStr (
5130 L"PATH=",
5131 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
5132 (VOID *) DevicePath,
5133 1,
5134 &PathStr
5135 );
5136 if (AltCfgId != NULL) {
5137 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
5138 }
5139 if (Name != NULL) {
5140 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
5141 } else {
5142 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
5143 }
5144
5145 while (*StringPtr != 0) {
5146 //
5147 // Try to match the GUID
5148 //
5149 if (!GuidFlag) {
5150 TmpPtr = StrStr (StringPtr, GuidStr);
5151 if (TmpPtr == NULL) {
5152 Status = EFI_NOT_FOUND;
5153 goto Exit;
5154 }
5155 HdrStart = TmpPtr;
5156
5157 //
5158 // Jump to <NameHdr>
5159 //
5160 if (Guid != NULL) {
5161 StringPtr = TmpPtr + StrLen (GuidStr);
5162 } else {
5163 StringPtr = StrStr (TmpPtr, L"NAME=");
5164 if (StringPtr == NULL) {
5165 Status = EFI_NOT_FOUND;
5166 goto Exit;
5167 }
5168 }
5169 GuidFlag = TRUE;
5170 }
5171
5172 //
5173 // Try to match the NAME
5174 //
5175 if (GuidFlag && !NameFlag) {
5176 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
5177 GuidFlag = FALSE;
5178 } else {
5179 //
5180 // Jump to <PathHdr>
5181 //
5182 if (Name != NULL) {
5183 StringPtr += StrLen (NameStr);
5184 } else {
5185 StringPtr = StrStr (StringPtr, L"PATH=");
5186 if (StringPtr == NULL) {
5187 Status = EFI_NOT_FOUND;
5188 goto Exit;
5189 }
5190 }
5191 NameFlag = TRUE;
5192 }
5193 }
5194
5195 //
5196 // Try to match the DevicePath
5197 //
5198 if (GuidFlag && NameFlag && !PathFlag) {
5199 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
5200 GuidFlag = FALSE;
5201 NameFlag = FALSE;
5202 } else {
5203 //
5204 // Jump to '&' before <DescHdr> or <ConfigBody>
5205 //
5206 if (DevicePath != NULL) {
5207 StringPtr += StrLen (PathStr);
5208 } else {
5209 StringPtr = StrStr (StringPtr, L"&");
5210 if (StringPtr == NULL) {
5211 Status = EFI_NOT_FOUND;
5212 goto Exit;
5213 }
5214 StringPtr ++;
5215 }
5216 PathFlag = TRUE;
5217 HdrEnd = StringPtr;
5218 }
5219 }
5220
5221 //
5222 // Try to match the AltCfgId
5223 //
5224 if (GuidFlag && NameFlag && PathFlag) {
5225 if (AltCfgId == NULL) {
5226 //
5227 // Return Current Setting when AltCfgId is NULL.
5228 //
5229 Status = OutputConfigBody (StringPtr, &Result);
5230 goto Exit;
5231 }
5232 //
5233 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5234 //
5235 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
5236 GuidFlag = FALSE;
5237 NameFlag = FALSE;
5238 PathFlag = FALSE;
5239 } else {
5240 //
5241 // Skip AltIdStr and &
5242 //
5243 StringPtr = StringPtr + StrLen (AltIdStr);
5244 Status = OutputConfigBody (StringPtr, &Result);
5245 goto Exit;
5246 }
5247 }
5248 }
5249
5250 Status = EFI_NOT_FOUND;
5251
5252 Exit:
5253 *AltCfgResp = NULL;
5254 if (!EFI_ERROR (Status) && (Result != NULL)) {
5255 //
5256 // Copy the <ConfigHdr> and <ConfigBody>
5257 //
5258 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
5259 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
5260 if (*AltCfgResp == NULL) {
5261 Status = EFI_OUT_OF_RESOURCES;
5262 } else {
5263 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
5264 StrCatS (*AltCfgResp, Length, Result);
5265 Status = EFI_SUCCESS;
5266 }
5267 }
5268
5269 if (GuidStr != NULL) {
5270 FreePool (GuidStr);
5271 }
5272 if (NameStr != NULL) {
5273 FreePool (NameStr);
5274 }
5275 if (PathStr != NULL) {
5276 FreePool (PathStr);
5277 }
5278 if (AltIdStr != NULL) {
5279 FreePool (AltIdStr);
5280 }
5281 if (Result != NULL) {
5282 FreePool (Result);
5283 }
5284
5285 return Status;
5286
5287 }
5288
5289