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