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