]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
2ed02cdaa4843c016cc55c75af90fce2070a79e7
[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 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate;
18
19 /**
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
22
23 This is a internal function.
24
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
27
28 @return The number of Unicode characters.
29
30 **/
31 UINTN
32 CalculateConfigStringLen (
33 IN EFI_STRING String
34 )
35 {
36 EFI_STRING TmpPtr;
37
38 //
39 // "GUID=" should be the first element of incoming string.
40 //
41 ASSERT (String != NULL);
42 ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
43
44 //
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
47 //
48 TmpPtr = StrStr (String, L"&GUID=");
49 if (TmpPtr == NULL) {
50 return StrLen (String);
51 }
52
53 return (TmpPtr - String);
54 }
55
56
57 /**
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
60
61 This is a internal function.
62
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
65
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
70 binary format.
71
72 **/
73 EFI_STATUS
74 GetDevicePath (
75 IN EFI_STRING String,
76 OUT UINT8 **DevicePathData
77 )
78 {
79 UINTN Length;
80 EFI_STRING PathHdr;
81 UINT8 *DevicePathBuffer;
82 CHAR16 TemStr[2];
83 UINTN Index;
84 UINT8 DigitUint8;
85 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
86
87
88 if (String == NULL || DevicePathData == NULL) {
89 return EFI_INVALID_PARAMETER;
90 }
91
92 //
93 // Find the 'PATH=' of <PathHdr> and skip it.
94 //
95 for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
96 if (*String == 0) {
97 return EFI_INVALID_PARAMETER;
98 }
99 //
100 // Check whether path data does exist.
101 //
102 String += StrLen (L"PATH=");
103 if (*String == 0) {
104 return EFI_INVALID_PARAMETER;
105 }
106 PathHdr = String;
107
108 //
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
112 //
113 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
114 //
115 // Check DevicePath Length
116 //
117 if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
118 return EFI_NOT_FOUND;
119 }
120
121 //
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
125 //
126 DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
127 if (DevicePathBuffer == NULL) {
128 return EFI_OUT_OF_RESOURCES;
129 }
130
131 //
132 // Convert DevicePath
133 //
134 ZeroMem (TemStr, sizeof (TemStr));
135 for (Index = 0; Index < Length; Index ++) {
136 TemStr[0] = PathHdr[Index];
137 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
138 if ((Index & 1) == 0) {
139 DevicePathBuffer [Index/2] = DigitUint8;
140 } else {
141 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
142 }
143 }
144
145 //
146 // Validate DevicePath
147 //
148 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;
149 while (!IsDevicePathEnd (DevicePath)) {
150 if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
151 //
152 // Invalid device path
153 //
154 FreePool (DevicePathBuffer);
155 return EFI_NOT_FOUND;
156 }
157 DevicePath = NextDevicePathNode (DevicePath);
158 }
159
160 //
161 // return the device path
162 //
163 *DevicePathData = DevicePathBuffer;
164 return EFI_SUCCESS;
165 }
166
167 /**
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
170
171 @param ConfigString String to be converted
172
173 **/
174 VOID
175 EFIAPI
176 HiiToLower (
177 IN EFI_STRING ConfigString
178 )
179 {
180 EFI_STRING String;
181 BOOLEAN Lower;
182
183 ASSERT (ConfigString != NULL);
184
185 //
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
187 //
188 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
189 if (*String == L'=') {
190 Lower = TRUE;
191 } else if (*String == L'&') {
192 Lower = FALSE;
193 } else if (Lower && *String >= L'A' && *String <= L'F') {
194 *String = (CHAR16) (*String - L'A' + L'a');
195 }
196 }
197
198 return;
199 }
200
201 /**
202 Generate a sub string then output it.
203
204 This is a internal function.
205
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
208
209 @param BufferLen The length of the Buffer in bytes.
210
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
213
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
217
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
220
221
222 **/
223 VOID
224 GenerateSubStr (
225 IN CONST EFI_STRING String,
226 IN UINTN BufferLen,
227 IN VOID *Buffer,
228 IN UINT8 Flag,
229 OUT EFI_STRING *SubStr
230 )
231 {
232 UINTN Length;
233 EFI_STRING Str;
234 EFI_STRING StringHeader;
235 CHAR16 *TemString;
236 CHAR16 *TemName;
237 UINT8 *TemBuffer;
238 UINTN Index;
239
240 ASSERT (String != NULL && SubStr != NULL);
241
242 if (Buffer == NULL) {
243 *SubStr = AllocateCopyPool (StrSize (String), String);
244 ASSERT (*SubStr != NULL);
245 return;
246 }
247
248 //
249 // Header + Data + '&' + '\0'
250 //
251 Length = StrLen (String) + BufferLen * 2 + 1 + 1;
252 Str = AllocateZeroPool (Length * sizeof (CHAR16));
253 ASSERT (Str != NULL);
254
255 StrCpy (Str, String);
256 Length = (BufferLen * 2 + 1) * sizeof (CHAR16);
257
258 StringHeader = Str + StrLen (String);
259 TemString = (CHAR16 *) StringHeader;
260
261 switch (Flag) {
262 case 1:
263 //
264 // Convert Buffer to Hex String in reverse order
265 //
266 TemBuffer = ((UINT8 *) Buffer);
267 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
268 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
269 }
270 break;
271 case 2:
272 //
273 // Check buffer is enough
274 //
275 TemName = (CHAR16 *) Buffer;
276 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
277 //
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 //
280 for (; *TemName != L'\0'; TemName++) {
281 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
282 }
283 break;
284 case 3:
285 //
286 // Convert Buffer to Hex String
287 //
288 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
289 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
290 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
291 }
292 break;
293 default:
294 break;
295 }
296
297 //
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 //
300 StrCat (Str, L"&");
301 HiiToLower (Str);
302
303 *SubStr = Str;
304 }
305
306
307 /**
308 Retrieve the <ConfigBody> from String then output it.
309
310 This is a internal function.
311
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
316
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
320
321 **/
322 EFI_STATUS
323 OutputConfigBody (
324 IN EFI_STRING String,
325 OUT EFI_STRING *ConfigBody
326 )
327 {
328 EFI_STRING TmpPtr;
329 EFI_STRING Result;
330 UINTN Length;
331
332 if (String == NULL || ConfigBody == NULL) {
333 return EFI_INVALID_PARAMETER;
334 }
335
336 //
337 // The setting information should start OFFSET, not ALTCFG.
338 //
339 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 TmpPtr = StrStr (String, L"GUID=");
344 if (TmpPtr == NULL) {
345 //
346 // It is the last <ConfigResp> of the incoming configuration string.
347 //
348 Result = AllocateCopyPool (StrSize (String), String);
349 if (Result == NULL) {
350 return EFI_OUT_OF_RESOURCES;
351 } else {
352 *ConfigBody = Result;
353 return EFI_SUCCESS;
354 }
355 }
356
357 Length = TmpPtr - String;
358 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
359 if (Result == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362
363 *(Result + Length - 1) = 0;
364 *ConfigBody = Result;
365 return EFI_SUCCESS;
366 }
367
368 /**
369 Append a string to a multi-string format.
370
371 This is a internal function.
372
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
377 might be updated.
378 @param AppendString NULL-terminated Unicode string.
379
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
382
383 **/
384 EFI_STATUS
385 AppendToMultiString (
386 IN OUT EFI_STRING *MultiString,
387 IN EFI_STRING AppendString
388 )
389 {
390 UINTN AppendStringSize;
391 UINTN MultiStringSize;
392
393 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
394 return EFI_INVALID_PARAMETER;
395 }
396
397 AppendStringSize = StrSize (AppendString);
398 MultiStringSize = StrSize (*MultiString);
399
400 //
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
402 //
403 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
404 MultiStringSize > MAX_STRING_LENGTH) {
405 *MultiString = (EFI_STRING) ReallocatePool (
406 MultiStringSize,
407 MultiStringSize + AppendStringSize,
408 (VOID *) (*MultiString)
409 );
410 ASSERT (*MultiString != NULL);
411 }
412 //
413 // Append the incoming string
414 //
415 StrCat (*MultiString, AppendString);
416
417 return EFI_SUCCESS;
418 }
419
420
421 /**
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
423 or WIDTH or VALUE.
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
425
426 This is a internal function.
427
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
431 to free memory.
432 @param Len Length of the <Number>, in characters.
433
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
435 structures.
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
437 successfully.
438
439 **/
440 EFI_STATUS
441 GetValueOfNumber (
442 IN EFI_STRING StringPtr,
443 OUT UINT8 **Number,
444 OUT UINTN *Len
445 )
446 {
447 EFI_STRING TmpPtr;
448 UINTN Length;
449 EFI_STRING Str;
450 UINT8 *Buf;
451 EFI_STATUS Status;
452 UINT8 DigitUint8;
453 UINTN Index;
454 CHAR16 TemStr[2];
455
456 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 Buf = NULL;
461
462 TmpPtr = StringPtr;
463 while (*StringPtr != L'\0' && *StringPtr != L'&') {
464 StringPtr++;
465 }
466 *Len = StringPtr - TmpPtr;
467 Length = *Len + 1;
468
469 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
470 if (Str == NULL) {
471 Status = EFI_OUT_OF_RESOURCES;
472 goto Exit;
473 }
474 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
475 *(Str + *Len) = L'\0';
476
477 Length = (Length + 1) / 2;
478 Buf = (UINT8 *) AllocateZeroPool (Length);
479 if (Buf == NULL) {
480 Status = EFI_OUT_OF_RESOURCES;
481 goto Exit;
482 }
483
484 Length = *Len;
485 ZeroMem (TemStr, sizeof (TemStr));
486 for (Index = 0; Index < Length; Index ++) {
487 TemStr[0] = Str[Length - Index - 1];
488 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
489 if ((Index & 1) == 0) {
490 Buf [Index/2] = DigitUint8;
491 } else {
492 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
493 }
494 }
495
496 *Number = Buf;
497 Status = EFI_SUCCESS;
498
499 Exit:
500 if (Str != NULL) {
501 FreePool (Str);
502 }
503
504 return Status;
505 }
506
507 /**
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
510
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
518
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
521 **/
522 EFI_STATUS
523 EFIAPI
524 MergeDefaultString (
525 IN OUT EFI_STRING *AltCfgResp,
526 IN EFI_STRING DefaultAltCfgResp
527 )
528 {
529 EFI_STRING StringPtrDefault;
530 EFI_STRING StringPtrEnd;
531 CHAR16 TempChar;
532 EFI_STRING StringPtr;
533 EFI_STRING AltConfigHdr;
534 UINTN HeaderLength;
535 UINTN SizeAltCfgResp;
536
537 if (*AltCfgResp == NULL) {
538 return EFI_INVALID_PARAMETER;
539 }
540
541 //
542 // Get the requestr ConfigHdr
543 //
544 SizeAltCfgResp = 0;
545 StringPtr = *AltCfgResp;
546
547 //
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
549 //
550 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER;
552 }
553 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
554 StringPtr++;
555 }
556 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
557 StringPtr++;
558 }
559 if (*StringPtr == L'\0') {
560 return EFI_INVALID_PARAMETER;
561 }
562 StringPtr += StrLen (L"&PATH=");
563 while (*StringPtr != L'\0' && *StringPtr != L'&') {
564 StringPtr ++;
565 }
566 HeaderLength = StringPtr - *AltCfgResp;
567
568 //
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
571 //
572 AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));
573 if (AltConfigHdr == NULL) {
574 return EFI_OUT_OF_RESOURCES;
575 }
576 StrCpy (AltConfigHdr, L"&");
577 StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);
578 StrCat (AltConfigHdr, L"&ALTCFG=");
579 HeaderLength = StrLen (AltConfigHdr);
580
581 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
582 while (StringPtrDefault != NULL) {
583 //
584 // Get AltCfg Name
585 //
586 StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);
587 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
588
589 //
590 // Append the found default value string to the input AltCfgResp
591 //
592 if (StringPtr == NULL) {
593 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
594 SizeAltCfgResp = StrSize (*AltCfgResp);
595 if (StringPtrEnd == NULL) {
596 //
597 // No more default string is found.
598 //
599 *AltCfgResp = (EFI_STRING) ReallocatePool (
600 SizeAltCfgResp,
601 SizeAltCfgResp + StrSize (StringPtrDefault),
602 (VOID *) (*AltCfgResp)
603 );
604 if (*AltCfgResp == NULL) {
605 FreePool (AltConfigHdr);
606 return EFI_OUT_OF_RESOURCES;
607 }
608 StrCat (*AltCfgResp, StringPtrDefault);
609 break;
610 } else {
611 TempChar = *StringPtrEnd;
612 *StringPtrEnd = L'\0';
613 *AltCfgResp = (EFI_STRING) ReallocatePool (
614 SizeAltCfgResp,
615 SizeAltCfgResp + StrSize (StringPtrDefault),
616 (VOID *) (*AltCfgResp)
617 );
618 if (*AltCfgResp == NULL) {
619 FreePool (AltConfigHdr);
620 return EFI_OUT_OF_RESOURCES;
621 }
622 StrCat (*AltCfgResp, StringPtrDefault);
623 *StringPtrEnd = TempChar;
624 }
625 }
626
627 //
628 // Find next AltCfg String
629 //
630 *(AltConfigHdr + HeaderLength) = L'\0';
631 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
632 }
633
634 FreePool (AltConfigHdr);
635 return EFI_SUCCESS;
636 }
637
638 /**
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.
640
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
643
644 **/
645 VOID
646 InsertDefaultValue (
647 IN IFR_BLOCK_DATA *BlockData,
648 IN IFR_DEFAULT_DATA *DefaultValueData
649 )
650 {
651 LIST_ENTRY *Link;
652 IFR_DEFAULT_DATA *DefaultValueArray;
653 LIST_ENTRY *DefaultLink;
654
655 DefaultLink = &BlockData->DefaultValueEntry;
656
657 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
658 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
659 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
660 //
661 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
662 //
663 if (DefaultValueData->Type > DefaultValueArray->Type) {
664 //
665 // Update the default value array in BlockData.
666 //
667 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
668 DefaultValueArray->Type = DefaultValueData->Type;
669 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
670 }
671 return;
672 }
673 }
674
675 //
676 // Insert new default value data in tail.
677 //
678 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
679 ASSERT (DefaultValueArray != NULL);
680 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
681 InsertTailList (Link, &DefaultValueArray->Entry);
682 }
683
684 /**
685 This function inserts new BlockData into the block link
686
687 @param BlockLink The list entry points to block array.
688 @param BlockData The point to BlockData is added.
689
690 **/
691 VOID
692 InsertBlockData (
693 IN LIST_ENTRY *BlockLink,
694 IN IFR_BLOCK_DATA **BlockData
695 )
696 {
697 LIST_ENTRY *Link;
698 IFR_BLOCK_DATA *BlockArray;
699 IFR_BLOCK_DATA *BlockSingleData;
700
701 BlockSingleData = *BlockData;
702
703 if (BlockSingleData->Name != NULL) {
704 InsertTailList (BlockLink, &BlockSingleData->Entry);
705 return;
706 }
707
708 //
709 // Insert block data in its Offset and Width order.
710 //
711 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
712 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
713 if (BlockArray->Offset == BlockSingleData->Offset) {
714 if (BlockArray->Width > BlockSingleData->Width) {
715 //
716 // Insert this block data in the front of block array
717 //
718 InsertTailList (Link, &BlockSingleData->Entry);
719 return;
720 }
721
722 if (BlockArray->Width == BlockSingleData->Width) {
723 //
724 // The same block array has been added.
725 //
726 if (BlockSingleData != BlockArray) {
727 FreePool (BlockSingleData);
728 *BlockData = BlockArray;
729 }
730 return;
731 }
732 } else if (BlockArray->Offset > BlockSingleData->Offset) {
733 //
734 // Insert new block data in the front of block array
735 //
736 InsertTailList (Link, &BlockSingleData->Entry);
737 return;
738 }
739 }
740
741 //
742 // Add new block data into the tail.
743 //
744 InsertTailList (Link, &BlockSingleData->Entry);
745 }
746
747 /**
748 Retrieves a pointer to the a Null-terminated ASCII string containing the list
749 of languages that an HII handle in the HII Database supports. The returned
750 string is allocated using AllocatePool(). The caller is responsible for freeing
751 the returned string using FreePool(). The format of the returned string follows
752 the language format assumed the HII Database.
753
754 If HiiHandle is NULL, then ASSERT().
755
756 @param[in] HiiHandle A handle that was previously registered in the HII Database.
757
758 @retval NULL HiiHandle is not registered in the HII database
759 @retval NULL There are not enough resources available to retrieve the suported
760 languages.
761 @retval NULL The list of suported languages could not be retrieved.
762 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
763
764 **/
765 CHAR8 *
766 GetSupportedLanguages (
767 IN EFI_HII_HANDLE HiiHandle
768 )
769 {
770 EFI_STATUS Status;
771 UINTN LanguageSize;
772 CHAR8 TempSupportedLanguages;
773 CHAR8 *SupportedLanguages;
774
775 ASSERT (HiiHandle != NULL);
776
777 //
778 // Retrieve the size required for the supported languages buffer.
779 //
780 LanguageSize = 0;
781 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
782
783 //
784 // If GetLanguages() returns EFI_SUCCESS for a zero size,
785 // then there are no supported languages registered for HiiHandle. If GetLanguages()
786 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
787 // in the HII Database
788 //
789 if (Status != EFI_BUFFER_TOO_SMALL) {
790 //
791 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
792 //
793 return NULL;
794 }
795
796 //
797 // Allocate the supported languages buffer.
798 //
799 SupportedLanguages = AllocateZeroPool (LanguageSize);
800 if (SupportedLanguages == NULL) {
801 //
802 // Return NULL if allocation fails.
803 //
804 return NULL;
805 }
806
807 //
808 // Retrieve the supported languages string
809 //
810 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
811 if (EFI_ERROR (Status)) {
812 //
813 // Free the buffer and return NULL if the supported languages can not be retrieved.
814 //
815 FreePool (SupportedLanguages);
816 return NULL;
817 }
818
819 //
820 // Return the Null-terminated ASCII string of supported languages
821 //
822 return SupportedLanguages;
823 }
824
825 /**
826 Retrieves a string from a string package.
827
828 If HiiHandle is NULL, then ASSERT().
829 If StringId is 0, then ASSET.
830
831 @param[in] HiiHandle A handle that was previously registered in the HII Database.
832 @param[in] StringId The identifier of the string to retrieved from the string
833 package associated with HiiHandle.
834
835 @retval NULL The string specified by StringId is not present in the string package.
836 @retval Other The string was returned.
837
838 **/
839 EFI_STRING
840 InternalGetString (
841 IN EFI_HII_HANDLE HiiHandle,
842 IN EFI_STRING_ID StringId
843 )
844 {
845 EFI_STATUS Status;
846 UINTN StringSize;
847 CHAR16 TempString;
848 EFI_STRING String;
849 CHAR8 *SupportedLanguages;
850 CHAR8 *PlatformLanguage;
851 CHAR8 *BestLanguage;
852 CHAR8 *Language;
853
854 ASSERT (HiiHandle != NULL);
855 ASSERT (StringId != 0);
856
857 //
858 // Initialize all allocated buffers to NULL
859 //
860 SupportedLanguages = NULL;
861 PlatformLanguage = NULL;
862 BestLanguage = NULL;
863 String = NULL;
864 Language = "";
865
866 //
867 // Get the languages that the package specified by HiiHandle supports
868 //
869 SupportedLanguages = GetSupportedLanguages (HiiHandle);
870 if (SupportedLanguages == NULL) {
871 goto Error;
872 }
873
874 //
875 // Get the current platform language setting
876 //
877 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
878
879 //
880 // Get the best matching language from SupportedLanguages
881 //
882 BestLanguage = GetBestLanguage (
883 SupportedLanguages,
884 FALSE, // RFC 4646 mode
885 Language, // Highest priority
886 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
887 SupportedLanguages, // Lowest priority
888 NULL
889 );
890 if (BestLanguage == NULL) {
891 goto Error;
892 }
893
894 //
895 // Retrieve the size of the string in the string package for the BestLanguage
896 //
897 StringSize = 0;
898 Status = mPrivate.HiiString.GetString (
899 &mPrivate.HiiString,
900 BestLanguage,
901 HiiHandle,
902 StringId,
903 &TempString,
904 &StringSize,
905 NULL
906 );
907 //
908 // If GetString() returns EFI_SUCCESS for a zero size,
909 // then there are no supported languages registered for HiiHandle. If GetString()
910 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
911 // in the HII Database
912 //
913 if (Status != EFI_BUFFER_TOO_SMALL) {
914 goto Error;
915 }
916
917 //
918 // Allocate a buffer for the return string
919 //
920 String = AllocateZeroPool (StringSize);
921 if (String == NULL) {
922 goto Error;
923 }
924
925 //
926 // Retrieve the string from the string package
927 //
928 Status = mPrivate.HiiString.GetString (
929 &mPrivate.HiiString,
930 BestLanguage,
931 HiiHandle,
932 StringId,
933 String,
934 &StringSize,
935 NULL
936 );
937 if (EFI_ERROR (Status)) {
938 //
939 // Free the buffer and return NULL if the supported languages can not be retrieved.
940 //
941 FreePool (String);
942 String = NULL;
943 }
944
945 Error:
946 //
947 // Free allocated buffers
948 //
949 if (SupportedLanguages != NULL) {
950 FreePool (SupportedLanguages);
951 }
952 if (PlatformLanguage != NULL) {
953 FreePool (PlatformLanguage);
954 }
955 if (BestLanguage != NULL) {
956 FreePool (BestLanguage);
957 }
958
959 //
960 // Return the Null-terminated Unicode string
961 //
962 return String;
963 }
964
965 /**
966 This function checks VarOffset and VarWidth is in the block range.
967
968 @param RequestBlockArray The block array is to be checked.
969 @param VarOffset Offset of var to the structure
970 @param VarWidth Width of var.
971 @param IsNameValueType Whether this varstore is name/value varstore or not.
972 @param HiiHandle Hii handle for this hii package.
973
974 @retval TRUE This Var is in the block range.
975 @retval FALSE This Var is not in the block range.
976 **/
977 BOOLEAN
978 BlockArrayCheck (
979 IN IFR_BLOCK_DATA *RequestBlockArray,
980 IN UINT16 VarOffset,
981 IN UINT16 VarWidth,
982 IN BOOLEAN IsNameValueType,
983 IN EFI_HII_HANDLE HiiHandle
984 )
985 {
986 LIST_ENTRY *Link;
987 IFR_BLOCK_DATA *BlockData;
988 EFI_STRING Name;
989
990 //
991 // No Request Block array, all vars are got.
992 //
993 if (RequestBlockArray == NULL) {
994 return TRUE;
995 }
996
997 //
998 // Check the input var is in the request block range.
999 //
1000 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
1001 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1002
1003 if (IsNameValueType) {
1004 Name = InternalGetString (HiiHandle, VarOffset);
1005 ASSERT (Name != NULL);
1006
1007 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
1008 FreePool (Name);
1009 return TRUE;
1010 }
1011 FreePool (Name);
1012 } else {
1013 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
1014 return TRUE;
1015 }
1016 }
1017 }
1018
1019 return FALSE;
1020 }
1021
1022 /**
1023 Get form package data from data base.
1024
1025 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1026 @param HiiFormPackage The buffer saves the package data.
1027 @param PackageSize The buffer size of the package data.
1028
1029 **/
1030 EFI_STATUS
1031 GetFormPackageData (
1032 IN HII_DATABASE_RECORD *DataBaseRecord,
1033 IN OUT UINT8 **HiiFormPackage,
1034 OUT UINTN *PackageSize
1035 )
1036 {
1037 EFI_STATUS Status;
1038 UINTN Size;
1039 UINTN ResultSize;
1040
1041 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
1042 return EFI_INVALID_PARAMETER;
1043 }
1044
1045 Size = 0;
1046 ResultSize = 0;
1047 //
1048 // 0. Get Hii Form Package by HiiHandle
1049 //
1050 Status = ExportFormPackages (
1051 &mPrivate,
1052 DataBaseRecord->Handle,
1053 DataBaseRecord->PackageList,
1054 0,
1055 Size,
1056 HiiFormPackage,
1057 &ResultSize
1058 );
1059 if (EFI_ERROR (Status)) {
1060 return Status;
1061 }
1062
1063 (*HiiFormPackage) = AllocatePool (ResultSize);
1064 if (*HiiFormPackage == NULL) {
1065 Status = EFI_OUT_OF_RESOURCES;
1066 return Status;
1067 }
1068
1069 //
1070 // Get HiiFormPackage by HiiHandle
1071 //
1072 Size = ResultSize;
1073 ResultSize = 0;
1074 Status = ExportFormPackages (
1075 &mPrivate,
1076 DataBaseRecord->Handle,
1077 DataBaseRecord->PackageList,
1078 0,
1079 Size,
1080 *HiiFormPackage,
1081 &ResultSize
1082 );
1083 if (EFI_ERROR (Status)) {
1084 FreePool (*HiiFormPackage);
1085 }
1086
1087 *PackageSize = Size;
1088
1089 return Status;
1090 }
1091
1092
1093 /**
1094 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1095
1096 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1097 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1098 the first found varstore will be as ConfigHdr.
1099 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1100 @param EfiVarStore The efi varstore info which will return.
1101 **/
1102 EFI_STATUS
1103 GetVarStoreType (
1104 IN HII_DATABASE_RECORD *DataBaseRecord,
1105 IN EFI_STRING ConfigHdr,
1106 OUT BOOLEAN *IsEfiVarstore,
1107 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
1108 )
1109 {
1110 EFI_STATUS Status;
1111 UINTN IfrOffset;
1112 UINTN PackageOffset;
1113 EFI_IFR_OP_HEADER *IfrOpHdr;
1114 CHAR16 *VarStoreName;
1115 EFI_STRING GuidStr;
1116 EFI_STRING NameStr;
1117 EFI_STRING TempStr;
1118 UINTN LengthString;
1119 UINT8 *HiiFormPackage;
1120 UINTN PackageSize;
1121 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1122 EFI_HII_PACKAGE_HEADER *PackageHeader;
1123
1124 HiiFormPackage = NULL;
1125 LengthString = 0;
1126 Status = EFI_SUCCESS;
1127 GuidStr = NULL;
1128 NameStr = NULL;
1129 TempStr = NULL;
1130 *IsEfiVarstore = FALSE;
1131
1132 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1133 if (EFI_ERROR (Status)) {
1134 return Status;
1135 }
1136
1137 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1138 PackageOffset = IfrOffset;
1139 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1140
1141 while (IfrOffset < PackageSize) {
1142 //
1143 // More than one form packages exist.
1144 //
1145 if (PackageOffset >= PackageHeader->Length) {
1146 //
1147 // Process the new form package.
1148 //
1149 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1150 IfrOffset += PackageOffset;
1151 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1152 }
1153
1154 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1155 IfrOffset += IfrOpHdr->Length;
1156 PackageOffset += IfrOpHdr->Length;
1157
1158 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1159 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1160 //
1161 // If the length is small than the structure, this is from old efi
1162 // varstore definition. Old efi varstore get config directly from
1163 // GetVariable function.
1164 //
1165 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1166 continue;
1167 }
1168
1169 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1170 if (VarStoreName == NULL) {
1171 Status = EFI_OUT_OF_RESOURCES;
1172 goto Done;
1173 }
1174 AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
1175
1176 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1177 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1178 LengthString = StrLen (GuidStr);
1179 LengthString = LengthString + StrLen (NameStr) + 1;
1180 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1181 if (TempStr == NULL) {
1182 FreePool (GuidStr);
1183 FreePool (NameStr);
1184 FreePool (VarStoreName);
1185 Status = EFI_OUT_OF_RESOURCES;
1186 goto Done;
1187 }
1188 StrCpy (TempStr, GuidStr);
1189 StrCat (TempStr, NameStr);
1190 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1191 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
1192 if (*EfiVarStore == NULL) {
1193 FreePool (VarStoreName);
1194 FreePool (GuidStr);
1195 FreePool (NameStr);
1196 FreePool (TempStr);
1197 Status = EFI_OUT_OF_RESOURCES;
1198 goto Done;
1199 }
1200 *IsEfiVarstore = TRUE;
1201 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1202 }
1203
1204 //
1205 // Free alllocated temp string.
1206 //
1207 FreePool (VarStoreName);
1208 FreePool (GuidStr);
1209 FreePool (NameStr);
1210 FreePool (TempStr);
1211
1212 //
1213 // Already found the varstore, break;
1214 //
1215 if (*IsEfiVarstore) {
1216 break;
1217 }
1218 }
1219 }
1220 Done:
1221 if (HiiFormPackage != NULL) {
1222 FreePool (HiiFormPackage);
1223 }
1224
1225 return Status;
1226 }
1227
1228 /**
1229 Check whether the ConfigRequest string has the request elements.
1230 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1231 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1232
1233 @param ConfigRequest The input config request string.
1234
1235 @retval TRUE The input include config request elements.
1236 @retval FALSE The input string not includes.
1237
1238 **/
1239 BOOLEAN
1240 GetElementsFromRequest (
1241 IN EFI_STRING ConfigRequest
1242 )
1243 {
1244 EFI_STRING TmpRequest;
1245
1246 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1247 ASSERT (TmpRequest != NULL);
1248
1249 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1250 return TRUE;
1251 }
1252
1253 return FALSE;
1254 }
1255
1256 /**
1257 Check whether the this varstore is the request varstore.
1258
1259 @param VarstoreGuid Varstore guid.
1260 @param Name Varstore name.
1261 @param ConfigHdr Current configRequest info.
1262
1263 @retval TRUE This varstore is the requst one.
1264 @retval FALSE This varstore is not the requst one.
1265
1266 **/
1267 BOOLEAN
1268 IsThisVarstore (
1269 IN EFI_GUID *VarstoreGuid,
1270 IN CHAR16 *Name,
1271 IN CHAR16 *ConfigHdr
1272 )
1273 {
1274 EFI_STRING GuidStr;
1275 EFI_STRING NameStr;
1276 EFI_STRING TempStr;
1277 UINTN LengthString;
1278 BOOLEAN RetVal;
1279
1280 RetVal = FALSE;
1281 GuidStr = NULL;
1282 TempStr = NULL;
1283
1284 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1285 if (Name != NULL) {
1286 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
1287 } else {
1288 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1289 }
1290 LengthString = StrLen (GuidStr);
1291 LengthString = LengthString + StrLen (NameStr) + 1;
1292 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1293 if (TempStr == NULL) {
1294 goto Done;
1295 }
1296
1297 StrCpy (TempStr, GuidStr);
1298 StrCat (TempStr, NameStr);
1299
1300 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1301 RetVal = TRUE;
1302 }
1303
1304 Done:
1305 if (GuidStr != NULL) {
1306 FreePool (GuidStr);
1307 }
1308
1309 if (NameStr != NULL) {
1310 FreePool (NameStr);
1311 }
1312
1313 if (TempStr != NULL) {
1314 FreePool (TempStr);
1315 }
1316
1317 return RetVal;
1318 }
1319
1320 /**
1321 Check whether the this op code is required.
1322
1323 @param RequestBlockArray The array includes all the request info or NULL.
1324 @param HiiHandle The hii handle for this form package.
1325 @param VarStorageData The varstore data strucure.
1326 @param IfrOpHdr Ifr opcode header for this opcode.
1327 @param VarWidth The buffer width for this opcode.
1328 @param ReturnData The data block added for this opcode.
1329
1330 @retval EFI_SUCCESS This opcode is required.
1331 @retval Others This opcode is not required or error occur.
1332
1333 **/
1334 EFI_STATUS
1335 IsThisOpcodeRequired (
1336 IN IFR_BLOCK_DATA *RequestBlockArray,
1337 IN EFI_HII_HANDLE HiiHandle,
1338 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1339 IN EFI_IFR_OP_HEADER *IfrOpHdr,
1340 IN UINT16 VarWidth,
1341 OUT IFR_BLOCK_DATA **ReturnData
1342 )
1343 {
1344 IFR_BLOCK_DATA *BlockData;
1345 UINT16 VarOffset;
1346 EFI_STRING_ID NameId;
1347 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
1348
1349 NameId = 0;
1350 VarOffset = 0;
1351 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
1352
1353 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1354 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
1355
1356 //
1357 // Check whether this question is in requested block array.
1358 //
1359 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
1360 //
1361 // This question is not in the requested string. Skip it.
1362 //
1363 return EFI_SUCCESS;
1364 }
1365 } else {
1366 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
1367
1368 //
1369 // Check whether this question is in requested block array.
1370 //
1371 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
1372 //
1373 // This question is not in the requested string. Skip it.
1374 //
1375 return EFI_SUCCESS;
1376 }
1377
1378 //
1379 // Check this var question is in the var storage
1380 //
1381 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
1382 return EFI_INVALID_PARAMETER;
1383 }
1384 }
1385
1386 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
1387 if (BlockData == NULL) {
1388 return EFI_OUT_OF_RESOURCES;
1389 }
1390
1391 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1392 BlockData->Name = InternalGetString(HiiHandle, NameId);
1393 } else {
1394 BlockData->Offset = VarOffset;
1395 }
1396
1397 BlockData->Width = VarWidth;
1398 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
1399 BlockData->OpCode = IfrOpHdr->OpCode;
1400 BlockData->Scope = IfrOpHdr->Scope;
1401 InitializeListHead (&BlockData->DefaultValueEntry);
1402 //
1403 // Add Block Data into VarStorageData BlockEntry
1404 //
1405 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
1406 *ReturnData = BlockData;
1407
1408 return EFI_SUCCESS;
1409 }
1410
1411 /**
1412 This function parses Form Package to get the block array and the default
1413 value array according to the request ConfigHdr.
1414
1415 @param HiiHandle Hii Handle for this hii package.
1416 @param Package Pointer to the form package data.
1417 @param PackageLength Length of the pacakge.
1418 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1419 the first found varstore will be as ConfigHdr.
1420 @param RequestBlockArray The block array is retrieved from the request string.
1421 @param VarStorageData VarStorage structure contains the got block and default value.
1422 @param DefaultIdArray Point to the got default id and default name array.
1423
1424 @retval EFI_SUCCESS The block array and the default value array are got.
1425 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1426 are conflicted.
1427 @retval EFI_OUT_OF_RESOURCES No enough memory.
1428 **/
1429 EFI_STATUS
1430 EFIAPI
1431 ParseIfrData (
1432 IN EFI_HII_HANDLE HiiHandle,
1433 IN UINT8 *Package,
1434 IN UINT32 PackageLength,
1435 IN EFI_STRING ConfigHdr,
1436 IN IFR_BLOCK_DATA *RequestBlockArray,
1437 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1438 OUT IFR_DEFAULT_DATA *DefaultIdArray
1439 )
1440 {
1441 EFI_STATUS Status;
1442 UINTN IfrOffset;
1443 UINTN PackageOffset;
1444 EFI_IFR_VARSTORE *IfrVarStore;
1445 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1446 EFI_IFR_OP_HEADER *IfrOpHdr;
1447 EFI_IFR_ONE_OF *IfrOneOf;
1448 EFI_IFR_REF4 *IfrRef;
1449 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
1450 EFI_IFR_DEFAULT *IfrDefault;
1451 EFI_IFR_ORDERED_LIST *IfrOrderedList;
1452 EFI_IFR_CHECKBOX *IfrCheckBox;
1453 EFI_IFR_PASSWORD *IfrPassword;
1454 EFI_IFR_STRING *IfrString;
1455 EFI_IFR_DATE *IfrDate;
1456 EFI_IFR_TIME *IfrTime;
1457 IFR_DEFAULT_DATA DefaultData;
1458 IFR_DEFAULT_DATA *DefaultDataPtr;
1459 IFR_BLOCK_DATA *BlockData;
1460 CHAR16 *VarStoreName;
1461 UINT16 VarWidth;
1462 UINT16 VarDefaultId;
1463 BOOLEAN FirstOneOfOption;
1464 LIST_ENTRY *LinkData;
1465 LIST_ENTRY *LinkDefault;
1466 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1467 EFI_HII_PACKAGE_HEADER *PackageHeader;
1468 EFI_VARSTORE_ID VarStoreId;
1469
1470 Status = EFI_SUCCESS;
1471 BlockData = NULL;
1472 DefaultDataPtr = NULL;
1473 FirstOneOfOption = FALSE;
1474 VarStoreId = 0;
1475 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
1476
1477 //
1478 // Go through the form package to parse OpCode one by one.
1479 //
1480 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1481 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
1482 IfrOffset = PackageOffset;
1483 while (IfrOffset < PackageLength) {
1484
1485 //
1486 // More than one form package found.
1487 //
1488 if (PackageOffset >= PackageHeader->Length) {
1489 //
1490 // Already found varstore for this request, break;
1491 //
1492 if (VarStoreId != 0) {
1493 VarStoreId = 0;
1494 }
1495
1496 //
1497 // Get next package header info.
1498 //
1499 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
1500 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1501 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
1502 }
1503
1504 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
1505 switch (IfrOpHdr->OpCode) {
1506 case EFI_IFR_VARSTORE_OP:
1507 //
1508 // VarStore is found. Don't need to search any more.
1509 //
1510 if (VarStoreId != 0) {
1511 break;
1512 }
1513
1514 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1515
1516 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
1517 if (VarStoreName == NULL) {
1518 Status = EFI_OUT_OF_RESOURCES;
1519 goto Done;
1520 }
1521 AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
1522
1523 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1524 //
1525 // Find the matched VarStore
1526 //
1527 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
1528 VarStorageData->Size = IfrVarStore->Size;
1529 VarStorageData->Name = VarStoreName;
1530 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
1531 VarStoreId = IfrVarStore->VarStoreId;
1532 }
1533 break;
1534
1535 case EFI_IFR_VARSTORE_EFI_OP:
1536 //
1537 // VarStore is found. Don't need to search any more.
1538 //
1539 if (VarStoreId != 0) {
1540 break;
1541 }
1542
1543 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1544
1545 //
1546 // If the length is small than the structure, this is from old efi
1547 // varstore definition. Old efi varstore get config directly from
1548 // GetVariable function.
1549 //
1550 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1551 break;
1552 }
1553
1554 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
1555 if (VarStoreName == NULL) {
1556 Status = EFI_OUT_OF_RESOURCES;
1557 goto Done;
1558 }
1559 AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
1560
1561 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1562 //
1563 // Find the matched VarStore
1564 //
1565 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
1566 VarStorageData->Size = IfrEfiVarStore->Size;
1567 VarStorageData->Name = VarStoreName;
1568 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
1569 VarStoreId = IfrEfiVarStore->VarStoreId;
1570 }
1571 break;
1572
1573 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1574 //
1575 // VarStore is found. Don't need to search any more.
1576 //
1577 if (VarStoreId != 0) {
1578 break;
1579 }
1580
1581 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1582
1583 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1584 //
1585 // Find the matched VarStore
1586 //
1587 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
1588 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
1589 VarStoreId = IfrNameValueVarStore->VarStoreId;
1590 }
1591 break;
1592
1593 case EFI_IFR_DEFAULTSTORE_OP:
1594 //
1595 // Add new the map between default id and default name.
1596 //
1597 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1598 if (DefaultDataPtr == NULL) {
1599 Status = EFI_OUT_OF_RESOURCES;
1600 goto Done;
1601 }
1602 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
1603 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
1604 DefaultDataPtr = NULL;
1605 break;
1606
1607 case EFI_IFR_FORM_OP:
1608 case EFI_IFR_FORM_MAP_OP:
1609 //
1610 // No matched varstore is found and directly return.
1611 //
1612 if ( VarStoreId == 0) {
1613 Status = EFI_SUCCESS;
1614 goto Done;
1615 }
1616 break;
1617
1618 case EFI_IFR_REF_OP:
1619 //
1620 // Ref question is not in IFR Form. This IFR form is not valid.
1621 //
1622 if ( VarStoreId == 0) {
1623 Status = EFI_INVALID_PARAMETER;
1624 goto Done;
1625 }
1626 //
1627 // Check whether this question is for the requested varstore.
1628 //
1629 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
1630 if (IfrRef->Question.VarStoreId != VarStoreId) {
1631 break;
1632 }
1633 VarWidth = (UINT16) (sizeof (EFI_HII_REF));
1634
1635 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1636 if (EFI_ERROR (Status)) {
1637 goto Done;
1638 }
1639 break;
1640
1641 case EFI_IFR_ONE_OF_OP:
1642 case EFI_IFR_NUMERIC_OP:
1643 //
1644 // Numeric and OneOf has the same opcode structure.
1645 //
1646
1647 //
1648 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1649 //
1650 if (VarStoreId == 0) {
1651 Status = EFI_INVALID_PARAMETER;
1652 goto Done;
1653 }
1654 //
1655 // Check whether this question is for the requested varstore.
1656 //
1657 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
1658 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
1659 break;
1660 }
1661 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
1662
1663 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1664 if (EFI_ERROR (Status)) {
1665 goto Done;
1666 }
1667
1668 if (BlockData == NULL) {
1669 //
1670 // BlockData == NULL means this opcode is not in the requst array.
1671 //
1672 break;
1673 }
1674
1675 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
1676 //
1677 // Set this flag to TRUE for the first oneof option.
1678 //
1679 FirstOneOfOption = TRUE;
1680 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
1681 //
1682 // Numeric minimum value will be used as default value when no default is specified.
1683 //
1684 DefaultData.Type = DefaultValueFromDefault;
1685 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
1686 case EFI_IFR_NUMERIC_SIZE_1:
1687 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
1688 break;
1689
1690 case EFI_IFR_NUMERIC_SIZE_2:
1691 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
1692 break;
1693
1694 case EFI_IFR_NUMERIC_SIZE_4:
1695 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
1696 break;
1697
1698 case EFI_IFR_NUMERIC_SIZE_8:
1699 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
1700 break;
1701
1702 default:
1703 Status = EFI_INVALID_PARAMETER;
1704 goto Done;
1705 }
1706 //
1707 // Set default value base on the DefaultId list get from IFR data.
1708 //
1709 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
1710 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
1711 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
1712 InsertDefaultValue (BlockData, &DefaultData);
1713 }
1714 }
1715 break;
1716
1717 case EFI_IFR_ORDERED_LIST_OP:
1718 //
1719 // offset by question header
1720 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1721 // no default value and default id, how to define its default value?
1722 //
1723
1724 //
1725 // OrderedList question is not in IFR Form. This IFR form is not valid.
1726 //
1727 if (VarStoreId == 0) {
1728 Status = EFI_INVALID_PARAMETER;
1729 goto Done;
1730 }
1731 //
1732 // Check whether this question is for the requested varstore.
1733 //
1734 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
1735 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
1736 BlockData = NULL;
1737 break;
1738 }
1739 VarWidth = IfrOrderedList->MaxContainers;
1740 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1741 if (EFI_ERROR (Status)) {
1742 goto Done;
1743 }
1744 break;
1745
1746 case EFI_IFR_CHECKBOX_OP:
1747 //
1748 // EFI_IFR_DEFAULT_OP
1749 // offset by question header
1750 // width is 1 sizeof (BOOLEAN)
1751 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1752 // value by DefaultOption
1753 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1754 //
1755
1756 //
1757 // CheckBox question is not in IFR Form. This IFR form is not valid.
1758 //
1759 if (VarStoreId == 0) {
1760 Status = EFI_INVALID_PARAMETER;
1761 goto Done;
1762 }
1763 //
1764 // Check whether this question is for the requested varstore.
1765 //
1766 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
1767 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
1768 break;
1769 }
1770 VarWidth = (UINT16) sizeof (BOOLEAN);
1771 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1772 if (EFI_ERROR (Status)) {
1773 goto Done;
1774 }
1775
1776 if (BlockData == NULL) {
1777 //
1778 // BlockData == NULL means this opcode is not in the requst array.
1779 //
1780 break;
1781 }
1782
1783 //
1784 // Add default value for standard ID by CheckBox Flag
1785 //
1786 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
1787 //
1788 // Prepare new DefaultValue
1789 //
1790 DefaultData.DefaultId = VarDefaultId;
1791 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
1792 //
1793 // When flag is set, defautl value is TRUE.
1794 //
1795 DefaultData.Type = DefaultValueFromFlag;
1796 DefaultData.Value.b = TRUE;
1797 } else {
1798 //
1799 // When flag is not set, defautl value is FASLE.
1800 //
1801 DefaultData.Type = DefaultValueFromDefault;
1802 DefaultData.Value.b = FALSE;
1803 }
1804 //
1805 // Add DefaultValue into current BlockData
1806 //
1807 InsertDefaultValue (BlockData, &DefaultData);
1808
1809 //
1810 // Add default value for Manufacture ID by CheckBox Flag
1811 //
1812 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
1813 //
1814 // Prepare new DefaultValue
1815 //
1816 DefaultData.DefaultId = VarDefaultId;
1817 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
1818 //
1819 // When flag is set, defautl value is TRUE.
1820 //
1821 DefaultData.Type = DefaultValueFromFlag;
1822 DefaultData.Value.b = TRUE;
1823 } else {
1824 //
1825 // When flag is not set, defautl value is FASLE.
1826 //
1827 DefaultData.Type = DefaultValueFromDefault;
1828 DefaultData.Value.b = FALSE;
1829 }
1830 //
1831 // Add DefaultValue into current BlockData
1832 //
1833 InsertDefaultValue (BlockData, &DefaultData);
1834 break;
1835
1836 case EFI_IFR_DATE_OP:
1837 //
1838 // offset by question header
1839 // width MaxSize * sizeof (CHAR16)
1840 // no default value, only block array
1841 //
1842
1843 //
1844 // Date question is not in IFR Form. This IFR form is not valid.
1845 //
1846 if (VarStoreId == 0) {
1847 Status = EFI_INVALID_PARAMETER;
1848 goto Done;
1849 }
1850 //
1851 // Check whether this question is for the requested varstore.
1852 //
1853 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
1854 if (IfrDate->Question.VarStoreId != VarStoreId) {
1855 break;
1856 }
1857
1858 VarWidth = (UINT16) sizeof (EFI_HII_DATE);
1859 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1860 if (EFI_ERROR (Status)) {
1861 goto Done;
1862 }
1863 break;
1864
1865 case EFI_IFR_TIME_OP:
1866 //
1867 // offset by question header
1868 // width MaxSize * sizeof (CHAR16)
1869 // no default value, only block array
1870 //
1871
1872 //
1873 // Time question is not in IFR Form. This IFR form is not valid.
1874 //
1875 if (VarStoreId == 0) {
1876 Status = EFI_INVALID_PARAMETER;
1877 goto Done;
1878 }
1879 //
1880 // Check whether this question is for the requested varstore.
1881 //
1882 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
1883 if (IfrTime->Question.VarStoreId != VarStoreId) {
1884 break;
1885 }
1886
1887 VarWidth = (UINT16) sizeof (EFI_HII_TIME);
1888 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1889 if (EFI_ERROR (Status)) {
1890 goto Done;
1891 }
1892 break;
1893
1894 case EFI_IFR_STRING_OP:
1895 //
1896 // offset by question header
1897 // width MaxSize * sizeof (CHAR16)
1898 // no default value, only block array
1899 //
1900
1901 //
1902 // String question is not in IFR Form. This IFR form is not valid.
1903 //
1904 if (VarStoreId == 0) {
1905 Status = EFI_INVALID_PARAMETER;
1906 goto Done;
1907 }
1908 //
1909 // Check whether this question is for the requested varstore.
1910 //
1911 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
1912 if (IfrString->Question.VarStoreId != VarStoreId) {
1913 break;
1914 }
1915
1916 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
1917 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1918 if (EFI_ERROR (Status)) {
1919 goto Done;
1920 }
1921
1922 //
1923 // No default value for string.
1924 //
1925 BlockData = NULL;
1926 break;
1927
1928 case EFI_IFR_PASSWORD_OP:
1929 //
1930 // offset by question header
1931 // width MaxSize * sizeof (CHAR16)
1932 // no default value, only block array
1933 //
1934
1935 //
1936 // Password question is not in IFR Form. This IFR form is not valid.
1937 //
1938 if (VarStoreId == 0) {
1939 Status = EFI_INVALID_PARAMETER;
1940 goto Done;
1941 }
1942 //
1943 // Check whether this question is for the requested varstore.
1944 //
1945 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
1946 if (IfrPassword->Question.VarStoreId != VarStoreId) {
1947 break;
1948 }
1949
1950 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
1951 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
1952 if (EFI_ERROR (Status)) {
1953 goto Done;
1954 }
1955
1956 //
1957 // No default value for string.
1958 //
1959 BlockData = NULL;
1960 break;
1961
1962 case EFI_IFR_ONE_OF_OPTION_OP:
1963 //
1964 // No matched block data is ignored.
1965 //
1966 if (BlockData == NULL || BlockData->Scope == 0) {
1967 break;
1968 }
1969
1970 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
1971 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
1972 //
1973 // Get ordered list option data type.
1974 //
1975 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
1976 VarWidth = 1;
1977 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1978 VarWidth = 2;
1979 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1980 VarWidth = 4;
1981 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1982 VarWidth = 8;
1983 } else {
1984 //
1985 // Invalid ordered list option data type.
1986 //
1987 Status = EFI_INVALID_PARAMETER;
1988 if (BlockData->Name != NULL) {
1989 FreePool (BlockData->Name);
1990 }
1991 FreePool (BlockData);
1992 goto Done;
1993 }
1994
1995 //
1996 // Calculate Ordered list QuestionId width.
1997 //
1998 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
1999 //
2000 // Check whether this question is in requested block array.
2001 //
2002 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2003 //
2004 // This question is not in the requested string. Skip it.
2005 //
2006 if (BlockData->Name != NULL) {
2007 FreePool (BlockData->Name);
2008 }
2009 FreePool (BlockData);
2010 BlockData = NULL;
2011 break;
2012 }
2013 //
2014 // Check this var question is in the var storage
2015 //
2016 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2017 Status = EFI_INVALID_PARAMETER;
2018 if (BlockData->Name != NULL) {
2019 FreePool (BlockData->Name);
2020 }
2021 FreePool (BlockData);
2022 goto Done;
2023 }
2024 //
2025 // Add Block Data into VarStorageData BlockEntry
2026 //
2027 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2028 //
2029 // No default data for OrderedList.
2030 //
2031 BlockData = NULL;
2032 break;
2033 }
2034
2035 //
2036 // 1. Set default value for OneOf option when flag field has default attribute.
2037 //
2038 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2039 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
2040 //
2041 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2042 // The first oneof option value will be used as default value when no default value is specified.
2043 //
2044 FirstOneOfOption = FALSE;
2045
2046 // Prepare new DefaultValue
2047 //
2048 DefaultData.Type = DefaultValueFromFlag;
2049 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2050 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
2051 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2052 InsertDefaultValue (BlockData, &DefaultData);
2053 }
2054 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
2055 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2056 InsertDefaultValue (BlockData, &DefaultData);
2057 }
2058 }
2059
2060 //
2061 // 2. Set as the default value when this is the first option.
2062 // The first oneof option value will be used as default value when no default value is specified.
2063 //
2064 if (FirstOneOfOption) {
2065 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2066 FirstOneOfOption = FALSE;
2067
2068 //
2069 // Prepare new DefaultValue
2070 //
2071 DefaultData.Type = DefaultValueFromDefault;
2072 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2073 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2074 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2075 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2076 InsertDefaultValue (BlockData, &DefaultData);
2077 }
2078 }
2079 break;
2080
2081 case EFI_IFR_DEFAULT_OP:
2082 //
2083 // Update Current BlockData to the default value.
2084 //
2085 if (BlockData == NULL || BlockData->Scope == 0) {
2086 //
2087 // No matched block data is ignored.
2088 //
2089 break;
2090 }
2091
2092 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2093 //
2094 // OrderedList Opcode is no default value.
2095 //
2096 break;
2097 }
2098 //
2099 // Get the DefaultId
2100 //
2101 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
2102 VarDefaultId = IfrDefault->DefaultId;
2103 //
2104 // Prepare new DefaultValue
2105 //
2106 DefaultData.Type = DefaultValueFromOpcode;
2107 DefaultData.DefaultId = VarDefaultId;
2108 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2109
2110 // If the value field is expression, set the cleaned flag.
2111 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
2112 DefaultData.Cleaned = TRUE;
2113 }
2114 //
2115 // Add DefaultValue into current BlockData
2116 //
2117 InsertDefaultValue (BlockData, &DefaultData);
2118
2119 //
2120 // After insert the default value, reset the cleaned value for next
2121 // time used. If not set here, need to set the value before everytime
2122 // use it.
2123 //
2124 DefaultData.Cleaned = FALSE;
2125 break;
2126
2127 case EFI_IFR_END_OP:
2128 //
2129 // End Opcode is for Var question.
2130 //
2131 if (BlockData != NULL && BlockData->Scope > 0) {
2132 BlockData->Scope--;
2133 }
2134 break;
2135
2136 default:
2137 if (BlockData != NULL && BlockData->Scope > 0) {
2138 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
2139 }
2140 break;
2141 }
2142
2143 IfrOffset += IfrOpHdr->Length;
2144 PackageOffset += IfrOpHdr->Length;
2145 }
2146
2147 Done:
2148 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2149 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2150 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
2151 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2152 LinkDefault = LinkDefault->ForwardLink;
2153 if (DefaultDataPtr->Cleaned == TRUE) {
2154 RemoveEntryList (&DefaultDataPtr->Entry);
2155 FreePool (DefaultDataPtr);
2156 }
2157 }
2158 }
2159
2160 return Status;
2161 }
2162
2163 /**
2164 parse the configrequest string, get the elements.
2165
2166 @param ConfigRequest The input configrequest string.
2167 @param Progress Return the progress data.
2168
2169 @retval Block data pointer.
2170 **/
2171 IFR_BLOCK_DATA *
2172 GetBlockElement (
2173 IN EFI_STRING ConfigRequest,
2174 OUT EFI_STRING *Progress
2175 )
2176 {
2177 EFI_STRING StringPtr;
2178 IFR_BLOCK_DATA *BlockData;
2179 IFR_BLOCK_DATA *RequestBlockArray;
2180 EFI_STATUS Status;
2181 UINT8 *TmpBuffer;
2182 UINT16 Offset;
2183 UINT16 Width;
2184 LIST_ENTRY *Link;
2185 IFR_BLOCK_DATA *NextBlockData;
2186 UINTN Length;
2187
2188 //
2189 // Init RequestBlockArray
2190 //
2191 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2192 if (RequestBlockArray == NULL) {
2193 goto Done;
2194 }
2195 InitializeListHead (&RequestBlockArray->Entry);
2196
2197 //
2198 // Get the request Block array from the request string
2199 // Offset and Width
2200 //
2201
2202 //
2203 // Parse each <RequestElement> if exists
2204 // Only <BlockName> format is supported by this help function.
2205 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2206 //
2207 StringPtr = ConfigRequest;
2208 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
2209 //
2210 // Skip the OFFSET string
2211 //
2212 *Progress = StringPtr;
2213 StringPtr += StrLen (L"&OFFSET=");
2214 //
2215 // Get Offset
2216 //
2217 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2218 if (EFI_ERROR (Status)) {
2219 goto Done;
2220 }
2221 Offset = 0;
2222 CopyMem (
2223 &Offset,
2224 TmpBuffer,
2225 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2226 );
2227 FreePool (TmpBuffer);
2228
2229 StringPtr += Length;
2230 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
2231 goto Done;
2232 }
2233 StringPtr += StrLen (L"&WIDTH=");
2234
2235 //
2236 // Get Width
2237 //
2238 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2239 if (EFI_ERROR (Status)) {
2240 goto Done;
2241 }
2242 Width = 0;
2243 CopyMem (
2244 &Width,
2245 TmpBuffer,
2246 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2247 );
2248 FreePool (TmpBuffer);
2249
2250 StringPtr += Length;
2251 if (*StringPtr != 0 && *StringPtr != L'&') {
2252 goto Done;
2253 }
2254
2255 //
2256 // Set Block Data
2257 //
2258 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2259 if (BlockData == NULL) {
2260 goto Done;
2261 }
2262 BlockData->Offset = Offset;
2263 BlockData->Width = Width;
2264 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
2265
2266 //
2267 // Skip &VALUE string if &VALUE does exists.
2268 //
2269 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
2270 StringPtr += StrLen (L"&VALUE=");
2271
2272 //
2273 // Get Value
2274 //
2275 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2276 if (EFI_ERROR (Status)) {
2277 goto Done;
2278 }
2279
2280 StringPtr += Length;
2281 if (*StringPtr != 0 && *StringPtr != L'&') {
2282 goto Done;
2283 }
2284 }
2285 //
2286 // If '\0', parsing is finished.
2287 //
2288 if (*StringPtr == 0) {
2289 break;
2290 }
2291 }
2292
2293 //
2294 // Merge the requested block data.
2295 //
2296 Link = RequestBlockArray->Entry.ForwardLink;
2297 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
2298 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2299 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
2300 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
2301 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
2302 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
2303 }
2304 RemoveEntryList (Link->ForwardLink);
2305 FreePool (NextBlockData);
2306 continue;
2307 }
2308 Link = Link->ForwardLink;
2309 }
2310
2311 return RequestBlockArray;
2312
2313 Done:
2314 if (RequestBlockArray != NULL) {
2315 //
2316 // Free Link Array RequestBlockArray
2317 //
2318 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2319 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2320 RemoveEntryList (&BlockData->Entry);
2321 FreePool (BlockData);
2322 }
2323
2324 FreePool (RequestBlockArray);
2325 }
2326
2327 return NULL;
2328 }
2329
2330 /**
2331 parse the configrequest string, get the elements.
2332
2333 @param ConfigRequest The input config request string.
2334 @param Progress Return the progress data.
2335
2336 @retval return data block array.
2337 **/
2338 IFR_BLOCK_DATA *
2339 GetNameElement (
2340 IN EFI_STRING ConfigRequest,
2341 OUT EFI_STRING *Progress
2342 )
2343 {
2344 EFI_STRING StringPtr;
2345 EFI_STRING NextTag;
2346 IFR_BLOCK_DATA *BlockData;
2347 IFR_BLOCK_DATA *RequestBlockArray;
2348 BOOLEAN HasValue;
2349
2350 StringPtr = ConfigRequest;
2351
2352 //
2353 // Init RequestBlockArray
2354 //
2355 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2356 if (RequestBlockArray == NULL) {
2357 goto Done;
2358 }
2359 InitializeListHead (&RequestBlockArray->Entry);
2360
2361 //
2362 // Get the request Block array from the request string
2363 //
2364
2365 //
2366 // Parse each <RequestElement> if exists
2367 // Only <BlockName> format is supported by this help function.
2368 // <BlockName> ::= &'Name***=***
2369 //
2370 while (StringPtr != NULL && *StringPtr == L'&') {
2371
2372 *Progress = StringPtr;
2373 //
2374 // Skip the L"&" string
2375 //
2376 StringPtr += 1;
2377
2378 HasValue = FALSE;
2379 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
2380 *NextTag = L'\0';
2381 HasValue = TRUE;
2382 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
2383 *NextTag = L'\0';
2384 }
2385
2386 //
2387 // Set Block Data
2388 //
2389 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2390 if (BlockData == NULL) {
2391 goto Done;
2392 }
2393
2394 //
2395 // Get Name
2396 //
2397 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
2398 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
2399
2400 if (HasValue) {
2401 //
2402 // If has value, skip the value.
2403 //
2404 StringPtr = NextTag + 1;
2405 *NextTag = L'=';
2406 StringPtr = StrStr (StringPtr, L"&");
2407 } else if (NextTag != NULL) {
2408 //
2409 // restore the '&' text.
2410 //
2411 StringPtr = NextTag;
2412 *NextTag = L'&';
2413 }
2414 }
2415
2416 return RequestBlockArray;
2417
2418 Done:
2419 if (RequestBlockArray != NULL) {
2420 //
2421 // Free Link Array RequestBlockArray
2422 //
2423 while (!IsListEmpty (&RequestBlockArray->Entry)) {
2424 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
2425 RemoveEntryList (&BlockData->Entry);
2426 if (BlockData->Name != NULL) {
2427 FreePool (BlockData->Name);
2428 }
2429 FreePool (BlockData);
2430 }
2431
2432 FreePool (RequestBlockArray);
2433 }
2434
2435 return NULL;
2436 }
2437
2438 /**
2439 Generate ConfigRequest string base on the varstore info.
2440
2441 @param ConfigHdr The config header for this varstore.
2442 @param VarStorageData The varstore info.
2443 @param Status Return Status.
2444 @param ConfigRequest The ConfigRequest info may be return.
2445
2446 @retval TRUE Need to continue
2447 @retval Others NO need to continue or error occur.
2448 **/
2449 BOOLEAN
2450 GenerateConfigRequest (
2451 IN CHAR16 *ConfigHdr,
2452 IN IFR_VARSTORAGE_DATA *VarStorageData,
2453 OUT EFI_STATUS *Status,
2454 IN OUT EFI_STRING *ConfigRequest
2455 )
2456 {
2457 BOOLEAN DataExist;
2458 UINTN Length;
2459 LIST_ENTRY *Link;
2460 CHAR16 *FullConfigRequest;
2461 CHAR16 *StringPtr;
2462 IFR_BLOCK_DATA *BlockData;
2463
2464 //
2465 // Append VarStorageData BlockEntry into *Request string
2466 // Now support only one varstore in a form package.
2467 //
2468
2469 //
2470 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2471 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2472 //
2473
2474 //
2475 // Compute the length of the entire request starting with <ConfigHdr> and a
2476 // Null-terminator
2477 //
2478 DataExist = FALSE;
2479 Length = StrLen (ConfigHdr) + 1;
2480
2481 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2482 DataExist = TRUE;
2483 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2484 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2485 //
2486 // Add <BlockName> length for each Name
2487 //
2488 // <BlockName> ::= &Name1&Name2&...
2489 // |1| StrLen(Name1)
2490 //
2491 Length = Length + (1 + StrLen (BlockData->Name));
2492 } else {
2493 //
2494 // Add <BlockName> length for each Offset/Width pair
2495 //
2496 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2497 // | 8 | 4 | 7 | 4 |
2498 //
2499 Length = Length + (8 + 4 + 7 + 4);
2500 }
2501 }
2502 //
2503 // No any request block data is found. The request string can't be constructed.
2504 //
2505 if (!DataExist) {
2506 *Status = EFI_SUCCESS;
2507 return FALSE;
2508 }
2509
2510 //
2511 // Allocate buffer for the entire <ConfigRequest>
2512 //
2513 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
2514 if (FullConfigRequest == NULL) {
2515 *Status = EFI_OUT_OF_RESOURCES;
2516 return FALSE;
2517 }
2518 StringPtr = FullConfigRequest;
2519
2520 //
2521 // Start with <ConfigHdr>
2522 //
2523 StrCpy (StringPtr, ConfigHdr);
2524 StringPtr += StrLen (StringPtr);
2525
2526 //
2527 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2528 //
2529 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
2530 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
2531 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2532 //
2533 // Append &Name1\0
2534 //
2535 UnicodeSPrint (
2536 StringPtr,
2537 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
2538 L"&%s",
2539 BlockData->Name
2540 );
2541 } else {
2542 //
2543 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2544 //
2545 UnicodeSPrint (
2546 StringPtr,
2547 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
2548 L"&OFFSET=%04X&WIDTH=%04X",
2549 BlockData->Offset,
2550 BlockData->Width
2551 );
2552 }
2553 StringPtr += StrLen (StringPtr);
2554 }
2555 //
2556 // Set to the got full request string.
2557 //
2558 HiiToLower (FullConfigRequest);
2559
2560 if (*ConfigRequest != NULL) {
2561 FreePool (*ConfigRequest);
2562 }
2563 *ConfigRequest = FullConfigRequest;
2564
2565 return TRUE;
2566 }
2567
2568 /**
2569 Generate ConfigRequest Header base on the varstore info.
2570
2571 @param VarStorageData The varstore info.
2572 @param DevicePath Device path for this varstore.
2573 @param ConfigHdr The config header for this varstore.
2574
2575 @retval EFI_SUCCESS Generate the header success.
2576 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2577 **/
2578 EFI_STATUS
2579 GenerateHdr (
2580 IN IFR_VARSTORAGE_DATA *VarStorageData,
2581 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2582 OUT EFI_STRING *ConfigHdr
2583 )
2584 {
2585 EFI_STRING GuidStr;
2586 EFI_STRING NameStr;
2587 EFI_STRING PathStr;
2588 UINTN Length;
2589 EFI_STATUS Status;
2590
2591 Status = EFI_SUCCESS;
2592 NameStr = NULL;
2593 GuidStr = NULL;
2594 PathStr = NULL;
2595
2596 //
2597 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2598 //
2599 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
2600 if (VarStorageData->Name != NULL) {
2601 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
2602 } else {
2603 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
2604 }
2605 GenerateSubStr (
2606 L"PATH=",
2607 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
2608 (VOID *) DevicePath,
2609 1,
2610 &PathStr
2611 );
2612 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
2613 if (VarStorageData->Name == NULL) {
2614 Length += 1;
2615 }
2616
2617 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
2618 if (*ConfigHdr == NULL) {
2619 Status = EFI_OUT_OF_RESOURCES;
2620 goto Done;
2621 }
2622 StrCpy (*ConfigHdr, GuidStr);
2623 StrCat (*ConfigHdr, NameStr);
2624 if (VarStorageData->Name == NULL) {
2625 StrCat (*ConfigHdr, L"&");
2626 }
2627 StrCat (*ConfigHdr, PathStr);
2628
2629 //
2630 // Remove the last character L'&'
2631 //
2632 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
2633
2634 Done:
2635 if (GuidStr != NULL) {
2636 FreePool (GuidStr);
2637 }
2638
2639 if (NameStr != NULL) {
2640 FreePool (NameStr);
2641 }
2642
2643 if (PathStr != NULL) {
2644 FreePool (PathStr);
2645 }
2646
2647 return Status;
2648 }
2649
2650 /**
2651 Get Data buffer size based on data type.
2652
2653 @param ValueType The input data type.
2654
2655 @retval The data buffer size for the input type.
2656 **/
2657 UINT16
2658 GetStorageWidth (
2659 IN UINT8 ValueType
2660 )
2661 {
2662 UINT16 StorageWidth;
2663
2664 switch (ValueType) {
2665 case EFI_IFR_NUMERIC_SIZE_1:
2666 case EFI_IFR_TYPE_BOOLEAN:
2667 StorageWidth = (UINT16) sizeof (UINT8);
2668 break;
2669
2670 case EFI_IFR_NUMERIC_SIZE_2:
2671 StorageWidth = (UINT16) sizeof (UINT16);
2672 break;
2673
2674 case EFI_IFR_NUMERIC_SIZE_4:
2675 StorageWidth = (UINT16) sizeof (UINT32);
2676 break;
2677
2678 case EFI_IFR_NUMERIC_SIZE_8:
2679 StorageWidth = (UINT16) sizeof (UINT64);
2680 break;
2681
2682 case EFI_IFR_TYPE_TIME:
2683 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
2684 break;
2685
2686 case EFI_IFR_TYPE_DATE:
2687 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
2688 break;
2689
2690 default:
2691 StorageWidth = 0;
2692 break;
2693 }
2694
2695 return StorageWidth;
2696 }
2697
2698 /**
2699 Generate ConfigAltResp string base on the varstore info.
2700
2701 @param ConfigHdr The config header for this varstore.
2702 @param VarStorageData The varstore info.
2703 @param DefaultIdArray The Default id array.
2704 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2705
2706 @retval TRUE Need to continue
2707 @retval Others NO need to continue or error occur.
2708 **/
2709 EFI_STATUS
2710 GenerateAltConfigResp (
2711 IN CHAR16 *ConfigHdr,
2712 IN IFR_VARSTORAGE_DATA *VarStorageData,
2713 IN IFR_DEFAULT_DATA *DefaultIdArray,
2714 IN OUT EFI_STRING *DefaultAltCfgResp
2715 )
2716 {
2717 BOOLEAN DataExist;
2718 UINTN Length;
2719 LIST_ENTRY *Link;
2720 LIST_ENTRY *LinkData;
2721 LIST_ENTRY *LinkDefault;
2722 LIST_ENTRY *ListEntry;
2723 CHAR16 *StringPtr;
2724 IFR_BLOCK_DATA *BlockData;
2725 IFR_DEFAULT_DATA *DefaultId;
2726 IFR_DEFAULT_DATA *DefaultValueData;
2727 UINTN Width;
2728 UINT8 *TmpBuffer;
2729
2730 BlockData = NULL;
2731 DataExist = FALSE;
2732
2733 //
2734 // Add length for <ConfigHdr> + '\0'
2735 //
2736 Length = StrLen (ConfigHdr) + 1;
2737
2738 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2739 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2740 //
2741 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2742 // |1| StrLen (ConfigHdr) | 8 | 4 |
2743 //
2744 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
2745
2746 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2747 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2748 ListEntry = &BlockData->DefaultValueEntry;
2749 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
2750 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2751 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
2752 continue;
2753 }
2754 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2755 //
2756 // Add length for "&Name1=zzzzzzzzzzzz"
2757 // |1|Name|1|Value|
2758 //
2759 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
2760 } else {
2761 //
2762 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2763 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2764 //
2765 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
2766 }
2767 DataExist = TRUE;
2768 }
2769 }
2770 }
2771
2772 //
2773 // No default value is found. The default string doesn't exist.
2774 //
2775 if (!DataExist) {
2776 return EFI_SUCCESS;
2777 }
2778
2779 //
2780 // Allocate buffer for the entire <DefaultAltCfgResp>
2781 //
2782 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
2783 if (*DefaultAltCfgResp == NULL) {
2784 return EFI_OUT_OF_RESOURCES;
2785 }
2786 StringPtr = *DefaultAltCfgResp;
2787
2788 //
2789 // Start with <ConfigHdr>
2790 //
2791 StrCpy (StringPtr, ConfigHdr);
2792 StringPtr += StrLen (StringPtr);
2793
2794 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
2795 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
2796 //
2797 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2798 // |1| StrLen (ConfigHdr) | 8 | 4 |
2799 //
2800 UnicodeSPrint (
2801 StringPtr,
2802 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
2803 L"&%s&ALTCFG=%04X",
2804 ConfigHdr,
2805 DefaultId->DefaultId
2806 );
2807 StringPtr += StrLen (StringPtr);
2808
2809 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2810 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2811 ListEntry = &BlockData->DefaultValueEntry;
2812 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
2813 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2814 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
2815 continue;
2816 }
2817 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2818 UnicodeSPrint (
2819 StringPtr,
2820 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
2821 L"&%s=",
2822 BlockData->Name
2823 );
2824 StringPtr += StrLen (StringPtr);
2825 } else {
2826 //
2827 // Add <BlockConfig>
2828 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2829 //
2830 UnicodeSPrint (
2831 StringPtr,
2832 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
2833 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2834 BlockData->Offset,
2835 BlockData->Width
2836 );
2837 StringPtr += StrLen (StringPtr);
2838 }
2839 Width = BlockData->Width;
2840 //
2841 // Convert Value to a hex string in "%x" format
2842 // NOTE: This is in the opposite byte that GUID and PATH use
2843 //
2844 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
2845 for (; Width > 0; Width--) {
2846 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
2847 }
2848 }
2849 }
2850 }
2851
2852 HiiToLower (*DefaultAltCfgResp);
2853
2854 return EFI_SUCCESS;
2855 }
2856
2857 /**
2858 This function gets the full request string and full default value string by
2859 parsing IFR data in HII form packages.
2860
2861 When Request points to NULL string, the request string and default value string
2862 for each varstore in form package will return.
2863
2864 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
2865 @param DevicePath Device Path which Hii Config Access Protocol is registered.
2866 @param Request Pointer to a null-terminated Unicode string in
2867 <ConfigRequest> format. When it doesn't contain
2868 any RequestElement, it will be updated to return
2869 the full RequestElement retrieved from IFR data.
2870 If it points to NULL, the request string for the first
2871 varstore in form package will be merged into a
2872 <MultiConfigRequest> format string and return.
2873 @param AltCfgResp Pointer to a null-terminated Unicode string in
2874 <ConfigAltResp> format. When the pointer is to NULL,
2875 the full default value string retrieved from IFR data
2876 will return. When the pinter is to a string, the
2877 full default value string retrieved from IFR data
2878 will be merged into the input string and return.
2879 When Request points to NULL, the default value string
2880 for each varstore in form package will be merged into
2881 a <MultiConfigAltResp> format string and return.
2882 @param PointerProgress Optional parameter, it can be be NULL.
2883 When it is not NULL, if Request is NULL, it returns NULL.
2884 On return, points to a character in the Request
2885 string. Points to the string's null terminator if
2886 request was successful. Points to the most recent
2887 & before the first failing name / value pair (or
2888 the beginning of the string if the failure is in
2889 the first name / value pair) if the request was
2890 not successful.
2891 @retval EFI_SUCCESS The Results string is set to the full request string.
2892 And AltCfgResp contains all default value string.
2893 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2894 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
2895 can't be found in Form package.
2896 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
2897 @retval EFI_INVALID_PARAMETER Request points to NULL.
2898
2899 **/
2900 EFI_STATUS
2901 EFIAPI
2902 GetFullStringFromHiiFormPackages (
2903 IN HII_DATABASE_RECORD *DataBaseRecord,
2904 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2905 IN OUT EFI_STRING *Request,
2906 IN OUT EFI_STRING *AltCfgResp,
2907 OUT EFI_STRING *PointerProgress OPTIONAL
2908 )
2909 {
2910 EFI_STATUS Status;
2911 UINT8 *HiiFormPackage;
2912 UINTN PackageSize;
2913 IFR_BLOCK_DATA *RequestBlockArray;
2914 IFR_BLOCK_DATA *BlockData;
2915 IFR_DEFAULT_DATA *DefaultValueData;
2916 IFR_DEFAULT_DATA *DefaultId;
2917 IFR_DEFAULT_DATA *DefaultIdArray;
2918 IFR_VARSTORAGE_DATA *VarStorageData;
2919 EFI_STRING DefaultAltCfgResp;
2920 EFI_STRING ConfigHdr;
2921 EFI_STRING StringPtr;
2922 EFI_STRING Progress;
2923
2924 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
2925 return EFI_INVALID_PARAMETER;
2926 }
2927
2928 //
2929 // Initialize the local variables.
2930 //
2931 RequestBlockArray = NULL;
2932 DefaultIdArray = NULL;
2933 VarStorageData = NULL;
2934 DefaultAltCfgResp = NULL;
2935 ConfigHdr = NULL;
2936 HiiFormPackage = NULL;
2937 PackageSize = 0;
2938 Progress = *Request;
2939
2940 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
2941 if (EFI_ERROR (Status)) {
2942 return Status;
2943 }
2944
2945 //
2946 // 1. Get the request block array by Request String when Request string containts the block array.
2947 //
2948 StringPtr = NULL;
2949 if (*Request != NULL) {
2950 StringPtr = *Request;
2951 //
2952 // Jump <ConfigHdr>
2953 //
2954 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
2955 Status = EFI_INVALID_PARAMETER;
2956 goto Done;
2957 }
2958 StringPtr += StrLen (L"GUID=");
2959 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
2960 StringPtr++;
2961 }
2962 if (*StringPtr == L'\0') {
2963 Status = EFI_INVALID_PARAMETER;
2964 goto Done;
2965 }
2966 StringPtr += StrLen (L"&NAME=");
2967 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
2968 StringPtr++;
2969 }
2970 if (*StringPtr == L'\0') {
2971 Status = EFI_INVALID_PARAMETER;
2972 goto Done;
2973 }
2974 StringPtr += StrLen (L"&PATH=");
2975 while (*StringPtr != L'\0' && *StringPtr != L'&') {
2976 StringPtr ++;
2977 }
2978
2979 if (*StringPtr == L'\0') {
2980 //
2981 // No request block is found.
2982 //
2983 StringPtr = NULL;
2984 }
2985 }
2986
2987 //
2988 // If StringPtr != NULL, get the request elements.
2989 //
2990 if (StringPtr != NULL) {
2991 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
2992 RequestBlockArray = GetBlockElement(StringPtr, &Progress);
2993 } else {
2994 RequestBlockArray = GetNameElement(StringPtr, &Progress);
2995 }
2996
2997 if (RequestBlockArray == NULL) {
2998 Status = EFI_INVALID_PARAMETER;
2999 goto Done;
3000 }
3001 }
3002
3003 //
3004 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3005 //
3006 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
3007 if (DefaultIdArray == NULL) {
3008 Status = EFI_OUT_OF_RESOURCES;
3009 goto Done;
3010 }
3011 InitializeListHead (&DefaultIdArray->Entry);
3012
3013 //
3014 // Initialize VarStorageData to store the var store Block and Default value information.
3015 //
3016 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
3017 if (VarStorageData == NULL) {
3018 Status = EFI_OUT_OF_RESOURCES;
3019 goto Done;
3020 }
3021 InitializeListHead (&VarStorageData->Entry);
3022 InitializeListHead (&VarStorageData->BlockEntry);
3023
3024 //
3025 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3026 //
3027
3028 //
3029 // Parse the opcode in form pacakge to get the default setting.
3030 //
3031 Status = ParseIfrData (DataBaseRecord->Handle,
3032 HiiFormPackage,
3033 (UINT32) PackageSize,
3034 *Request,
3035 RequestBlockArray,
3036 VarStorageData,
3037 DefaultIdArray);
3038 if (EFI_ERROR (Status)) {
3039 goto Done;
3040 }
3041
3042 //
3043 // No requested varstore in IFR data and directly return
3044 //
3045 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
3046 Status = EFI_SUCCESS;
3047 goto Done;
3048 }
3049
3050 //
3051 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3052 //
3053 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
3054 if (EFI_ERROR (Status)) {
3055 goto Done;
3056 }
3057
3058 if (RequestBlockArray == NULL) {
3059 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
3060 goto Done;
3061 }
3062 }
3063
3064 //
3065 // 4. Construct Default Value string in AltResp according to request element.
3066 // Go through all VarStorageData Entry and get the DefaultId array for each one
3067 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3068 //
3069 Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
3070 if (EFI_ERROR (Status)) {
3071 goto Done;
3072 }
3073
3074 //
3075 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3076 //
3077 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
3078 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
3079 FreePool (DefaultAltCfgResp);
3080 } else if (*AltCfgResp == NULL) {
3081 *AltCfgResp = DefaultAltCfgResp;
3082 }
3083
3084 Done:
3085 if (RequestBlockArray != NULL) {
3086 //
3087 // Free Link Array RequestBlockArray
3088 //
3089 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3090 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3091 RemoveEntryList (&BlockData->Entry);
3092 if (BlockData->Name != NULL) {
3093 FreePool (BlockData->Name);
3094 }
3095 FreePool (BlockData);
3096 }
3097
3098 FreePool (RequestBlockArray);
3099 }
3100
3101 if (VarStorageData != NULL) {
3102 //
3103 // Free link array VarStorageData
3104 //
3105 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
3106 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
3107 RemoveEntryList (&BlockData->Entry);
3108 if (BlockData->Name != NULL) {
3109 FreePool (BlockData->Name);
3110 }
3111 //
3112 // Free default value link array
3113 //
3114 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
3115 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3116 RemoveEntryList (&DefaultValueData->Entry);
3117 FreePool (DefaultValueData);
3118 }
3119 FreePool (BlockData);
3120 }
3121 FreePool (VarStorageData);
3122 }
3123
3124 if (DefaultIdArray != NULL) {
3125 //
3126 // Free DefaultId Array
3127 //
3128 while (!IsListEmpty (&DefaultIdArray->Entry)) {
3129 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3130 RemoveEntryList (&DefaultId->Entry);
3131 FreePool (DefaultId);
3132 }
3133 FreePool (DefaultIdArray);
3134 }
3135
3136 //
3137 // Free the allocated string
3138 //
3139 if (ConfigHdr != NULL) {
3140 FreePool (ConfigHdr);
3141 }
3142
3143 //
3144 // Free Pacakge data
3145 //
3146 if (HiiFormPackage != NULL) {
3147 FreePool (HiiFormPackage);
3148 }
3149
3150 if (PointerProgress != NULL) {
3151 if (*Request == NULL) {
3152 *PointerProgress = NULL;
3153 } else if (EFI_ERROR (Status)) {
3154 *PointerProgress = *Request;
3155 } else {
3156 *PointerProgress = *Request + StrLen (*Request);
3157 }
3158 }
3159
3160 return Status;
3161 }
3162
3163 /**
3164 This function gets the full request resp string by
3165 parsing IFR data in HII form packages.
3166
3167 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3168 instance.
3169 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3170 varstore data structure.
3171 @param Request Pointer to a null-terminated Unicode string in
3172 <ConfigRequest> format.
3173 @param RequestResp Pointer to a null-terminated Unicode string in
3174 <ConfigResp> format.
3175 @param AccessProgress On return, points to a character in the Request
3176 string. Points to the string's null terminator if
3177 request was successful. Points to the most recent
3178 & before the first failing name / value pair (or
3179 the beginning of the string if the failure is in
3180 the first name / value pair) if the request was
3181 not successful.
3182
3183 @retval EFI_SUCCESS The Results string is set to the full request string.
3184 And AltCfgResp contains all default value string.
3185 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3186 @retval EFI_INVALID_PARAMETER Request points to NULL.
3187
3188 **/
3189 EFI_STATUS
3190 GetConfigRespFromEfiVarStore (
3191 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3192 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3193 IN EFI_STRING Request,
3194 OUT EFI_STRING *RequestResp,
3195 OUT EFI_STRING *AccessProgress
3196 )
3197 {
3198 EFI_STATUS Status;
3199 EFI_STRING VarStoreName;
3200 UINT8 *VarStore;
3201 UINTN BufferSize;
3202
3203 Status = EFI_SUCCESS;
3204 BufferSize = 0;
3205 VarStore = NULL;
3206 VarStoreName = NULL;
3207
3208 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
3209 if (VarStoreName == NULL) {
3210 Status = EFI_OUT_OF_RESOURCES;
3211 goto Done;
3212 }
3213 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
3214
3215
3216 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3217 if (Status != EFI_BUFFER_TOO_SMALL) {
3218 goto Done;
3219 }
3220
3221 VarStore = AllocateZeroPool (BufferSize);
3222 ASSERT (VarStore != NULL);
3223 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
3224 if (EFI_ERROR (Status)) {
3225 goto Done;
3226 }
3227
3228 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
3229 if (EFI_ERROR (Status)) {
3230 goto Done;
3231 }
3232
3233 Done:
3234 if (VarStoreName != NULL) {
3235 FreePool (VarStoreName);
3236 }
3237
3238 if (VarStore != NULL) {
3239 FreePool (VarStore);
3240 }
3241
3242 return Status;
3243 }
3244
3245
3246 /**
3247 This function route the full request resp string for efi varstore.
3248
3249 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3250 instance.
3251 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3252 varstore data structure.
3253 @param RequestResp Pointer to a null-terminated Unicode string in
3254 <ConfigResp> format.
3255 @param Result Pointer to a null-terminated Unicode string in
3256 <ConfigResp> format.
3257
3258 @retval EFI_SUCCESS The Results string is set to the full request string.
3259 And AltCfgResp contains all default value string.
3260 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3261 @retval EFI_INVALID_PARAMETER Request points to NULL.
3262
3263 **/
3264 EFI_STATUS
3265 RouteConfigRespForEfiVarStore (
3266 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3267 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3268 IN EFI_STRING RequestResp,
3269 OUT EFI_STRING *Result
3270 )
3271 {
3272 EFI_STATUS Status;
3273 EFI_STRING VarStoreName;
3274 UINT8 *VarStore;
3275 UINTN BufferSize;
3276 UINTN BlockSize;
3277
3278 Status = EFI_SUCCESS;
3279 BufferSize = 0;
3280 VarStore = NULL;
3281 VarStoreName = NULL;
3282
3283 VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
3284 if (VarStoreName == NULL) {
3285 Status = EFI_OUT_OF_RESOURCES;
3286 goto Done;
3287 }
3288 AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
3289
3290 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3291 if (Status != EFI_BUFFER_TOO_SMALL) {
3292 goto Done;
3293 }
3294
3295 BlockSize = BufferSize;
3296 VarStore = AllocateZeroPool (BufferSize);
3297 ASSERT (VarStore != NULL);
3298 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
3299 if (EFI_ERROR (Status)) {
3300 goto Done;
3301 }
3302
3303 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
3304 if (EFI_ERROR (Status)) {
3305 goto Done;
3306 }
3307
3308 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
3309 if (EFI_ERROR (Status)) {
3310 goto Done;
3311 }
3312
3313 Done:
3314 if (VarStoreName != NULL) {
3315 FreePool (VarStoreName);
3316 }
3317
3318 if (VarStore != NULL) {
3319 FreePool (VarStore);
3320 }
3321
3322 return Status;
3323 }
3324
3325 /**
3326 Validate the config request elements.
3327
3328 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3329 without configHdr field.
3330
3331 @retval CHAR16 * THE first Name/value pair not correct.
3332 @retval NULL Success parse the name/value pair
3333 **/
3334 CHAR16 *
3335 OffsetWidthValidate (
3336 CHAR16 *ConfigElements
3337 )
3338 {
3339 CHAR16 *StringPtr;
3340 CHAR16 *RetVal;
3341
3342 StringPtr = ConfigElements;
3343
3344 while (1) {
3345 RetVal = StringPtr;
3346 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
3347 return RetVal;
3348 }
3349
3350 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3351 StringPtr++;
3352 }
3353 if (*StringPtr == L'\0') {
3354 return RetVal;
3355 }
3356
3357 StringPtr += StrLen (L"&WIDTH=");
3358 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
3359 StringPtr ++;
3360 }
3361
3362 if (*StringPtr == L'\0') {
3363 return NULL;
3364 }
3365 }
3366 }
3367
3368 /**
3369 Validate the config request elements.
3370
3371 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3372 without configHdr field.
3373
3374 @retval CHAR16 * THE first Name/value pair not correct.
3375 @retval NULL Success parse the name/value pair
3376
3377 **/
3378 CHAR16 *
3379 NameValueValidate (
3380 CHAR16 *ConfigElements
3381 )
3382 {
3383 CHAR16 *StringPtr;
3384 CHAR16 *RetVal;
3385
3386 StringPtr = ConfigElements;
3387
3388 while (1) {
3389 RetVal = StringPtr;
3390 if (*StringPtr != L'&') {
3391 return RetVal;
3392 }
3393 StringPtr += 1;
3394
3395 StringPtr = StrStr (StringPtr, L"&");
3396
3397 if (StringPtr == NULL) {
3398 return NULL;
3399 }
3400 }
3401 }
3402
3403 /**
3404 Validate the config request string.
3405
3406 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3407
3408 @retval CHAR16 * THE first element not correct.
3409 @retval NULL Success parse the name/value pair
3410
3411 **/
3412 CHAR16 *
3413 ConfigRequestValidate (
3414 CHAR16 *ConfigRequest
3415 )
3416 {
3417 BOOLEAN HasNameField;
3418 CHAR16 *StringPtr;
3419
3420 HasNameField = TRUE;
3421 StringPtr = ConfigRequest;
3422
3423 //
3424 // Check <ConfigHdr>
3425 //
3426 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3427 return ConfigRequest;
3428 }
3429 StringPtr += StrLen (L"GUID=");
3430 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3431 StringPtr++;
3432 }
3433 if (*StringPtr == L'\0') {
3434 return ConfigRequest;
3435 }
3436 StringPtr += StrLen (L"&NAME=");
3437 if (*StringPtr == L'&') {
3438 HasNameField = FALSE;
3439 }
3440 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3441 StringPtr++;
3442 }
3443 if (*StringPtr == L'\0') {
3444 return ConfigRequest;
3445 }
3446 StringPtr += StrLen (L"&PATH=");
3447 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3448 StringPtr ++;
3449 }
3450
3451 if (*StringPtr == L'\0') {
3452 return NULL;
3453 }
3454
3455 if (HasNameField) {
3456 //
3457 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3458 //
3459 return OffsetWidthValidate(StringPtr);
3460 } else {
3461 //
3462 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3463 //
3464 return NameValueValidate(StringPtr);
3465 }
3466 }
3467
3468 /**
3469 This function allows a caller to extract the current configuration
3470 for one or more named elements from one or more drivers.
3471
3472 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3473 instance.
3474 @param Request A null-terminated Unicode string in
3475 <MultiConfigRequest> format.
3476 @param Progress On return, points to a character in the Request
3477 string. Points to the string's null terminator if
3478 request was successful. Points to the most recent
3479 & before the first failing name / value pair (or
3480 the beginning of the string if the failure is in
3481 the first name / value pair) if the request was
3482 not successful.
3483 @param Results Null-terminated Unicode string in
3484 <MultiConfigAltResp> format which has all values
3485 filled in for the names in the Request string.
3486 String to be allocated by the called function.
3487
3488 @retval EFI_SUCCESS The Results string is filled with the values
3489 corresponding to all requested names.
3490 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3491 results that must be stored awaiting possible
3492 future protocols.
3493 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3494 Progress set to the "G" in "GUID" of the routing
3495 header that doesn't match. Note: There is no
3496 requirement that all routing data be validated
3497 before any configuration extraction.
3498 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3499 parameter would result in this type of error. The
3500 Progress parameter is set to NULL.
3501 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3502 before the error or the beginning of the string.
3503 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3504 Configuration Access Protocol returned
3505 EFI_INVALID_PARAMETER. Progress set to most recent
3506 & before the error or the beginning of the string.
3507
3508 **/
3509 EFI_STATUS
3510 EFIAPI
3511 HiiConfigRoutingExtractConfig (
3512 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3513 IN CONST EFI_STRING Request,
3514 OUT EFI_STRING *Progress,
3515 OUT EFI_STRING *Results
3516 )
3517 {
3518 HII_DATABASE_PRIVATE_DATA *Private;
3519 EFI_STRING StringPtr;
3520 EFI_STRING ConfigRequest;
3521 UINTN Length;
3522 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3523 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
3524 EFI_STATUS Status;
3525 LIST_ENTRY *Link;
3526 HII_DATABASE_RECORD *Database;
3527 UINT8 *DevicePathPkg;
3528 UINT8 *CurrentDevicePath;
3529 EFI_HANDLE DriverHandle;
3530 EFI_HII_HANDLE HiiHandle;
3531 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
3532 EFI_STRING AccessProgress;
3533 EFI_STRING AccessResults;
3534 EFI_STRING DefaultResults;
3535 BOOLEAN FirstElement;
3536 BOOLEAN IfrDataParsedFlag;
3537 BOOLEAN IsEfiVarStore;
3538 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
3539 EFI_STRING ErrorPtr;
3540
3541 if (This == NULL || Progress == NULL || Results == NULL) {
3542 return EFI_INVALID_PARAMETER;
3543 }
3544
3545 if (Request == NULL) {
3546 *Progress = NULL;
3547 return EFI_INVALID_PARAMETER;
3548 }
3549
3550 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3551 StringPtr = Request;
3552 *Progress = StringPtr;
3553 DefaultResults = NULL;
3554 ConfigRequest = NULL;
3555 Status = EFI_SUCCESS;
3556 AccessResults = NULL;
3557 AccessProgress = NULL;
3558 DevicePath = NULL;
3559 IfrDataParsedFlag = FALSE;
3560 IsEfiVarStore = FALSE;
3561 EfiVarStoreInfo = NULL;
3562
3563 //
3564 // The first element of <MultiConfigRequest> should be
3565 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3566 //
3567 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3568 return EFI_INVALID_PARAMETER;
3569 }
3570
3571 FirstElement = TRUE;
3572
3573 //
3574 // Allocate a fix length of memory to store Results. Reallocate memory for
3575 // Results if this fix length is insufficient.
3576 //
3577 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
3578 if (*Results == NULL) {
3579 return EFI_OUT_OF_RESOURCES;
3580 }
3581
3582 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
3583 //
3584 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3585 // or most recent & before the error.
3586 //
3587 if (StringPtr == Request) {
3588 *Progress = StringPtr;
3589 } else {
3590 *Progress = StringPtr - 1;
3591 }
3592
3593 //
3594 // Process each <ConfigRequest> of <MultiConfigRequest>
3595 //
3596 Length = CalculateConfigStringLen (StringPtr);
3597 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
3598 if (ConfigRequest == NULL) {
3599 Status = EFI_OUT_OF_RESOURCES;
3600 goto Done;
3601 }
3602 *(ConfigRequest + Length) = 0;
3603
3604 //
3605 // Get the UEFI device path
3606 //
3607 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
3608 if (EFI_ERROR (Status)) {
3609 goto Done;
3610 }
3611
3612 //
3613 // Find driver which matches the routing data.
3614 //
3615 DriverHandle = NULL;
3616 HiiHandle = NULL;
3617 Database = NULL;
3618 for (Link = Private->DatabaseList.ForwardLink;
3619 Link != &Private->DatabaseList;
3620 Link = Link->ForwardLink
3621 ) {
3622 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3623 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
3624 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
3625 if (CompareMem (
3626 DevicePath,
3627 CurrentDevicePath,
3628 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
3629 ) == 0) {
3630 DriverHandle = Database->DriverHandle;
3631 HiiHandle = Database->Handle;
3632 break;
3633 }
3634 }
3635 }
3636
3637 //
3638 // Try to find driver handle by device path.
3639 //
3640 if (DriverHandle == NULL) {
3641 TempDevicePath = DevicePath;
3642 Status = gBS->LocateDevicePath (
3643 &gEfiDevicePathProtocolGuid,
3644 &TempDevicePath,
3645 &DriverHandle
3646 );
3647 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
3648 //
3649 // Routing data does not match any known driver.
3650 // Set Progress to the 'G' in "GUID" of the routing header.
3651 //
3652 *Progress = StringPtr;
3653 Status = EFI_NOT_FOUND;
3654 goto Done;
3655 }
3656 }
3657
3658 //
3659 // Validate ConfigRequest String.
3660 //
3661 ErrorPtr = ConfigRequestValidate(ConfigRequest);
3662 if (ErrorPtr != NULL) {
3663 *Progress = StrStr (StringPtr, ErrorPtr);
3664 Status = EFI_INVALID_PARAMETER;
3665 goto Done;
3666 }
3667
3668 //
3669 // Check whether ConfigRequest contains request string.
3670 //
3671 IfrDataParsedFlag = FALSE;
3672 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
3673 //
3674 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3675 //
3676 IfrDataParsedFlag = TRUE;
3677 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
3678 if (EFI_ERROR (Status)) {
3679 //
3680 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3681 // Map it to the progress on <MultiConfigRequest> then return it.
3682 //
3683 ASSERT (AccessProgress != NULL);
3684 *Progress = StrStr (StringPtr, AccessProgress);
3685 goto Done;
3686 }
3687 //
3688 // Not any request block is found.
3689 //
3690 if (!GetElementsFromRequest(ConfigRequest)) {
3691 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
3692 goto NextConfigString;
3693 }
3694 }
3695
3696 //
3697 // Check whether this ConfigRequest is search from Efi varstore type storage.
3698 //
3699 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
3700 if (EFI_ERROR (Status)) {
3701 goto Done;
3702 }
3703
3704 if (IsEfiVarStore) {
3705 //
3706 // Call the GetVariable function to extract settings.
3707 //
3708 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
3709 FreePool (EfiVarStoreInfo);
3710 } else {
3711 //
3712 // Call corresponding ConfigAccess protocol to extract settings
3713 //
3714 Status = gBS->HandleProtocol (
3715 DriverHandle,
3716 &gEfiHiiConfigAccessProtocolGuid,
3717 (VOID **) &ConfigAccess
3718 );
3719 ASSERT_EFI_ERROR (Status);
3720
3721 Status = ConfigAccess->ExtractConfig (
3722 ConfigAccess,
3723 ConfigRequest,
3724 &AccessProgress,
3725 &AccessResults
3726 );
3727 }
3728 if (EFI_ERROR (Status)) {
3729 //
3730 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3731 // Map it to the progress on <MultiConfigRequest> then return it.
3732 //
3733 *Progress = StrStr (StringPtr, AccessProgress);
3734 goto Done;
3735 }
3736
3737 //
3738 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3739 // which seperates the first <ConfigAltResp> and the following ones.
3740 //
3741 ASSERT (*AccessProgress == 0);
3742
3743 //
3744 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3745 //
3746 if (!IfrDataParsedFlag && HiiHandle != NULL) {
3747 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
3748 ASSERT_EFI_ERROR (Status);
3749 }
3750
3751 FreePool (DevicePath);
3752 DevicePath = NULL;
3753
3754 if (DefaultResults != NULL) {
3755 Status = MergeDefaultString (&AccessResults, DefaultResults);
3756 ASSERT_EFI_ERROR (Status);
3757 FreePool (DefaultResults);
3758 DefaultResults = NULL;
3759 }
3760
3761 NextConfigString:
3762 if (!FirstElement) {
3763 Status = AppendToMultiString (Results, L"&");
3764 ASSERT_EFI_ERROR (Status);
3765 }
3766
3767 Status = AppendToMultiString (Results, AccessResults);
3768 ASSERT_EFI_ERROR (Status);
3769
3770 FirstElement = FALSE;
3771
3772 FreePool (AccessResults);
3773 AccessResults = NULL;
3774 FreePool (ConfigRequest);
3775 ConfigRequest = NULL;
3776
3777 //
3778 // Go to next <ConfigRequest> (skip '&').
3779 //
3780 StringPtr += Length;
3781 if (*StringPtr == 0) {
3782 *Progress = StringPtr;
3783 break;
3784 }
3785
3786 StringPtr++;
3787 }
3788
3789 Done:
3790 if (EFI_ERROR (Status)) {
3791 FreePool (*Results);
3792 *Results = NULL;
3793 }
3794
3795 if (ConfigRequest != NULL) {
3796 FreePool (ConfigRequest);
3797 }
3798
3799 if (AccessResults != NULL) {
3800 FreePool (AccessResults);
3801 }
3802
3803 if (DefaultResults != NULL) {
3804 FreePool (DefaultResults);
3805 }
3806
3807 if (DevicePath != NULL) {
3808 FreePool (DevicePath);
3809 }
3810
3811 return Status;
3812 }
3813
3814
3815 /**
3816 This function allows the caller to request the current configuration for the
3817 entirety of the current HII database and returns the data in a
3818 null-terminated Unicode string.
3819
3820 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3821 instance.
3822 @param Results Null-terminated Unicode string in
3823 <MultiConfigAltResp> format which has all values
3824 filled in for the entirety of the current HII
3825 database. String to be allocated by the called
3826 function. De-allocation is up to the caller.
3827
3828 @retval EFI_SUCCESS The Results string is filled with the values
3829 corresponding to all requested names.
3830 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3831 results that must be stored awaiting possible
3832 future protocols.
3833 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3834 parameter would result in this type of error.
3835
3836 **/
3837 EFI_STATUS
3838 EFIAPI
3839 HiiConfigRoutingExportConfig (
3840 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3841 OUT EFI_STRING *Results
3842 )
3843 {
3844 EFI_STATUS Status;
3845 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
3846 EFI_STRING AccessResults;
3847 EFI_STRING Progress;
3848 EFI_STRING StringPtr;
3849 EFI_STRING ConfigRequest;
3850 UINTN Index;
3851 EFI_HANDLE *ConfigAccessHandles;
3852 UINTN NumberConfigAccessHandles;
3853 BOOLEAN FirstElement;
3854 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3855 EFI_HII_HANDLE HiiHandle;
3856 EFI_STRING DefaultResults;
3857 HII_DATABASE_PRIVATE_DATA *Private;
3858 LIST_ENTRY *Link;
3859 HII_DATABASE_RECORD *Database;
3860 UINT8 *DevicePathPkg;
3861 UINT8 *CurrentDevicePath;
3862 BOOLEAN IfrDataParsedFlag;
3863
3864 if (This == NULL || Results == NULL) {
3865 return EFI_INVALID_PARAMETER;
3866 }
3867
3868 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3869
3870 //
3871 // Allocate a fix length of memory to store Results. Reallocate memory for
3872 // Results if this fix length is insufficient.
3873 //
3874 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
3875 if (*Results == NULL) {
3876 return EFI_OUT_OF_RESOURCES;
3877 }
3878
3879 NumberConfigAccessHandles = 0;
3880 Status = gBS->LocateHandleBuffer (
3881 ByProtocol,
3882 &gEfiHiiConfigAccessProtocolGuid,
3883 NULL,
3884 &NumberConfigAccessHandles,
3885 &ConfigAccessHandles
3886 );
3887 if (EFI_ERROR (Status)) {
3888 return Status;
3889 }
3890
3891 FirstElement = TRUE;
3892
3893 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
3894 Status = gBS->HandleProtocol (
3895 ConfigAccessHandles[Index],
3896 &gEfiHiiConfigAccessProtocolGuid,
3897 (VOID **) &ConfigAccess
3898 );
3899 if (EFI_ERROR (Status)) {
3900 continue;
3901 }
3902
3903 //
3904 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3905 //
3906 IfrDataParsedFlag = FALSE;
3907 Progress = NULL;
3908 HiiHandle = NULL;
3909 DefaultResults = NULL;
3910 Database = NULL;
3911 ConfigRequest = NULL;
3912 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
3913 if (DevicePath != NULL) {
3914 for (Link = Private->DatabaseList.ForwardLink;
3915 Link != &Private->DatabaseList;
3916 Link = Link->ForwardLink
3917 ) {
3918 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3919 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
3920 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
3921 if (CompareMem (
3922 DevicePath,
3923 CurrentDevicePath,
3924 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
3925 ) == 0) {
3926 HiiHandle = Database->Handle;
3927 break;
3928 }
3929 }
3930 }
3931 }
3932
3933 Status = ConfigAccess->ExtractConfig (
3934 ConfigAccess,
3935 NULL,
3936 &Progress,
3937 &AccessResults
3938 );
3939 if (EFI_ERROR (Status)) {
3940 //
3941 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3942 //
3943 if (HiiHandle != NULL && DevicePath != NULL) {
3944 IfrDataParsedFlag = TRUE;
3945 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
3946 //
3947 // Get the full request string to get the Current setting again.
3948 //
3949 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
3950 Status = ConfigAccess->ExtractConfig (
3951 ConfigAccess,
3952 ConfigRequest,
3953 &Progress,
3954 &AccessResults
3955 );
3956 FreePool (ConfigRequest);
3957 } else {
3958 Status = EFI_NOT_FOUND;
3959 }
3960 }
3961 }
3962
3963 if (!EFI_ERROR (Status)) {
3964 //
3965 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3966 //
3967 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
3968 StringPtr = StrStr (AccessResults, L"&GUID=");
3969 if (StringPtr != NULL) {
3970 *StringPtr = 0;
3971 }
3972 if (GetElementsFromRequest (AccessResults)) {
3973 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
3974 ASSERT_EFI_ERROR (Status);
3975 }
3976 if (StringPtr != NULL) {
3977 *StringPtr = L'&';
3978 }
3979 }
3980 //
3981 // Merge the default sting from IFR code into the got setting from driver.
3982 //
3983 if (DefaultResults != NULL) {
3984 Status = MergeDefaultString (&AccessResults, DefaultResults);
3985 ASSERT_EFI_ERROR (Status);
3986 FreePool (DefaultResults);
3987 DefaultResults = NULL;
3988 }
3989
3990 //
3991 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3992 // which seperates the first <ConfigAltResp> and the following ones.
3993 //
3994 if (!FirstElement) {
3995 Status = AppendToMultiString (Results, L"&");
3996 ASSERT_EFI_ERROR (Status);
3997 }
3998
3999 Status = AppendToMultiString (Results, AccessResults);
4000 ASSERT_EFI_ERROR (Status);
4001
4002 FirstElement = FALSE;
4003
4004 FreePool (AccessResults);
4005 AccessResults = NULL;
4006 }
4007 }
4008 FreePool (ConfigAccessHandles);
4009
4010 return EFI_SUCCESS;
4011 }
4012
4013
4014 /**
4015 This function processes the results of processing forms and routes it to the
4016 appropriate handlers or storage.
4017
4018 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4019 instance.
4020 @param Configuration A null-terminated Unicode string in
4021 <MulltiConfigResp> format.
4022 @param Progress A pointer to a string filled in with the offset of
4023 the most recent & before the first failing name /
4024 value pair (or the beginning of the string if the
4025 failure is in the first name / value pair) or the
4026 terminating NULL if all was successful.
4027
4028 @retval EFI_SUCCESS The results have been distributed or are awaiting
4029 distribution.
4030 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4031 results that must be stored awaiting possible
4032 future protocols.
4033 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4034 would result in this type of error.
4035 @retval EFI_NOT_FOUND Target for the specified routing data was not
4036 found.
4037
4038 **/
4039 EFI_STATUS
4040 EFIAPI
4041 HiiConfigRoutingRouteConfig (
4042 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4043 IN CONST EFI_STRING Configuration,
4044 OUT EFI_STRING *Progress
4045 )
4046 {
4047 HII_DATABASE_PRIVATE_DATA *Private;
4048 EFI_STRING StringPtr;
4049 EFI_STRING ConfigResp;
4050 UINTN Length;
4051 EFI_STATUS Status;
4052 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4053 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4054 LIST_ENTRY *Link;
4055 HII_DATABASE_RECORD *Database;
4056 UINT8 *DevicePathPkg;
4057 UINT8 *CurrentDevicePath;
4058 EFI_HANDLE DriverHandle;
4059 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4060 EFI_STRING AccessProgress;
4061 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4062 BOOLEAN IsEfiVarstore;
4063
4064 if (This == NULL || Progress == NULL) {
4065 return EFI_INVALID_PARAMETER;
4066 }
4067
4068 if (Configuration == NULL) {
4069 *Progress = NULL;
4070 return EFI_INVALID_PARAMETER;
4071 }
4072
4073 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4074 StringPtr = Configuration;
4075 *Progress = StringPtr;
4076 Database = NULL;
4077 AccessProgress = NULL;
4078 EfiVarStoreInfo= NULL;
4079 IsEfiVarstore = FALSE;
4080
4081 //
4082 // The first element of <MultiConfigResp> should be
4083 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4084 //
4085 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4086 return EFI_INVALID_PARAMETER;
4087 }
4088
4089 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4090 //
4091 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4092 // or most recent & before the error.
4093 //
4094 if (StringPtr == Configuration) {
4095 *Progress = StringPtr;
4096 } else {
4097 *Progress = StringPtr - 1;
4098 }
4099
4100 //
4101 // Process each <ConfigResp> of <MultiConfigResp>
4102 //
4103 Length = CalculateConfigStringLen (StringPtr);
4104 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4105 if (ConfigResp == NULL) {
4106 return EFI_OUT_OF_RESOURCES;
4107 }
4108 //
4109 // Append '\0' to the end of ConfigRequest
4110 //
4111 *(ConfigResp + Length) = 0;
4112
4113 //
4114 // Get the UEFI device path
4115 //
4116 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
4117 if (EFI_ERROR (Status)) {
4118 FreePool (ConfigResp);
4119 return Status;
4120 }
4121
4122 //
4123 // Find driver which matches the routing data.
4124 //
4125 DriverHandle = NULL;
4126 for (Link = Private->DatabaseList.ForwardLink;
4127 Link != &Private->DatabaseList;
4128 Link = Link->ForwardLink
4129 ) {
4130 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4131
4132 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4133 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4134 if (CompareMem (
4135 DevicePath,
4136 CurrentDevicePath,
4137 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
4138 ) == 0) {
4139 DriverHandle = Database->DriverHandle;
4140 break;
4141 }
4142 }
4143 }
4144
4145 //
4146 // Try to find driver handle by device path.
4147 //
4148 if (DriverHandle == NULL) {
4149 TempDevicePath = DevicePath;
4150 Status = gBS->LocateDevicePath (
4151 &gEfiDevicePathProtocolGuid,
4152 &TempDevicePath,
4153 &DriverHandle
4154 );
4155 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4156 //
4157 // Routing data does not match any known driver.
4158 // Set Progress to the 'G' in "GUID" of the routing header.
4159 //
4160 FreePool (DevicePath);
4161 *Progress = StringPtr;
4162 FreePool (ConfigResp);
4163 return EFI_NOT_FOUND;
4164 }
4165 }
4166
4167 FreePool (DevicePath);
4168
4169 //
4170 // Check whether this ConfigRequest is search from Efi varstore type storage.
4171 //
4172 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
4173 if (EFI_ERROR (Status)) {
4174 return Status;
4175 }
4176
4177 if (IsEfiVarstore) {
4178 //
4179 // Call the SetVariable function to route settings.
4180 //
4181 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
4182 FreePool (EfiVarStoreInfo);
4183 } else {
4184 //
4185 // Call corresponding ConfigAccess protocol to route settings
4186 //
4187 Status = gBS->HandleProtocol (
4188 DriverHandle,
4189 &gEfiHiiConfigAccessProtocolGuid,
4190 (VOID **) &ConfigAccess
4191 );
4192 ASSERT_EFI_ERROR (Status);
4193
4194 Status = ConfigAccess->RouteConfig (
4195 ConfigAccess,
4196 ConfigResp,
4197 &AccessProgress
4198 );
4199 }
4200 if (EFI_ERROR (Status)) {
4201 //
4202 // AccessProgress indicates the parsing progress on <ConfigResp>.
4203 // Map it to the progress on <MultiConfigResp> then return it.
4204 //
4205 *Progress = StrStr (StringPtr, AccessProgress);
4206
4207 FreePool (ConfigResp);
4208 return Status;
4209 }
4210
4211 FreePool (ConfigResp);
4212 ConfigResp = NULL;
4213
4214 //
4215 // Go to next <ConfigResp> (skip '&').
4216 //
4217 StringPtr += Length;
4218 if (*StringPtr == 0) {
4219 *Progress = StringPtr;
4220 break;
4221 }
4222
4223 StringPtr++;
4224
4225 }
4226
4227 return EFI_SUCCESS;
4228 }
4229
4230
4231 /**
4232 This helper function is to be called by drivers to map configuration data
4233 stored in byte array ("block") formats such as UEFI Variables into current
4234 configuration strings.
4235
4236 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4237 instance.
4238 @param ConfigRequest A null-terminated Unicode string in
4239 <ConfigRequest> format.
4240 @param Block Array of bytes defining the block's configuration.
4241 @param BlockSize Length in bytes of Block.
4242 @param Config Filled-in configuration string. String allocated
4243 by the function. Returned only if call is
4244 successful. It is <ConfigResp> string format.
4245 @param Progress A pointer to a string filled in with the offset of
4246 the most recent & before the first failing
4247 name/value pair (or the beginning of the string if
4248 the failure is in the first name / value pair) or
4249 the terminating NULL if all was successful.
4250
4251 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4252 terminator at the end of the ConfigRequest
4253 string.
4254 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4255 points to the first character of ConfigRequest.
4256 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4257 Block parameter would result in this type of
4258 error. Progress points to the first character of
4259 ConfigRequest.
4260 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4261 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4262 Block is left updated and Progress points at
4263 the "&" preceding the first non-<BlockName>.
4264
4265 **/
4266 EFI_STATUS
4267 EFIAPI
4268 HiiBlockToConfig (
4269 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4270 IN CONST EFI_STRING ConfigRequest,
4271 IN CONST UINT8 *Block,
4272 IN CONST UINTN BlockSize,
4273 OUT EFI_STRING *Config,
4274 OUT EFI_STRING *Progress
4275 )
4276 {
4277 HII_DATABASE_PRIVATE_DATA *Private;
4278 EFI_STRING StringPtr;
4279 UINTN Length;
4280 EFI_STATUS Status;
4281 EFI_STRING TmpPtr;
4282 UINT8 *TmpBuffer;
4283 UINTN Offset;
4284 UINTN Width;
4285 UINT8 *Value;
4286 EFI_STRING ValueStr;
4287 EFI_STRING ConfigElement;
4288 UINTN Index;
4289 UINT8 *TemBuffer;
4290 CHAR16 *TemString;
4291 CHAR16 TemChar;
4292
4293 if (This == NULL || Progress == NULL || Config == NULL) {
4294 return EFI_INVALID_PARAMETER;
4295 }
4296
4297 if (Block == NULL || ConfigRequest == NULL) {
4298 *Progress = ConfigRequest;
4299 return EFI_INVALID_PARAMETER;
4300 }
4301
4302
4303 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4304 ASSERT (Private != NULL);
4305
4306 StringPtr = ConfigRequest;
4307 ValueStr = NULL;
4308 Value = NULL;
4309 ConfigElement = NULL;
4310
4311 //
4312 // Allocate a fix length of memory to store Results. Reallocate memory for
4313 // Results if this fix length is insufficient.
4314 //
4315 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4316 if (*Config == NULL) {
4317 return EFI_OUT_OF_RESOURCES;
4318 }
4319
4320 //
4321 // Jump <ConfigHdr>
4322 //
4323 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4324 *Progress = StringPtr;
4325 Status = EFI_INVALID_PARAMETER;
4326 goto Exit;
4327 }
4328 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
4329 StringPtr++;
4330 }
4331 if (*StringPtr == 0) {
4332 *Progress = StringPtr - 1;
4333 Status = EFI_INVALID_PARAMETER;
4334 goto Exit;
4335 }
4336
4337 while (*StringPtr != L'&' && *StringPtr != 0) {
4338 StringPtr++;
4339 }
4340 if (*StringPtr == 0) {
4341 *Progress = StringPtr;
4342 Status = EFI_SUCCESS;
4343
4344 AppendToMultiString(Config, ConfigRequest);
4345 HiiToLower (*Config);
4346
4347 goto Exit;
4348 }
4349 //
4350 // Skip '&'
4351 //
4352 StringPtr++;
4353
4354 //
4355 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4356 //
4357 TemChar = *StringPtr;
4358 *StringPtr = '\0';
4359 AppendToMultiString(Config, ConfigRequest);
4360 *StringPtr = TemChar;
4361
4362 //
4363 // Parse each <RequestElement> if exists
4364 // Only <BlockName> format is supported by this help function.
4365 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4366 //
4367 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
4368 //
4369 // Back up the header of one <BlockName>
4370 //
4371 TmpPtr = StringPtr;
4372
4373 StringPtr += StrLen (L"OFFSET=");
4374 //
4375 // Get Offset
4376 //
4377 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4378 if (EFI_ERROR (Status)) {
4379 *Progress = TmpPtr - 1;
4380 goto Exit;
4381 }
4382 Offset = 0;
4383 CopyMem (
4384 &Offset,
4385 TmpBuffer,
4386 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4387 );
4388 FreePool (TmpBuffer);
4389
4390 StringPtr += Length;
4391 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4392 *Progress = TmpPtr - 1;
4393 Status = EFI_INVALID_PARAMETER;
4394 goto Exit;
4395 }
4396 StringPtr += StrLen (L"&WIDTH=");
4397
4398 //
4399 // Get Width
4400 //
4401 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4402 if (EFI_ERROR (Status)) {
4403 *Progress = TmpPtr - 1;
4404 goto Exit;
4405 }
4406 Width = 0;
4407 CopyMem (
4408 &Width,
4409 TmpBuffer,
4410 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4411 );
4412 FreePool (TmpBuffer);
4413
4414 StringPtr += Length;
4415 if (*StringPtr != 0 && *StringPtr != L'&') {
4416 *Progress = TmpPtr - 1;
4417 Status = EFI_INVALID_PARAMETER;
4418 goto Exit;
4419 }
4420
4421 //
4422 // Calculate Value and convert it to hex string.
4423 //
4424 if (Offset + Width > BlockSize) {
4425 *Progress = StringPtr;
4426 Status = EFI_DEVICE_ERROR;
4427 goto Exit;
4428 }
4429
4430 Value = (UINT8 *) AllocateZeroPool (Width);
4431 if (Value == NULL) {
4432 *Progress = ConfigRequest;
4433 Status = EFI_OUT_OF_RESOURCES;
4434 goto Exit;
4435 }
4436
4437 CopyMem (Value, (UINT8 *) Block + Offset, Width);
4438
4439 Length = Width * 2 + 1;
4440 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
4441 if (ValueStr == NULL) {
4442 *Progress = ConfigRequest;
4443 Status = EFI_OUT_OF_RESOURCES;
4444 goto Exit;
4445 }
4446
4447 TemString = ValueStr;
4448 TemBuffer = Value + Width - 1;
4449 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
4450 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
4451 }
4452
4453 FreePool (Value);
4454 Value = NULL;
4455
4456 //
4457 // Build a ConfigElement
4458 //
4459 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
4460 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
4461 if (ConfigElement == NULL) {
4462 Status = EFI_OUT_OF_RESOURCES;
4463 goto Exit;
4464 }
4465 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
4466 if (*StringPtr == 0) {
4467 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
4468 }
4469 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
4470 StrCat (ConfigElement, L"VALUE=");
4471 StrCat (ConfigElement, ValueStr);
4472
4473 AppendToMultiString (Config, ConfigElement);
4474
4475 FreePool (ConfigElement);
4476 FreePool (ValueStr);
4477 ConfigElement = NULL;
4478 ValueStr = NULL;
4479
4480 //
4481 // If '\0', parsing is finished. Otherwise skip '&' to continue
4482 //
4483 if (*StringPtr == 0) {
4484 break;
4485 }
4486 AppendToMultiString (Config, L"&");
4487 StringPtr++;
4488
4489 }
4490
4491 if (*StringPtr != 0) {
4492 *Progress = StringPtr - 1;
4493 Status = EFI_INVALID_PARAMETER;
4494 goto Exit;
4495 }
4496
4497 HiiToLower (*Config);
4498 *Progress = StringPtr;
4499 return EFI_SUCCESS;
4500
4501 Exit:
4502 if (*Config != NULL) {
4503 FreePool (*Config);
4504 *Config = NULL;
4505 }
4506 if (ValueStr != NULL) {
4507 FreePool (ValueStr);
4508 }
4509 if (Value != NULL) {
4510 FreePool (Value);
4511 }
4512 if (ConfigElement != NULL) {
4513 FreePool (ConfigElement);
4514 }
4515
4516 return Status;
4517
4518 }
4519
4520
4521 /**
4522 This helper function is to be called by drivers to map configuration strings
4523 to configurations stored in byte array ("block") formats such as UEFI Variables.
4524
4525 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4526 instance.
4527 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4528 format.
4529 @param Block A possibly null array of bytes representing the
4530 current block. Only bytes referenced in the
4531 ConfigResp string in the block are modified. If
4532 this parameter is null or if the *BlockSize
4533 parameter is (on input) shorter than required by
4534 the Configuration string, only the BlockSize
4535 parameter is updated and an appropriate status
4536 (see below) is returned.
4537 @param BlockSize The length of the Block in units of UINT8. On
4538 input, this is the size of the Block. On output,
4539 if successful, contains the largest index of the
4540 modified byte in the Block, or the required buffer
4541 size if the Block is not large enough.
4542 @param Progress On return, points to an element of the ConfigResp
4543 string filled in with the offset of the most
4544 recent '&' before the first failing name / value
4545 pair (or the beginning of the string if the
4546 failure is in the first name / value pair) or the
4547 terminating NULL if all was successful.
4548
4549 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4550 terminator at the end of the ConfigResp string.
4551 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4552 points to the first character of ConfigResp.
4553 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4554 Block parameter would result in this type of
4555 error. Progress points to the first character of
4556 ConfigResp.
4557 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4558 value pair. Block is left updated and
4559 Progress points at the '&' preceding the first
4560 non-<BlockName>.
4561 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4562 BlockSize is updated with the required buffer size.
4563 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4564 Progress points to the "G" in "GUID" of the errant
4565 routing data.
4566
4567 **/
4568 EFI_STATUS
4569 EFIAPI
4570 HiiConfigToBlock (
4571 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4572 IN CONST EFI_STRING ConfigResp,
4573 IN OUT UINT8 *Block,
4574 IN OUT UINTN *BlockSize,
4575 OUT EFI_STRING *Progress
4576 )
4577 {
4578 HII_DATABASE_PRIVATE_DATA *Private;
4579 EFI_STRING StringPtr;
4580 EFI_STRING TmpPtr;
4581 UINTN Length;
4582 EFI_STATUS Status;
4583 UINT8 *TmpBuffer;
4584 UINTN Offset;
4585 UINTN Width;
4586 UINT8 *Value;
4587 UINTN BufferSize;
4588 UINTN MaxBlockSize;
4589
4590 if (This == NULL || BlockSize == NULL || Progress == NULL) {
4591 return EFI_INVALID_PARAMETER;
4592 }
4593
4594 *Progress = ConfigResp;
4595 if (ConfigResp == NULL) {
4596 return EFI_INVALID_PARAMETER;
4597 }
4598
4599 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4600 ASSERT (Private != NULL);
4601
4602 StringPtr = ConfigResp;
4603 BufferSize = *BlockSize;
4604 Value = NULL;
4605 MaxBlockSize = 0;
4606
4607 //
4608 // Jump <ConfigHdr>
4609 //
4610 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4611 *Progress = StringPtr;
4612 Status = EFI_INVALID_PARAMETER;
4613 goto Exit;
4614 }
4615 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
4616 StringPtr++;
4617 }
4618 if (*StringPtr == 0) {
4619 *Progress = StringPtr;
4620 Status = EFI_INVALID_PARAMETER;
4621 goto Exit;
4622 }
4623
4624 while (*StringPtr != L'&' && *StringPtr != 0) {
4625 StringPtr++;
4626 }
4627 if (*StringPtr == 0) {
4628 *Progress = StringPtr;
4629 Status = EFI_INVALID_PARAMETER;
4630 goto Exit;
4631 }
4632
4633 //
4634 // Parse each <ConfigElement> if exists
4635 // Only '&'<BlockConfig> format is supported by this help function.
4636 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4637 //
4638 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
4639 TmpPtr = StringPtr;
4640 StringPtr += StrLen (L"&OFFSET=");
4641 //
4642 // Get Offset
4643 //
4644 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4645 if (EFI_ERROR (Status)) {
4646 *Progress = TmpPtr;
4647 goto Exit;
4648 }
4649 Offset = 0;
4650 CopyMem (
4651 &Offset,
4652 TmpBuffer,
4653 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4654 );
4655 FreePool (TmpBuffer);
4656
4657 StringPtr += Length;
4658 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4659 *Progress = TmpPtr;
4660 Status = EFI_INVALID_PARAMETER;
4661 goto Exit;
4662 }
4663 StringPtr += StrLen (L"&WIDTH=");
4664
4665 //
4666 // Get Width
4667 //
4668 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
4669 if (EFI_ERROR (Status)) {
4670 *Progress = TmpPtr;
4671 goto Exit;
4672 }
4673 Width = 0;
4674 CopyMem (
4675 &Width,
4676 TmpBuffer,
4677 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
4678 );
4679 FreePool (TmpBuffer);
4680
4681 StringPtr += Length;
4682 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
4683 *Progress = TmpPtr;
4684 Status = EFI_INVALID_PARAMETER;
4685 goto Exit;
4686 }
4687 StringPtr += StrLen (L"&VALUE=");
4688
4689 //
4690 // Get Value
4691 //
4692 Status = GetValueOfNumber (StringPtr, &Value, &Length);
4693 if (EFI_ERROR (Status)) {
4694 *Progress = TmpPtr;
4695 goto Exit;
4696 }
4697
4698 StringPtr += Length;
4699 if (*StringPtr != 0 && *StringPtr != L'&') {
4700 *Progress = TmpPtr;
4701 Status = EFI_INVALID_PARAMETER;
4702 goto Exit;
4703 }
4704
4705 //
4706 // Update the Block with configuration info
4707 //
4708 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
4709 CopyMem (Block + Offset, Value, Width);
4710 }
4711 if (Offset + Width > MaxBlockSize) {
4712 MaxBlockSize = Offset + Width;
4713 }
4714
4715 FreePool (Value);
4716 Value = NULL;
4717
4718 //
4719 // If '\0', parsing is finished.
4720 //
4721 if (*StringPtr == 0) {
4722 break;
4723 }
4724 }
4725
4726 //
4727 // The input string is not ConfigResp format, return error.
4728 //
4729 if (*StringPtr != 0) {
4730 *Progress = StringPtr;
4731 Status = EFI_INVALID_PARAMETER;
4732 goto Exit;
4733 }
4734
4735 *Progress = StringPtr + StrLen (StringPtr);
4736 *BlockSize = MaxBlockSize - 1;
4737
4738 if (MaxBlockSize > BufferSize) {
4739 *BlockSize = MaxBlockSize;
4740 if (Block != NULL) {
4741 return EFI_BUFFER_TOO_SMALL;
4742 }
4743 }
4744
4745 if (Block == NULL) {
4746 *Progress = ConfigResp;
4747 return EFI_INVALID_PARAMETER;
4748 }
4749
4750 return EFI_SUCCESS;
4751
4752 Exit:
4753
4754 if (Value != NULL) {
4755 FreePool (Value);
4756 }
4757 return Status;
4758 }
4759
4760
4761 /**
4762 This helper function is to be called by drivers to extract portions of
4763 a larger configuration string.
4764
4765 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4766 instance.
4767 @param Configuration A null-terminated Unicode string in
4768 <MultiConfigAltResp> format.
4769 @param Guid A pointer to the GUID value to search for in the
4770 routing portion of the ConfigResp string when
4771 retrieving the requested data. If Guid is NULL,
4772 then all GUID values will be searched for.
4773 @param Name A pointer to the NAME value to search for in the
4774 routing portion of the ConfigResp string when
4775 retrieving the requested data. If Name is NULL,
4776 then all Name values will be searched for.
4777 @param DevicePath A pointer to the PATH value to search for in the
4778 routing portion of the ConfigResp string when
4779 retrieving the requested data. If DevicePath is
4780 NULL, then all DevicePath values will be searched
4781 for.
4782 @param AltCfgId A pointer to the ALTCFG value to search for in the
4783 routing portion of the ConfigResp string when
4784 retrieving the requested data. If this parameter
4785 is NULL, then the current setting will be
4786 retrieved.
4787 @param AltCfgResp A pointer to a buffer which will be allocated by
4788 the function which contains the retrieved string
4789 as requested. This buffer is only allocated if
4790 the call was successful. It is <ConfigResp> format.
4791
4792 @retval EFI_SUCCESS The request succeeded. The requested data was
4793 extracted and placed in the newly allocated
4794 AltCfgResp buffer.
4795 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4796 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4797 @retval EFI_NOT_FOUND Target for the specified routing data was not
4798 found.
4799
4800 **/
4801 EFI_STATUS
4802 EFIAPI
4803 HiiGetAltCfg (
4804 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4805 IN CONST EFI_STRING Configuration,
4806 IN CONST EFI_GUID *Guid,
4807 IN CONST EFI_STRING Name,
4808 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
4809 IN CONST UINT16 *AltCfgId,
4810 OUT EFI_STRING *AltCfgResp
4811 )
4812 {
4813 EFI_STATUS Status;
4814 EFI_STRING StringPtr;
4815 EFI_STRING HdrStart;
4816 EFI_STRING HdrEnd;
4817 EFI_STRING TmpPtr;
4818 UINTN Length;
4819 EFI_STRING GuidStr;
4820 EFI_STRING NameStr;
4821 EFI_STRING PathStr;
4822 EFI_STRING AltIdStr;
4823 EFI_STRING Result;
4824 BOOLEAN GuidFlag;
4825 BOOLEAN NameFlag;
4826 BOOLEAN PathFlag;
4827
4828 HdrStart = NULL;
4829 HdrEnd = NULL;
4830 GuidStr = NULL;
4831 NameStr = NULL;
4832 PathStr = NULL;
4833 AltIdStr = NULL;
4834 Result = NULL;
4835 GuidFlag = FALSE;
4836 NameFlag = FALSE;
4837 PathFlag = FALSE;
4838
4839 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
4840 return EFI_INVALID_PARAMETER;
4841 }
4842
4843 StringPtr = Configuration;
4844 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4845 return EFI_INVALID_PARAMETER;
4846 }
4847
4848 //
4849 // Generate the sub string for later matching.
4850 //
4851 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
4852 GenerateSubStr (
4853 L"PATH=",
4854 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
4855 (VOID *) DevicePath,
4856 1,
4857 &PathStr
4858 );
4859 if (AltCfgId != NULL) {
4860 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
4861 }
4862 if (Name != NULL) {
4863 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
4864 } else {
4865 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
4866 }
4867
4868 while (*StringPtr != 0) {
4869 //
4870 // Try to match the GUID
4871 //
4872 if (!GuidFlag) {
4873 TmpPtr = StrStr (StringPtr, GuidStr);
4874 if (TmpPtr == NULL) {
4875 Status = EFI_NOT_FOUND;
4876 goto Exit;
4877 }
4878 HdrStart = TmpPtr;
4879
4880 //
4881 // Jump to <NameHdr>
4882 //
4883 if (Guid != NULL) {
4884 StringPtr = TmpPtr + StrLen (GuidStr);
4885 } else {
4886 StringPtr = StrStr (TmpPtr, L"NAME=");
4887 if (StringPtr == NULL) {
4888 Status = EFI_NOT_FOUND;
4889 goto Exit;
4890 }
4891 }
4892 GuidFlag = TRUE;
4893 }
4894
4895 //
4896 // Try to match the NAME
4897 //
4898 if (GuidFlag && !NameFlag) {
4899 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
4900 GuidFlag = FALSE;
4901 } else {
4902 //
4903 // Jump to <PathHdr>
4904 //
4905 if (Name != NULL) {
4906 StringPtr += StrLen (NameStr);
4907 } else {
4908 StringPtr = StrStr (StringPtr, L"PATH=");
4909 if (StringPtr == NULL) {
4910 Status = EFI_NOT_FOUND;
4911 goto Exit;
4912 }
4913 }
4914 NameFlag = TRUE;
4915 }
4916 }
4917
4918 //
4919 // Try to match the DevicePath
4920 //
4921 if (GuidFlag && NameFlag && !PathFlag) {
4922 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
4923 GuidFlag = FALSE;
4924 NameFlag = FALSE;
4925 } else {
4926 //
4927 // Jump to '&' before <DescHdr> or <ConfigBody>
4928 //
4929 if (DevicePath != NULL) {
4930 StringPtr += StrLen (PathStr);
4931 } else {
4932 StringPtr = StrStr (StringPtr, L"&");
4933 if (StringPtr == NULL) {
4934 Status = EFI_NOT_FOUND;
4935 goto Exit;
4936 }
4937 StringPtr ++;
4938 }
4939 PathFlag = TRUE;
4940 HdrEnd = StringPtr;
4941 }
4942 }
4943
4944 //
4945 // Try to match the AltCfgId
4946 //
4947 if (GuidFlag && NameFlag && PathFlag) {
4948 if (AltCfgId == NULL) {
4949 //
4950 // Return Current Setting when AltCfgId is NULL.
4951 //
4952 Status = OutputConfigBody (StringPtr, &Result);
4953 goto Exit;
4954 }
4955 //
4956 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4957 //
4958 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
4959 GuidFlag = FALSE;
4960 NameFlag = FALSE;
4961 PathFlag = FALSE;
4962 } else {
4963 //
4964 // Skip AltIdStr and &
4965 //
4966 StringPtr = StringPtr + StrLen (AltIdStr);
4967 Status = OutputConfigBody (StringPtr, &Result);
4968 goto Exit;
4969 }
4970 }
4971 }
4972
4973 Status = EFI_NOT_FOUND;
4974
4975 Exit:
4976 *AltCfgResp = NULL;
4977 if (!EFI_ERROR (Status) && (Result != NULL)) {
4978 //
4979 // Copy the <ConfigHdr> and <ConfigBody>
4980 //
4981 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
4982 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
4983 if (*AltCfgResp == NULL) {
4984 Status = EFI_OUT_OF_RESOURCES;
4985 } else {
4986 StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
4987 StrCat (*AltCfgResp, Result);
4988 Status = EFI_SUCCESS;
4989 }
4990 }
4991
4992 if (GuidStr != NULL) {
4993 FreePool (GuidStr);
4994 }
4995 if (NameStr != NULL) {
4996 FreePool (NameStr);
4997 }
4998 if (PathStr != NULL) {
4999 FreePool (PathStr);
5000 }
5001 if (AltIdStr != NULL) {
5002 FreePool (AltIdStr);
5003 }
5004 if (Result != NULL) {
5005 FreePool (Result);
5006 }
5007
5008 return Status;
5009
5010 }
5011
5012