]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg DXE Core: Update implementation of SetMemorySpaceAttributes() DXE Servic...
[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 - 2011, 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 StrCpy (Str, String);
256 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);
257
258 StringHeader = Str + StrLen (String);
259 TemString = (CHAR16 *) StringHeader;
260
261 switch (Flag) {
262 case 1:
263 //
264 // Convert Buffer to Hex String in reverse order
265 //
266 TemBuffer = ((UINT8 *) Buffer);
267 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
268 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
269 }
270 break;
271 case 2:
272 //
273 // Check buffer is enough
274 //
275 TemName = (CHAR16 *) Buffer;
276 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
277 //
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 //
280 for (; *TemName != L'\0'; TemName++) {
281 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
282 }
283 break;
284 case 3:
285 //
286 // Convert Buffer to Hex String
287 //
288 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
289 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
290 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
291 }
292 break;
293 default:
294 break;
295 }
296
297 //
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 //
300 StrCat (Str, L"&");
301 HiiToLower (Str);
302
303 *SubStr = Str;
304 }
305
306
307 /**
308 Retrieve the <ConfigBody> from String then output it.
309
310 This is a internal function.
311
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
316
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
320
321 **/
322 EFI_STATUS
323 OutputConfigBody (
324 IN EFI_STRING String,
325 OUT EFI_STRING *ConfigBody
326 )
327 {
328 EFI_STRING TmpPtr;
329 EFI_STRING Result;
330 UINTN Length;
331
332 if (String == NULL || ConfigBody == NULL) {
333 return EFI_INVALID_PARAMETER;
334 }
335
336 //
337 // The setting information should start OFFSET, not ALTCFG.
338 //
339 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 TmpPtr = StrStr (String, L"GUID=");
344 if (TmpPtr == NULL) {
345 //
346 // It is the last <ConfigResp> of the incoming configuration string.
347 //
348 Result = AllocateCopyPool (StrSize (String), String);
349 if (Result == NULL) {
350 return EFI_OUT_OF_RESOURCES;
351 } else {
352 *ConfigBody = Result;
353 return EFI_SUCCESS;
354 }
355 }
356
357 Length = TmpPtr - String;
358 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
359 if (Result == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362
363 *(Result + Length - 1) = 0;
364 *ConfigBody = Result;
365 return EFI_SUCCESS;
366 }
367
368 /**
369 Append a string to a multi-string format.
370
371 This is a internal function.
372
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
377 might be updated.
378 @param AppendString NULL-terminated Unicode string.
379
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
382
383 **/
384 EFI_STATUS
385 AppendToMultiString (
386 IN OUT EFI_STRING *MultiString,
387 IN EFI_STRING AppendString
388 )
389 {
390 UINTN AppendStringSize;
391 UINTN MultiStringSize;
392
393 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
394 return EFI_INVALID_PARAMETER;
395 }
396
397 AppendStringSize = StrSize (AppendString);
398 MultiStringSize = StrSize (*MultiString);
399
400 //
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
402 //
403 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
404 MultiStringSize > MAX_STRING_LENGTH) {
405 *MultiString = (EFI_STRING) ReallocatePool (
406 MultiStringSize,
407 MultiStringSize + AppendStringSize,
408 (VOID *) (*MultiString)
409 );
410 ASSERT (*MultiString != NULL);
411 }
412 //
413 // Append the incoming string
414 //
415 StrCat (*MultiString, AppendString);
416
417 return EFI_SUCCESS;
418 }
419
420
421 /**
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
423 or WIDTH or VALUE.
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
425
426 This is a internal function.
427
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
431 to free memory.
432 @param Len Length of the <Number>, in characters.
433
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
435 structures.
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
437 successfully.
438
439 **/
440 EFI_STATUS
441 GetValueOfNumber (
442 IN EFI_STRING StringPtr,
443 OUT UINT8 **Number,
444 OUT UINTN *Len
445 )
446 {
447 EFI_STRING TmpPtr;
448 UINTN Length;
449 EFI_STRING Str;
450 UINT8 *Buf;
451 EFI_STATUS Status;
452 UINT8 DigitUint8;
453 UINTN Index;
454 CHAR16 TemStr[2];
455
456 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 Buf = NULL;
461
462 TmpPtr = StringPtr;
463 while (*StringPtr != L'\0' && *StringPtr != L'&') {
464 StringPtr++;
465 }
466 *Len = StringPtr - TmpPtr;
467 Length = *Len + 1;
468
469 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
470 if (Str == NULL) {
471 Status = EFI_OUT_OF_RESOURCES;
472 goto Exit;
473 }
474 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
475 *(Str + *Len) = L'\0';
476
477 Length = (Length + 1) / 2;
478 Buf = (UINT8 *) AllocateZeroPool (Length);
479 if (Buf == NULL) {
480 Status = EFI_OUT_OF_RESOURCES;
481 goto Exit;
482 }
483
484 Length = *Len;
485 ZeroMem (TemStr, sizeof (TemStr));
486 for (Index = 0; Index < Length; Index ++) {
487 TemStr[0] = Str[Length - Index - 1];
488 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
489 if ((Index & 1) == 0) {
490 Buf [Index/2] = DigitUint8;
491 } else {
492 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
493 }
494 }
495
496 *Number = Buf;
497 Status = EFI_SUCCESS;
498
499 Exit:
500 if (Str != NULL) {
501 FreePool (Str);
502 }
503
504 return Status;
505 }
506
507 /**
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
510
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
518
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
521 **/
522 EFI_STATUS
523 EFIAPI
524 MergeDefaultString (
525 IN OUT EFI_STRING *AltCfgResp,
526 IN EFI_STRING DefaultAltCfgResp
527 )
528 {
529 EFI_STRING StringPtrDefault;
530 EFI_STRING StringPtrEnd;
531 CHAR16 TempChar;
532 EFI_STRING StringPtr;
533 EFI_STRING AltConfigHdr;
534 UINTN HeaderLength;
535 UINTN SizeAltCfgResp;
536
537 if (*AltCfgResp == NULL) {
538 return EFI_INVALID_PARAMETER;
539 }
540
541 //
542 // Get the requestr ConfigHdr
543 //
544 SizeAltCfgResp = 0;
545 StringPtr = *AltCfgResp;
546
547 //
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
549 //
550 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER;
552 }
553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
554 StringPtr++;
555 }
556 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
557 StringPtr++;
558 }
559 if (*StringPtr == L'\0') {
560 return EFI_INVALID_PARAMETER;
561 }
562 StringPtr += StrLen (L"&PATH=");
563 while (*StringPtr != L'\0' && *StringPtr != L'&') {
564 StringPtr ++;
565 }
566 HeaderLength = StringPtr - *AltCfgResp;
567
568 //
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
571 //
572 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));
573 if (AltConfigHdr == NULL) {
574 return EFI_OUT_OF_RESOURCES;
575 }
576 StrCpy (AltConfigHdr, L"&");
577 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);
578 StrCat (AltConfigHdr, L"&ALTCFG=");
579 HeaderLength = StrLen (AltConfigHdr);
580
581 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
582 while (StringPtrDefault != NULL) {
583 //
584 // Get AltCfg Name
585 //
586 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);
587 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
588
589 //
590 // Append the found default value string to the input AltCfgResp
591 //
592 if (StringPtr == NULL) {
593 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
594 SizeAltCfgResp = StrSize (*AltCfgResp);
595 if (StringPtrEnd == NULL) {
596 //
597 // No more default string is found.
598 //
599 *AltCfgResp = (EFI_STRING) ReallocatePool (
600 SizeAltCfgResp,
601 SizeAltCfgResp + StrSize (StringPtrDefault),
602 (VOID *) (*AltCfgResp)
603 );
604 if (*AltCfgResp == NULL) {
605 FreePool (AltConfigHdr);
606 return EFI_OUT_OF_RESOURCES;
607 }
608 StrCat (*AltCfgResp, StringPtrDefault);
609 break;
610 } else {
611 TempChar = *StringPtrEnd;
612 *StringPtrEnd = L'\0';
613 *AltCfgResp = (EFI_STRING) ReallocatePool (
614 SizeAltCfgResp,
615 SizeAltCfgResp + StrSize (StringPtrDefault),
616 (VOID *) (*AltCfgResp)
617 );
618 if (*AltCfgResp == NULL) {
619 FreePool (AltConfigHdr);
620 return EFI_OUT_OF_RESOURCES;
621 }
622 StrCat (*AltCfgResp, StringPtrDefault);
623 *StringPtrEnd = TempChar;
624 }
625 }
626
627 //
628 // Find next AltCfg String
629 //
630 *(AltConfigHdr + HeaderLength) = L'\0';
631 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
632 }
633
634 FreePool (AltConfigHdr);
635 return EFI_SUCCESS;
636 }
637
638 /**
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.
640
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
643
644 **/
645 VOID
646 InsertDefaultValue (
647 IN IFR_BLOCK_DATA *BlockData,
648 IN IFR_DEFAULT_DATA *DefaultValueData
649 )
650 {
651 LIST_ENTRY *Link;
652 IFR_DEFAULT_DATA *DefaultValueArray;
653
654 for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {
655 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
656 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
657 //
658 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
659 //
660 if (DefaultValueData->Type > DefaultValueArray->Type) {
661 //
662 // Update the default value array in BlockData.
663 //
664 DefaultValueArray->Value = DefaultValueData->Value;
665 DefaultValueArray->Type = DefaultValueData->Type;
666 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
667 }
668 return;
669 }
670 }
671
672 //
673 // Insert new default value data in tail.
674 //
675 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
676 ASSERT (DefaultValueArray != NULL);
677 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
678 InsertTailList (Link, &DefaultValueArray->Entry);
679 }
680
681 /**
682 This function inserts new BlockData into the block link
683
684 @param BlockLink The list entry points to block array.
685 @param BlockData The point to BlockData is added.
686
687 **/
688 VOID
689 InsertBlockData (
690 IN LIST_ENTRY *BlockLink,
691 IN IFR_BLOCK_DATA **BlockData
692 )
693 {
694 LIST_ENTRY *Link;
695 IFR_BLOCK_DATA *BlockArray;
696 IFR_BLOCK_DATA *BlockSingleData;
697
698 BlockSingleData = *BlockData;
699
700 //
701 // Insert block data in its Offset and Width order.
702 //
703 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
704 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
705 if (BlockArray->Offset == BlockSingleData->Offset) {
706 if (BlockArray->Width > BlockSingleData->Width) {
707 //
708 // Insert this block data in the front of block array
709 //
710 InsertTailList (Link, &BlockSingleData->Entry);
711 return;
712 }
713
714 if (BlockArray->Width == BlockSingleData->Width) {
715 //
716 // The same block array has been added.
717 //
718 FreePool (BlockSingleData);
719 *BlockData = BlockArray;
720 return;
721 }
722 } else if (BlockArray->Offset > BlockSingleData->Offset) {
723 //
724 // Insert new block data in the front of block array
725 //
726 InsertTailList (Link, &BlockSingleData->Entry);
727 return;
728 }
729 }
730
731 //
732 // Add new block data into the tail.
733 //
734 InsertTailList (Link, &BlockSingleData->Entry);
735 return;
736 }
737
738 /**
739 This function checks VarOffset and VarWidth is in the block range.
740
741 @param RequestBlockArray The block array is to be checked.
742 @param VarOffset Offset of var to the structure
743 @param VarWidth Width of var.
744
745 @retval TRUE This Var is in the block range.
746 @retval FALSE This Var is not in the block range.
747 **/
748 BOOLEAN
749 BlockArrayCheck (
750 IN IFR_BLOCK_DATA *RequestBlockArray,
751 IN UINT16 VarOffset,
752 IN UINT16 VarWidth
753 )
754 {
755 LIST_ENTRY *Link;
756 IFR_BLOCK_DATA *BlockData;
757
758 //
759 // No Request Block array, all vars are got.
760 //
761 if (RequestBlockArray == NULL) {
762 return TRUE;
763 }
764
765 //
766 // Check the input var is in the request block range.
767 //
768 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
769 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
770 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
771 return TRUE;
772 }
773 }
774
775 return FALSE;
776 }
777
778 /**
779 Get form package data from data base.
780
781 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
782 @param HiiFormPackage The buffer saves the package data.
783 @param PackageSize The buffer size of the package data.
784
785 **/
786 EFI_STATUS
787 GetFormPackageData (
788 IN HII_DATABASE_RECORD *DataBaseRecord,
789 IN OUT UINT8 **HiiFormPackage,
790 OUT UINTN *PackageSize
791 )
792 {
793 EFI_STATUS Status;
794 UINTN Size;
795 UINTN ResultSize;
796
797 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
798 return EFI_INVALID_PARAMETER;
799 }
800
801 Size = 0;
802 ResultSize = 0;
803 //
804 // 0. Get Hii Form Package by HiiHandle
805 //
806 Status = ExportFormPackages (
807 &mPrivate,
808 DataBaseRecord->Handle,
809 DataBaseRecord->PackageList,
810 0,
811 Size,
812 HiiFormPackage,
813 &ResultSize
814 );
815 if (EFI_ERROR (Status)) {
816 return Status;
817 }
818
819 (*HiiFormPackage) = AllocatePool (ResultSize);
820 if (*HiiFormPackage == NULL) {
821 Status = EFI_OUT_OF_RESOURCES;
822 return Status;
823 }
824
825 //
826 // Get HiiFormPackage by HiiHandle
827 //
828 Size = ResultSize;
829 ResultSize = 0;
830 Status = ExportFormPackages (
831 &mPrivate,
832 DataBaseRecord->Handle,
833 DataBaseRecord->PackageList,
834 0,
835 Size,
836 *HiiFormPackage,
837 &ResultSize
838 );
839 if (EFI_ERROR (Status)) {
840 FreePool (*HiiFormPackage);
841 }
842
843 *PackageSize = Size;
844
845 return Status;
846 }
847
848
849 /**
850 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
851
852 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
853 @param ConfigHdr Request string ConfigHdr. If it is NULL,
854 the first found varstore will be as ConfigHdr.
855 @param IsEfiVarstore Whether the request storage type is efi varstore type.
856 @param EfiVarStore The efi varstore info which will return.
857 **/
858 EFI_STATUS
859 GetVarStoreType (
860 IN HII_DATABASE_RECORD *DataBaseRecord,
861 IN EFI_STRING ConfigHdr,
862 OUT BOOLEAN *IsEfiVarstore,
863 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
864
865 )
866 {
867 EFI_STATUS Status;
868 UINTN IfrOffset;
869 EFI_IFR_OP_HEADER *IfrOpHdr;
870 CHAR16 *VarStoreName;
871 EFI_STRING GuidStr;
872 EFI_STRING NameStr;
873 EFI_STRING TempStr;
874 UINTN LengthString;
875 UINT8 *HiiFormPackage;
876 UINTN PackageSize;
877 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
878
879 HiiFormPackage = NULL;
880 LengthString = 0;
881 Status = EFI_SUCCESS;
882 GuidStr = NULL;
883 NameStr = NULL;
884 TempStr = NULL;
885
886 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
887 if (EFI_ERROR (Status)) {
888 return Status;
889 }
890
891 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
892 while (IfrOffset < PackageSize) {
893 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
894 IfrOffset += IfrOpHdr->Length;
895
896 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
897 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
898 //
899 // If the length is small than the structure, this is from old efi
900 // varstore definition. Old efi varstore get config directly from
901 // GetVariable function.
902 //
903 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
904 continue;
905 }
906
907 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
908 if (VarStoreName == NULL) {
909 Status = EFI_OUT_OF_RESOURCES;
910 goto Done;
911 }
912 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
913
914 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
915 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
916 LengthString = StrLen (GuidStr);
917 LengthString = LengthString + StrLen (NameStr) + 1;
918 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
919 if (TempStr == NULL) {
920 FreePool (GuidStr);
921 FreePool (NameStr);
922 FreePool (VarStoreName);
923 Status = EFI_OUT_OF_RESOURCES;
924 goto Done;
925 }
926 StrCpy (TempStr, GuidStr);
927 StrCat (TempStr, NameStr);
928 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
929 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
930 if (*EfiVarStore == NULL) {
931 FreePool (VarStoreName);
932 FreePool (GuidStr);
933 FreePool (NameStr);
934 FreePool (TempStr);
935 Status = EFI_OUT_OF_RESOURCES;
936 goto Done;
937 }
938 *IsEfiVarstore = TRUE;
939 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
940 }
941
942 //
943 // Free alllocated temp string.
944 //
945 FreePool (VarStoreName);
946 FreePool (GuidStr);
947 FreePool (NameStr);
948 FreePool (TempStr);
949 }
950 }
951 Done:
952 if (HiiFormPackage != NULL) {
953 FreePool (HiiFormPackage);
954 }
955
956 return Status;
957 }
958
959 /**
960 This function parses Form Package to get the block array and the default
961 value array according to the request ConfigHdr.
962
963 @param Package Pointer to the form package data.
964 @param PackageLength Length of the pacakge.
965 @param ConfigHdr Request string ConfigHdr. If it is NULL,
966 the first found varstore will be as ConfigHdr.
967 @param RequestBlockArray The block array is retrieved from the request string.
968 @param VarStorageData VarStorage structure contains the got block and default value.
969 @param PIfrDefaultIdArray Point to the got default id and default name array.
970
971 @retval EFI_SUCCESS The block array and the default value array are got.
972 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
973 are conflicted.
974 @retval EFI_OUT_OF_RESOURCES No enough memory.
975 **/
976 EFI_STATUS
977 EFIAPI
978 ParseIfrData (
979 IN UINT8 *Package,
980 IN UINT32 PackageLength,
981 IN EFI_STRING ConfigHdr,
982 IN IFR_BLOCK_DATA *RequestBlockArray,
983 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
984 OUT IFR_DEFAULT_DATA *DefaultIdArray
985 )
986 {
987 EFI_STATUS Status;
988 UINTN IfrOffset;
989 EFI_IFR_VARSTORE *IfrVarStore;
990 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
991 EFI_IFR_OP_HEADER *IfrOpHdr;
992 EFI_IFR_ONE_OF *IfrOneOf;
993 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
994 EFI_IFR_DEFAULT *IfrDefault;
995 EFI_IFR_ORDERED_LIST *IfrOrderedList;
996 EFI_IFR_CHECKBOX *IfrCheckBox;
997 EFI_IFR_PASSWORD *IfrPassword;
998 EFI_IFR_STRING *IfrString;
999 IFR_DEFAULT_DATA DefaultData;
1000 IFR_DEFAULT_DATA *DefaultDataPtr;
1001 IFR_BLOCK_DATA *BlockData;
1002 CHAR16 *VarStoreName;
1003 UINT16 VarOffset;
1004 UINT16 VarWidth;
1005 UINT16 VarDefaultId;
1006 EFI_STRING GuidStr;
1007 EFI_STRING NameStr;
1008 EFI_STRING TempStr;
1009 UINTN LengthString;
1010 BOOLEAN FirstOneOfOption;
1011 LIST_ENTRY *LinkData;
1012 LIST_ENTRY *LinkDefault;
1013
1014 LengthString = 0;
1015 Status = EFI_SUCCESS;
1016 GuidStr = NULL;
1017 NameStr = NULL;
1018 TempStr = NULL;
1019 BlockData = NULL;
1020 DefaultDataPtr = NULL;
1021 FirstOneOfOption = FALSE;
1022 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
1023
1024 //
1025 // Go through the form package to parse OpCode one by one.
1026 //
1027 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1028 while (IfrOffset < PackageLength) {
1029 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
1030
1031 switch (IfrOpHdr->OpCode) {
1032 case EFI_IFR_VARSTORE_OP:
1033 //
1034 // VarStore is found. Don't need to search any more.
1035 //
1036 if (VarStorageData->Size != 0) {
1037 break;
1038 }
1039
1040 //
1041 // Get the requied varstore information
1042 // Add varstore by Guid and Name in ConfigHdr
1043 // Make sure Offset is in varstore size and varstoreid
1044 //
1045 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1046 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
1047 if (VarStoreName == NULL) {
1048 Status = EFI_OUT_OF_RESOURCES;
1049 goto Done;
1050 }
1051 AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);
1052
1053 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);
1054 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1055 LengthString = StrLen (GuidStr);
1056 LengthString = LengthString + StrLen (NameStr) + 1;
1057 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1058 if (TempStr == NULL) {
1059 FreePool (GuidStr);
1060 FreePool (NameStr);
1061 FreePool (VarStoreName);
1062 Status = EFI_OUT_OF_RESOURCES;
1063 goto Done;
1064 }
1065 StrCpy (TempStr, GuidStr);
1066 StrCat (TempStr, NameStr);
1067 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1068 //
1069 // Find the matched VarStore
1070 //
1071 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
1072 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;
1073 VarStorageData->Size = IfrVarStore->Size;
1074 VarStorageData->Name = VarStoreName;
1075 } else {
1076 //
1077 // No found, free the allocated memory
1078 //
1079 FreePool (VarStoreName);
1080 }
1081 //
1082 // Free alllocated temp string.
1083 //
1084 FreePool (GuidStr);
1085 FreePool (NameStr);
1086 FreePool (TempStr);
1087 break;
1088
1089 case EFI_IFR_VARSTORE_EFI_OP:
1090 //
1091 // VarStore is found. Don't need to search any more.
1092 //
1093 if (VarStorageData->Size != 0) {
1094 break;
1095 }
1096
1097 //
1098 // Get the requied varstore information
1099 // Add varstore by Guid and Name in ConfigHdr
1100 // Make sure Offset is in varstore size and varstoreid
1101 //
1102 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1103
1104 //
1105 // If the length is small than the structure, this is from old efi
1106 // varstore definition. Old efi varstore get config directly from
1107 // GetVariable function.
1108 //
1109 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1110 break;
1111 }
1112
1113 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1114 if (VarStoreName == NULL) {
1115 Status = EFI_OUT_OF_RESOURCES;
1116 goto Done;
1117 }
1118 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
1119
1120 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1121 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1122 LengthString = StrLen (GuidStr);
1123 LengthString = LengthString + StrLen (NameStr) + 1;
1124 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1125 if (TempStr == NULL) {
1126 FreePool (GuidStr);
1127 FreePool (NameStr);
1128 FreePool (VarStoreName);
1129 Status = EFI_OUT_OF_RESOURCES;
1130 goto Done;
1131 }
1132 StrCpy (TempStr, GuidStr);
1133 StrCat (TempStr, NameStr);
1134 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1135 //
1136 // Find the matched VarStore
1137 //
1138 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
1139 VarStorageData->VarStoreId = IfrEfiVarStore->VarStoreId;
1140 VarStorageData->Size = IfrEfiVarStore->Size;
1141 VarStorageData->Name = VarStoreName;
1142 } else {
1143 //
1144 // No found, free the allocated memory
1145 //
1146 FreePool (VarStoreName);
1147 }
1148 //
1149 // Free alllocated temp string.
1150 //
1151 FreePool (GuidStr);
1152 FreePool (NameStr);
1153 FreePool (TempStr);
1154 break;
1155
1156 case EFI_IFR_DEFAULTSTORE_OP:
1157 //
1158 // Add new the map between default id and default name.
1159 //
1160 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1161 if (DefaultDataPtr == NULL) {
1162 Status = EFI_OUT_OF_RESOURCES;
1163 goto Done;
1164 }
1165 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
1166 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
1167 DefaultDataPtr = NULL;
1168 break;
1169
1170 case EFI_IFR_FORM_OP:
1171 case EFI_IFR_FORM_MAP_OP:
1172 //
1173 // No matched varstore is found and directly return.
1174 //
1175 if (VarStorageData->Size == 0) {
1176 Status = EFI_SUCCESS;
1177 goto Done;
1178 }
1179 break;
1180
1181 case EFI_IFR_ONE_OF_OP:
1182 case EFI_IFR_NUMERIC_OP:
1183 //
1184 // Numeric and OneOf has the same opcode structure.
1185 //
1186
1187 //
1188 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1189 //
1190 if (VarStorageData->Size == 0) {
1191 Status = EFI_INVALID_PARAMETER;
1192 goto Done;
1193 }
1194 //
1195 // Check whether this question is for the requested varstore.
1196 //
1197 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
1198 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {
1199 break;
1200 }
1201
1202 //
1203 // Get Offset/Width by Question header and OneOf Flags
1204 //
1205 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;
1206 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
1207 //
1208 // Check whether this question is in requested block array.
1209 //
1210 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1211 //
1212 // This question is not in the requested string. Skip it.
1213 //
1214 break;
1215 }
1216
1217 //
1218 // Check this var question is in the var storage
1219 //
1220 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1221 Status = EFI_INVALID_PARAMETER;
1222 goto Done;
1223 }
1224
1225 //
1226 // Set Block Data
1227 //
1228 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1229 if (BlockData == NULL) {
1230 Status = EFI_OUT_OF_RESOURCES;
1231 goto Done;
1232 }
1233 BlockData->Offset = VarOffset;
1234 BlockData->Width = VarWidth;
1235 BlockData->QuestionId = IfrOneOf->Question.QuestionId;
1236 BlockData->OpCode = IfrOpHdr->OpCode;
1237 BlockData->Scope = IfrOpHdr->Scope;
1238 InitializeListHead (&BlockData->DefaultValueEntry);
1239 //
1240 // Add Block Data into VarStorageData BlockEntry
1241 //
1242 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1243
1244 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
1245 //
1246 // Set this flag to TRUE for the first oneof option.
1247 //
1248 FirstOneOfOption = TRUE;
1249 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
1250 //
1251 // Numeric minimum value will be used as default value when no default is specified.
1252 //
1253 DefaultData.Type = DEFAULT_VALUE_FROM_DEFAULT;
1254 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
1255 case EFI_IFR_NUMERIC_SIZE_1:
1256 DefaultData.Value = (UINT64) IfrOneOf->data.u8.MinValue;
1257 break;
1258
1259 case EFI_IFR_NUMERIC_SIZE_2:
1260 CopyMem (&DefaultData.Value, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
1261 break;
1262
1263 case EFI_IFR_NUMERIC_SIZE_4:
1264 CopyMem (&DefaultData.Value, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
1265 break;
1266
1267 case EFI_IFR_NUMERIC_SIZE_8:
1268 CopyMem (&DefaultData.Value, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
1269 break;
1270 }
1271 //
1272 // Set default value base on the DefaultId list get from IFR data.
1273 //
1274 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
1275 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
1276 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
1277 InsertDefaultValue (BlockData, &DefaultData);
1278 }
1279 }
1280 break;
1281
1282 case EFI_IFR_ORDERED_LIST_OP:
1283 //
1284 // offset by question header
1285 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1286 // no default value and default id, how to define its default value?
1287 //
1288
1289 //
1290 // OrderedList question is not in IFR Form. This IFR form is not valid.
1291 //
1292 if (VarStorageData->Size == 0) {
1293 Status = EFI_INVALID_PARAMETER;
1294 goto Done;
1295 }
1296 //
1297 // Check whether this question is for the requested varstore.
1298 //
1299 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
1300 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {
1301 BlockData = NULL;
1302 break;
1303 }
1304
1305 //
1306 // Get Offset/Width by Question header and OneOf Flags
1307 //
1308 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;
1309 VarWidth = IfrOrderedList->MaxContainers;
1310
1311 //
1312 // Set Block Data
1313 //
1314 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1315 if (BlockData == NULL) {
1316 Status = EFI_OUT_OF_RESOURCES;
1317 goto Done;
1318 }
1319 BlockData->Offset = VarOffset;
1320 BlockData->Width = VarWidth;
1321 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;
1322 BlockData->OpCode = IfrOpHdr->OpCode;
1323 BlockData->Scope = IfrOpHdr->Scope;
1324 InitializeListHead (&BlockData->DefaultValueEntry);
1325 break;
1326
1327 case EFI_IFR_CHECKBOX_OP:
1328 //
1329 // EFI_IFR_DEFAULT_OP
1330 // offset by question header
1331 // width is 1 sizeof (BOOLEAN)
1332 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1333 // value by DefaultOption
1334 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1335 //
1336
1337 //
1338 // CheckBox question is not in IFR Form. This IFR form is not valid.
1339 //
1340 if (VarStorageData->Size == 0) {
1341 Status = EFI_INVALID_PARAMETER;
1342 goto Done;
1343 }
1344 //
1345 // Check whether this question is for the requested varstore.
1346 //
1347 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
1348 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {
1349 break;
1350 }
1351
1352 //
1353 // Get Offset/Width by Question header and OneOf Flags
1354 //
1355 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
1356 VarWidth = (UINT16) sizeof (BOOLEAN);
1357
1358 //
1359 // Check whether this question is in requested block array.
1360 //
1361 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1362 //
1363 // This question is not in the requested string. Skip it.
1364 //
1365 break;
1366 }
1367
1368 //
1369 // Check this var question is in the var storage
1370 //
1371 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1372 Status = EFI_INVALID_PARAMETER;
1373 goto Done;
1374 }
1375
1376 //
1377 // Set Block Data
1378 //
1379 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1380 if (BlockData == NULL) {
1381 Status = EFI_OUT_OF_RESOURCES;
1382 goto Done;
1383 }
1384 BlockData->Offset = VarOffset;
1385 BlockData->Width = VarWidth;
1386 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;
1387 BlockData->OpCode = IfrOpHdr->OpCode;
1388 BlockData->Scope = IfrOpHdr->Scope;
1389 InitializeListHead (&BlockData->DefaultValueEntry);
1390 //
1391 // Add Block Data into VarStorageData BlockEntry
1392 //
1393 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1394
1395 //
1396 // Add default value for standard ID by CheckBox Flag
1397 //
1398 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1399 //
1400 // Prepare new DefaultValue
1401 //
1402 DefaultData.DefaultId = VarDefaultId;
1403 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
1404 //
1405 // When flag is set, defautl value is TRUE.
1406 //
1407 DefaultData.Type = DEFAULT_VALUE_FROM_FLAG;
1408 DefaultData.Value = 1;
1409 } else {
1410 //
1411 // When flag is not set, defautl value is FASLE.
1412 //
1413 DefaultData.Type = DEFAULT_VALUE_FROM_DEFAULT;
1414 DefaultData.Value = 0;
1415 }
1416 //
1417 // Add DefaultValue into current BlockData
1418 //
1419 InsertDefaultValue (BlockData, &DefaultData);
1420
1421 //
1422 // Add default value for Manufacture ID by CheckBox Flag
1423 //
1424 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1425 //
1426 // Prepare new DefaultValue
1427 //
1428 DefaultData.DefaultId = VarDefaultId;
1429 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
1430 //
1431 // When flag is set, defautl value is TRUE.
1432 //
1433 DefaultData.Type = DEFAULT_VALUE_FROM_FLAG;
1434 DefaultData.Value = 1;
1435 } else {
1436 //
1437 // When flag is not set, defautl value is FASLE.
1438 //
1439 DefaultData.Type = DEFAULT_VALUE_FROM_DEFAULT;
1440 DefaultData.Value = 0;
1441 }
1442 //
1443 // Add DefaultValue into current BlockData
1444 //
1445 InsertDefaultValue (BlockData, &DefaultData);
1446 break;
1447
1448 case EFI_IFR_STRING_OP:
1449 //
1450 // offset by question header
1451 // width MaxSize * sizeof (CHAR16)
1452 // no default value, only block array
1453 //
1454
1455 //
1456 // String question is not in IFR Form. This IFR form is not valid.
1457 //
1458 if (VarStorageData->Size == 0) {
1459 Status = EFI_INVALID_PARAMETER;
1460 goto Done;
1461 }
1462 //
1463 // Check whether this question is for the requested varstore.
1464 //
1465 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
1466 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {
1467 break;
1468 }
1469
1470 //
1471 // Get Offset/Width by Question header and OneOf Flags
1472 //
1473 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;
1474 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
1475
1476 //
1477 // Check whether this question is in requested block array.
1478 //
1479 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1480 //
1481 // This question is not in the requested string. Skip it.
1482 //
1483 break;
1484 }
1485
1486 //
1487 // Check this var question is in the var storage
1488 //
1489 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1490 Status = EFI_INVALID_PARAMETER;
1491 goto Done;
1492 }
1493
1494 //
1495 // Set Block Data
1496 //
1497 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1498 if (BlockData == NULL) {
1499 Status = EFI_OUT_OF_RESOURCES;
1500 goto Done;
1501 }
1502 BlockData->Offset = VarOffset;
1503 BlockData->Width = VarWidth;
1504 BlockData->QuestionId = IfrString->Question.QuestionId;
1505 BlockData->OpCode = IfrOpHdr->OpCode;
1506 InitializeListHead (&BlockData->DefaultValueEntry);
1507
1508 //
1509 // Add Block Data into VarStorageData BlockEntry
1510 //
1511 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1512
1513 //
1514 // No default value for string.
1515 //
1516 BlockData = NULL;
1517 break;
1518
1519 case EFI_IFR_PASSWORD_OP:
1520 //
1521 // offset by question header
1522 // width MaxSize * sizeof (CHAR16)
1523 // no default value, only block array
1524 //
1525
1526 //
1527 // Password question is not in IFR Form. This IFR form is not valid.
1528 //
1529 if (VarStorageData->Size == 0) {
1530 Status = EFI_INVALID_PARAMETER;
1531 goto Done;
1532 }
1533 //
1534 // Check whether this question is for the requested varstore.
1535 //
1536 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
1537 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {
1538 break;
1539 }
1540
1541 //
1542 // Get Offset/Width by Question header and OneOf Flags
1543 //
1544 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;
1545 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
1546
1547 //
1548 // Check whether this question is in requested block array.
1549 //
1550 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1551 //
1552 // This question is not in the requested string. Skip it.
1553 //
1554 break;
1555 }
1556
1557 //
1558 // Check this var question is in the var storage
1559 //
1560 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1561 Status = EFI_INVALID_PARAMETER;
1562 goto Done;
1563 }
1564
1565 //
1566 // Set Block Data
1567 //
1568 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1569 if (BlockData == NULL) {
1570 Status = EFI_OUT_OF_RESOURCES;
1571 goto Done;
1572 }
1573 BlockData->Offset = VarOffset;
1574 BlockData->Width = VarWidth;
1575 BlockData->QuestionId = IfrPassword->Question.QuestionId;
1576 BlockData->OpCode = IfrOpHdr->OpCode;
1577 InitializeListHead (&BlockData->DefaultValueEntry);
1578
1579 //
1580 // Add Block Data into VarStorageData BlockEntry
1581 //
1582 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1583
1584 //
1585 // No default value for string.
1586 //
1587 BlockData = NULL;
1588 break;
1589
1590 case EFI_IFR_ONE_OF_OPTION_OP:
1591 //
1592 // No matched block data is ignored.
1593 //
1594 if (BlockData == NULL || BlockData->Scope == 0) {
1595 break;
1596 }
1597
1598 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
1599 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1600 //
1601 // Get ordered list option data type.
1602 //
1603 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
1604 VarWidth = 1;
1605 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1606 VarWidth = 2;
1607 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1608 VarWidth = 4;
1609 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1610 VarWidth = 8;
1611 } else {
1612 //
1613 // Invalid ordered list option data type.
1614 //
1615 Status = EFI_INVALID_PARAMETER;
1616 FreePool (BlockData);
1617 goto Done;
1618 }
1619
1620 //
1621 // Calculate Ordered list QuestionId width.
1622 //
1623 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
1624 //
1625 // Check whether this question is in requested block array.
1626 //
1627 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width)) {
1628 //
1629 // This question is not in the requested string. Skip it.
1630 //
1631 FreePool (BlockData);
1632 BlockData = NULL;
1633 break;
1634 }
1635 //
1636 // Check this var question is in the var storage
1637 //
1638 if ((BlockData->Offset + BlockData->Width) > VarStorageData->Size) {
1639 Status = EFI_INVALID_PARAMETER;
1640 FreePool (BlockData);
1641 goto Done;
1642 }
1643 //
1644 // Add Block Data into VarStorageData BlockEntry
1645 //
1646 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1647 //
1648 // No default data for OrderedList.
1649 //
1650 BlockData = NULL;
1651 break;
1652 }
1653
1654 //
1655 // 1. Set default value for OneOf option when flag field has default attribute.
1656 //
1657 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
1658 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
1659 //
1660 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1661 // The first oneof option value will be used as default value when no default value is specified.
1662 //
1663 FirstOneOfOption = FALSE;
1664
1665 // Prepare new DefaultValue
1666 //
1667 DefaultData.Type = DEFAULT_VALUE_FROM_FLAG;
1668 DefaultData.Value = IfrOneOfOption->Value.u64;
1669 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
1670 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1671 InsertDefaultValue (BlockData, &DefaultData);
1672 }
1673 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
1674 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1675 InsertDefaultValue (BlockData, &DefaultData);
1676 }
1677
1678
1679 }
1680
1681 //
1682 // 2. Set as the default value when this is the first option.
1683 // The first oneof option value will be used as default value when no default value is specified.
1684 //
1685 if (FirstOneOfOption) {
1686 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1687 FirstOneOfOption = FALSE;
1688
1689 //
1690 // Prepare new DefaultValue
1691 //
1692 DefaultData.Type = DEFAULT_VALUE_FROM_DEFAULT;
1693 DefaultData.Value = IfrOneOfOption->Value.u64;
1694 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
1695 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
1696 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
1697 InsertDefaultValue (BlockData, &DefaultData);
1698 }
1699 }
1700 break;
1701
1702 case EFI_IFR_DEFAULT_OP:
1703 //
1704 // Update Current BlockData to the default value.
1705 //
1706 if (BlockData == NULL || BlockData->Scope == 0) {
1707 //
1708 // No matched block data is ignored.
1709 //
1710 break;
1711 }
1712
1713 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1714 //
1715 // OrderedList Opcode is no default value.
1716 //
1717 break;
1718 }
1719 //
1720 // Get the DefaultId
1721 //
1722 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
1723 VarDefaultId = IfrDefault->DefaultId;
1724 //
1725 // Prepare new DefaultValue
1726 //
1727 DefaultData.Type = DEFAULT_VALUE_FROM_OPCODE;
1728 DefaultData.DefaultId = VarDefaultId;
1729 DefaultData.Value = IfrDefault->Value.u64;
1730
1731 // If the value field is expression, set the cleaned flag.
1732 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
1733 DefaultData.Cleaned = TRUE;
1734 }
1735 //
1736 // Add DefaultValue into current BlockData
1737 //
1738 InsertDefaultValue (BlockData, &DefaultData);
1739
1740 //
1741 // After insert the default value, reset the cleaned value for next
1742 // time used. If not set here, need to set the value before everytime
1743 // use it.
1744 //
1745 DefaultData.Cleaned = FALSE;
1746 break;
1747 case EFI_IFR_END_OP:
1748 //
1749 // End Opcode is for Var question.
1750 //
1751 if (BlockData != NULL && BlockData->Scope > 0) {
1752 BlockData->Scope--;
1753 }
1754 break;
1755 default:
1756 if (BlockData != NULL && BlockData->Scope > 0) {
1757 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
1758 }
1759 break;
1760 }
1761
1762 IfrOffset += IfrOpHdr->Length;
1763 }
1764
1765 Done:
1766 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
1767 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
1768 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
1769 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
1770 LinkDefault = LinkDefault->ForwardLink;
1771 if (DefaultDataPtr->Cleaned == TRUE) {
1772 RemoveEntryList (&DefaultDataPtr->Entry);
1773 FreePool (DefaultDataPtr);
1774 }
1775 }
1776 }
1777
1778 return Status;
1779 }
1780
1781 /**
1782 This function gets the full request string and full default value string by
1783 parsing IFR data in HII form packages.
1784
1785 When Request points to NULL string, the request string and default value string
1786 for each varstore in form package will return.
1787
1788 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1789 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1790 @param Request Pointer to a null-terminated Unicode string in
1791 <ConfigRequest> format. When it doesn't contain
1792 any RequestElement, it will be updated to return
1793 the full RequestElement retrieved from IFR data.
1794 If it points to NULL, the request string for the first
1795 varstore in form package will be merged into a
1796 <MultiConfigRequest> format string and return.
1797 @param AltCfgResp Pointer to a null-terminated Unicode string in
1798 <ConfigAltResp> format. When the pointer is to NULL,
1799 the full default value string retrieved from IFR data
1800 will return. When the pinter is to a string, the
1801 full default value string retrieved from IFR data
1802 will be merged into the input string and return.
1803 When Request points to NULL, the default value string
1804 for each varstore in form package will be merged into
1805 a <MultiConfigAltResp> format string and return.
1806 @param PointerProgress Optional parameter, it can be be NULL.
1807 When it is not NULL, if Request is NULL, it returns NULL.
1808 On return, points to a character in the Request
1809 string. Points to the string's null terminator if
1810 request was successful. Points to the most recent
1811 & before the first failing name / value pair (or
1812 the beginning of the string if the failure is in
1813 the first name / value pair) if the request was
1814 not successful.
1815 @retval EFI_SUCCESS The Results string is set to the full request string.
1816 And AltCfgResp contains all default value string.
1817 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1818 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1819 can't be found in Form package.
1820 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1821 @retval EFI_INVALID_PARAMETER Request points to NULL.
1822
1823 **/
1824 EFI_STATUS
1825 EFIAPI
1826 GetFullStringFromHiiFormPackages (
1827 IN HII_DATABASE_RECORD *DataBaseRecord,
1828 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1829 IN OUT EFI_STRING *Request,
1830 IN OUT EFI_STRING *AltCfgResp,
1831 OUT EFI_STRING *PointerProgress OPTIONAL
1832 )
1833 {
1834 EFI_STATUS Status;
1835 UINT8 *HiiFormPackage;
1836 UINTN PackageSize;
1837 IFR_BLOCK_DATA *RequestBlockArray;
1838 IFR_BLOCK_DATA *BlockData;
1839 IFR_BLOCK_DATA *NextBlockData;
1840 IFR_DEFAULT_DATA *DefaultValueData;
1841 IFR_DEFAULT_DATA *DefaultId;
1842 IFR_DEFAULT_DATA *DefaultIdArray;
1843 IFR_VARSTORAGE_DATA *VarStorageData;
1844 EFI_STRING DefaultAltCfgResp;
1845 EFI_STRING FullConfigRequest;
1846 EFI_STRING ConfigHdr;
1847 EFI_STRING GuidStr;
1848 EFI_STRING NameStr;
1849 EFI_STRING PathStr;
1850 EFI_STRING StringPtr;
1851 EFI_STRING Progress;
1852 UINTN Length;
1853 UINT8 *TmpBuffer;
1854 UINT16 Offset;
1855 UINT16 Width;
1856 LIST_ENTRY *Link;
1857 LIST_ENTRY *LinkData;
1858 LIST_ENTRY *LinkDefault;
1859 BOOLEAN DataExist;
1860
1861 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
1862 return EFI_INVALID_PARAMETER;
1863 }
1864
1865 //
1866 // Initialize the local variables.
1867 //
1868 RequestBlockArray = NULL;
1869 DefaultIdArray = NULL;
1870 VarStorageData = NULL;
1871 DefaultAltCfgResp = NULL;
1872 FullConfigRequest = NULL;
1873 ConfigHdr = NULL;
1874 GuidStr = NULL;
1875 NameStr = NULL;
1876 PathStr = NULL;
1877 HiiFormPackage = NULL;
1878 PackageSize = 0;
1879 DataExist = FALSE;
1880 Progress = *Request;
1881
1882 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
1883 if (EFI_ERROR (Status)) {
1884 return Status;
1885 }
1886
1887 //
1888 // 1. Get the request block array by Request String when Request string containts the block array.
1889 //
1890 StringPtr = NULL;
1891 if (*Request != NULL) {
1892 StringPtr = *Request;
1893 //
1894 // Jump <ConfigHdr>
1895 //
1896 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
1897 Status = EFI_INVALID_PARAMETER;
1898 goto Done;
1899 }
1900 StringPtr += StrLen (L"GUID=");
1901 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
1902 StringPtr++;
1903 }
1904 if (*StringPtr == L'\0') {
1905 Status = EFI_INVALID_PARAMETER;
1906 goto Done;
1907 }
1908 StringPtr += StrLen (L"&NAME=");
1909 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
1910 StringPtr++;
1911 }
1912 if (*StringPtr == L'\0') {
1913 Status = EFI_INVALID_PARAMETER;
1914 goto Done;
1915 }
1916 StringPtr += StrLen (L"&PATH=");
1917 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1918 StringPtr ++;
1919 }
1920 //
1921 // Check the following string &OFFSET=
1922 //
1923 if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
1924 Progress = StringPtr;
1925 Status = EFI_INVALID_PARAMETER;
1926 goto Done;
1927 } else if (*StringPtr == L'\0') {
1928 //
1929 // No request block is found.
1930 //
1931 StringPtr = NULL;
1932 }
1933 }
1934 if (StringPtr != NULL) {
1935 //
1936 // Init RequestBlockArray
1937 //
1938 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1939 if (RequestBlockArray == NULL) {
1940 Status = EFI_OUT_OF_RESOURCES;
1941 goto Done;
1942 }
1943 InitializeListHead (&RequestBlockArray->Entry);
1944
1945 //
1946 // Get the request Block array from the request string
1947 // Offset and Width
1948 //
1949
1950 //
1951 // Parse each <RequestElement> if exists
1952 // Only <BlockName> format is supported by this help function.
1953 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1954 //
1955 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
1956 //
1957 // Skip the OFFSET string
1958 //
1959 Progress = StringPtr;
1960 StringPtr += StrLen (L"&OFFSET=");
1961 //
1962 // Get Offset
1963 //
1964 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1965 if (EFI_ERROR (Status)) {
1966 goto Done;
1967 }
1968 Offset = 0;
1969 CopyMem (
1970 &Offset,
1971 TmpBuffer,
1972 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1973 );
1974 FreePool (TmpBuffer);
1975
1976 StringPtr += Length;
1977 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
1978 Status = EFI_INVALID_PARAMETER;
1979 goto Done;
1980 }
1981 StringPtr += StrLen (L"&WIDTH=");
1982
1983 //
1984 // Get Width
1985 //
1986 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1987 if (EFI_ERROR (Status)) {
1988 goto Done;
1989 }
1990 Width = 0;
1991 CopyMem (
1992 &Width,
1993 TmpBuffer,
1994 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1995 );
1996 FreePool (TmpBuffer);
1997
1998 StringPtr += Length;
1999 if (*StringPtr != 0 && *StringPtr != L'&') {
2000 Status = EFI_INVALID_PARAMETER;
2001 goto Done;
2002 }
2003
2004 //
2005 // Set Block Data
2006 //
2007 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2008 if (BlockData == NULL) {
2009 Status = EFI_OUT_OF_RESOURCES;
2010 goto Done;
2011 }
2012 BlockData->Offset = Offset;
2013 BlockData->Width = Width;
2014 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
2015
2016 //
2017 // Skip &VALUE string if &VALUE does exists.
2018 //
2019 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
2020 StringPtr += StrLen (L"&VALUE=");
2021
2022 //
2023 // Get Value
2024 //
2025 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2026 if (EFI_ERROR (Status)) {
2027 Status = EFI_INVALID_PARAMETER;
2028 goto Done;
2029 }
2030
2031 StringPtr += Length;
2032 if (*StringPtr != 0 && *StringPtr != L'&') {
2033 Status = EFI_INVALID_PARAMETER;
2034 goto Done;
2035 }
2036 }
2037 //
2038 // If '\0', parsing is finished.
2039 //
2040 if (*StringPtr == 0) {
2041 break;
2042 }
2043 }
2044
2045 //
2046 // Merge the requested block data.
2047 //
2048 Link = RequestBlockArray->Entry.ForwardLink;
2049 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
2050 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2051 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
2052 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
2053 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
2054 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
2055 }
2056 RemoveEntryList (Link->ForwardLink);
2057 FreePool (NextBlockData);
2058 continue;
2059 }
2060 Link = Link->ForwardLink;
2061 }
2062 }
2063
2064 //
2065 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2066 //
2067
2068 //
2069 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2070 //
2071 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
2072 if (DefaultIdArray == NULL) {
2073 Status = EFI_OUT_OF_RESOURCES;
2074 goto Done;
2075 }
2076 InitializeListHead (&DefaultIdArray->Entry);
2077
2078 //
2079 // Initialize VarStorageData to store the var store Block and Default value information.
2080 //
2081 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
2082 if (VarStorageData == NULL) {
2083 Status = EFI_OUT_OF_RESOURCES;
2084 goto Done;
2085 }
2086 InitializeListHead (&VarStorageData->Entry);
2087 InitializeListHead (&VarStorageData->BlockEntry);
2088
2089 //
2090 // Parse the opcode in form pacakge to get the default setting.
2091 //
2092 Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);
2093 if (EFI_ERROR (Status)) {
2094 goto Done;
2095 }
2096
2097 //
2098 // No requested varstore in IFR data and directly return
2099 //
2100 if (VarStorageData->Size == 0) {
2101 Status = EFI_SUCCESS;
2102 goto Done;
2103 }
2104
2105 //
2106 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
2107 //
2108
2109 //
2110 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2111 //
2112 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
2113 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
2114 GenerateSubStr (
2115 L"PATH=",
2116 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
2117 (VOID *) DevicePath,
2118 1,
2119 &PathStr
2120 );
2121 Length = StrLen (GuidStr);
2122 Length = Length + StrLen (NameStr);
2123 Length = Length + StrLen (PathStr) + 1;
2124 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
2125 if (ConfigHdr == NULL) {
2126 Status = EFI_OUT_OF_RESOURCES;
2127 goto Done;
2128 }
2129 StrCpy (ConfigHdr, GuidStr);
2130 StrCat (ConfigHdr, NameStr);
2131 StrCat (ConfigHdr, PathStr);
2132
2133 //
2134 // Remove the last character L'&'
2135 //
2136 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';
2137
2138 if (RequestBlockArray == NULL) {
2139 //
2140 // Append VarStorageData BlockEntry into *Request string
2141 // Now support only one varstore in a form package.
2142 //
2143
2144 //
2145 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2146 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2147 //
2148
2149 //
2150 // Compute the length of the entire request starting with <ConfigHdr> and a
2151 // Null-terminator
2152 //
2153 DataExist = FALSE;
2154 Length = StrLen (ConfigHdr) + 1;
2155
2156 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2157 //
2158 // Add <BlockName> length for each Offset/Width pair
2159 //
2160 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2161 // | 8 | 4 | 7 | 4 |
2162 //
2163 DataExist = TRUE;
2164 Length = Length + (8 + 4 + 7 + 4);
2165 }
2166
2167 //
2168 // No any request block data is found. The request string can't be constructed.
2169 //
2170 if (!DataExist) {
2171 Status = EFI_SUCCESS;
2172 goto Done;
2173 }
2174
2175 //
2176 // Allocate buffer for the entire <ConfigRequest>
2177 //
2178 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
2179 if (FullConfigRequest == NULL) {
2180 Status = EFI_OUT_OF_RESOURCES;
2181 goto Done;
2182 }
2183 StringPtr = FullConfigRequest;
2184
2185 //
2186 // Start with <ConfigHdr>
2187 //
2188 StrCpy (StringPtr, ConfigHdr);
2189 StringPtr += StrLen (StringPtr);
2190
2191 //
2192 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2193 //
2194 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2195 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2196 //
2197 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2198 //
2199 UnicodeSPrint (
2200 StringPtr,
2201 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
2202 L"&OFFSET=%04X&WIDTH=%04X",
2203 BlockData->Offset,
2204 BlockData->Width
2205 );
2206 StringPtr += StrLen (StringPtr);
2207 }
2208 //
2209 // Set to the got full request string.
2210 //
2211 HiiToLower (FullConfigRequest);
2212 if (*Request != NULL) {
2213 FreePool (*Request);
2214 }
2215 *Request = FullConfigRequest;
2216 }
2217
2218 //
2219 // 4. Construct Default Value string in AltResp according to request element.
2220 // Go through all VarStorageData Entry and get the DefaultId array for each one
2221 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2222 //
2223 DataExist = FALSE;
2224 //
2225 // Add length for <ConfigHdr> + '\0'
2226 //
2227 Length = StrLen (ConfigHdr) + 1;
2228
2229 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2230 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2231 //
2232 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2233 // |1| StrLen (ConfigHdr) | 8 | 4 |
2234 //
2235 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
2236
2237 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2238 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2239 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
2240 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2241 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
2242 //
2243 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2244 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2245 //
2246 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
2247 DataExist = TRUE;
2248 }
2249 }
2250 }
2251 }
2252
2253 //
2254 // No default value is found. The default string doesn't exist.
2255 //
2256 if (!DataExist) {
2257 Status = EFI_SUCCESS;
2258 goto Done;
2259 }
2260
2261 //
2262 // Allocate buffer for the entire <DefaultAltCfgResp>
2263 //
2264 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
2265 if (DefaultAltCfgResp == NULL) {
2266 Status = EFI_OUT_OF_RESOURCES;
2267 goto Done;
2268 }
2269 StringPtr = DefaultAltCfgResp;
2270
2271 //
2272 // Start with <ConfigHdr>
2273 //
2274 StrCpy (StringPtr, ConfigHdr);
2275 StringPtr += StrLen (StringPtr);
2276
2277 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2278 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2279 //
2280 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2281 // |1| StrLen (ConfigHdr) | 8 | 4 |
2282 //
2283 UnicodeSPrint (
2284 StringPtr,
2285 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
2286 L"&%s&ALTCFG=%04X",
2287 ConfigHdr,
2288 DefaultId->DefaultId
2289 );
2290 StringPtr += StrLen (StringPtr);
2291
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; LinkDefault = LinkDefault->ForwardLink) {
2295 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2296 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
2297 //
2298 // Add <BlockConfig>
2299 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2300 //
2301 UnicodeSPrint (
2302 StringPtr,
2303 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
2304 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2305 BlockData->Offset,
2306 BlockData->Width
2307 );
2308 StringPtr += StrLen (StringPtr);
2309
2310 //
2311 // Convert Value to a hex string in "%x" format
2312 // NOTE: This is in the opposite byte that GUID and PATH use
2313 //
2314 Width = BlockData->Width;
2315 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
2316 for (; Width > 0; Width--) {
2317 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
2318 }
2319 }
2320 }
2321 }
2322 }
2323 HiiToLower (DefaultAltCfgResp);
2324
2325 //
2326 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2327 //
2328 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
2329 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
2330 FreePool (DefaultAltCfgResp);
2331 } else if (*AltCfgResp == NULL) {
2332 *AltCfgResp = DefaultAltCfgResp;
2333 }
2334
2335 Done:
2336 if (RequestBlockArray != NULL) {
2337 //
2338 // Free Link Array RequestBlockArray
2339 //
2340 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2341 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2342 RemoveEntryList (&BlockData->Entry);
2343 FreePool (BlockData);
2344 }
2345
2346 FreePool (RequestBlockArray);
2347 }
2348
2349 if (VarStorageData != NULL) {
2350 //
2351 // Free link array VarStorageData
2352 //
2353 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
2354 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
2355 RemoveEntryList (&BlockData->Entry);
2356 //
2357 // Free default value link array
2358 //
2359 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
2360 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
2361 RemoveEntryList (&DefaultValueData->Entry);
2362 FreePool (DefaultValueData);
2363 }
2364 FreePool (BlockData);
2365 }
2366 FreePool (VarStorageData);
2367 }
2368
2369 if (DefaultIdArray != NULL) {
2370 //
2371 // Free DefaultId Array
2372 //
2373 while (!IsListEmpty (&DefaultIdArray->Entry)) {
2374 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
2375 RemoveEntryList (&DefaultId->Entry);
2376 FreePool (DefaultId);
2377 }
2378 FreePool (DefaultIdArray);
2379 }
2380
2381 //
2382 // Free the allocated string
2383 //
2384 if (GuidStr != NULL) {
2385 FreePool (GuidStr);
2386 }
2387 if (NameStr != NULL) {
2388 FreePool (NameStr);
2389 }
2390 if (PathStr != NULL) {
2391 FreePool (PathStr);
2392 }
2393 if (ConfigHdr != NULL) {
2394 FreePool (ConfigHdr);
2395 }
2396
2397 //
2398 // Free Pacakge data
2399 //
2400 if (HiiFormPackage != NULL) {
2401 FreePool (HiiFormPackage);
2402 }
2403
2404 if (PointerProgress != NULL) {
2405 if (*Request == NULL) {
2406 *PointerProgress = NULL;
2407 } else if (EFI_ERROR (Status)) {
2408 *PointerProgress = Progress;
2409 } else {
2410 *PointerProgress = *Request + StrLen (*Request);
2411 }
2412 }
2413
2414 return Status;
2415 }
2416
2417 /**
2418 This function gets the full request resp string by
2419 parsing IFR data in HII form packages.
2420
2421 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2422 instance.
2423 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2424 varstore data structure.
2425 @param Request Pointer to a null-terminated Unicode string in
2426 <ConfigRequest> format.
2427 @param RequestResp Pointer to a null-terminated Unicode string in
2428 <ConfigResp> format.
2429 @param AccessProgress On return, points to a character in the Request
2430 string. Points to the string's null terminator if
2431 request was successful. Points to the most recent
2432 & before the first failing name / value pair (or
2433 the beginning of the string if the failure is in
2434 the first name / value pair) if the request was
2435 not successful.
2436
2437 @retval EFI_SUCCESS The Results string is set to the full request string.
2438 And AltCfgResp contains all default value string.
2439 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2440 @retval EFI_INVALID_PARAMETER Request points to NULL.
2441
2442 **/
2443 EFI_STATUS
2444 GetConfigRespFromEfiVarStore (
2445 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2446 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
2447 IN EFI_STRING Request,
2448 OUT EFI_STRING *RequestResp,
2449 OUT EFI_STRING *AccessProgress
2450 )
2451 {
2452 EFI_STATUS Status;
2453 EFI_STRING VarStoreName;
2454 UINT8 *VarStore;
2455 UINTN BufferSize;
2456
2457 Status = EFI_SUCCESS;
2458 BufferSize = 0;
2459 VarStore = NULL;
2460 VarStoreName = NULL;
2461
2462 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
2463 if (VarStoreName == NULL) {
2464 Status = EFI_OUT_OF_RESOURCES;
2465 goto Done;
2466 }
2467 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
2468
2469
2470 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
2471 if (Status != EFI_BUFFER_TOO_SMALL) {
2472 goto Done;
2473 }
2474
2475 VarStore = AllocateZeroPool (BufferSize);
2476 ASSERT (VarStore != NULL);
2477 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
2478 if (EFI_ERROR (Status)) {
2479 goto Done;
2480 }
2481
2482 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
2483 if (EFI_ERROR (Status)) {
2484 goto Done;
2485 }
2486
2487 Done:
2488 if (VarStoreName != NULL) {
2489 FreePool (VarStoreName);
2490 }
2491
2492 if (VarStore != NULL) {
2493 FreePool (VarStore);
2494 }
2495
2496 return Status;
2497 }
2498
2499
2500 /**
2501 This function route the full request resp string for efi varstore.
2502
2503 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2504 instance.
2505 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2506 varstore data structure.
2507 @param RequestResp Pointer to a null-terminated Unicode string in
2508 <ConfigResp> format.
2509 @param Result Pointer to a null-terminated Unicode string in
2510 <ConfigResp> format.
2511
2512 @retval EFI_SUCCESS The Results string is set to the full request string.
2513 And AltCfgResp contains all default value string.
2514 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2515 @retval EFI_INVALID_PARAMETER Request points to NULL.
2516
2517 **/
2518 EFI_STATUS
2519 RouteConfigRespForEfiVarStore (
2520 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2521 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
2522 IN EFI_STRING RequestResp,
2523 OUT EFI_STRING *Result
2524 )
2525 {
2526 EFI_STATUS Status;
2527 EFI_STRING VarStoreName;
2528 UINT8 *VarStore;
2529 UINTN BufferSize;
2530 UINTN BlockSize;
2531
2532 Status = EFI_SUCCESS;
2533 BufferSize = 0;
2534 VarStore = NULL;
2535 VarStoreName = NULL;
2536
2537 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
2538 if (VarStoreName == NULL) {
2539 Status = EFI_OUT_OF_RESOURCES;
2540 goto Done;
2541 }
2542 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
2543
2544 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
2545 if (Status != EFI_BUFFER_TOO_SMALL) {
2546 goto Done;
2547 }
2548
2549 BlockSize = BufferSize;
2550 VarStore = AllocateZeroPool (BufferSize);
2551 ASSERT (VarStore != NULL);
2552 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
2553 if (EFI_ERROR (Status)) {
2554 goto Done;
2555 }
2556
2557 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
2558 if (EFI_ERROR (Status)) {
2559 goto Done;
2560 }
2561
2562 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
2563 if (EFI_ERROR (Status)) {
2564 goto Done;
2565 }
2566
2567 Done:
2568 if (VarStoreName != NULL) {
2569 FreePool (VarStoreName);
2570 }
2571
2572 if (VarStore != NULL) {
2573 FreePool (VarStore);
2574 }
2575
2576 return Status;
2577 }
2578
2579 /**
2580 This function allows a caller to extract the current configuration
2581 for one or more named elements from one or more drivers.
2582
2583 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2584 instance.
2585 @param Request A null-terminated Unicode string in
2586 <MultiConfigRequest> format.
2587 @param Progress On return, points to a character in the Request
2588 string. Points to the string's null terminator if
2589 request was successful. Points to the most recent
2590 & before the first failing name / value pair (or
2591 the beginning of the string if the failure is in
2592 the first name / value pair) if the request was
2593 not successful.
2594 @param Results Null-terminated Unicode string in
2595 <MultiConfigAltResp> format which has all values
2596 filled in for the names in the Request string.
2597 String to be allocated by the called function.
2598
2599 @retval EFI_SUCCESS The Results string is filled with the values
2600 corresponding to all requested names.
2601 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2602 results that must be stored awaiting possible
2603 future protocols.
2604 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2605 Progress set to the "G" in "GUID" of the routing
2606 header that doesn't match. Note: There is no
2607 requirement that all routing data be validated
2608 before any configuration extraction.
2609 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2610 parameter would result in this type of error. The
2611 Progress parameter is set to NULL.
2612 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2613 before the error or the beginning of the string.
2614 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2615 name in question.
2616
2617 **/
2618 EFI_STATUS
2619 EFIAPI
2620 HiiConfigRoutingExtractConfig (
2621 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2622 IN CONST EFI_STRING Request,
2623 OUT EFI_STRING *Progress,
2624 OUT EFI_STRING *Results
2625 )
2626 {
2627 HII_DATABASE_PRIVATE_DATA *Private;
2628 EFI_STRING StringPtr;
2629 EFI_STRING ConfigRequest;
2630 UINTN Length;
2631 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2632 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
2633 EFI_STATUS Status;
2634 LIST_ENTRY *Link;
2635 HII_DATABASE_RECORD *Database;
2636 UINT8 *DevicePathPkg;
2637 UINT8 *CurrentDevicePath;
2638 EFI_HANDLE DriverHandle;
2639 EFI_HII_HANDLE HiiHandle;
2640 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2641 EFI_STRING AccessProgress;
2642 EFI_STRING AccessResults;
2643 EFI_STRING DefaultResults;
2644 BOOLEAN FirstElement;
2645 BOOLEAN IfrDataParsedFlag;
2646 BOOLEAN IsEfiVarStore;
2647 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
2648
2649 if (This == NULL || Progress == NULL || Results == NULL) {
2650 return EFI_INVALID_PARAMETER;
2651 }
2652
2653 if (Request == NULL) {
2654 *Progress = NULL;
2655 return EFI_INVALID_PARAMETER;
2656 }
2657
2658 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2659 StringPtr = Request;
2660 *Progress = StringPtr;
2661 DefaultResults = NULL;
2662 ConfigRequest = NULL;
2663 Status = EFI_SUCCESS;
2664 AccessResults = NULL;
2665 AccessProgress = NULL;
2666 DevicePath = NULL;
2667 IfrDataParsedFlag = FALSE;
2668 IsEfiVarStore = FALSE;
2669 EfiVarStoreInfo = NULL;
2670
2671 //
2672 // The first element of <MultiConfigRequest> should be
2673 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2674 //
2675 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2676 return EFI_INVALID_PARAMETER;
2677 }
2678
2679 FirstElement = TRUE;
2680
2681 //
2682 // Allocate a fix length of memory to store Results. Reallocate memory for
2683 // Results if this fix length is insufficient.
2684 //
2685 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2686 if (*Results == NULL) {
2687 return EFI_OUT_OF_RESOURCES;
2688 }
2689
2690 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
2691 //
2692 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2693 // or most recent & before the error.
2694 //
2695 if (StringPtr == Request) {
2696 *Progress = StringPtr;
2697 } else {
2698 *Progress = StringPtr - 1;
2699 }
2700
2701 //
2702 // Process each <ConfigRequest> of <MultiConfigRequest>
2703 //
2704 Length = CalculateConfigStringLen (StringPtr);
2705 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
2706 if (ConfigRequest == NULL) {
2707 Status = EFI_OUT_OF_RESOURCES;
2708 goto Done;
2709 }
2710 *(ConfigRequest + Length) = 0;
2711
2712 //
2713 // Get the UEFI device path
2714 //
2715 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
2716 if (EFI_ERROR (Status)) {
2717 goto Done;
2718 }
2719
2720 //
2721 // Find driver which matches the routing data.
2722 //
2723 DriverHandle = NULL;
2724 HiiHandle = NULL;
2725 Database = NULL;
2726 for (Link = Private->DatabaseList.ForwardLink;
2727 Link != &Private->DatabaseList;
2728 Link = Link->ForwardLink
2729 ) {
2730 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2731 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2732 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2733 if (CompareMem (
2734 DevicePath,
2735 CurrentDevicePath,
2736 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
2737 ) == 0) {
2738 DriverHandle = Database->DriverHandle;
2739 HiiHandle = Database->Handle;
2740 break;
2741 }
2742 }
2743 }
2744
2745 //
2746 // Try to find driver handle by device path.
2747 //
2748 if (DriverHandle == NULL) {
2749 TempDevicePath = DevicePath;
2750 Status = gBS->LocateDevicePath (
2751 &gEfiDevicePathProtocolGuid,
2752 &TempDevicePath,
2753 &DriverHandle
2754 );
2755 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
2756 //
2757 // Routing data does not match any known driver.
2758 // Set Progress to the 'G' in "GUID" of the routing header.
2759 //
2760 *Progress = StringPtr;
2761 Status = EFI_NOT_FOUND;
2762 goto Done;
2763 }
2764 }
2765
2766 //
2767 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2768 //
2769 IfrDataParsedFlag = FALSE;
2770 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {
2771 //
2772 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2773 //
2774 IfrDataParsedFlag = TRUE;
2775 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
2776 if (EFI_ERROR (Status)) {
2777 //
2778 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2779 // Map it to the progress on <MultiConfigRequest> then return it.
2780 //
2781 *Progress = StrStr (StringPtr, AccessProgress);
2782 goto Done;
2783 }
2784 //
2785 // Not any request block is found.
2786 //
2787 if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {
2788 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
2789 goto NextConfigString;
2790 }
2791 }
2792
2793 //
2794 // Check whether this ConfigRequest is search from Efi varstore type storage.
2795 //
2796 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
2797 if (EFI_ERROR (Status)) {
2798 goto Done;
2799 }
2800
2801 if (IsEfiVarStore) {
2802 //
2803 // Call the GetVariable function to extract settings.
2804 //
2805 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
2806 FreePool (EfiVarStoreInfo);
2807 } else {
2808 //
2809 // Call corresponding ConfigAccess protocol to extract settings
2810 //
2811 Status = gBS->HandleProtocol (
2812 DriverHandle,
2813 &gEfiHiiConfigAccessProtocolGuid,
2814 (VOID **) &ConfigAccess
2815 );
2816 ASSERT_EFI_ERROR (Status);
2817
2818 Status = ConfigAccess->ExtractConfig (
2819 ConfigAccess,
2820 ConfigRequest,
2821 &AccessProgress,
2822 &AccessResults
2823 );
2824 }
2825 if (EFI_ERROR (Status)) {
2826 //
2827 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2828 // Map it to the progress on <MultiConfigRequest> then return it.
2829 //
2830 *Progress = StrStr (StringPtr, AccessProgress);
2831 goto Done;
2832 }
2833
2834 //
2835 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2836 // which seperates the first <ConfigAltResp> and the following ones.
2837 //
2838 ASSERT (*AccessProgress == 0);
2839
2840 //
2841 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2842 //
2843 if (!IfrDataParsedFlag && HiiHandle != NULL) {
2844 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
2845 ASSERT_EFI_ERROR (Status);
2846 }
2847
2848 FreePool (DevicePath);
2849 DevicePath = NULL;
2850
2851 if (DefaultResults != NULL) {
2852 Status = MergeDefaultString (&AccessResults, DefaultResults);
2853 ASSERT_EFI_ERROR (Status);
2854 FreePool (DefaultResults);
2855 DefaultResults = NULL;
2856 }
2857
2858 NextConfigString:
2859 if (!FirstElement) {
2860 Status = AppendToMultiString (Results, L"&");
2861 ASSERT_EFI_ERROR (Status);
2862 }
2863
2864 Status = AppendToMultiString (Results, AccessResults);
2865 ASSERT_EFI_ERROR (Status);
2866
2867 FirstElement = FALSE;
2868
2869 FreePool (AccessResults);
2870 AccessResults = NULL;
2871 FreePool (ConfigRequest);
2872 ConfigRequest = NULL;
2873
2874 //
2875 // Go to next <ConfigRequest> (skip '&').
2876 //
2877 StringPtr += Length;
2878 if (*StringPtr == 0) {
2879 *Progress = StringPtr;
2880 break;
2881 }
2882
2883 StringPtr++;
2884 }
2885
2886 Done:
2887 if (EFI_ERROR (Status)) {
2888 FreePool (*Results);
2889 *Results = NULL;
2890 }
2891
2892 if (ConfigRequest != NULL) {
2893 FreePool (ConfigRequest);
2894 }
2895
2896 if (AccessResults != NULL) {
2897 FreePool (AccessResults);
2898 }
2899
2900 if (DefaultResults != NULL) {
2901 FreePool (DefaultResults);
2902 }
2903
2904 if (DevicePath != NULL) {
2905 FreePool (DevicePath);
2906 }
2907
2908 return Status;
2909 }
2910
2911
2912 /**
2913 This function allows the caller to request the current configuration for the
2914 entirety of the current HII database and returns the data in a
2915 null-terminated Unicode string.
2916
2917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2918 instance.
2919 @param Results Null-terminated Unicode string in
2920 <MultiConfigAltResp> format which has all values
2921 filled in for the names in the Request string.
2922 String to be allocated by the called function.
2923 De-allocation is up to the caller.
2924
2925 @retval EFI_SUCCESS The Results string is filled with the values
2926 corresponding to all requested names.
2927 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2928 results that must be stored awaiting possible
2929 future protocols.
2930 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2931 parameter would result in this type of error.
2932
2933 **/
2934 EFI_STATUS
2935 EFIAPI
2936 HiiConfigRoutingExportConfig (
2937 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2938 OUT EFI_STRING *Results
2939 )
2940 {
2941 EFI_STATUS Status;
2942 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2943 EFI_STRING AccessResults;
2944 EFI_STRING Progress;
2945 EFI_STRING StringPtr;
2946 EFI_STRING ConfigRequest;
2947 UINTN Index;
2948 EFI_HANDLE *ConfigAccessHandles;
2949 UINTN NumberConfigAccessHandles;
2950 BOOLEAN FirstElement;
2951 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2952 EFI_HII_HANDLE HiiHandle;
2953 EFI_STRING DefaultResults;
2954 HII_DATABASE_PRIVATE_DATA *Private;
2955 LIST_ENTRY *Link;
2956 HII_DATABASE_RECORD *Database;
2957 UINT8 *DevicePathPkg;
2958 UINT8 *CurrentDevicePath;
2959 BOOLEAN IfrDataParsedFlag;
2960
2961 if (This == NULL || Results == NULL) {
2962 return EFI_INVALID_PARAMETER;
2963 }
2964
2965 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2966
2967 //
2968 // Allocate a fix length of memory to store Results. Reallocate memory for
2969 // Results if this fix length is insufficient.
2970 //
2971 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2972 if (*Results == NULL) {
2973 return EFI_OUT_OF_RESOURCES;
2974 }
2975
2976 NumberConfigAccessHandles = 0;
2977 Status = gBS->LocateHandleBuffer (
2978 ByProtocol,
2979 &gEfiHiiConfigAccessProtocolGuid,
2980 NULL,
2981 &NumberConfigAccessHandles,
2982 &ConfigAccessHandles
2983 );
2984 if (EFI_ERROR (Status)) {
2985 return Status;
2986 }
2987
2988 FirstElement = TRUE;
2989
2990 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
2991 Status = gBS->HandleProtocol (
2992 ConfigAccessHandles[Index],
2993 &gEfiHiiConfigAccessProtocolGuid,
2994 (VOID **) &ConfigAccess
2995 );
2996 if (EFI_ERROR (Status)) {
2997 continue;
2998 }
2999
3000 //
3001 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3002 //
3003 IfrDataParsedFlag = FALSE;
3004 Progress = NULL;
3005 HiiHandle = NULL;
3006 DefaultResults = NULL;
3007 Database = NULL;
3008 ConfigRequest = NULL;
3009 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
3010 if (DevicePath != NULL) {
3011 for (Link = Private->DatabaseList.ForwardLink;
3012 Link != &Private->DatabaseList;
3013 Link = Link->ForwardLink
3014 ) {
3015 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3016 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
3017 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
3018 if (CompareMem (
3019 DevicePath,
3020 CurrentDevicePath,
3021 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
3022 ) == 0) {
3023 HiiHandle = Database->Handle;
3024 break;
3025 }
3026 }
3027 }
3028 }
3029
3030 Status = ConfigAccess->ExtractConfig (
3031 ConfigAccess,
3032 NULL,
3033 &Progress,
3034 &AccessResults
3035 );
3036 if (EFI_ERROR (Status)) {
3037 //
3038 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3039 //
3040 if (HiiHandle != NULL && DevicePath != NULL) {
3041 IfrDataParsedFlag = TRUE;
3042 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
3043 //
3044 // Get the full request string to get the Current setting again.
3045 //
3046 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
3047 Status = ConfigAccess->ExtractConfig (
3048 ConfigAccess,
3049 ConfigRequest,
3050 &Progress,
3051 &AccessResults
3052 );
3053 FreePool (ConfigRequest);
3054 } else {
3055 Status = EFI_NOT_FOUND;
3056 }
3057 }
3058 }
3059
3060 if (!EFI_ERROR (Status)) {
3061 //
3062 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3063 //
3064 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
3065 StringPtr = StrStr (AccessResults, L"&GUID=");
3066 if (StringPtr != NULL) {
3067 *StringPtr = 0;
3068 }
3069 if (StrStr (AccessResults, L"&OFFSET=") != NULL) {
3070 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
3071 ASSERT_EFI_ERROR (Status);
3072 }
3073 if (StringPtr != NULL) {
3074 *StringPtr = L'&';
3075 }
3076 }
3077 //
3078 // Merge the default sting from IFR code into the got setting from driver.
3079 //
3080 if (DefaultResults != NULL) {
3081 Status = MergeDefaultString (&AccessResults, DefaultResults);
3082 ASSERT_EFI_ERROR (Status);
3083 FreePool (DefaultResults);
3084 DefaultResults = NULL;
3085 }
3086
3087 //
3088 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3089 // which seperates the first <ConfigAltResp> and the following ones.
3090 //
3091 if (!FirstElement) {
3092 Status = AppendToMultiString (Results, L"&");
3093 ASSERT_EFI_ERROR (Status);
3094 }
3095
3096 Status = AppendToMultiString (Results, AccessResults);
3097 ASSERT_EFI_ERROR (Status);
3098
3099 FirstElement = FALSE;
3100
3101 FreePool (AccessResults);
3102 AccessResults = NULL;
3103 }
3104 }
3105 FreePool (ConfigAccessHandles);
3106
3107 return EFI_SUCCESS;
3108 }
3109
3110
3111 /**
3112 This function processes the results of processing forms and routes it to the
3113 appropriate handlers or storage.
3114
3115 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3116 instance.
3117 @param Configuration A null-terminated Unicode string in
3118 <MulltiConfigResp> format.
3119 @param Progress A pointer to a string filled in with the offset of
3120 the most recent & before the first failing name /
3121 value pair (or the beginning of the string if the
3122 failure is in the first name / value pair) or the
3123 terminating NULL if all was successful.
3124
3125 @retval EFI_SUCCESS The results have been distributed or are awaiting
3126 distribution.
3127 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3128 results that must be stored awaiting possible
3129 future protocols.
3130 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3131 would result in this type of error.
3132 @retval EFI_NOT_FOUND Target for the specified routing data was not
3133 found.
3134
3135 **/
3136 EFI_STATUS
3137 EFIAPI
3138 HiiConfigRoutingRouteConfig (
3139 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3140 IN CONST EFI_STRING Configuration,
3141 OUT EFI_STRING *Progress
3142 )
3143 {
3144 HII_DATABASE_PRIVATE_DATA *Private;
3145 EFI_STRING StringPtr;
3146 EFI_STRING ConfigResp;
3147 UINTN Length;
3148 EFI_STATUS Status;
3149 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3150 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
3151 LIST_ENTRY *Link;
3152 HII_DATABASE_RECORD *Database;
3153 UINT8 *DevicePathPkg;
3154 UINT8 *CurrentDevicePath;
3155 EFI_HANDLE DriverHandle;
3156 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
3157 EFI_STRING AccessProgress;
3158 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
3159 BOOLEAN IsEfiVarstore;
3160
3161 if (This == NULL || Progress == NULL) {
3162 return EFI_INVALID_PARAMETER;
3163 }
3164
3165 if (Configuration == NULL) {
3166 *Progress = NULL;
3167 return EFI_INVALID_PARAMETER;
3168 }
3169
3170 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3171 StringPtr = Configuration;
3172 *Progress = StringPtr;
3173 Database = NULL;
3174 AccessProgress = NULL;
3175 EfiVarStoreInfo= NULL;
3176 IsEfiVarstore = FALSE;
3177
3178 //
3179 // The first element of <MultiConfigResp> should be
3180 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3181 //
3182 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3183 return EFI_INVALID_PARAMETER;
3184 }
3185
3186 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
3187 //
3188 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
3189 // or most recent & before the error.
3190 //
3191 if (StringPtr == Configuration) {
3192 *Progress = StringPtr;
3193 } else {
3194 *Progress = StringPtr - 1;
3195 }
3196
3197 //
3198 // Process each <ConfigResp> of <MultiConfigResp>
3199 //
3200 Length = CalculateConfigStringLen (StringPtr);
3201 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
3202 if (ConfigResp == NULL) {
3203 return EFI_OUT_OF_RESOURCES;
3204 }
3205 //
3206 // Append '\0' to the end of ConfigRequest
3207 //
3208 *(ConfigResp + Length) = 0;
3209
3210 //
3211 // Get the UEFI device path
3212 //
3213 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
3214 if (EFI_ERROR (Status)) {
3215 FreePool (ConfigResp);
3216 return Status;
3217 }
3218
3219 //
3220 // Find driver which matches the routing data.
3221 //
3222 DriverHandle = NULL;
3223 for (Link = Private->DatabaseList.ForwardLink;
3224 Link != &Private->DatabaseList;
3225 Link = Link->ForwardLink
3226 ) {
3227 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3228
3229 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
3230 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
3231 if (CompareMem (
3232 DevicePath,
3233 CurrentDevicePath,
3234 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
3235 ) == 0) {
3236 DriverHandle = Database->DriverHandle;
3237 break;
3238 }
3239 }
3240 }
3241
3242 //
3243 // Try to find driver handle by device path.
3244 //
3245 if (DriverHandle == NULL) {
3246 TempDevicePath = DevicePath;
3247 Status = gBS->LocateDevicePath (
3248 &gEfiDevicePathProtocolGuid,
3249 &TempDevicePath,
3250 &DriverHandle
3251 );
3252 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
3253 //
3254 // Routing data does not match any known driver.
3255 // Set Progress to the 'G' in "GUID" of the routing header.
3256 //
3257 FreePool (DevicePath);
3258 *Progress = StringPtr;
3259 FreePool (ConfigResp);
3260 return EFI_NOT_FOUND;
3261 }
3262 }
3263
3264 FreePool (DevicePath);
3265
3266 //
3267 // Check whether this ConfigRequest is search from Efi varstore type storage.
3268 //
3269 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
3270 if (EFI_ERROR (Status)) {
3271 return Status;
3272 }
3273
3274 if (IsEfiVarstore) {
3275 //
3276 // Call the SetVariable function to route settings.
3277 //
3278 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
3279 FreePool (EfiVarStoreInfo);
3280 } else {
3281 //
3282 // Call corresponding ConfigAccess protocol to route settings
3283 //
3284 Status = gBS->HandleProtocol (
3285 DriverHandle,
3286 &gEfiHiiConfigAccessProtocolGuid,
3287 (VOID **) &ConfigAccess
3288 );
3289 ASSERT_EFI_ERROR (Status);
3290
3291 Status = ConfigAccess->RouteConfig (
3292 ConfigAccess,
3293 ConfigResp,
3294 &AccessProgress
3295 );
3296 }
3297 if (EFI_ERROR (Status)) {
3298 //
3299 // AccessProgress indicates the parsing progress on <ConfigResp>.
3300 // Map it to the progress on <MultiConfigResp> then return it.
3301 //
3302 *Progress = StrStr (StringPtr, AccessProgress);
3303
3304 FreePool (ConfigResp);
3305 return Status;
3306 }
3307
3308 FreePool (ConfigResp);
3309 ConfigResp = NULL;
3310
3311 //
3312 // Go to next <ConfigResp> (skip '&').
3313 //
3314 StringPtr += Length;
3315 if (*StringPtr == 0) {
3316 *Progress = StringPtr;
3317 break;
3318 }
3319
3320 StringPtr++;
3321
3322 }
3323
3324 return EFI_SUCCESS;
3325 }
3326
3327
3328 /**
3329 This helper function is to be called by drivers to map configuration data
3330 stored in byte array ("block") formats such as UEFI Variables into current
3331 configuration strings.
3332
3333 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3334 instance.
3335 @param ConfigRequest A null-terminated Unicode string in
3336 <ConfigRequest> format.
3337 @param Block Array of bytes defining the block's configuration.
3338 @param BlockSize Length in bytes of Block.
3339 @param Config Filled-in configuration string. String allocated
3340 by the function. Returned only if call is
3341 successful. It is <ConfigResp> string format.
3342 @param Progress A pointer to a string filled in with the offset of
3343 the most recent & before the first failing
3344 name/value pair (or the beginning of the string if
3345 the failure is in the first name / value pair) or
3346 the terminating NULL if all was successful.
3347
3348 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3349 terminator at the end of the ConfigRequest
3350 string.
3351 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3352 points to the first character of ConfigRequest.
3353 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
3354 Block parameter would result in this type of
3355 error. Progress points to the first character of
3356 ConfigRequest.
3357 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3358 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
3359 Block is left updated and Progress points at
3360 the "&" preceding the first non-<BlockName>.
3361
3362 **/
3363 EFI_STATUS
3364 EFIAPI
3365 HiiBlockToConfig (
3366 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3367 IN CONST EFI_STRING ConfigRequest,
3368 IN CONST UINT8 *Block,
3369 IN CONST UINTN BlockSize,
3370 OUT EFI_STRING *Config,
3371 OUT EFI_STRING *Progress
3372 )
3373 {
3374 HII_DATABASE_PRIVATE_DATA *Private;
3375 EFI_STRING StringPtr;
3376 UINTN Length;
3377 EFI_STATUS Status;
3378 EFI_STRING TmpPtr;
3379 UINT8 *TmpBuffer;
3380 UINTN Offset;
3381 UINTN Width;
3382 UINT8 *Value;
3383 EFI_STRING ValueStr;
3384 EFI_STRING ConfigElement;
3385 UINTN Index;
3386 UINT8 *TemBuffer;
3387 CHAR16 *TemString;
3388 CHAR16 TemChar;
3389
3390 if (This == NULL || Progress == NULL || Config == NULL) {
3391 return EFI_INVALID_PARAMETER;
3392 }
3393
3394 if (Block == NULL || ConfigRequest == NULL) {
3395 *Progress = ConfigRequest;
3396 return EFI_INVALID_PARAMETER;
3397 }
3398
3399
3400 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3401 ASSERT (Private != NULL);
3402
3403 StringPtr = ConfigRequest;
3404 ValueStr = NULL;
3405 Value = NULL;
3406 ConfigElement = NULL;
3407
3408 //
3409 // Allocate a fix length of memory to store Results. Reallocate memory for
3410 // Results if this fix length is insufficient.
3411 //
3412 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
3413 if (*Config == NULL) {
3414 return EFI_OUT_OF_RESOURCES;
3415 }
3416
3417 //
3418 // Jump <ConfigHdr>
3419 //
3420 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3421 *Progress = StringPtr;
3422 Status = EFI_INVALID_PARAMETER;
3423 goto Exit;
3424 }
3425 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
3426 StringPtr++;
3427 }
3428 if (*StringPtr == 0) {
3429 *Progress = StringPtr - 1;
3430 Status = EFI_INVALID_PARAMETER;
3431 goto Exit;
3432 }
3433
3434 while (*StringPtr != L'&' && *StringPtr != 0) {
3435 StringPtr++;
3436 }
3437 if (*StringPtr == 0) {
3438 *Progress = StringPtr;
3439 Status = EFI_SUCCESS;
3440
3441 AppendToMultiString(Config, ConfigRequest);
3442 HiiToLower (*Config);
3443
3444 goto Exit;
3445 }
3446 //
3447 // Skip '&'
3448 //
3449 StringPtr++;
3450
3451 //
3452 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3453 //
3454 TemChar = *StringPtr;
3455 *StringPtr = '\0';
3456 AppendToMultiString(Config, ConfigRequest);
3457 *StringPtr = TemChar;
3458
3459 //
3460 // Parse each <RequestElement> if exists
3461 // Only <BlockName> format is supported by this help function.
3462 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3463 //
3464 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
3465 //
3466 // Back up the header of one <BlockName>
3467 //
3468 TmpPtr = StringPtr;
3469
3470 StringPtr += StrLen (L"OFFSET=");
3471 //
3472 // Get Offset
3473 //
3474 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3475 if (EFI_ERROR (Status)) {
3476 *Progress = ConfigRequest;
3477 goto Exit;
3478 }
3479 Offset = 0;
3480 CopyMem (
3481 &Offset,
3482 TmpBuffer,
3483 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3484 );
3485 FreePool (TmpBuffer);
3486
3487 StringPtr += Length;
3488 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3489 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
3490 Status = EFI_INVALID_PARAMETER;
3491 goto Exit;
3492 }
3493 StringPtr += StrLen (L"&WIDTH=");
3494
3495 //
3496 // Get Width
3497 //
3498 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3499 if (EFI_ERROR (Status)) {
3500 *Progress = ConfigRequest;
3501 goto Exit;
3502 }
3503 Width = 0;
3504 CopyMem (
3505 &Width,
3506 TmpBuffer,
3507 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3508 );
3509 FreePool (TmpBuffer);
3510
3511 StringPtr += Length;
3512 if (*StringPtr != 0 && *StringPtr != L'&') {
3513 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
3514 Status = EFI_INVALID_PARAMETER;
3515 goto Exit;
3516 }
3517
3518 //
3519 // Calculate Value and convert it to hex string.
3520 //
3521 if (Offset + Width > BlockSize) {
3522 *Progress = StringPtr;
3523 Status = EFI_DEVICE_ERROR;
3524 goto Exit;
3525 }
3526
3527 Value = (UINT8 *) AllocateZeroPool (Width);
3528 if (Value == NULL) {
3529 *Progress = ConfigRequest;
3530 Status = EFI_OUT_OF_RESOURCES;
3531 goto Exit;
3532 }
3533
3534 CopyMem (Value, (UINT8 *) Block + Offset, Width);
3535
3536 Length = Width * 2 + 1;
3537 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
3538 if (ValueStr == NULL) {
3539 *Progress = ConfigRequest;
3540 Status = EFI_OUT_OF_RESOURCES;
3541 goto Exit;
3542 }
3543
3544 TemString = ValueStr;
3545 TemBuffer = Value + Width - 1;
3546 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
3547 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
3548 }
3549
3550 FreePool (Value);
3551 Value = NULL;
3552
3553 //
3554 // Build a ConfigElement
3555 //
3556 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
3557 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
3558 if (ConfigElement == NULL) {
3559 Status = EFI_OUT_OF_RESOURCES;
3560 goto Exit;
3561 }
3562 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
3563 if (*StringPtr == 0) {
3564 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
3565 }
3566 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
3567 StrCat (ConfigElement, L"VALUE=");
3568 StrCat (ConfigElement, ValueStr);
3569
3570 AppendToMultiString (Config, ConfigElement);
3571
3572 FreePool (ConfigElement);
3573 FreePool (ValueStr);
3574 ConfigElement = NULL;
3575 ValueStr = NULL;
3576
3577 //
3578 // If '\0', parsing is finished. Otherwise skip '&' to continue
3579 //
3580 if (*StringPtr == 0) {
3581 break;
3582 }
3583 AppendToMultiString (Config, L"&");
3584 StringPtr++;
3585
3586 }
3587
3588 if (*StringPtr != 0) {
3589 *Progress = StringPtr - 1;
3590 Status = EFI_INVALID_PARAMETER;
3591 goto Exit;
3592 }
3593
3594 HiiToLower (*Config);
3595 *Progress = StringPtr;
3596 return EFI_SUCCESS;
3597
3598 Exit:
3599 if (*Config != NULL) {
3600 FreePool (*Config);
3601 *Config = NULL;
3602 }
3603 if (ValueStr != NULL) {
3604 FreePool (ValueStr);
3605 }
3606 if (Value != NULL) {
3607 FreePool (Value);
3608 }
3609 if (ConfigElement != NULL) {
3610 FreePool (ConfigElement);
3611 }
3612
3613 return Status;
3614
3615 }
3616
3617
3618 /**
3619 This helper function is to be called by drivers to map configuration strings
3620 to configurations stored in byte array ("block") formats such as UEFI Variables.
3621
3622 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3623 instance.
3624 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3625 format.
3626 @param Block A possibly null array of bytes representing the
3627 current block. Only bytes referenced in the
3628 ConfigResp string in the block are modified. If
3629 this parameter is null or if the *BlockSize
3630 parameter is (on input) shorter than required by
3631 the Configuration string, only the BlockSize
3632 parameter is updated and an appropriate status
3633 (see below) is returned.
3634 @param BlockSize The length of the Block in units of UINT8. On
3635 input, this is the size of the Block. On output,
3636 if successful, contains the index of the last
3637 modified byte in the Block.
3638 @param Progress On return, points to an element of the ConfigResp
3639 string filled in with the offset of the most
3640 recent '&' before the first failing name / value
3641 pair (or the beginning of the string if the
3642 failure is in the first name / value pair) or the
3643 terminating NULL if all was successful.
3644
3645 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3646 terminator at the end of the ConfigResp string.
3647 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3648 points to the first character of ConfigResp.
3649 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3650 Block parameter would result in this type of
3651 error. Progress points to the first character of
3652 ConfigResp.
3653 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3654 value pair. Block is left updated and
3655 Progress points at the '&' preceding the first
3656 non-<BlockName>.
3657 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3658 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3659 Progress points to the "G" in "GUID" of the errant
3660 routing data.
3661
3662 **/
3663 EFI_STATUS
3664 EFIAPI
3665 HiiConfigToBlock (
3666 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3667 IN CONST EFI_STRING ConfigResp,
3668 IN OUT UINT8 *Block,
3669 IN OUT UINTN *BlockSize,
3670 OUT EFI_STRING *Progress
3671 )
3672 {
3673 HII_DATABASE_PRIVATE_DATA *Private;
3674 EFI_STRING StringPtr;
3675 UINTN Length;
3676 EFI_STATUS Status;
3677 UINT8 *TmpBuffer;
3678 UINTN Offset;
3679 UINTN Width;
3680 UINT8 *Value;
3681 UINTN BufferSize;
3682 UINTN MaxBlockSize;
3683
3684 if (This == NULL || BlockSize == NULL || Progress == NULL) {
3685 return EFI_INVALID_PARAMETER;
3686 }
3687
3688 *Progress = ConfigResp;
3689 if (ConfigResp == NULL) {
3690 return EFI_INVALID_PARAMETER;
3691 }
3692
3693 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3694 ASSERT (Private != NULL);
3695
3696 StringPtr = ConfigResp;
3697 BufferSize = *BlockSize;
3698 Value = NULL;
3699 MaxBlockSize = 0;
3700
3701 //
3702 // Jump <ConfigHdr>
3703 //
3704 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3705 *Progress = StringPtr;
3706 Status = EFI_INVALID_PARAMETER;
3707 goto Exit;
3708 }
3709 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
3710 StringPtr++;
3711 }
3712 if (*StringPtr == 0) {
3713 *Progress = StringPtr;
3714 Status = EFI_INVALID_PARAMETER;
3715 goto Exit;
3716 }
3717
3718 while (*StringPtr != L'&' && *StringPtr != 0) {
3719 StringPtr++;
3720 }
3721 if (*StringPtr == 0) {
3722 *Progress = StringPtr;
3723 Status = EFI_INVALID_PARAMETER;
3724 goto Exit;
3725 }
3726 //
3727 // Skip '&'
3728 //
3729 StringPtr++;
3730
3731 //
3732 // Parse each <ConfigElement> if exists
3733 // Only <BlockConfig> format is supported by this help function.
3734 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3735 //
3736 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
3737 StringPtr += StrLen (L"OFFSET=");
3738 //
3739 // Get Offset
3740 //
3741 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3742 if (EFI_ERROR (Status)) {
3743 *Progress = ConfigResp;
3744 goto Exit;
3745 }
3746 Offset = 0;
3747 CopyMem (
3748 &Offset,
3749 TmpBuffer,
3750 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3751 );
3752 FreePool (TmpBuffer);
3753
3754 StringPtr += Length;
3755 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3756 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
3757 Status = EFI_INVALID_PARAMETER;
3758 goto Exit;
3759 }
3760 StringPtr += StrLen (L"&WIDTH=");
3761
3762 //
3763 // Get Width
3764 //
3765 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3766 if (EFI_ERROR (Status)) {
3767 *Progress = ConfigResp;
3768 goto Exit;
3769 }
3770 Width = 0;
3771 CopyMem (
3772 &Width,
3773 TmpBuffer,
3774 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3775 );
3776 FreePool (TmpBuffer);
3777
3778 StringPtr += Length;
3779 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
3780 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
3781 Status = EFI_INVALID_PARAMETER;
3782 goto Exit;
3783 }
3784 StringPtr += StrLen (L"&VALUE=");
3785
3786 //
3787 // Get Value
3788 //
3789 Status = GetValueOfNumber (StringPtr, &Value, &Length);
3790 if (EFI_ERROR (Status)) {
3791 *Progress = ConfigResp;
3792 goto Exit;
3793 }
3794
3795 StringPtr += Length;
3796 if (*StringPtr != 0 && *StringPtr != L'&') {
3797 *Progress = StringPtr - Length - 7;
3798 Status = EFI_INVALID_PARAMETER;
3799 goto Exit;
3800 }
3801
3802 //
3803 // Update the Block with configuration info
3804 //
3805 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
3806 CopyMem (Block + Offset, Value, Width);
3807 }
3808 if (Offset + Width > MaxBlockSize) {
3809 MaxBlockSize = Offset + Width;
3810 }
3811
3812 FreePool (Value);
3813 Value = NULL;
3814
3815 //
3816 // If '\0', parsing is finished. Otherwise skip '&' to continue
3817 //
3818 if (*StringPtr == 0) {
3819 break;
3820 }
3821
3822 StringPtr++;
3823 }
3824
3825 //
3826 // The input string is ConfigAltResp format.
3827 //
3828 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {
3829 *Progress = StringPtr - 1;
3830 Status = EFI_INVALID_PARAMETER;
3831 goto Exit;
3832 }
3833
3834 *Progress = StringPtr + StrLen (StringPtr);
3835 *BlockSize = MaxBlockSize - 1;
3836
3837 if (MaxBlockSize > BufferSize) {
3838 *BlockSize = MaxBlockSize;
3839 if (Block != NULL) {
3840 return EFI_DEVICE_ERROR;
3841 }
3842 }
3843
3844 if (Block == NULL) {
3845 *Progress = ConfigResp;
3846 return EFI_INVALID_PARAMETER;
3847 }
3848
3849 return EFI_SUCCESS;
3850
3851 Exit:
3852
3853 if (Value != NULL) {
3854 FreePool (Value);
3855 }
3856 return Status;
3857 }
3858
3859
3860 /**
3861 This helper function is to be called by drivers to extract portions of
3862 a larger configuration string.
3863
3864 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3865 instance.
3866 @param Configuration A null-terminated Unicode string in
3867 <MultiConfigAltResp> format.
3868 @param Guid A pointer to the GUID value to search for in the
3869 routing portion of the ConfigResp string when
3870 retrieving the requested data. If Guid is NULL,
3871 then all GUID values will be searched for.
3872 @param Name A pointer to the NAME value to search for in the
3873 routing portion of the ConfigResp string when
3874 retrieving the requested data. If Name is NULL,
3875 then all Name values will be searched for.
3876 @param DevicePath A pointer to the PATH value to search for in the
3877 routing portion of the ConfigResp string when
3878 retrieving the requested data. If DevicePath is
3879 NULL, then all DevicePath values will be searched
3880 for.
3881 @param AltCfgId A pointer to the ALTCFG value to search for in the
3882 routing portion of the ConfigResp string when
3883 retrieving the requested data. If this parameter
3884 is NULL, then the current setting will be
3885 retrieved.
3886 @param AltCfgResp A pointer to a buffer which will be allocated by
3887 the function which contains the retrieved string
3888 as requested. This buffer is only allocated if
3889 the call was successful. It is <ConfigResp> format.
3890
3891 @retval EFI_SUCCESS The request succeeded. The requested data was
3892 extracted and placed in the newly allocated
3893 AltCfgResp buffer.
3894 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3895 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3896 @retval EFI_NOT_FOUND Target for the specified routing data was not
3897 found.
3898
3899 **/
3900 EFI_STATUS
3901 EFIAPI
3902 HiiGetAltCfg (
3903 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3904 IN CONST EFI_STRING Configuration,
3905 IN CONST EFI_GUID *Guid,
3906 IN CONST EFI_STRING Name,
3907 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3908 IN CONST UINT16 *AltCfgId,
3909 OUT EFI_STRING *AltCfgResp
3910 )
3911 {
3912 EFI_STATUS Status;
3913 EFI_STRING StringPtr;
3914 EFI_STRING HdrStart;
3915 EFI_STRING HdrEnd;
3916 EFI_STRING TmpPtr;
3917 UINTN Length;
3918 EFI_STRING GuidStr;
3919 EFI_STRING NameStr;
3920 EFI_STRING PathStr;
3921 EFI_STRING AltIdStr;
3922 EFI_STRING Result;
3923 BOOLEAN GuidFlag;
3924 BOOLEAN NameFlag;
3925 BOOLEAN PathFlag;
3926
3927 HdrStart = NULL;
3928 HdrEnd = NULL;
3929 GuidStr = NULL;
3930 NameStr = NULL;
3931 PathStr = NULL;
3932 AltIdStr = NULL;
3933 Result = NULL;
3934 GuidFlag = FALSE;
3935 NameFlag = FALSE;
3936 PathFlag = FALSE;
3937
3938 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
3939 return EFI_INVALID_PARAMETER;
3940 }
3941
3942 StringPtr = Configuration;
3943 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3944 return EFI_INVALID_PARAMETER;
3945 }
3946
3947 //
3948 // Generate the sub string for later matching.
3949 //
3950 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
3951 GenerateSubStr (
3952 L"PATH=",
3953 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3954 (VOID *) DevicePath,
3955 1,
3956 &PathStr
3957 );
3958 if (AltCfgId != NULL) {
3959 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
3960 }
3961 if (Name != NULL) {
3962 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
3963 } else {
3964 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3965 }
3966
3967 while (*StringPtr != 0) {
3968 //
3969 // Try to match the GUID
3970 //
3971 if (!GuidFlag) {
3972 TmpPtr = StrStr (StringPtr, GuidStr);
3973 if (TmpPtr == NULL) {
3974 Status = EFI_NOT_FOUND;
3975 goto Exit;
3976 }
3977 HdrStart = TmpPtr;
3978
3979 //
3980 // Jump to <NameHdr>
3981 //
3982 if (Guid != NULL) {
3983 StringPtr = TmpPtr + StrLen (GuidStr);
3984 } else {
3985 StringPtr = StrStr (TmpPtr, L"NAME=");
3986 if (StringPtr == NULL) {
3987 Status = EFI_NOT_FOUND;
3988 goto Exit;
3989 }
3990 }
3991 GuidFlag = TRUE;
3992 }
3993
3994 //
3995 // Try to match the NAME
3996 //
3997 if (GuidFlag && !NameFlag) {
3998 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
3999 GuidFlag = FALSE;
4000 } else {
4001 //
4002 // Jump to <PathHdr>
4003 //
4004 if (Name != NULL) {
4005 StringPtr += StrLen (NameStr);
4006 } else {
4007 StringPtr = StrStr (StringPtr, L"PATH=");
4008 if (StringPtr == NULL) {
4009 Status = EFI_NOT_FOUND;
4010 goto Exit;
4011 }
4012 }
4013 NameFlag = TRUE;
4014 }
4015 }
4016
4017 //
4018 // Try to match the DevicePath
4019 //
4020 if (GuidFlag && NameFlag && !PathFlag) {
4021 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
4022 GuidFlag = FALSE;
4023 NameFlag = FALSE;
4024 } else {
4025 //
4026 // Jump to '&' before <DescHdr> or <ConfigBody>
4027 //
4028 if (DevicePath != NULL) {
4029 StringPtr += StrLen (PathStr);
4030 } else {
4031 StringPtr = StrStr (StringPtr, L"&");
4032 if (StringPtr == NULL) {
4033 Status = EFI_NOT_FOUND;
4034 goto Exit;
4035 }
4036 StringPtr ++;
4037 }
4038 PathFlag = TRUE;
4039 HdrEnd = StringPtr;
4040 }
4041 }
4042
4043 //
4044 // Try to match the AltCfgId
4045 //
4046 if (GuidFlag && NameFlag && PathFlag) {
4047 if (AltCfgId == NULL) {
4048 //
4049 // Return Current Setting when AltCfgId is NULL.
4050 //
4051 Status = OutputConfigBody (StringPtr, &Result);
4052 goto Exit;
4053 }
4054 //
4055 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4056 //
4057 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
4058 GuidFlag = FALSE;
4059 NameFlag = FALSE;
4060 PathFlag = FALSE;
4061 } else {
4062 //
4063 // Skip AltIdStr and &
4064 //
4065 StringPtr = StringPtr + StrLen (AltIdStr);
4066 Status = OutputConfigBody (StringPtr, &Result);
4067 goto Exit;
4068 }
4069 }
4070 }
4071
4072 Status = EFI_NOT_FOUND;
4073
4074 Exit:
4075 *AltCfgResp = NULL;
4076 if (!EFI_ERROR (Status) && (Result != NULL)) {
4077 //
4078 // Copy the <ConfigHdr> and <ConfigBody>
4079 //
4080 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
4081 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
4082 if (*AltCfgResp == NULL) {
4083 Status = EFI_OUT_OF_RESOURCES;
4084 } else {
4085 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
4086 StrCat (*AltCfgResp, Result);
4087 Status = EFI_SUCCESS;
4088 }
4089 }
4090
4091 if (GuidStr != NULL) {
4092 FreePool (GuidStr);
4093 }
4094 if (NameStr != NULL) {
4095 FreePool (NameStr);
4096 }
4097 if (PathStr != NULL) {
4098 FreePool (PathStr);
4099 }
4100 if (AltIdStr != NULL) {
4101 FreePool (AltIdStr);
4102 }
4103 if (Result != NULL) {
4104 FreePool (Result);
4105 }
4106
4107 return Status;
4108
4109 }
4110
4111