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