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