]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
1. Update the implementation of HII ConfigRouting Protocol in HiiDataBase module...
[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 if (TempStr == NULL) {
877 FreePool (GuidStr);
878 FreePool (NameStr);
879 Status = EFI_OUT_OF_RESOURCES;
880 goto Done;
881 }
882 StrCpy (TempStr, GuidStr);
883 StrCat (TempStr, NameStr);
884 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
885 //
886 // Find the matched VarStore
887 //
888 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
889 VarStorageData->VarStoreId = IfrVarStore->VarStoreId;
890 VarStorageData->Size = IfrVarStore->Size;
891 VarStorageData->Name = VarStoreName;
892 } else {
893 //
894 // No found, free the allocated memory
895 //
896 FreePool (VarStoreName);
897 }
898 //
899 // Free alllocated temp string.
900 //
901 FreePool (TempStr);
902 FreePool (GuidStr);
903 FreePool (NameStr);
904 break;
905
906 case EFI_IFR_DEFAULTSTORE_OP:
907 //
908 // Add new the map between default id and default name.
909 //
910 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
911 if (DefaultData == NULL) {
912 Status = EFI_OUT_OF_RESOURCES;
913 goto Done;
914 }
915 DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
916 DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;
917 InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);
918 DefaultData = NULL;
919 break;
920
921 case EFI_IFR_FORM_OP:
922 //
923 // No matched varstore is found and directly return.
924 //
925 if (VarStorageData->Size == 0) {
926 Status = EFI_SUCCESS;
927 goto Done;
928 }
929 break;
930
931 case EFI_IFR_ONE_OF_OP:
932 case EFI_IFR_NUMERIC_OP:
933 //
934 // Numeric and OneOf has the same opcode structure.
935 //
936
937 //
938 // Check whether this question is for the requested varstore.
939 //
940 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
941 if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {
942 break;
943 }
944
945 //
946 // Get Offset/Width by Question header and OneOf Flags
947 //
948 VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;
949 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
950 //
951 // Check whether this question is in requested block array.
952 //
953 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
954 //
955 // This question is not in the requested string. Skip it.
956 //
957 break;
958 }
959
960 //
961 // Check this var question is in the var storage
962 //
963 if ((VarOffset + VarWidth) > VarStorageData->Size) {
964 Status = EFI_INVALID_PARAMETER;
965 goto Done;
966 }
967
968 //
969 // Set Block Data
970 //
971 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
972 if (BlockData == NULL) {
973 Status = EFI_OUT_OF_RESOURCES;
974 goto Done;
975 }
976 BlockData->Offset = VarOffset;
977 BlockData->Width = VarWidth;
978 BlockData->QuestionId = IfrOneOf->Question.QuestionId;
979 BlockData->OpCode = IfrOpHdr->OpCode;
980 BlockData->Scope = IfrOpHdr->Scope;
981 InitializeListHead (&BlockData->DefaultValueEntry);
982 //
983 // Add Block Data into VarStorageData BlockEntry
984 //
985 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
986 break;
987
988 case EFI_IFR_ORDERED_LIST_OP:
989 //
990 // offset by question header
991 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
992 // no default value and default id, how to define its default value?
993 //
994
995 //
996 // Check whether this question is for the requested varstore.
997 //
998 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
999 if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {
1000 break;
1001 }
1002
1003 //
1004 // Get Offset/Width by Question header and OneOf Flags
1005 //
1006 VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;
1007 VarWidth = IfrOrderedList->MaxContainers;
1008
1009 //
1010 // Check whether this question is in requested block array.
1011 //
1012 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1013 //
1014 // This question is not in the requested string. Skip it.
1015 //
1016 break;
1017 }
1018
1019 //
1020 // Check this var question is in the var storage
1021 //
1022 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1023 Status = EFI_INVALID_PARAMETER;
1024 goto Done;
1025 }
1026
1027 //
1028 // Set Block Data
1029 //
1030 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1031 if (BlockData == NULL) {
1032 Status = EFI_OUT_OF_RESOURCES;
1033 goto Done;
1034 }
1035 BlockData->Offset = VarOffset;
1036 BlockData->Width = VarWidth;
1037 BlockData->QuestionId = IfrOrderedList->Question.QuestionId;
1038 BlockData->OpCode = IfrOpHdr->OpCode;
1039 BlockData->Scope = IfrOpHdr->Scope;
1040 InitializeListHead (&BlockData->DefaultValueEntry);
1041
1042 //
1043 // Add Block Data into VarStorageData BlockEntry
1044 //
1045 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1046 break;
1047
1048 case EFI_IFR_CHECKBOX_OP:
1049 //
1050 // EFI_IFR_DEFAULT_OP
1051 // offset by question header
1052 // width is 1 sizeof (BOOLEAN)
1053 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1054 // value by DefaultOption
1055 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1056 //
1057
1058 //
1059 // Check whether this question is for the requested varstore.
1060 //
1061 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
1062 if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {
1063 break;
1064 }
1065
1066 //
1067 // Get Offset/Width by Question header and OneOf Flags
1068 //
1069 VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
1070 VarWidth = sizeof (BOOLEAN);
1071
1072 //
1073 // Check whether this question is in requested block array.
1074 //
1075 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1076 //
1077 // This question is not in the requested string. Skip it.
1078 //
1079 break;
1080 }
1081
1082 //
1083 // Check this var question is in the var storage
1084 //
1085 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1086 Status = EFI_INVALID_PARAMETER;
1087 goto Done;
1088 }
1089
1090 //
1091 // Set Block Data
1092 //
1093 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1094 if (BlockData == NULL) {
1095 Status = EFI_OUT_OF_RESOURCES;
1096 goto Done;
1097 }
1098 BlockData->Offset = VarOffset;
1099 BlockData->Width = VarWidth;
1100 BlockData->QuestionId = IfrCheckBox->Question.QuestionId;
1101 BlockData->OpCode = IfrOpHdr->OpCode;
1102 BlockData->Scope = IfrOpHdr->Scope;
1103 InitializeListHead (&BlockData->DefaultValueEntry);
1104 //
1105 // Add Block Data into VarStorageData BlockEntry
1106 //
1107 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1108
1109 //
1110 // Add default value by CheckBox Flags
1111 //
1112 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
1113 //
1114 // Set standard ID to Manufacture ID and Get DefaultName String ID
1115 //
1116 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1117 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1118 if (EFI_ERROR (Status)) {
1119 goto Done;
1120 }
1121 //
1122 // Prepare new DefaultValue
1123 //
1124 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1125 if (DefaultData == NULL) {
1126 Status = EFI_OUT_OF_RESOURCES;
1127 goto Done;
1128 }
1129 DefaultData->DefaultId = VarDefaultId;
1130 DefaultData->DefaultName = VarDefaultName;
1131 DefaultData->Value = 1;
1132 //
1133 // Add DefaultValue into current BlockData
1134 //
1135 InsertDefaultValue (BlockData, DefaultData);
1136 }
1137
1138 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
1139 //
1140 // Set standard ID to Manufacture ID and Get DefaultName String ID
1141 //
1142 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1143 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1144 if (EFI_ERROR (Status)) {
1145 goto Done;
1146 }
1147 //
1148 // Prepare new DefaultValue
1149 //
1150 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1151 if (DefaultData == NULL) {
1152 Status = EFI_OUT_OF_RESOURCES;
1153 goto Done;
1154 }
1155 DefaultData->DefaultId = VarDefaultId;
1156 DefaultData->DefaultName = VarDefaultName;
1157 DefaultData->Value = 1;
1158 //
1159 // Add DefaultValue into current BlockData
1160 //
1161 InsertDefaultValue (BlockData, DefaultData);
1162 }
1163 break;
1164
1165 case EFI_IFR_STRING_OP:
1166 //
1167 // offset by question header
1168 // width MaxSize * sizeof (CHAR16)
1169 // no default value, only block array
1170 //
1171
1172 //
1173 // Check whether this question is for the requested varstore.
1174 //
1175 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
1176 if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {
1177 break;
1178 }
1179
1180 //
1181 // Get Offset/Width by Question header and OneOf Flags
1182 //
1183 VarOffset = IfrString->Question.VarStoreInfo.VarOffset;
1184 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
1185
1186 //
1187 // Check whether this question is in requested block array.
1188 //
1189 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1190 //
1191 // This question is not in the requested string. Skip it.
1192 //
1193 break;
1194 }
1195
1196 //
1197 // Check this var question is in the var storage
1198 //
1199 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1200 Status = EFI_INVALID_PARAMETER;
1201 goto Done;
1202 }
1203
1204 //
1205 // Set Block Data
1206 //
1207 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1208 if (BlockData == NULL) {
1209 Status = EFI_OUT_OF_RESOURCES;
1210 goto Done;
1211 }
1212 BlockData->Offset = VarOffset;
1213 BlockData->Width = VarWidth;
1214 BlockData->QuestionId = IfrString->Question.QuestionId;
1215 BlockData->OpCode = IfrOpHdr->OpCode;
1216 InitializeListHead (&BlockData->DefaultValueEntry);
1217
1218 //
1219 // Add Block Data into VarStorageData BlockEntry
1220 //
1221 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1222
1223 //
1224 // No default value for string.
1225 //
1226 BlockData = NULL;
1227 break;
1228
1229 case EFI_IFR_PASSWORD_OP:
1230 //
1231 // offset by question header
1232 // width MaxSize * sizeof (CHAR16)
1233 // no default value, only block array
1234 //
1235
1236 //
1237 // Check whether this question is for the requested varstore.
1238 //
1239 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
1240 if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {
1241 break;
1242 }
1243
1244 //
1245 // Get Offset/Width by Question header and OneOf Flags
1246 //
1247 VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;
1248 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
1249
1250 //
1251 // Check whether this question is in requested block array.
1252 //
1253 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
1254 //
1255 // This question is not in the requested string. Skip it.
1256 //
1257 break;
1258 }
1259
1260 //
1261 // Check this var question is in the var storage
1262 //
1263 if ((VarOffset + VarWidth) > VarStorageData->Size) {
1264 Status = EFI_INVALID_PARAMETER;
1265 goto Done;
1266 }
1267
1268 //
1269 // Set Block Data
1270 //
1271 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1272 if (BlockData == NULL) {
1273 Status = EFI_OUT_OF_RESOURCES;
1274 goto Done;
1275 }
1276 BlockData->Offset = VarOffset;
1277 BlockData->Width = VarWidth;
1278 BlockData->QuestionId = IfrPassword->Question.QuestionId;
1279 BlockData->OpCode = IfrOpHdr->OpCode;
1280 InitializeListHead (&BlockData->DefaultValueEntry);
1281
1282 //
1283 // Add Block Data into VarStorageData BlockEntry
1284 //
1285 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1286
1287 //
1288 // No default value for string.
1289 //
1290 BlockData = NULL;
1291 break;
1292
1293 case EFI_IFR_ONE_OF_OPTION_OP:
1294 //
1295 // No matched block data is ignored.
1296 //
1297 if (BlockData == NULL || BlockData->Scope == 0) {
1298 break;
1299 }
1300
1301 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
1302 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1303 //
1304 // Get ordered list option data type.
1305 //
1306 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
1307 VarWidth = 1;
1308 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1309 VarWidth = 2;
1310 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1311 VarWidth = 4;
1312 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1313 VarWidth = 8;
1314 } else {
1315 //
1316 // Invalid ordered list option data type.
1317 //
1318 Status = EFI_INVALID_PARAMETER;
1319 goto Done;
1320 }
1321 //
1322 // Calculate Ordered list QuestionId width.
1323 //
1324 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
1325 BlockData = NULL;
1326 break;
1327 }
1328
1329 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
1330 //
1331 // Set standard ID to Manufacture ID and Get DefaultName String ID
1332 //
1333 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1334 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1335 if (EFI_ERROR (Status)) {
1336 goto Done;
1337 }
1338 //
1339 // Prepare new DefaultValue
1340 //
1341 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1342 if (DefaultData == NULL) {
1343 Status = EFI_OUT_OF_RESOURCES;
1344 goto Done;
1345 }
1346 DefaultData->DefaultId = VarDefaultId;
1347 DefaultData->DefaultName = VarDefaultName;
1348 DefaultData->Value = IfrOneOfOption->Value.u64;
1349 //
1350 // Add DefaultValue into current BlockData
1351 //
1352 InsertDefaultValue (BlockData, DefaultData);
1353 }
1354
1355 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
1356 //
1357 // Set default ID to Manufacture ID and Get DefaultName String ID
1358 //
1359 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1360 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1361 if (EFI_ERROR (Status)) {
1362 goto Done;
1363 }
1364 //
1365 // Prepare new DefaultValue
1366 //
1367 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1368 if (DefaultData == NULL) {
1369 Status = EFI_OUT_OF_RESOURCES;
1370 goto Done;
1371 }
1372 DefaultData->DefaultId = VarDefaultId;
1373 DefaultData->DefaultName = VarDefaultName;
1374 DefaultData->Value = IfrOneOfOption->Value.u64;
1375 //
1376 // Add DefaultValue into current BlockData
1377 //
1378 InsertDefaultValue (BlockData, DefaultData);
1379 }
1380 break;
1381
1382 case EFI_IFR_DEFAULT_OP:
1383 //
1384 // Update Current BlockData to the default value.
1385 //
1386 if (BlockData == NULL || BlockData->Scope == 0) {
1387 //
1388 // No matched block data is ignored.
1389 //
1390 break;
1391 }
1392
1393 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1394 //
1395 // OrderedList Opcode is no default value.
1396 //
1397 break;
1398 }
1399 //
1400 // Get the DefaultId and DefaultName String ID
1401 //
1402 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
1403 VarDefaultId = IfrDefault->DefaultId;
1404 Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);
1405 if (EFI_ERROR (Status)) {
1406 goto Done;
1407 }
1408 //
1409 // Prepare new DefaultValue
1410 //
1411 DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1412 if (DefaultData == NULL) {
1413 Status = EFI_OUT_OF_RESOURCES;
1414 goto Done;
1415 }
1416 DefaultData->DefaultId = VarDefaultId;
1417 DefaultData->DefaultName = VarDefaultName;
1418 DefaultData->Value = IfrDefault->Value.u64;
1419 //
1420 // Add DefaultValue into current BlockData
1421 //
1422 InsertDefaultValue (BlockData, DefaultData);
1423 break;
1424 case EFI_IFR_END_OP:
1425 //
1426 // End Opcode is for Var.
1427 //
1428 if (BlockData != NULL && BlockData->Scope > 0) {
1429 BlockData->Scope--;
1430 }
1431 break;
1432 default:
1433 if (BlockData != NULL && BlockData->Scope > 0) {
1434 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
1435 }
1436 break;
1437 }
1438
1439 IfrOffset += IfrOpHdr->Length;
1440 }
1441
1442 Done:
1443 //
1444 // Set the defualt ID array.
1445 //
1446 *PIfrDefaultIdArray = DefaultIdArray;
1447
1448 return Status;
1449 }
1450
1451 /**
1452 This function gets the full request string and full default value string by
1453 parsing IFR data in HII form packages.
1454
1455 When Request points to NULL string, the request string and default value string
1456 for each varstore in form package will return.
1457
1458 @param HiiHandle Hii Handle which Hii Packages are registered.
1459 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1460 @param Request Pointer to a null-terminated Unicode string in
1461 <ConfigRequest> format. When it doesn't contain
1462 any RequestElement, it will be updated to return
1463 the full RequestElement retrieved from IFR data.
1464 If it points to NULL, the request string for the first
1465 varstore in form package will be merged into a
1466 <MultiConfigRequest> format string and return.
1467 @param AltCfgResp Pointer to a null-terminated Unicode string in
1468 <ConfigAltResp> format. When the pointer is to NULL,
1469 the full default value string retrieved from IFR data
1470 will return. When the pinter is to a string, the
1471 full default value string retrieved from IFR data
1472 will be merged into the input string and return.
1473 When Request points to NULL, the default value string
1474 for each varstore in form package will be merged into
1475 a <MultiConfigAltResp> format string and return.
1476 @retval EFI_SUCCESS The Results string is set to the full request string.
1477 And AltCfgResp contains all default value string.
1478 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1479 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1480 can't be found in Form package.
1481 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1482 @retval EFI_INVALID_PARAMETER *Request points to NULL.
1483
1484 **/
1485 EFI_STATUS
1486 EFIAPI
1487 GetFullStringFromHiiFormPackages (
1488 IN EFI_HII_HANDLE HiiHandle,
1489 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1490 IN OUT EFI_STRING *Request,
1491 IN OUT EFI_STRING *AltCfgResp
1492 )
1493 {
1494 EFI_STATUS Status;
1495 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
1496 UINT32 PackageListLength;
1497 UINTN BufferSize;
1498 IFR_BLOCK_DATA *RequestBlockArray;
1499 IFR_BLOCK_DATA *BlockData;
1500 IFR_BLOCK_DATA *NextBlockData;
1501 IFR_DEFAULT_DATA *DefaultValueData;
1502 IFR_DEFAULT_DATA *DefaultId;
1503 IFR_DEFAULT_DATA *DefaultIdArray;
1504 EFI_HII_PACKAGE_HEADER PacakgeHeader;
1505 UINT32 PackageOffset;
1506 IFR_VARSTORAGE_DATA *VarStorageData;
1507 EFI_STRING DefaultAltCfgResp;
1508 EFI_STRING FullConfigRequest;
1509 EFI_STRING ConfigHdr;
1510 EFI_STRING GuidStr;
1511 EFI_STRING NameStr;
1512 EFI_STRING PathStr;
1513 EFI_STRING StringPtr;
1514 UINTN Length;
1515 UINT8 *TmpBuffer;
1516 UINT16 Offset;
1517 UINT16 Width;
1518 LIST_ENTRY *Link;
1519 LIST_ENTRY *LinkData;
1520 LIST_ENTRY *LinkDefault;
1521
1522 //
1523 // Initialize the local variables.
1524 //
1525 RequestBlockArray = NULL;
1526 VarStorageData = NULL;
1527 DefaultAltCfgResp = NULL;
1528 FullConfigRequest = NULL;
1529 ConfigHdr = NULL;
1530 DefaultIdArray = NULL;
1531 GuidStr = NULL;
1532 NameStr = NULL;
1533 PathStr = NULL;
1534
1535 //
1536 // 1. Get HiiPackage by HiiHandle
1537 //
1538 BufferSize = 0;
1539 HiiPackageList = NULL;
1540 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
1541
1542 //
1543 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1544 //
1545 if (Status != EFI_BUFFER_TOO_SMALL) {
1546 return Status;
1547 }
1548
1549 HiiPackageList = AllocatePool (BufferSize);
1550 if (HiiPackageList == NULL) {
1551 return EFI_OUT_OF_RESOURCES;
1552 }
1553
1554 //
1555 // Get PackageList on HiiHandle
1556 //
1557 Status = HiiExportPackageLists (&mPrivate.HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
1558 if (EFI_ERROR (Status)) {
1559 goto Done;
1560 }
1561
1562 //
1563 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1564 // 1) Request is NULL.
1565 // 2) Request is not NULL. And it doesn't contain any BlockArray.
1566 // 3) Request is not NULL. And it containts BlockArray.
1567 //
1568
1569 //
1570 // Initialize VarStorageData to store the var store Block and Default value information.
1571 //
1572 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
1573 if (VarStorageData == NULL) {
1574 Status = EFI_OUT_OF_RESOURCES;
1575 goto Done;
1576 }
1577
1578 InitializeListHead (&VarStorageData->Entry);
1579 InitializeListHead (&VarStorageData->BlockEntry);
1580
1581 //
1582 // Gte the request block array by Request String
1583 //
1584 StringPtr = NULL;
1585 if (*Request != NULL) {
1586 StringPtr = StrStr (*Request, L"&OFFSET=");
1587 }
1588 if (StringPtr != NULL) {
1589 //
1590 // Init RequestBlockArray
1591 //
1592 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1593 if (RequestBlockArray == NULL) {
1594 Status = EFI_OUT_OF_RESOURCES;
1595 goto Done;
1596 }
1597 InitializeListHead (&RequestBlockArray->Entry);
1598
1599 //
1600 // Get the request Block array from the request string
1601 // Offset and Width
1602 //
1603
1604 //
1605 // Parse each <RequestElement> if exists
1606 // Only <BlockName> format is supported by this help function.
1607 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1608 //
1609 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
1610 //
1611 // Skip the OFFSET string
1612 //
1613 StringPtr += StrLen (L"&OFFSET=");
1614 //
1615 // Get Offset
1616 //
1617 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1618 if (EFI_ERROR (Status)) {
1619 goto Done;
1620 }
1621 Offset = 0;
1622 CopyMem (
1623 &Offset,
1624 TmpBuffer,
1625 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1626 );
1627 FreePool (TmpBuffer);
1628
1629 StringPtr += Length;
1630 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
1631 Status = EFI_INVALID_PARAMETER;
1632 goto Done;
1633 }
1634 StringPtr += StrLen (L"&WIDTH=");
1635
1636 //
1637 // Get Width
1638 //
1639 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
1640 if (EFI_ERROR (Status)) {
1641 goto Done;
1642 }
1643 Width = 0;
1644 CopyMem (
1645 &Width,
1646 TmpBuffer,
1647 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
1648 );
1649 FreePool (TmpBuffer);
1650
1651 StringPtr += Length;
1652 if (*StringPtr != 0 && *StringPtr != L'&') {
1653 Status = EFI_INVALID_PARAMETER;
1654 goto Done;
1655 }
1656
1657 //
1658 // Set Block Data
1659 //
1660 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1661 if (BlockData == NULL) {
1662 Status = EFI_OUT_OF_RESOURCES;
1663 goto Done;
1664 }
1665 BlockData->Offset = Offset;
1666 BlockData->Width = Width;
1667 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
1668
1669 //
1670 // If '\0', parsing is finished.
1671 //
1672 if (*StringPtr == 0) {
1673 break;
1674 }
1675 }
1676
1677 //
1678 // Merge the requested block data.
1679 //
1680 Link = RequestBlockArray->Entry.ForwardLink;
1681 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
1682 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1683 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
1684 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
1685 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
1686 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
1687 }
1688 RemoveEntryList (Link->ForwardLink);
1689 FreePool (NextBlockData);
1690 continue;
1691 }
1692 Link = Link->ForwardLink;
1693 }
1694 }
1695
1696 //
1697 // Get the form package
1698 //
1699 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
1700 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
1701 while (PackageOffset < PackageListLength) {
1702 CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
1703
1704 if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {
1705 //
1706 // Reset VarStorageData
1707 //
1708 VarStorageData->Size = 0;
1709 VarStorageData->VarStoreId = 0;
1710 if (VarStorageData->Name != NULL) {
1711 FreePool (VarStorageData->Name);
1712 VarStorageData->Name = NULL;
1713 }
1714
1715 //
1716 // Parse the opcode in form package
1717 //
1718 Status = ParseIfrData ((UINT8 *) HiiPackageList + PackageOffset, PacakgeHeader.Length, *Request, RequestBlockArray, VarStorageData, &DefaultIdArray);
1719 if (EFI_ERROR (Status)) {
1720 goto Done;
1721 }
1722
1723 //
1724 // Only one form is in a pacakge list.
1725 //
1726 break;
1727 }
1728
1729 PackageOffset += PacakgeHeader.Length;
1730 }
1731
1732 //
1733 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1734 //
1735
1736 //
1737 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1738 //
1739 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
1740 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
1741 GenerateSubStr (
1742 L"PATH=",
1743 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
1744 (VOID *) DevicePath,
1745 1,
1746 &PathStr
1747 );
1748 Length = StrLen (GuidStr);
1749 Length = Length + StrLen (NameStr);
1750 Length = Length + StrLen (PathStr) + 1;
1751 ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
1752 if (ConfigHdr == NULL) {
1753 Status = EFI_OUT_OF_RESOURCES;
1754 goto Done;
1755 }
1756 StrCpy (ConfigHdr, GuidStr);
1757 StrCat (ConfigHdr, NameStr);
1758 StrCat (ConfigHdr, PathStr);
1759
1760 //
1761 // Remove the last character L'&'
1762 //
1763 *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';
1764
1765 if (RequestBlockArray == NULL) {
1766 //
1767 // Append VarStorageData BlockEntry into *Request string
1768 // Now support only one varstore in a form package.
1769 //
1770
1771 //
1772 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1773 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1774 //
1775
1776 //
1777 // Compute the length of the entire request starting with <ConfigHdr> and a
1778 // Null-terminator
1779 //
1780 Length = StrLen (ConfigHdr) + 1;
1781
1782 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
1783 //
1784 // Add <BlockName> length for each Offset/Width pair
1785 //
1786 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1787 // | 8 | 4 | 7 | 4 |
1788 //
1789 Length = Length + (8 + 4 + 7 + 4);
1790 }
1791
1792 //
1793 // Allocate buffer for the entire <ConfigRequest>
1794 //
1795 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
1796 if (FullConfigRequest == NULL) {
1797 goto Done;
1798 }
1799 StringPtr = FullConfigRequest;
1800
1801 //
1802 // Start with <ConfigHdr>
1803 //
1804 StrCpy (StringPtr, ConfigHdr);
1805 StringPtr += StrLen (StringPtr);
1806
1807 //
1808 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1809 //
1810 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
1811 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1812 //
1813 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1814 //
1815 UnicodeSPrint (
1816 StringPtr,
1817 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
1818 L"&OFFSET=%04X&WIDTH=%04X",
1819 BlockData->Offset,
1820 BlockData->Width
1821 );
1822 StringPtr += StrLen (StringPtr);
1823 }
1824 //
1825 // Set to the got full request string.
1826 //
1827 HiiToLower (FullConfigRequest);
1828 if (*Request != NULL) {
1829 FreePool (*Request);
1830 }
1831 *Request = FullConfigRequest;
1832 }
1833
1834 //
1835 // 4. Construct Default Value string in AltResp according to request element.
1836 // Go through all VarStorageData Entry and get the DefaultId array for each one
1837 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
1838 //
1839
1840 //
1841 // Add length for <ConfigHdr> + '\0'
1842 //
1843 Length = StrLen (ConfigHdr) + 1;
1844
1845 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
1846 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
1847 //
1848 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
1849 // |1| StrLen (ConfigHdr) | 8 | 4 |
1850 //
1851 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
1852
1853 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
1854 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
1855 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
1856 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
1857 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
1858 //
1859 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
1860 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
1861 //
1862 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
1863 }
1864 }
1865 }
1866 }
1867
1868 //
1869 // Allocate buffer for the entire <DefaultAltCfgResp>
1870 //
1871 DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
1872 if (DefaultAltCfgResp == NULL) {
1873 goto Done;
1874 }
1875 StringPtr = DefaultAltCfgResp;
1876
1877 //
1878 // Start with <ConfigHdr>
1879 //
1880 StrCpy (StringPtr, ConfigHdr);
1881 StringPtr += StrLen (StringPtr);
1882
1883 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
1884 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
1885 //
1886 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
1887 // |1| StrLen (ConfigHdr) | 8 | 4 |
1888 //
1889 UnicodeSPrint (
1890 StringPtr,
1891 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
1892 L"&%s&ALTCFG=%04X",
1893 ConfigHdr,
1894 DefaultId->DefaultName
1895 );
1896 StringPtr += StrLen (StringPtr);
1897
1898 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
1899 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
1900 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
1901 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
1902 if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
1903 //
1904 // Add <BlockConfig>
1905 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
1906 //
1907 UnicodeSPrint (
1908 StringPtr,
1909 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
1910 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
1911 BlockData->Offset,
1912 BlockData->Width
1913 );
1914 StringPtr += StrLen (StringPtr);
1915
1916 //
1917 // Convert Value to a hex string in "%x" format
1918 // NOTE: This is in the opposite byte that GUID and PATH use
1919 //
1920 Width = BlockData->Width;
1921 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
1922 for (; Width > 0; Width--) {
1923 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
1924 }
1925 }
1926 }
1927 }
1928 }
1929 HiiToLower (DefaultAltCfgResp);
1930
1931 //
1932 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
1933 //
1934 if (*AltCfgResp != NULL) {
1935 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
1936 FreePool (DefaultAltCfgResp);
1937 } else {
1938 *AltCfgResp = DefaultAltCfgResp;
1939 }
1940
1941 Done:
1942 if (RequestBlockArray != NULL) {
1943 //
1944 // Free Link Array RequestBlockArray
1945 //
1946 while (!IsListEmpty (&RequestBlockArray->Entry)) {
1947 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
1948 RemoveEntryList (&BlockData->Entry);
1949 FreePool (BlockData);
1950 }
1951
1952 FreePool (RequestBlockArray);
1953 }
1954
1955 if (VarStorageData != NULL) {
1956 //
1957 // Free link array VarStorageData
1958 //
1959 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
1960 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
1961 RemoveEntryList (&BlockData->Entry);
1962 //
1963 // Free default value link array
1964 //
1965 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
1966 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
1967 RemoveEntryList (&DefaultValueData->Entry);
1968 FreePool (DefaultValueData);
1969 }
1970 FreePool (BlockData);
1971 }
1972 FreePool (VarStorageData);
1973 }
1974
1975 if (DefaultIdArray != NULL) {
1976 //
1977 // Free DefaultId Array
1978 //
1979 while (!IsListEmpty (&DefaultIdArray->Entry)) {
1980 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
1981 RemoveEntryList (&DefaultId->Entry);
1982 FreePool (DefaultId);
1983 }
1984 FreePool (DefaultIdArray);
1985 }
1986
1987 //
1988 // Free the allocated string
1989 //
1990 if (GuidStr != NULL) {
1991 FreePool (GuidStr);
1992 }
1993 if (NameStr != NULL) {
1994 FreePool (NameStr);
1995 }
1996 if (PathStr != NULL) {
1997 FreePool (PathStr);
1998 }
1999 if (ConfigHdr != NULL) {
2000 FreePool (ConfigHdr);
2001 }
2002
2003 //
2004 // Free Pacakge data
2005 //
2006 if (HiiPackageList != NULL) {
2007 FreePool (HiiPackageList);
2008 }
2009
2010 return Status;
2011 }
2012
2013 /**
2014 This function allows a caller to extract the current configuration
2015 for one or more named elements from one or more drivers.
2016
2017 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2018 instance.
2019 @param Request A null-terminated Unicode string in
2020 <MultiConfigRequest> format.
2021 @param Progress On return, points to a character in the Request
2022 string. Points to the string's null terminator if
2023 request was successful. Points to the most recent
2024 & before the first failing name / value pair (or
2025 the beginning of the string if the failure is in
2026 the first name / value pair) if the request was
2027 not successful.
2028 @param Results Null-terminated Unicode string in
2029 <MultiConfigAltResp> format which has all values
2030 filled in for the names in the Request string.
2031 String to be allocated by the called function.
2032
2033 @retval EFI_SUCCESS The Results string is filled with the values
2034 corresponding to all requested names.
2035 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2036 results that must be stored awaiting possible
2037 future protocols.
2038 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2039 Progress set to the "G" in "GUID" of the routing
2040 header that doesn't match. Note: There is no
2041 requirement that all routing data be validated
2042 before any configuration extraction.
2043 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2044 parameter would result in this type of error. The
2045 Progress parameter is set to NULL.
2046 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2047 before the error or the beginning of the string.
2048 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2049 name in question.
2050
2051 **/
2052 EFI_STATUS
2053 EFIAPI
2054 HiiConfigRoutingExtractConfig (
2055 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2056 IN CONST EFI_STRING Request,
2057 OUT EFI_STRING *Progress,
2058 OUT EFI_STRING *Results
2059 )
2060 {
2061 HII_DATABASE_PRIVATE_DATA *Private;
2062 EFI_STRING StringPtr;
2063 EFI_STRING ConfigRequest;
2064 UINTN Length;
2065 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2066 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
2067 EFI_STATUS Status;
2068 LIST_ENTRY *Link;
2069 HII_DATABASE_RECORD *Database;
2070 UINT8 *DevicePathPkg;
2071 UINT8 *CurrentDevicePath;
2072 EFI_HANDLE DriverHandle;
2073 EFI_HII_HANDLE HiiHandle;
2074 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2075 EFI_STRING AccessProgress;
2076 EFI_STRING AccessResults;
2077 EFI_STRING DefaultResults;
2078 BOOLEAN FirstElement;
2079 UINTN DevicePathLength;
2080
2081 if (This == NULL || Progress == NULL || Results == NULL) {
2082 return EFI_INVALID_PARAMETER;
2083 }
2084
2085 if (Request == NULL) {
2086 *Progress = NULL;
2087 return EFI_INVALID_PARAMETER;
2088 }
2089
2090 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2091 StringPtr = Request;
2092 *Progress = StringPtr;
2093 DefaultResults = NULL;
2094 ConfigRequest = NULL;
2095 Status = EFI_SUCCESS;
2096 AccessResults = NULL;
2097 DevicePath = NULL;
2098
2099 //
2100 // The first element of <MultiConfigRequest> should be
2101 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2102 //
2103 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2104 return EFI_INVALID_PARAMETER;
2105 }
2106
2107 FirstElement = TRUE;
2108
2109 //
2110 // Allocate a fix length of memory to store Results. Reallocate memory for
2111 // Results if this fix length is insufficient.
2112 //
2113 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2114 if (*Results == NULL) {
2115 return EFI_OUT_OF_RESOURCES;
2116 }
2117
2118 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
2119 //
2120 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2121 // or most recent & before the error.
2122 //
2123 if (StringPtr == Request) {
2124 *Progress = StringPtr;
2125 } else {
2126 *Progress = StringPtr - 1;
2127 }
2128
2129 //
2130 // Process each <ConfigRequest> of <MultiConfigRequest>
2131 //
2132 Length = CalculateConfigStringLen (StringPtr);
2133 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
2134 if (ConfigRequest == NULL) {
2135 Status = EFI_OUT_OF_RESOURCES;
2136 goto Done;
2137 }
2138 *(ConfigRequest + Length) = 0;
2139
2140 //
2141 // Get the UEFI device path
2142 //
2143 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
2144 if (EFI_ERROR (Status)) {
2145 goto Done;
2146 }
2147
2148 //
2149 // Find driver which matches the routing data.
2150 //
2151 DriverHandle = NULL;
2152 HiiHandle = NULL;
2153 DevicePathLength = GetDevicePathSize (DevicePath);
2154 for (Link = Private->DatabaseList.ForwardLink;
2155 Link != &Private->DatabaseList;
2156 Link = Link->ForwardLink
2157 ) {
2158 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2159
2160 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2161 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2162 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&
2163 (CompareMem (
2164 DevicePath,
2165 CurrentDevicePath,
2166 DevicePathLength
2167 ) == 0)) {
2168 DriverHandle = Database->DriverHandle;
2169 HiiHandle = Database->Handle;
2170 break;
2171 }
2172 }
2173 }
2174
2175 //
2176 // Try to find driver handle by device path.
2177 //
2178 if (DriverHandle == NULL) {
2179 TempDevicePath = DevicePath;
2180 Status = gBS->LocateDevicePath (
2181 &gEfiDevicePathProtocolGuid,
2182 &TempDevicePath,
2183 &DriverHandle
2184 );
2185 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
2186 //
2187 // Routing data does not match any known driver.
2188 // Set Progress to the 'G' in "GUID" of the routing header.
2189 //
2190 *Progress = StringPtr;
2191 Status = EFI_NOT_FOUND;
2192 goto Done;
2193 }
2194 }
2195
2196 //
2197 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2198 //
2199 if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {
2200 //
2201 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2202 //
2203 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);
2204 if (EFI_ERROR (Status)) {
2205 goto Done;
2206 }
2207 }
2208
2209 //
2210 // Call corresponding ConfigAccess protocol to extract settings
2211 //
2212 Status = gBS->HandleProtocol (
2213 DriverHandle,
2214 &gEfiHiiConfigAccessProtocolGuid,
2215 (VOID **) &ConfigAccess
2216 );
2217 ASSERT_EFI_ERROR (Status);
2218
2219 Status = ConfigAccess->ExtractConfig (
2220 ConfigAccess,
2221 ConfigRequest,
2222 &AccessProgress,
2223 &AccessResults
2224 );
2225 if (EFI_ERROR (Status)) {
2226 //
2227 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2228 // Map it to the progress on <MultiConfigRequest> then return it.
2229 //
2230 *Progress = StrStr (StringPtr, AccessProgress);
2231 goto Done;
2232 }
2233
2234 //
2235 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2236 // which seperates the first <ConfigAltResp> and the following ones.
2237 //
2238 ASSERT (*AccessProgress == 0);
2239
2240 //
2241 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2242 //
2243 if (HiiHandle != NULL) {
2244 if (DefaultResults == NULL) {
2245 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &AccessResults);
2246 } else {
2247 Status = MergeDefaultString (&AccessResults, DefaultResults);
2248 }
2249 }
2250 FreePool (DevicePath);
2251 DevicePath = NULL;
2252
2253 if (EFI_ERROR (Status)) {
2254 goto Done;
2255 }
2256
2257 //
2258 // Free the allocated memory.
2259 //
2260 if (DefaultResults != NULL) {
2261 FreePool (DefaultResults);
2262 DefaultResults = NULL;
2263 }
2264
2265 if (!FirstElement) {
2266 Status = AppendToMultiString (Results, L"&");
2267 ASSERT_EFI_ERROR (Status);
2268 }
2269
2270 Status = AppendToMultiString (Results, AccessResults);
2271 ASSERT_EFI_ERROR (Status);
2272
2273 FirstElement = FALSE;
2274
2275 FreePool (AccessResults);
2276 AccessResults = NULL;
2277 FreePool (ConfigRequest);
2278 ConfigRequest = NULL;
2279
2280 //
2281 // Go to next <ConfigRequest> (skip '&').
2282 //
2283 StringPtr += Length;
2284 if (*StringPtr == 0) {
2285 *Progress = StringPtr;
2286 break;
2287 }
2288
2289 StringPtr++;
2290 }
2291
2292 Done:
2293 if (EFI_ERROR (Status)) {
2294 FreePool (*Results);
2295 }
2296
2297 if (ConfigRequest != NULL) {
2298 FreePool (ConfigRequest);
2299 }
2300
2301 if (AccessResults != NULL) {
2302 FreePool (AccessResults);
2303 }
2304
2305 if (DefaultResults != NULL) {
2306 FreePool (DefaultResults);
2307 }
2308
2309 if (DevicePath != NULL) {
2310 FreePool (DevicePath);
2311 }
2312
2313 return Status;
2314 }
2315
2316
2317 /**
2318 This function allows the caller to request the current configuration for the
2319 entirety of the current HII database and returns the data in a
2320 null-terminated Unicode string.
2321
2322 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2323 instance.
2324 @param Results Null-terminated Unicode string in
2325 <MultiConfigAltResp> format which has all values
2326 filled in for the names in the Request string.
2327 String to be allocated by the called function.
2328 De-allocation is up to the caller.
2329
2330 @retval EFI_SUCCESS The Results string is filled with the values
2331 corresponding to all requested names.
2332 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2333 results that must be stored awaiting possible
2334 future protocols.
2335 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2336 parameter would result in this type of error.
2337
2338 **/
2339 EFI_STATUS
2340 EFIAPI
2341 HiiConfigRoutingExportConfig (
2342 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2343 OUT EFI_STRING *Results
2344 )
2345 {
2346 EFI_STATUS Status;
2347 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2348 EFI_STRING AccessResults;
2349 EFI_STRING Progress;
2350 EFI_STRING ConfigRequest;
2351 UINTN Index;
2352 EFI_HANDLE *ConfigAccessHandles;
2353 UINTN NumberConfigAccessHandles;
2354 BOOLEAN FirstElement;
2355 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2356 EFI_HII_HANDLE HiiHandle;
2357 EFI_STRING DefaultResults;
2358 HII_DATABASE_PRIVATE_DATA *Private;
2359 LIST_ENTRY *Link;
2360 HII_DATABASE_RECORD *Database;
2361 UINT8 *DevicePathPkg;
2362 UINT8 *CurrentDevicePath;
2363 UINTN DevicePathLength;
2364
2365 if (This == NULL || Results == NULL) {
2366 return EFI_INVALID_PARAMETER;
2367 }
2368
2369 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2370
2371 //
2372 // Allocate a fix length of memory to store Results. Reallocate memory for
2373 // Results if this fix length is insufficient.
2374 //
2375 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2376 if (*Results == NULL) {
2377 return EFI_OUT_OF_RESOURCES;
2378 }
2379
2380 NumberConfigAccessHandles = 0;
2381 Status = gBS->LocateHandleBuffer (
2382 ByProtocol,
2383 &gEfiHiiConfigAccessProtocolGuid,
2384 NULL,
2385 &NumberConfigAccessHandles,
2386 &ConfigAccessHandles
2387 );
2388 if (EFI_ERROR (Status)) {
2389 return Status;
2390 }
2391
2392 FirstElement = TRUE;
2393
2394 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
2395 Status = gBS->HandleProtocol (
2396 ConfigAccessHandles[Index],
2397 &gEfiHiiConfigAccessProtocolGuid,
2398 (VOID **) &ConfigAccess
2399 );
2400 if (EFI_ERROR (Status)) {
2401 continue;
2402 }
2403
2404 //
2405 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2406 //
2407 Progress = NULL;
2408 HiiHandle = NULL;
2409 ConfigRequest = NULL;
2410 DefaultResults = NULL;
2411 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
2412 DevicePathLength = GetDevicePathSize (DevicePath);
2413 if (DevicePath != NULL) {
2414 for (Link = Private->DatabaseList.ForwardLink;
2415 Link != &Private->DatabaseList;
2416 Link = Link->ForwardLink
2417 ) {
2418 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2419 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2420 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2421 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&
2422 (CompareMem (
2423 DevicePath,
2424 CurrentDevicePath,
2425 DevicePathLength
2426 ) == 0)) {
2427 HiiHandle = Database->Handle;
2428 break;
2429 }
2430 }
2431 }
2432 }
2433
2434 //
2435 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2436 //
2437 if (HiiHandle != NULL && DevicePath != NULL) {
2438 Status = GetFullStringFromHiiFormPackages (HiiHandle, DevicePath, &ConfigRequest, &DefaultResults);
2439 }
2440 //
2441 // Can't parse IFR data to get the request string and default string.
2442 //
2443 if (EFI_ERROR (Status)) {
2444 ConfigRequest = NULL;
2445 DefaultResults = NULL;
2446 }
2447
2448 Status = ConfigAccess->ExtractConfig (
2449 ConfigAccess,
2450 ConfigRequest,
2451 &Progress,
2452 &AccessResults
2453 );
2454 if (!EFI_ERROR (Status)) {
2455 //
2456 // Merge the default sting from IFR code into the got setting from driver.
2457 //
2458 if (DefaultResults != NULL) {
2459 MergeDefaultString (&AccessResults, DefaultResults);
2460 FreePool (DefaultResults);
2461 }
2462
2463 //
2464 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2465 // which seperates the first <ConfigAltResp> and the following ones.
2466 //
2467 if (!FirstElement) {
2468 Status = AppendToMultiString (Results, L"&");
2469 ASSERT_EFI_ERROR (Status);
2470 }
2471
2472 Status = AppendToMultiString (Results, AccessResults);
2473 ASSERT_EFI_ERROR (Status);
2474
2475 FirstElement = FALSE;
2476
2477 FreePool (AccessResults);
2478 AccessResults = NULL;
2479 }
2480 }
2481 FreePool (ConfigAccessHandles);
2482
2483 return EFI_SUCCESS;
2484 }
2485
2486
2487 /**
2488 This function processes the results of processing forms and routes it to the
2489 appropriate handlers or storage.
2490
2491 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2492 instance.
2493 @param Configuration A null-terminated Unicode string in
2494 <MulltiConfigResp> format.
2495 @param Progress A pointer to a string filled in with the offset of
2496 the most recent & before the first failing name /
2497 value pair (or the beginning of the string if the
2498 failure is in the first name / value pair) or the
2499 terminating NULL if all was successful.
2500
2501 @retval EFI_SUCCESS The results have been distributed or are awaiting
2502 distribution.
2503 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2504 results that must be stored awaiting possible
2505 future protocols.
2506 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2507 would result in this type of error.
2508 @retval EFI_NOT_FOUND Target for the specified routing data was not
2509 found.
2510
2511 **/
2512 EFI_STATUS
2513 EFIAPI
2514 HiiConfigRoutingRouteConfig (
2515 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2516 IN CONST EFI_STRING Configuration,
2517 OUT EFI_STRING *Progress
2518 )
2519 {
2520 HII_DATABASE_PRIVATE_DATA *Private;
2521 EFI_STRING StringPtr;
2522 EFI_STRING ConfigResp;
2523 UINTN Length;
2524 EFI_STATUS Status;
2525 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2526 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
2527 LIST_ENTRY *Link;
2528 HII_DATABASE_RECORD *Database;
2529 UINT8 *DevicePathPkg;
2530 UINT8 *CurrentDevicePath;
2531 EFI_HANDLE DriverHandle;
2532 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
2533 EFI_STRING AccessProgress;
2534 UINTN DevicePathLength;
2535
2536 if (This == NULL || Progress == NULL) {
2537 return EFI_INVALID_PARAMETER;
2538 }
2539
2540 if (Configuration == NULL) {
2541 *Progress = NULL;
2542 return EFI_INVALID_PARAMETER;
2543 }
2544
2545 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2546 StringPtr = Configuration;
2547 *Progress = StringPtr;
2548
2549 //
2550 // The first element of <MultiConfigResp> should be
2551 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2552 //
2553 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2554 return EFI_INVALID_PARAMETER;
2555 }
2556
2557 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
2558 //
2559 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2560 // or most recent & before the error.
2561 //
2562 if (StringPtr == Configuration) {
2563 *Progress = StringPtr;
2564 } else {
2565 *Progress = StringPtr - 1;
2566 }
2567
2568 //
2569 // Process each <ConfigResp> of <MultiConfigResp>
2570 //
2571 Length = CalculateConfigStringLen (StringPtr);
2572 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
2573 if (ConfigResp == NULL) {
2574 return EFI_OUT_OF_RESOURCES;
2575 }
2576 //
2577 // Append '\0' to the end of ConfigRequest
2578 //
2579 *(ConfigResp + Length) = 0;
2580
2581 //
2582 // Get the UEFI device path
2583 //
2584 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
2585 if (EFI_ERROR (Status)) {
2586 FreePool (ConfigResp);
2587 return Status;
2588 }
2589
2590 //
2591 // Find driver which matches the routing data.
2592 //
2593 DriverHandle = NULL;
2594 DevicePathLength = GetDevicePathSize (DevicePath);
2595 for (Link = Private->DatabaseList.ForwardLink;
2596 Link != &Private->DatabaseList;
2597 Link = Link->ForwardLink
2598 ) {
2599 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
2600
2601 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
2602 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
2603 if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) &&
2604 (CompareMem (
2605 DevicePath,
2606 CurrentDevicePath,
2607 DevicePathLength
2608 ) == 0)) {
2609 DriverHandle = Database->DriverHandle;
2610 break;
2611 }
2612 }
2613 }
2614
2615 //
2616 // Try to find driver handle by device path.
2617 //
2618 if (DriverHandle == NULL) {
2619 TempDevicePath = DevicePath;
2620 Status = gBS->LocateDevicePath (
2621 &gEfiDevicePathProtocolGuid,
2622 &TempDevicePath,
2623 &DriverHandle
2624 );
2625 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
2626 //
2627 // Routing data does not match any known driver.
2628 // Set Progress to the 'G' in "GUID" of the routing header.
2629 //
2630 FreePool (DevicePath);
2631 *Progress = StringPtr;
2632 FreePool (ConfigResp);
2633 return EFI_NOT_FOUND;
2634 }
2635 }
2636
2637 FreePool (DevicePath);
2638
2639 //
2640 // Call corresponding ConfigAccess protocol to route settings
2641 //
2642 Status = gBS->HandleProtocol (
2643 DriverHandle,
2644 &gEfiHiiConfigAccessProtocolGuid,
2645 (VOID **) &ConfigAccess
2646 );
2647 ASSERT_EFI_ERROR (Status);
2648
2649 Status = ConfigAccess->RouteConfig (
2650 ConfigAccess,
2651 ConfigResp,
2652 &AccessProgress
2653 );
2654
2655 if (EFI_ERROR (Status)) {
2656 //
2657 // AccessProgress indicates the parsing progress on <ConfigResp>.
2658 // Map it to the progress on <MultiConfigResp> then return it.
2659 //
2660 *Progress = StrStr (StringPtr, AccessProgress);
2661
2662 FreePool (ConfigResp);
2663 return Status;
2664 }
2665
2666 FreePool (ConfigResp);
2667 ConfigResp = NULL;
2668
2669 //
2670 // Go to next <ConfigResp> (skip '&').
2671 //
2672 StringPtr += Length;
2673 if (*StringPtr == 0) {
2674 *Progress = StringPtr;
2675 break;
2676 }
2677
2678 StringPtr++;
2679
2680 }
2681
2682 return EFI_SUCCESS;
2683 }
2684
2685
2686 /**
2687 This helper function is to be called by drivers to map configuration data
2688 stored in byte array ("block") formats such as UEFI Variables into current
2689 configuration strings.
2690
2691 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2692 instance.
2693 @param ConfigRequest A null-terminated Unicode string in
2694 <ConfigRequest> format.
2695 @param Block Array of bytes defining the block's configuration.
2696 @param BlockSize Length in bytes of Block.
2697 @param Config Filled-in configuration string. String allocated
2698 by the function. Returned only if call is
2699 successful. It is <ConfigResp> string format.
2700 @param Progress A pointer to a string filled in with the offset of
2701 the most recent & before the first failing
2702 name/value pair (or the beginning of the string if
2703 the failure is in the first name / value pair) or
2704 the terminating NULL if all was successful.
2705
2706 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2707 terminator at the end of the ConfigRequest
2708 string.
2709 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2710 points to the first character of ConfigRequest.
2711 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2712 Block parameter would result in this type of
2713 error. Progress points to the first character of
2714 ConfigRequest.
2715 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2716 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2717 Block is left updated and Progress points at
2718 the "&" preceding the first non-<BlockName>.
2719
2720 **/
2721 EFI_STATUS
2722 EFIAPI
2723 HiiBlockToConfig (
2724 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
2725 IN CONST EFI_STRING ConfigRequest,
2726 IN CONST UINT8 *Block,
2727 IN CONST UINTN BlockSize,
2728 OUT EFI_STRING *Config,
2729 OUT EFI_STRING *Progress
2730 )
2731 {
2732 HII_DATABASE_PRIVATE_DATA *Private;
2733 EFI_STRING StringPtr;
2734 UINTN Length;
2735 EFI_STATUS Status;
2736 EFI_STRING TmpPtr;
2737 UINT8 *TmpBuffer;
2738 UINTN Offset;
2739 UINTN Width;
2740 UINT8 *Value;
2741 EFI_STRING ValueStr;
2742 EFI_STRING ConfigElement;
2743 UINTN Index;
2744 UINT8 *TemBuffer;
2745 CHAR16 *TemString;
2746
2747 if (This == NULL || Progress == NULL || Config == NULL) {
2748 return EFI_INVALID_PARAMETER;
2749 }
2750
2751 if (Block == NULL || ConfigRequest == NULL) {
2752 *Progress = ConfigRequest;
2753 return EFI_INVALID_PARAMETER;
2754 }
2755
2756
2757 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
2758 ASSERT (Private != NULL);
2759
2760 StringPtr = ConfigRequest;
2761 ValueStr = NULL;
2762 Value = NULL;
2763 ConfigElement = NULL;
2764
2765 //
2766 // Allocate a fix length of memory to store Results. Reallocate memory for
2767 // Results if this fix length is insufficient.
2768 //
2769 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
2770 if (*Config == NULL) {
2771 return EFI_OUT_OF_RESOURCES;
2772 }
2773
2774 //
2775 // Jump <ConfigHdr>
2776 //
2777 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2778 *Progress = StringPtr;
2779 Status = EFI_INVALID_PARAMETER;
2780 goto Exit;
2781 }
2782 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
2783 StringPtr++;
2784 }
2785 if (*StringPtr == 0) {
2786 *Progress = StringPtr;
2787 Status = EFI_INVALID_PARAMETER;
2788 goto Exit;
2789 }
2790
2791 while (*StringPtr != L'&' && *StringPtr != 0) {
2792 StringPtr++;
2793 }
2794 if (*StringPtr == 0) {
2795 *Progress = StringPtr;
2796 Status = EFI_INVALID_PARAMETER;
2797 goto Exit;
2798 }
2799 //
2800 // Skip '&'
2801 //
2802 StringPtr++;
2803
2804 //
2805 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
2806 //
2807 Length = StringPtr - ConfigRequest;
2808 CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));
2809
2810 //
2811 // Parse each <RequestElement> if exists
2812 // Only <BlockName> format is supported by this help function.
2813 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
2814 //
2815 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
2816 //
2817 // Back up the header of one <BlockName>
2818 //
2819 TmpPtr = StringPtr;
2820
2821 StringPtr += StrLen (L"OFFSET=");
2822 //
2823 // Get Offset
2824 //
2825 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2826 if (Status == EFI_OUT_OF_RESOURCES) {
2827 *Progress = ConfigRequest;
2828 goto Exit;
2829 }
2830 Offset = 0;
2831 CopyMem (
2832 &Offset,
2833 TmpBuffer,
2834 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
2835 );
2836 FreePool (TmpBuffer);
2837
2838 StringPtr += Length;
2839 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
2840 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
2841 Status = EFI_INVALID_PARAMETER;
2842 goto Exit;
2843 }
2844 StringPtr += StrLen (L"&WIDTH=");
2845
2846 //
2847 // Get Width
2848 //
2849 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2850 if (Status == EFI_OUT_OF_RESOURCES) {
2851 *Progress = ConfigRequest;
2852 goto Exit;
2853 }
2854 Width = 0;
2855 CopyMem (
2856 &Width,
2857 TmpBuffer,
2858 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
2859 );
2860 FreePool (TmpBuffer);
2861
2862 StringPtr += Length;
2863 if (*StringPtr != 0 && *StringPtr != L'&') {
2864 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
2865 Status = EFI_INVALID_PARAMETER;
2866 goto Exit;
2867 }
2868
2869 //
2870 // Calculate Value and convert it to hex string.
2871 //
2872 if (Offset + Width > BlockSize) {
2873 *Progress = StringPtr;
2874 Status = EFI_DEVICE_ERROR;
2875 goto Exit;
2876 }
2877
2878 Value = (UINT8 *) AllocateZeroPool (Width);
2879 if (Value == NULL) {
2880 *Progress = ConfigRequest;
2881 Status = EFI_OUT_OF_RESOURCES;
2882 goto Exit;
2883 }
2884
2885 CopyMem (Value, (UINT8 *) Block + Offset, Width);
2886
2887 Length = Width * 2 + 1;
2888 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
2889 if (ValueStr == NULL) {
2890 *Progress = ConfigRequest;
2891 Status = EFI_OUT_OF_RESOURCES;
2892 goto Exit;
2893 }
2894
2895 TemString = ValueStr;
2896 TemBuffer = Value + Width - 1;
2897 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
2898 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
2899 }
2900
2901 FreePool (Value);
2902 Value = NULL;
2903
2904 //
2905 // Build a ConfigElement
2906 //
2907 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
2908 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
2909 if (ConfigElement == NULL) {
2910 Status = EFI_OUT_OF_RESOURCES;
2911 goto Exit;
2912 }
2913 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
2914 if (*StringPtr == 0) {
2915 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
2916 }
2917 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
2918 StrCat (ConfigElement, L"VALUE=");
2919 StrCat (ConfigElement, ValueStr);
2920
2921 AppendToMultiString (Config, ConfigElement);
2922
2923 FreePool (ConfigElement);
2924 FreePool (ValueStr);
2925 ConfigElement = NULL;
2926 ValueStr = NULL;
2927
2928 //
2929 // If '\0', parsing is finished. Otherwise skip '&' to continue
2930 //
2931 if (*StringPtr == 0) {
2932 break;
2933 }
2934 AppendToMultiString (Config, L"&");
2935 StringPtr++;
2936
2937 }
2938
2939 if (*StringPtr != 0) {
2940 *Progress = StringPtr - 1;
2941 Status = EFI_INVALID_PARAMETER;
2942 goto Exit;
2943 }
2944
2945 HiiToLower (*Config);
2946 *Progress = StringPtr;
2947 return EFI_SUCCESS;
2948
2949 Exit:
2950 FreePool (*Config);
2951 if (ValueStr != NULL) {
2952 FreePool (ValueStr);
2953 }
2954 if (Value != NULL) {
2955 FreePool (Value);
2956 }
2957 if (ConfigElement != NULL) {
2958 FreePool (ConfigElement);
2959 }
2960
2961 return Status;
2962
2963 }
2964
2965
2966 /**
2967 This helper function is to be called by drivers to map configuration strings
2968 to configurations stored in byte array ("block") formats such as UEFI Variables.
2969
2970 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2971 instance.
2972 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
2973 format. It can be ConfigAltResp format string.
2974 @param Block A possibly null array of bytes representing the
2975 current block. Only bytes referenced in the
2976 ConfigResp string in the block are modified. If
2977 this parameter is null or if the *BlockSize
2978 parameter is (on input) shorter than required by
2979 the Configuration string, only the BlockSize
2980 parameter is updated and an appropriate status
2981 (see below) is returned.
2982 @param BlockSize The length of the Block in units of UINT8. On
2983 input, this is the size of the Block. On output,
2984 if successful, contains the index of the last
2985 modified byte in the Block.
2986 @param Progress On return, points to an element of the ConfigResp
2987 string filled in with the offset of the most
2988 recent '&' before the first failing name / value
2989 pair (or the beginning of the string if the
2990 failure is in the first name / value pair) or the
2991 terminating NULL if all was successful.
2992
2993 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2994 terminator at the end of the ConfigResp string.
2995 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2996 points to the first character of ConfigResp.
2997 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
2998 Block parameter would result in this type of
2999 error. Progress points to the first character of
3000 ConfigResp.
3001 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3002 value pair. Block is left updated and
3003 Progress points at the '&' preceding the first
3004 non-<BlockName>.
3005
3006 **/
3007 EFI_STATUS
3008 EFIAPI
3009 HiiConfigToBlock (
3010 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3011 IN CONST EFI_STRING ConfigResp,
3012 IN OUT UINT8 *Block,
3013 IN OUT UINTN *BlockSize,
3014 OUT EFI_STRING *Progress
3015 )
3016 {
3017 HII_DATABASE_PRIVATE_DATA *Private;
3018 EFI_STRING StringPtr;
3019 UINTN Length;
3020 EFI_STATUS Status;
3021 UINT8 *TmpBuffer;
3022 UINTN Offset;
3023 UINTN Width;
3024 UINT8 *Value;
3025 UINTN BufferSize;
3026
3027 if (This == NULL || BlockSize == NULL || Progress == NULL) {
3028 return EFI_INVALID_PARAMETER;
3029 }
3030
3031 if (ConfigResp == NULL || Block == NULL) {
3032 *Progress = ConfigResp;
3033 return EFI_INVALID_PARAMETER;
3034 }
3035
3036 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3037 ASSERT (Private != NULL);
3038
3039 StringPtr = ConfigResp;
3040 BufferSize = *BlockSize;
3041 Value = NULL;
3042
3043 //
3044 // Jump <ConfigHdr>
3045 //
3046 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3047 *Progress = StringPtr;
3048 Status = EFI_INVALID_PARAMETER;
3049 goto Exit;
3050 }
3051 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
3052 StringPtr++;
3053 }
3054 if (*StringPtr == 0) {
3055 *Progress = StringPtr;
3056 Status = EFI_INVALID_PARAMETER;
3057 goto Exit;
3058 }
3059
3060 while (*StringPtr != L'&' && *StringPtr != 0) {
3061 StringPtr++;
3062 }
3063 if (*StringPtr == 0) {
3064 *Progress = StringPtr;
3065 Status = EFI_INVALID_PARAMETER;
3066 goto Exit;
3067 }
3068 //
3069 // Skip '&'
3070 //
3071 StringPtr++;
3072
3073 //
3074 // Parse each <ConfigElement> if exists
3075 // Only <BlockConfig> format is supported by this help function.
3076 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3077 //
3078 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
3079 StringPtr += StrLen (L"OFFSET=");
3080 //
3081 // Get Offset
3082 //
3083 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3084 if (EFI_ERROR (Status)) {
3085 *Progress = ConfigResp;
3086 goto Exit;
3087 }
3088 Offset = 0;
3089 CopyMem (
3090 &Offset,
3091 TmpBuffer,
3092 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3093 );
3094 FreePool (TmpBuffer);
3095
3096 StringPtr += Length;
3097 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3098 *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
3099 Status = EFI_INVALID_PARAMETER;
3100 goto Exit;
3101 }
3102 StringPtr += StrLen (L"&WIDTH=");
3103
3104 //
3105 // Get Width
3106 //
3107 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3108 if (Status == EFI_OUT_OF_RESOURCES) {
3109 *Progress = ConfigResp;
3110 goto Exit;
3111 }
3112 Width = 0;
3113 CopyMem (
3114 &Width,
3115 TmpBuffer,
3116 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
3117 );
3118 FreePool (TmpBuffer);
3119
3120 StringPtr += Length;
3121 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
3122 *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
3123 Status = EFI_INVALID_PARAMETER;
3124 goto Exit;
3125 }
3126 StringPtr += StrLen (L"&VALUE=");
3127
3128 //
3129 // Get Value
3130 //
3131 Status = GetValueOfNumber (StringPtr, &Value, &Length);
3132 if (EFI_ERROR (Status)) {
3133 *Progress = ConfigResp;
3134 goto Exit;
3135 }
3136
3137 StringPtr += Length;
3138 if (*StringPtr != 0 && *StringPtr != L'&') {
3139 *Progress = StringPtr - Length - 7;
3140 Status = EFI_INVALID_PARAMETER;
3141 goto Exit;
3142 }
3143
3144 //
3145 // Update the Block with configuration info
3146 //
3147
3148 if (Offset + Width > BufferSize) {
3149 return EFI_DEVICE_ERROR;
3150 }
3151
3152 CopyMem (Block + Offset, Value, Width);
3153 *BlockSize = Offset + Width - 1;
3154
3155 FreePool (Value);
3156 Value = NULL;
3157
3158 //
3159 // If '\0', parsing is finished. Otherwise skip '&' to continue
3160 //
3161 if (*StringPtr == 0) {
3162 break;
3163 }
3164
3165 StringPtr++;
3166 }
3167
3168 //
3169 // The input string is ConfigAltResp format.
3170 //
3171 if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) {
3172 *Progress = StringPtr - 1;
3173 Status = EFI_INVALID_PARAMETER;
3174 goto Exit;
3175 }
3176
3177 *Progress = StringPtr;
3178 return EFI_SUCCESS;
3179
3180 Exit:
3181
3182 if (Value != NULL) {
3183 FreePool (Value);
3184 }
3185 return Status;
3186 }
3187
3188
3189 /**
3190 This helper function is to be called by drivers to extract portions of
3191 a larger configuration string.
3192
3193 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3194 instance.
3195 @param Configuration A null-terminated Unicode string in
3196 <MultiConfigAltResp> format. It is <ConfigAltResp> format.
3197 @param Guid A pointer to the GUID value to search for in the
3198 routing portion of the ConfigResp string when
3199 retrieving the requested data. If Guid is NULL,
3200 then all GUID values will be searched for.
3201 @param Name A pointer to the NAME value to search for in the
3202 routing portion of the ConfigResp string when
3203 retrieving the requested data. If Name is NULL,
3204 then all Name values will be searched for.
3205 @param DevicePath A pointer to the PATH value to search for in the
3206 routing portion of the ConfigResp string when
3207 retrieving the requested data. If DevicePath is
3208 NULL, then all DevicePath values will be searched
3209 for.
3210 @param AltCfgId A pointer to the ALTCFG value to search for in the
3211 routing portion of the ConfigResp string when
3212 retrieving the requested data. If this parameter
3213 is NULL, then the current setting will be
3214 retrieved.
3215 @param AltCfgResp A pointer to a buffer which will be allocated by
3216 the function which contains the retrieved string
3217 as requested. This buffer is only allocated if
3218 the call was successful. It is <ConfigResp> format.
3219
3220 @retval EFI_SUCCESS The request succeeded. The requested data was
3221 extracted and placed in the newly allocated
3222 AltCfgResp buffer.
3223 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3224 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3225 @retval EFI_NOT_FOUND Target for the specified routing data was not
3226 found.
3227
3228 **/
3229 EFI_STATUS
3230 EFIAPI
3231 HiiGetAltCfg (
3232 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3233 IN CONST EFI_STRING Configuration,
3234 IN CONST EFI_GUID *Guid,
3235 IN CONST EFI_STRING Name,
3236 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3237 IN CONST UINT16 *AltCfgId,
3238 OUT EFI_STRING *AltCfgResp
3239 )
3240 {
3241 EFI_STATUS Status;
3242 EFI_STRING StringPtr;
3243 EFI_STRING HdrStart;
3244 EFI_STRING HdrEnd;
3245 EFI_STRING TmpPtr;
3246 UINTN Length;
3247 EFI_STRING GuidStr;
3248 EFI_STRING NameStr;
3249 EFI_STRING PathStr;
3250 EFI_STRING AltIdStr;
3251 EFI_STRING Result;
3252 BOOLEAN GuidFlag;
3253 BOOLEAN NameFlag;
3254 BOOLEAN PathFlag;
3255
3256 HdrStart = NULL;
3257 HdrEnd = NULL;
3258 GuidStr = NULL;
3259 NameStr = NULL;
3260 PathStr = NULL;
3261 AltIdStr = NULL;
3262 Result = NULL;
3263 GuidFlag = FALSE;
3264 NameFlag = FALSE;
3265 PathFlag = FALSE;
3266
3267 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
3268 return EFI_INVALID_PARAMETER;
3269 }
3270
3271 StringPtr = Configuration;
3272 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3273 return EFI_INVALID_PARAMETER;
3274 }
3275
3276 //
3277 // Generate the sub string for later matching.
3278 //
3279 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
3280 GenerateSubStr (
3281 L"PATH=",
3282 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3283 (VOID *) DevicePath,
3284 1,
3285 &PathStr
3286 );
3287 if (AltCfgId != NULL) {
3288 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
3289 }
3290 if (Name != NULL) {
3291 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
3292 } else {
3293 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3294 }
3295
3296 while (*StringPtr != 0) {
3297 //
3298 // Try to match the GUID
3299 //
3300 if (!GuidFlag) {
3301 TmpPtr = StrStr (StringPtr, GuidStr);
3302 if (TmpPtr == NULL) {
3303 Status = EFI_NOT_FOUND;
3304 goto Exit;
3305 }
3306 HdrStart = TmpPtr;
3307
3308 //
3309 // Jump to <NameHdr>
3310 //
3311 if (Guid != NULL) {
3312 StringPtr = TmpPtr + StrLen (GuidStr);
3313 } else {
3314 StringPtr = StrStr (TmpPtr, L"NAME=");
3315 if (StringPtr == NULL) {
3316 Status = EFI_NOT_FOUND;
3317 goto Exit;
3318 }
3319 }
3320 GuidFlag = TRUE;
3321 }
3322
3323 //
3324 // Try to match the NAME
3325 //
3326 if (GuidFlag && !NameFlag) {
3327 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
3328 GuidFlag = FALSE;
3329 } else {
3330 //
3331 // Jump to <PathHdr>
3332 //
3333 if (Name != NULL) {
3334 StringPtr += StrLen (NameStr);
3335 } else {
3336 StringPtr = StrStr (StringPtr, L"PATH=");
3337 if (StringPtr == NULL) {
3338 Status = EFI_NOT_FOUND;
3339 goto Exit;
3340 }
3341 }
3342 NameFlag = TRUE;
3343 }
3344 }
3345
3346 //
3347 // Try to match the DevicePath
3348 //
3349 if (GuidFlag && NameFlag && !PathFlag) {
3350 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
3351 GuidFlag = FALSE;
3352 NameFlag = FALSE;
3353 } else {
3354 //
3355 // Jump to '&' before <DescHdr> or <ConfigBody>
3356 //
3357 if (DevicePath != NULL) {
3358 StringPtr += StrLen (PathStr);
3359 } else {
3360 StringPtr = StrStr (StringPtr, L"&");
3361 if (StringPtr == NULL) {
3362 Status = EFI_NOT_FOUND;
3363 goto Exit;
3364 }
3365 StringPtr ++;
3366 }
3367 PathFlag = TRUE;
3368 HdrEnd = StringPtr;
3369 }
3370 }
3371
3372 //
3373 // Try to match the AltCfgId
3374 //
3375 if (GuidFlag && NameFlag && PathFlag) {
3376 if (AltCfgId == NULL) {
3377 //
3378 // Return Current Setting when AltCfgId is NULL.
3379 //
3380 Status = OutputConfigBody (StringPtr, &Result);
3381 goto Exit;
3382 }
3383 //
3384 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3385 //
3386 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
3387 GuidFlag = FALSE;
3388 NameFlag = FALSE;
3389 PathFlag = FALSE;
3390 } else {
3391 //
3392 // Skip AltIdStr and &
3393 //
3394 StringPtr = StringPtr + StrLen (AltIdStr);
3395 Status = OutputConfigBody (StringPtr, &Result);
3396 goto Exit;
3397 }
3398 }
3399 }
3400
3401 Status = EFI_NOT_FOUND;
3402
3403 Exit:
3404
3405 if (!EFI_ERROR (Status) && (Result != NULL)) {
3406 //
3407 // Copy the <ConfigHdr> and <ConfigBody>
3408 //
3409 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
3410 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3411 if (*AltCfgResp == NULL) {
3412 Status = EFI_OUT_OF_RESOURCES;
3413 } else {
3414 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
3415 StrCat (*AltCfgResp, Result);
3416 Status = EFI_SUCCESS;
3417 }
3418 }
3419
3420 if (GuidStr != NULL) {
3421 FreePool (GuidStr);
3422 }
3423 if (NameStr != NULL) {
3424 FreePool (NameStr);
3425 }
3426 if (PathStr != NULL) {
3427 FreePool (PathStr);
3428 }
3429 if (AltIdStr != NULL) {
3430 FreePool (AltIdStr);
3431 }
3432 if (Result != NULL) {
3433 FreePool (Result);
3434 }
3435
3436 return Status;
3437
3438 }
3439
3440