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