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