]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
MdeModulePkg: Replace [Ascii|Unicode]ValueToString
[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 - 2017, 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 necessary 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 StrCpyS (Str, Length, String);
256
257 StringHeader = Str + StrLen (String);
258 TemString = (CHAR16 *) StringHeader;
259
260 switch (Flag) {
261 case 1:
262 //
263 // Convert Buffer to Hex String in reverse order
264 //
265 TemBuffer = ((UINT8 *) Buffer);
266 for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
267 UnicodeValueToStringS (
268 TemString,
269 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
270 PREFIX_ZERO | RADIX_HEX,
271 *TemBuffer,
272 2
273 );
274 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
275 }
276 break;
277 case 2:
278 //
279 // Check buffer is enough
280 //
281 TemName = (CHAR16 *) Buffer;
282 ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
283 //
284 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
285 //
286 for (; *TemName != L'\0'; TemName++) {
287 UnicodeValueToStringS (
288 TemString,
289 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
290 PREFIX_ZERO | RADIX_HEX,
291 *TemName,
292 4
293 );
294 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
295 }
296 break;
297 case 3:
298 //
299 // Convert Buffer to Hex String
300 //
301 TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
302 for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
303 UnicodeValueToStringS (
304 TemString,
305 sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),
306 PREFIX_ZERO | RADIX_HEX,
307 *TemBuffer,
308 2
309 );
310 TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));
311 }
312 break;
313 default:
314 break;
315 }
316
317 //
318 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
319 //
320 StrCatS (Str, Length, L"&");
321 HiiToLower (Str);
322
323 *SubStr = Str;
324 }
325
326
327 /**
328 Retrieve the <ConfigBody> from String then output it.
329
330 This is a internal function.
331
332 @param String A sub string of a configuration string in
333 <MultiConfigAltResp> format.
334 @param ConfigBody Points to the output string. It's caller's
335 responsibility to free this buffer.
336
337 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
338 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
339 @retval EFI_SUCCESS All existing storage is exported.
340
341 **/
342 EFI_STATUS
343 OutputConfigBody (
344 IN EFI_STRING String,
345 OUT EFI_STRING *ConfigBody
346 )
347 {
348 EFI_STRING TmpPtr;
349 EFI_STRING Result;
350 UINTN Length;
351
352 if (String == NULL || ConfigBody == NULL) {
353 return EFI_INVALID_PARAMETER;
354 }
355
356 //
357 // The setting information should start OFFSET, not ALTCFG.
358 //
359 if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
360 return EFI_INVALID_PARAMETER;
361 }
362
363 TmpPtr = StrStr (String, L"GUID=");
364 if (TmpPtr == NULL) {
365 //
366 // It is the last <ConfigResp> of the incoming configuration string.
367 //
368 Result = AllocateCopyPool (StrSize (String), String);
369 if (Result == NULL) {
370 return EFI_OUT_OF_RESOURCES;
371 } else {
372 *ConfigBody = Result;
373 return EFI_SUCCESS;
374 }
375 }
376
377 Length = TmpPtr - String;
378 if (Length == 0) {
379 return EFI_NOT_FOUND;
380 }
381 Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
382 if (Result == NULL) {
383 return EFI_OUT_OF_RESOURCES;
384 }
385
386 *(Result + Length - 1) = 0;
387 *ConfigBody = Result;
388 return EFI_SUCCESS;
389 }
390
391 /**
392 Append a string to a multi-string format.
393
394 This is a internal function.
395
396 @param MultiString String in <MultiConfigRequest>,
397 <MultiConfigAltResp>, or <MultiConfigResp>. On
398 input, the buffer length of this string is
399 MAX_STRING_LENGTH. On output, the buffer length
400 might be updated.
401 @param AppendString NULL-terminated Unicode string.
402
403 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
404 @retval EFI_SUCCESS AppendString is append to the end of MultiString
405
406 **/
407 EFI_STATUS
408 AppendToMultiString (
409 IN OUT EFI_STRING *MultiString,
410 IN EFI_STRING AppendString
411 )
412 {
413 UINTN AppendStringSize;
414 UINTN MultiStringSize;
415 UINTN MaxLen;
416
417 if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
418 return EFI_INVALID_PARAMETER;
419 }
420
421 AppendStringSize = StrSize (AppendString);
422 MultiStringSize = StrSize (*MultiString);
423 MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
424
425 //
426 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
427 //
428 if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
429 MultiStringSize > MAX_STRING_LENGTH) {
430 *MultiString = (EFI_STRING) ReallocatePool (
431 MultiStringSize,
432 MultiStringSize + AppendStringSize,
433 (VOID *) (*MultiString)
434 );
435 MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
436 ASSERT (*MultiString != NULL);
437 }
438 //
439 // Append the incoming string
440 //
441 StrCatS (*MultiString, MaxLen, AppendString);
442
443 return EFI_SUCCESS;
444 }
445
446
447 /**
448 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
449 or WIDTH or VALUE.
450 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
451
452 This is a internal function.
453
454 @param StringPtr String in <BlockConfig> format and points to the
455 first character of <Number>.
456 @param Number The output value. Caller takes the responsibility
457 to free memory.
458 @param Len Length of the <Number>, in characters.
459
460 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
461 structures.
462 @retval EFI_SUCCESS Value of <Number> is outputted in Number
463 successfully.
464
465 **/
466 EFI_STATUS
467 GetValueOfNumber (
468 IN EFI_STRING StringPtr,
469 OUT UINT8 **Number,
470 OUT UINTN *Len
471 )
472 {
473 EFI_STRING TmpPtr;
474 UINTN Length;
475 EFI_STRING Str;
476 UINT8 *Buf;
477 EFI_STATUS Status;
478 UINT8 DigitUint8;
479 UINTN Index;
480 CHAR16 TemStr[2];
481
482 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
483 return EFI_INVALID_PARAMETER;
484 }
485
486 Buf = NULL;
487
488 TmpPtr = StringPtr;
489 while (*StringPtr != L'\0' && *StringPtr != L'&') {
490 StringPtr++;
491 }
492 *Len = StringPtr - TmpPtr;
493 Length = *Len + 1;
494
495 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
496 if (Str == NULL) {
497 Status = EFI_OUT_OF_RESOURCES;
498 goto Exit;
499 }
500 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
501 *(Str + *Len) = L'\0';
502
503 Length = (Length + 1) / 2;
504 Buf = (UINT8 *) AllocateZeroPool (Length);
505 if (Buf == NULL) {
506 Status = EFI_OUT_OF_RESOURCES;
507 goto Exit;
508 }
509
510 Length = *Len;
511 ZeroMem (TemStr, sizeof (TemStr));
512 for (Index = 0; Index < Length; Index ++) {
513 TemStr[0] = Str[Length - Index - 1];
514 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
515 if ((Index & 1) == 0) {
516 Buf [Index/2] = DigitUint8;
517 } else {
518 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
519 }
520 }
521
522 *Number = Buf;
523 Status = EFI_SUCCESS;
524
525 Exit:
526 if (Str != NULL) {
527 FreePool (Str);
528 }
529
530 return Status;
531 }
532
533 /**
534 To find the BlockName in the string with same value.
535
536 @param String Pointer to a Null-terminated Unicode string.
537 @param BlockName Pointer to a Null-terminated Unicode string to search for.
538 @param Buffer Pointer to the value correspond to the BlockName.
539 @param Found The Block whether has been found.
540 @param BufferLen The length of the buffer.
541
542 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
543 @retval EFI_SUCCESS The function finishes successfully.
544
545 **/
546 EFI_STATUS
547 FindSameBlockElement(
548 IN EFI_STRING String,
549 IN EFI_STRING BlockName,
550 IN UINT8 *Buffer,
551 OUT BOOLEAN *Found,
552 IN UINTN BufferLen
553 )
554 {
555 EFI_STRING BlockPtr;
556 UINTN Length;
557 UINT8 *TempBuffer;
558 EFI_STATUS Status;
559
560 TempBuffer = NULL;
561 *Found = FALSE;
562 BlockPtr = StrStr (String, BlockName);
563
564 while (BlockPtr != NULL) {
565 BlockPtr += StrLen (BlockName);
566 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
567 if (EFI_ERROR (Status)) {
568 return Status;
569 }
570 ASSERT (TempBuffer != NULL);
571 if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
572 *Found = TRUE;
573 FreePool (TempBuffer);
574 TempBuffer = NULL;
575 return EFI_SUCCESS;
576 } else {
577 FreePool (TempBuffer);
578 TempBuffer = NULL;
579 BlockPtr = StrStr (BlockPtr + 1, BlockName);
580 }
581 }
582 return EFI_SUCCESS;
583 }
584
585 /**
586 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
587 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
588
589 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
590 <MultiConfigAltResp> format. The default value
591 string may contain more than one ConfigAltResp
592 string for the different varstore buffer.
593 @param ConfigAltResp Pointer to a null-terminated Unicode string in
594 <ConfigAltResp> format.
595 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
596 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
597
598 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
599 @retval EFI_SUCCESS The function finishes successfully.
600
601 **/
602 EFI_STATUS
603 CompareBlockElementDefault (
604 IN EFI_STRING DefaultAltCfgResp,
605 IN OUT EFI_STRING *ConfigAltResp,
606 IN EFI_STRING AltConfigHdr,
607 IN OUT BOOLEAN *ConfigAltRespChanged
608 )
609 {
610 EFI_STATUS Status;
611 EFI_STRING BlockPtr;
612 EFI_STRING BlockPtrStart;
613 EFI_STRING StringPtr;
614 EFI_STRING AppendString;
615 EFI_STRING AltConfigHdrPtr;
616 UINT8 *TempBuffer;
617 UINTN OffsetLength;
618 UINTN AppendSize;
619 UINTN TotalSize;
620 BOOLEAN FoundOffset;
621
622 AppendString = NULL;
623 TempBuffer = NULL;
624 //
625 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
626 //
627 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
628 ASSERT (AltConfigHdrPtr != NULL);
629 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
630 //
631 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
632 //
633 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
634 ASSERT (StringPtr != NULL);
635
636 while (BlockPtr != NULL) {
637 //
638 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
639 //
640 BlockPtrStart = BlockPtr;
641 BlockPtr += StrLen (L"&OFFSET=");
642 Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
643 if (EFI_ERROR (Status)) {
644 Status = EFI_OUT_OF_RESOURCES;
645 goto Exit;
646 }
647 //
648 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
649 //
650 Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
651 if (TempBuffer != NULL) {
652 FreePool (TempBuffer);
653 TempBuffer = NULL;
654 }
655 if (EFI_ERROR (Status)) {
656 Status = EFI_OUT_OF_RESOURCES;
657 goto Exit;
658 }
659 if (!FoundOffset) {
660 //
661 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
662 // Calculate the size of <BlockConfig>.
663 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
664 //
665 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
666 if (BlockPtr != NULL) {
667 AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
668 } else {
669 AppendSize = StrSize (BlockPtrStart);
670 }
671 //
672 // Copy the <BlockConfig> to AppendString.
673 //
674 if (AppendString == NULL) {
675 AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
676 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
677 } else {
678 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
679 AppendString = (EFI_STRING) ReallocatePool (
680 StrSize (AppendString),
681 TotalSize,
682 AppendString
683 );
684 if (AppendString == NULL) {
685 Status = EFI_OUT_OF_RESOURCES;
686 goto Exit;
687 }
688 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
689 }
690 } else {
691 //
692 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
693 //
694 BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
695 }
696 }
697
698 if (AppendString != NULL) {
699 //
700 // Reallocate ConfigAltResp to copy the AppendString.
701 //
702 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
703 *ConfigAltResp = (EFI_STRING) ReallocatePool (
704 StrSize (*ConfigAltResp),
705 TotalSize,
706 *ConfigAltResp
707 );
708 if (*ConfigAltResp == NULL) {
709 Status = EFI_OUT_OF_RESOURCES;
710 goto Exit;
711 }
712 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
713 *ConfigAltRespChanged = TRUE;
714 }
715
716 Status = EFI_SUCCESS;
717
718 Exit:
719 if (AppendString != NULL) {
720 FreePool (AppendString);
721 }
722
723 return Status;
724 }
725
726 /**
727 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
728 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
729
730 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
731 <MultiConfigAltResp> format. The default value
732 string may contain more than one ConfigAltResp
733 string for the different varstore buffer.
734 @param ConfigAltResp Pointer to a null-terminated Unicode string in
735 <ConfigAltResp> format.
736 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
737 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
738
739 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
740 @retval EFI_SUCCESS The function finishes successfully.
741
742 **/
743 EFI_STATUS
744 CompareNameElementDefault (
745 IN EFI_STRING DefaultAltCfgResp,
746 IN OUT EFI_STRING *ConfigAltResp,
747 IN EFI_STRING AltConfigHdr,
748 IN OUT BOOLEAN *ConfigAltRespChanged
749 )
750 {
751 EFI_STATUS Status;
752 EFI_STRING NvConfigPtr;
753 EFI_STRING NvConfigStart;
754 EFI_STRING NvConfigValuePtr;
755 EFI_STRING StringPtr;
756 EFI_STRING NvConfigExist;
757 EFI_STRING AppendString;
758 CHAR16 TempChar;
759 UINTN AppendSize;
760 UINTN TotalSize;
761
762 AppendString = NULL;
763 NvConfigExist = NULL;
764 //
765 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
766 //
767 NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
768 ASSERT (NvConfigPtr != NULL);
769 NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&");
770 //
771 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
772 //
773 StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
774 ASSERT (StringPtr != NULL);
775 StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
776 ASSERT (StringPtr != NULL);
777
778 while (NvConfigPtr != NULL) {
779 //
780 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
781 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
782 //
783 NvConfigStart = NvConfigPtr;
784 NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
785 ASSERT (NvConfigValuePtr != NULL);
786 TempChar = *NvConfigValuePtr;
787 *NvConfigValuePtr = L'\0';
788 //
789 // Get the <Label> with AltConfigHdr in ConfigAltResp.
790 //
791 NvConfigExist = StrStr (StringPtr, NvConfigPtr);
792 if (NvConfigExist == NULL) {
793 //
794 // Don't find same <Label> in ConfigAltResp.
795 // Calculate the size of <NvConfig>.
796 //
797 *NvConfigValuePtr = TempChar;
798 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
799 if (NvConfigPtr != NULL) {
800 AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
801 } else {
802 AppendSize = StrSize (NvConfigStart);
803 }
804 //
805 // Copy the <NvConfig> to AppendString.
806 //
807 if (AppendString == NULL) {
808 AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
809 StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
810 } else {
811 TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
812 AppendString = (EFI_STRING) ReallocatePool (
813 StrSize (AppendString),
814 TotalSize,
815 AppendString
816 );
817 if (AppendString == NULL) {
818 Status = EFI_OUT_OF_RESOURCES;
819 goto Exit;
820 }
821 StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
822 }
823 } else {
824 //
825 // To find next <Label> in DefaultAltCfgResp.
826 //
827 *NvConfigValuePtr = TempChar;
828 NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
829 }
830 }
831 if (AppendString != NULL) {
832 //
833 // Reallocate ConfigAltResp to copy the AppendString.
834 //
835 TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
836 *ConfigAltResp = (EFI_STRING) ReallocatePool (
837 StrSize (*ConfigAltResp),
838 StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
839 *ConfigAltResp
840 );
841 if (*ConfigAltResp == NULL) {
842 Status = EFI_OUT_OF_RESOURCES;
843 goto Exit;
844 }
845 StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
846 *ConfigAltRespChanged = TRUE;
847 }
848 Status = EFI_SUCCESS;
849
850 Exit:
851 if (AppendString != NULL) {
852 FreePool (AppendString);
853 }
854 return Status;
855 }
856
857 /**
858 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
859 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
860
861 @param AltCfgResp Pointer to a null-terminated Unicode string in
862 <ConfigAltResp> format.
863 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
864 <MultiConfigAltResp> format. The default value
865 string may contain more than one ConfigAltResp
866 string for the different varstore buffer.
867 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
868
869 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
870 structures.
871 @retval EFI_SUCCESS The function finishes successfully.
872
873 **/
874 EFI_STATUS
875 CompareAndMergeDefaultString (
876 IN OUT EFI_STRING *AltCfgResp,
877 IN EFI_STRING DefaultAltCfgResp,
878 IN EFI_STRING AltConfigHdr
879 )
880 {
881 EFI_STATUS Status;
882 EFI_STRING AltCfgRespBackup;
883 EFI_STRING AltConfigHdrPtr;
884 EFI_STRING AltConfigHdrPtrNext;
885 EFI_STRING ConfigAltResp;
886 EFI_STRING StringPtr;
887 EFI_STRING StringPtrNext;
888 EFI_STRING BlockPtr;
889 UINTN ReallocateSize;
890 CHAR16 TempChar;
891 CHAR16 TempCharA;
892 BOOLEAN ConfigAltRespChanged;
893
894 Status = EFI_OUT_OF_RESOURCES;
895 BlockPtr = NULL;
896 AltConfigHdrPtrNext = NULL;
897 StringPtrNext = NULL;
898 ConfigAltResp = NULL;
899 AltCfgRespBackup = NULL;
900 TempChar = L'\0';
901 TempCharA = L'\0';
902 ConfigAltRespChanged = FALSE;
903
904 //
905 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
906 //
907 AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
908 ASSERT (AltConfigHdrPtr != NULL);
909 AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
910 if (AltConfigHdrPtrNext != NULL) {
911 TempChar = *AltConfigHdrPtrNext;
912 *AltConfigHdrPtrNext = L'\0';
913 }
914 //
915 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
916 //
917 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
918 StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
919 if (StringPtrNext != NULL) {
920 TempCharA = *StringPtrNext;
921 *StringPtrNext = L'\0';
922 }
923 //
924 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
925 //
926 ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
927 if (ConfigAltResp == NULL) {
928 goto Exit;
929 }
930 //
931 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
932 //
933 BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
934 if (BlockPtr != NULL) {
935 //
936 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
937 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
938 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
939 //
940 Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
941 if (EFI_ERROR(Status)) {
942 goto Exit;
943 }
944 } else {
945 //
946 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
947 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
948 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
949 //
950 Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
951 if (EFI_ERROR(Status)) {
952 goto Exit;
953 }
954 }
955 //
956 // Restore the AltCfgResp.
957 //
958 if (StringPtrNext != NULL) {
959 *StringPtrNext = TempCharA;
960 }
961
962 //
963 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
964 //
965 if (!ConfigAltRespChanged) {
966 Status = EFI_SUCCESS;
967 goto Exit;
968 }
969 //
970 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
971 //
972 if (StringPtrNext != NULL) {
973 ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
974 } else {
975 ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
976 }
977
978 AltCfgRespBackup = (EFI_STRING) AllocateZeroPool (ReallocateSize);
979 if (AltCfgRespBackup == NULL) {
980 goto Exit;
981 }
982
983 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
984 if (StringPtrNext != NULL) {
985 StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
986 }
987
988 FreePool (*AltCfgResp);
989 *AltCfgResp = AltCfgRespBackup;
990
991 Status = EFI_SUCCESS;
992
993 Exit:
994 if (ConfigAltResp != NULL) {
995 FreePool(ConfigAltResp);
996 }
997 //
998 // Restore the DefaultAltCfgResp.
999 //
1000 if ( AltConfigHdrPtrNext != NULL) {
1001 *AltConfigHdrPtrNext = TempChar;
1002 AltConfigHdrPtrNext = NULL;
1003 }
1004
1005 return Status;
1006 }
1007
1008 /**
1009 This function merges DefaultAltCfgResp string into AltCfgResp string for
1010 the missing AltCfgId in AltCfgResq.
1011
1012 @param AltCfgResp Pointer to a null-terminated Unicode string in
1013 <ConfigAltResp> format. The default value string
1014 will be merged into it.
1015 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
1016 <MultiConfigAltResp> format. The default value
1017 string may contain more than one ConfigAltResp
1018 string for the different varstore buffer.
1019
1020 @retval EFI_SUCCESS The merged string returns.
1021 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1022 **/
1023 EFI_STATUS
1024 EFIAPI
1025 MergeDefaultString (
1026 IN OUT EFI_STRING *AltCfgResp,
1027 IN EFI_STRING DefaultAltCfgResp
1028 )
1029 {
1030 EFI_STRING StringPtrDefault;
1031 EFI_STRING StringPtrEnd;
1032 CHAR16 TempChar;
1033 EFI_STRING StringPtr;
1034 EFI_STRING AltConfigHdr;
1035 UINTN HeaderLength;
1036 UINTN SizeAltCfgResp;
1037 UINTN MaxLen;
1038 UINTN TotalSize;
1039
1040 if (*AltCfgResp == NULL) {
1041 return EFI_INVALID_PARAMETER;
1042 }
1043
1044 //
1045 // Get the request ConfigHdr
1046 //
1047 SizeAltCfgResp = 0;
1048 StringPtr = *AltCfgResp;
1049
1050 //
1051 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1052 //
1053 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
1054 return EFI_INVALID_PARAMETER;
1055 }
1056 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
1057 StringPtr++;
1058 }
1059 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
1060 StringPtr++;
1061 }
1062 if (*StringPtr == L'\0') {
1063 return EFI_INVALID_PARAMETER;
1064 }
1065 StringPtr += StrLen (L"&PATH=");
1066 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1067 StringPtr ++;
1068 }
1069 HeaderLength = StringPtr - *AltCfgResp;
1070
1071 //
1072 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1073 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1074 //
1075 MaxLen = 1 + HeaderLength + 8 + 4 + 1;
1076 AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
1077 if (AltConfigHdr == NULL) {
1078 return EFI_OUT_OF_RESOURCES;
1079 }
1080 StrCpyS (AltConfigHdr, MaxLen, L"&");
1081 StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
1082 StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
1083 HeaderLength = StrLen (AltConfigHdr);
1084
1085 StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
1086 while (StringPtrDefault != NULL) {
1087 //
1088 // Get AltCfg Name
1089 //
1090 StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
1091 StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
1092
1093 //
1094 // Append the found default value string to the input AltCfgResp
1095 //
1096 if (StringPtr == NULL) {
1097 StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");
1098 SizeAltCfgResp = StrSize (*AltCfgResp);
1099 if (StringPtrEnd == NULL) {
1100 //
1101 // No more default string is found.
1102 //
1103 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1104 *AltCfgResp = (EFI_STRING) ReallocatePool (
1105 SizeAltCfgResp,
1106 TotalSize,
1107 (VOID *) (*AltCfgResp)
1108 );
1109 if (*AltCfgResp == NULL) {
1110 FreePool (AltConfigHdr);
1111 return EFI_OUT_OF_RESOURCES;
1112 }
1113 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1114 break;
1115 } else {
1116 TempChar = *StringPtrEnd;
1117 *StringPtrEnd = L'\0';
1118 TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
1119 *AltCfgResp = (EFI_STRING) ReallocatePool (
1120 SizeAltCfgResp,
1121 TotalSize,
1122 (VOID *) (*AltCfgResp)
1123 );
1124 if (*AltCfgResp == NULL) {
1125 FreePool (AltConfigHdr);
1126 return EFI_OUT_OF_RESOURCES;
1127 }
1128 StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
1129 *StringPtrEnd = TempChar;
1130 }
1131 } else {
1132 //
1133 // The AltCfgResp contains <AltCfgResp>.
1134 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1135 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1136 //
1137 CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
1138 }
1139
1140 //
1141 // Find next AltCfg String
1142 //
1143 *(AltConfigHdr + HeaderLength) = L'\0';
1144 StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
1145 }
1146
1147 FreePool (AltConfigHdr);
1148 return EFI_SUCCESS;
1149 }
1150
1151 /**
1152 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1153
1154 @param BlockData The BlockData is updated to add new default value.
1155 @param DefaultValueData The DefaultValue is added.
1156
1157 **/
1158 VOID
1159 InsertDefaultValue (
1160 IN IFR_BLOCK_DATA *BlockData,
1161 IN IFR_DEFAULT_DATA *DefaultValueData
1162 )
1163 {
1164 LIST_ENTRY *Link;
1165 IFR_DEFAULT_DATA *DefaultValueArray;
1166 LIST_ENTRY *DefaultLink;
1167
1168 DefaultLink = &BlockData->DefaultValueEntry;
1169
1170 for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
1171 DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
1172 if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
1173 //
1174 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1175 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1176 //
1177 if ((DefaultValueData->Type > DefaultValueArray->Type) || (DefaultValueData->Type == DefaultValueArray->Type && DefaultValueData->Type == DefaultValueFromOtherDefault)) {
1178 //
1179 // Update the default value array in BlockData.
1180 //
1181 CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
1182 DefaultValueArray->Type = DefaultValueData->Type;
1183 DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
1184 }
1185 return;
1186 }
1187 }
1188
1189 //
1190 // Insert new default value data in tail.
1191 //
1192 DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
1193 ASSERT (DefaultValueArray != NULL);
1194 CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
1195 InsertTailList (Link, &DefaultValueArray->Entry);
1196 }
1197
1198 /**
1199 This function inserts new BlockData into the block link
1200
1201 @param BlockLink The list entry points to block array.
1202 @param BlockData The point to BlockData is added.
1203
1204 **/
1205 VOID
1206 InsertBlockData (
1207 IN LIST_ENTRY *BlockLink,
1208 IN IFR_BLOCK_DATA **BlockData
1209 )
1210 {
1211 LIST_ENTRY *Link;
1212 IFR_BLOCK_DATA *BlockArray;
1213 IFR_BLOCK_DATA *BlockSingleData;
1214
1215 BlockSingleData = *BlockData;
1216
1217 if (BlockSingleData->Name != NULL) {
1218 InsertTailList (BlockLink, &BlockSingleData->Entry);
1219 return;
1220 }
1221
1222 //
1223 // Insert block data in its Offset and Width order.
1224 //
1225 for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
1226 BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1227 if (BlockArray->Offset == BlockSingleData->Offset) {
1228 if (BlockArray->Width > BlockSingleData->Width) {
1229 //
1230 // Insert this block data in the front of block array
1231 //
1232 InsertTailList (Link, &BlockSingleData->Entry);
1233 return;
1234 }
1235
1236 if (BlockArray->Width == BlockSingleData->Width) {
1237 //
1238 // The same block array has been added.
1239 //
1240 if (BlockSingleData != BlockArray) {
1241 FreePool (BlockSingleData);
1242 *BlockData = BlockArray;
1243 }
1244 return;
1245 }
1246 } else if (BlockArray->Offset > BlockSingleData->Offset) {
1247 //
1248 // Insert new block data in the front of block array
1249 //
1250 InsertTailList (Link, &BlockSingleData->Entry);
1251 return;
1252 }
1253 }
1254
1255 //
1256 // Add new block data into the tail.
1257 //
1258 InsertTailList (Link, &BlockSingleData->Entry);
1259 }
1260
1261 /**
1262 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1263 of languages that an HII handle in the HII Database supports. The returned
1264 string is allocated using AllocatePool(). The caller is responsible for freeing
1265 the returned string using FreePool(). The format of the returned string follows
1266 the language format assumed the HII Database.
1267
1268 If HiiHandle is NULL, then ASSERT().
1269
1270 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1271
1272 @retval NULL HiiHandle is not registered in the HII database
1273 @retval NULL There are not enough resources available to retrieve the supported
1274 languages.
1275 @retval NULL The list of supported languages could not be retrieved.
1276 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1277
1278 **/
1279 CHAR8 *
1280 GetSupportedLanguages (
1281 IN EFI_HII_HANDLE HiiHandle
1282 )
1283 {
1284 EFI_STATUS Status;
1285 UINTN LanguageSize;
1286 CHAR8 TempSupportedLanguages;
1287 CHAR8 *SupportedLanguages;
1288
1289 ASSERT (HiiHandle != NULL);
1290
1291 //
1292 // Retrieve the size required for the supported languages buffer.
1293 //
1294 LanguageSize = 0;
1295 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
1296
1297 //
1298 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1299 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1300 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1301 // in the HII Database
1302 //
1303 if (Status != EFI_BUFFER_TOO_SMALL) {
1304 //
1305 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1306 //
1307 return NULL;
1308 }
1309
1310 //
1311 // Allocate the supported languages buffer.
1312 //
1313 SupportedLanguages = AllocateZeroPool (LanguageSize);
1314 if (SupportedLanguages == NULL) {
1315 //
1316 // Return NULL if allocation fails.
1317 //
1318 return NULL;
1319 }
1320
1321 //
1322 // Retrieve the supported languages string
1323 //
1324 Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
1325 if (EFI_ERROR (Status)) {
1326 //
1327 // Free the buffer and return NULL if the supported languages can not be retrieved.
1328 //
1329 FreePool (SupportedLanguages);
1330 return NULL;
1331 }
1332
1333 //
1334 // Return the Null-terminated ASCII string of supported languages
1335 //
1336 return SupportedLanguages;
1337 }
1338
1339 /**
1340 Retrieves a string from a string package.
1341
1342 If HiiHandle is NULL, then ASSERT().
1343 If StringId is 0, then ASSET.
1344
1345 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1346 @param[in] StringId The identifier of the string to retrieved from the string
1347 package associated with HiiHandle.
1348
1349 @retval NULL The string specified by StringId is not present in the string package.
1350 @retval Other The string was returned.
1351
1352 **/
1353 EFI_STRING
1354 InternalGetString (
1355 IN EFI_HII_HANDLE HiiHandle,
1356 IN EFI_STRING_ID StringId
1357 )
1358 {
1359 EFI_STATUS Status;
1360 UINTN StringSize;
1361 CHAR16 TempString;
1362 EFI_STRING String;
1363 CHAR8 *SupportedLanguages;
1364 CHAR8 *PlatformLanguage;
1365 CHAR8 *BestLanguage;
1366 CHAR8 *Language;
1367
1368 ASSERT (HiiHandle != NULL);
1369 ASSERT (StringId != 0);
1370
1371 //
1372 // Initialize all allocated buffers to NULL
1373 //
1374 SupportedLanguages = NULL;
1375 PlatformLanguage = NULL;
1376 BestLanguage = NULL;
1377 String = NULL;
1378 Language = "";
1379
1380 //
1381 // Get the languages that the package specified by HiiHandle supports
1382 //
1383 SupportedLanguages = GetSupportedLanguages (HiiHandle);
1384 if (SupportedLanguages == NULL) {
1385 goto Error;
1386 }
1387
1388 //
1389 // Get the current platform language setting
1390 //
1391 GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
1392
1393 //
1394 // Get the best matching language from SupportedLanguages
1395 //
1396 BestLanguage = GetBestLanguage (
1397 SupportedLanguages,
1398 FALSE, // RFC 4646 mode
1399 Language, // Highest priority
1400 PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
1401 SupportedLanguages, // Lowest priority
1402 NULL
1403 );
1404 if (BestLanguage == NULL) {
1405 goto Error;
1406 }
1407
1408 //
1409 // Retrieve the size of the string in the string package for the BestLanguage
1410 //
1411 StringSize = 0;
1412 Status = mPrivate.HiiString.GetString (
1413 &mPrivate.HiiString,
1414 BestLanguage,
1415 HiiHandle,
1416 StringId,
1417 &TempString,
1418 &StringSize,
1419 NULL
1420 );
1421 //
1422 // If GetString() returns EFI_SUCCESS for a zero size,
1423 // then there are no supported languages registered for HiiHandle. If GetString()
1424 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1425 // in the HII Database
1426 //
1427 if (Status != EFI_BUFFER_TOO_SMALL) {
1428 goto Error;
1429 }
1430
1431 //
1432 // Allocate a buffer for the return string
1433 //
1434 String = AllocateZeroPool (StringSize);
1435 if (String == NULL) {
1436 goto Error;
1437 }
1438
1439 //
1440 // Retrieve the string from the string package
1441 //
1442 Status = mPrivate.HiiString.GetString (
1443 &mPrivate.HiiString,
1444 BestLanguage,
1445 HiiHandle,
1446 StringId,
1447 String,
1448 &StringSize,
1449 NULL
1450 );
1451 if (EFI_ERROR (Status)) {
1452 //
1453 // Free the buffer and return NULL if the supported languages can not be retrieved.
1454 //
1455 FreePool (String);
1456 String = NULL;
1457 }
1458
1459 Error:
1460 //
1461 // Free allocated buffers
1462 //
1463 if (SupportedLanguages != NULL) {
1464 FreePool (SupportedLanguages);
1465 }
1466 if (PlatformLanguage != NULL) {
1467 FreePool (PlatformLanguage);
1468 }
1469 if (BestLanguage != NULL) {
1470 FreePool (BestLanguage);
1471 }
1472
1473 //
1474 // Return the Null-terminated Unicode string
1475 //
1476 return String;
1477 }
1478
1479 /**
1480 This function checks VarOffset and VarWidth is in the block range.
1481
1482 @param RequestBlockArray The block array is to be checked.
1483 @param VarOffset Offset of var to the structure
1484 @param VarWidth Width of var.
1485 @param IsNameValueType Whether this varstore is name/value varstore or not.
1486 @param HiiHandle Hii handle for this hii package.
1487
1488 @retval TRUE This Var is in the block range.
1489 @retval FALSE This Var is not in the block range.
1490 **/
1491 BOOLEAN
1492 BlockArrayCheck (
1493 IN IFR_BLOCK_DATA *RequestBlockArray,
1494 IN UINT16 VarOffset,
1495 IN UINT16 VarWidth,
1496 IN BOOLEAN IsNameValueType,
1497 IN EFI_HII_HANDLE HiiHandle
1498 )
1499 {
1500 LIST_ENTRY *Link;
1501 IFR_BLOCK_DATA *BlockData;
1502 EFI_STRING Name;
1503
1504 //
1505 // No Request Block array, all vars are got.
1506 //
1507 if (RequestBlockArray == NULL) {
1508 return TRUE;
1509 }
1510
1511 //
1512 // Check the input var is in the request block range.
1513 //
1514 for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
1515 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
1516
1517 if (IsNameValueType) {
1518 Name = InternalGetString (HiiHandle, VarOffset);
1519 ASSERT (Name != NULL);
1520
1521 if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
1522 FreePool (Name);
1523 return TRUE;
1524 }
1525 FreePool (Name);
1526 } else {
1527 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
1528 return TRUE;
1529 }
1530 }
1531 }
1532
1533 return FALSE;
1534 }
1535
1536 /**
1537 Get form package data from data base.
1538
1539 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1540 @param HiiFormPackage The buffer saves the package data.
1541 @param PackageSize The buffer size of the package data.
1542
1543 **/
1544 EFI_STATUS
1545 GetFormPackageData (
1546 IN HII_DATABASE_RECORD *DataBaseRecord,
1547 IN OUT UINT8 **HiiFormPackage,
1548 OUT UINTN *PackageSize
1549 )
1550 {
1551 EFI_STATUS Status;
1552 UINTN Size;
1553 UINTN ResultSize;
1554
1555 if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
1556 return EFI_INVALID_PARAMETER;
1557 }
1558
1559 Size = 0;
1560 ResultSize = 0;
1561 //
1562 // 0. Get Hii Form Package by HiiHandle
1563 //
1564 Status = ExportFormPackages (
1565 &mPrivate,
1566 DataBaseRecord->Handle,
1567 DataBaseRecord->PackageList,
1568 0,
1569 Size,
1570 HiiFormPackage,
1571 &ResultSize
1572 );
1573 if (EFI_ERROR (Status)) {
1574 return Status;
1575 }
1576
1577 (*HiiFormPackage) = AllocatePool (ResultSize);
1578 if (*HiiFormPackage == NULL) {
1579 Status = EFI_OUT_OF_RESOURCES;
1580 return Status;
1581 }
1582
1583 //
1584 // Get HiiFormPackage by HiiHandle
1585 //
1586 Size = ResultSize;
1587 ResultSize = 0;
1588 Status = ExportFormPackages (
1589 &mPrivate,
1590 DataBaseRecord->Handle,
1591 DataBaseRecord->PackageList,
1592 0,
1593 Size,
1594 *HiiFormPackage,
1595 &ResultSize
1596 );
1597 if (EFI_ERROR (Status)) {
1598 FreePool (*HiiFormPackage);
1599 }
1600
1601 *PackageSize = Size;
1602
1603 return Status;
1604 }
1605
1606
1607 /**
1608 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1609
1610 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1611 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1612 the first found varstore will be as ConfigHdr.
1613 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1614 @param EfiVarStore The efi varstore info which will return.
1615 **/
1616 EFI_STATUS
1617 GetVarStoreType (
1618 IN HII_DATABASE_RECORD *DataBaseRecord,
1619 IN EFI_STRING ConfigHdr,
1620 OUT BOOLEAN *IsEfiVarstore,
1621 OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
1622 )
1623 {
1624 EFI_STATUS Status;
1625 UINTN IfrOffset;
1626 UINTN PackageOffset;
1627 EFI_IFR_OP_HEADER *IfrOpHdr;
1628 CHAR16 *VarStoreName;
1629 UINTN NameSize;
1630 EFI_STRING GuidStr;
1631 EFI_STRING NameStr;
1632 EFI_STRING TempStr;
1633 UINTN LengthString;
1634 UINT8 *HiiFormPackage;
1635 UINTN PackageSize;
1636 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1637 EFI_HII_PACKAGE_HEADER *PackageHeader;
1638
1639 HiiFormPackage = NULL;
1640 LengthString = 0;
1641 Status = EFI_SUCCESS;
1642 GuidStr = NULL;
1643 NameStr = NULL;
1644 TempStr = NULL;
1645 *IsEfiVarstore = FALSE;
1646
1647 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1648 if (EFI_ERROR (Status)) {
1649 return Status;
1650 }
1651
1652 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1653 PackageOffset = IfrOffset;
1654 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1655
1656 while (IfrOffset < PackageSize) {
1657 //
1658 // More than one form packages exist.
1659 //
1660 if (PackageOffset >= PackageHeader->Length) {
1661 //
1662 // Process the new form package.
1663 //
1664 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1665 IfrOffset += PackageOffset;
1666 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1667 }
1668
1669 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1670 IfrOffset += IfrOpHdr->Length;
1671 PackageOffset += IfrOpHdr->Length;
1672
1673 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1674 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1675 //
1676 // If the length is small than the structure, this is from old efi
1677 // varstore definition. Old efi varstore get config directly from
1678 // GetVariable function.
1679 //
1680 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1681 continue;
1682 }
1683
1684 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1685 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1686 if (VarStoreName == NULL) {
1687 Status = EFI_OUT_OF_RESOURCES;
1688 goto Done;
1689 }
1690 AsciiStrToUnicodeStrS ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName, NameSize);
1691
1692 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1693 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1694 LengthString = StrLen (GuidStr);
1695 LengthString = LengthString + StrLen (NameStr) + 1;
1696 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1697 if (TempStr == NULL) {
1698 FreePool (GuidStr);
1699 FreePool (NameStr);
1700 FreePool (VarStoreName);
1701 Status = EFI_OUT_OF_RESOURCES;
1702 goto Done;
1703 }
1704 StrCpyS (TempStr, LengthString, GuidStr);
1705 StrCatS (TempStr, LengthString, NameStr);
1706 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1707 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
1708 if (*EfiVarStore == NULL) {
1709 FreePool (VarStoreName);
1710 FreePool (GuidStr);
1711 FreePool (NameStr);
1712 FreePool (TempStr);
1713 Status = EFI_OUT_OF_RESOURCES;
1714 goto Done;
1715 }
1716 *IsEfiVarstore = TRUE;
1717 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1718 }
1719
1720 //
1721 // Free allocated temp string.
1722 //
1723 FreePool (VarStoreName);
1724 FreePool (GuidStr);
1725 FreePool (NameStr);
1726 FreePool (TempStr);
1727
1728 //
1729 // Already found the varstore, break;
1730 //
1731 if (*IsEfiVarstore) {
1732 break;
1733 }
1734 }
1735 }
1736 Done:
1737 if (HiiFormPackage != NULL) {
1738 FreePool (HiiFormPackage);
1739 }
1740
1741 return Status;
1742 }
1743
1744 /**
1745 Check whether the ConfigRequest string has the request elements.
1746 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1747 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1748
1749 @param ConfigRequest The input config request string.
1750
1751 @retval TRUE The input include config request elements.
1752 @retval FALSE The input string not includes.
1753
1754 **/
1755 BOOLEAN
1756 GetElementsFromRequest (
1757 IN EFI_STRING ConfigRequest
1758 )
1759 {
1760 EFI_STRING TmpRequest;
1761
1762 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1763 ASSERT (TmpRequest != NULL);
1764
1765 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1766 return TRUE;
1767 }
1768
1769 return FALSE;
1770 }
1771
1772 /**
1773 Check whether the this varstore is the request varstore.
1774
1775 @param VarstoreGuid Varstore guid.
1776 @param Name Varstore name.
1777 @param ConfigHdr Current configRequest info.
1778
1779 @retval TRUE This varstore is the request one.
1780 @retval FALSE This varstore is not the request one.
1781
1782 **/
1783 BOOLEAN
1784 IsThisVarstore (
1785 IN EFI_GUID *VarstoreGuid,
1786 IN CHAR16 *Name,
1787 IN CHAR16 *ConfigHdr
1788 )
1789 {
1790 EFI_STRING GuidStr;
1791 EFI_STRING NameStr;
1792 EFI_STRING TempStr;
1793 UINTN LengthString;
1794 BOOLEAN RetVal;
1795
1796 RetVal = FALSE;
1797 GuidStr = NULL;
1798 TempStr = NULL;
1799
1800 //
1801 // If ConfigHdr has name field and varstore not has name, return FALSE.
1802 //
1803 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
1804 return FALSE;
1805 }
1806
1807 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1808 if (Name != NULL) {
1809 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
1810 } else {
1811 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1812 }
1813 LengthString = StrLen (GuidStr);
1814 LengthString = LengthString + StrLen (NameStr) + 1;
1815 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1816 if (TempStr == NULL) {
1817 goto Done;
1818 }
1819
1820 StrCpyS (TempStr, LengthString, GuidStr);
1821 StrCatS (TempStr, LengthString, NameStr);
1822
1823 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1824 RetVal = TRUE;
1825 }
1826
1827 Done:
1828 if (GuidStr != NULL) {
1829 FreePool (GuidStr);
1830 }
1831
1832 if (NameStr != NULL) {
1833 FreePool (NameStr);
1834 }
1835
1836 if (TempStr != NULL) {
1837 FreePool (TempStr);
1838 }
1839
1840 return RetVal;
1841 }
1842
1843 /**
1844 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1845
1846 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1847 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1848 the first found varstore will be as ConfigHdr.
1849 @retval TRUE This hii package is the request one.
1850 @retval FALSE This hii package is not the request one.
1851 **/
1852 BOOLEAN
1853 IsThisPackageList (
1854 IN HII_DATABASE_RECORD *DataBaseRecord,
1855 IN EFI_STRING ConfigHdr
1856 )
1857 {
1858 EFI_STATUS Status;
1859 UINTN IfrOffset;
1860 UINTN PackageOffset;
1861 EFI_IFR_OP_HEADER *IfrOpHdr;
1862 CHAR16 *VarStoreName;
1863 UINTN NameSize;
1864 UINT8 *HiiFormPackage;
1865 UINTN PackageSize;
1866 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1867 EFI_HII_PACKAGE_HEADER *PackageHeader;
1868 EFI_IFR_VARSTORE *IfrVarStore;
1869 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1870 BOOLEAN FindVarstore;
1871
1872 HiiFormPackage = NULL;
1873 VarStoreName = NULL;
1874 Status = EFI_SUCCESS;
1875 FindVarstore = FALSE;
1876
1877 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1878 if (EFI_ERROR (Status)) {
1879 return FALSE;
1880 }
1881
1882 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1883 PackageOffset = IfrOffset;
1884 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1885
1886 while (IfrOffset < PackageSize) {
1887 //
1888 // More than one form packages exist.
1889 //
1890 if (PackageOffset >= PackageHeader->Length) {
1891 //
1892 // Process the new form package.
1893 //
1894 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1895 IfrOffset += PackageOffset;
1896 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1897 }
1898
1899 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1900 IfrOffset += IfrOpHdr->Length;
1901 PackageOffset += IfrOpHdr->Length;
1902
1903 switch (IfrOpHdr->OpCode) {
1904
1905 case EFI_IFR_VARSTORE_OP:
1906 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1907
1908 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
1909 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1910 if (VarStoreName == NULL) {
1911 goto Done;
1912 }
1913 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
1914
1915 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1916 FindVarstore = TRUE;
1917 goto Done;
1918 } else {
1919 FreePool (VarStoreName);
1920 VarStoreName = NULL;
1921 }
1922 break;
1923
1924 case EFI_IFR_VARSTORE_EFI_OP:
1925 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1926 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1927 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1928 if (VarStoreName == NULL) {
1929 goto Done;
1930 }
1931 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
1932
1933 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1934 FindVarstore = TRUE;
1935 goto Done;
1936 } else {
1937 FreePool (VarStoreName);
1938 VarStoreName = NULL;
1939 }
1940 break;
1941
1942 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1943 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1944
1945 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1946 FindVarstore = TRUE;
1947 goto Done;
1948 }
1949 break;
1950
1951 case EFI_IFR_FORM_OP:
1952 case EFI_IFR_FORM_MAP_OP:
1953 //
1954 // No matched varstore is found and directly return.
1955 //
1956 goto Done;
1957
1958 default:
1959 break;
1960 }
1961 }
1962 Done:
1963 if (HiiFormPackage != NULL) {
1964 FreePool (HiiFormPackage);
1965 }
1966
1967 if (VarStoreName != NULL) {
1968 FreePool (VarStoreName);
1969 }
1970
1971 return FindVarstore;
1972 }
1973
1974 /**
1975 Check whether the this op code is required.
1976
1977 @param RequestBlockArray The array includes all the request info or NULL.
1978 @param HiiHandle The hii handle for this form package.
1979 @param VarStorageData The varstore data structure.
1980 @param IfrOpHdr Ifr opcode header for this opcode.
1981 @param VarWidth The buffer width for this opcode.
1982 @param ReturnData The data block added for this opcode.
1983
1984 @retval EFI_SUCCESS This opcode is required.
1985 @retval EFI_NOT_FOUND This opcode is not required.
1986 @retval Others Contain some error.
1987
1988 **/
1989 EFI_STATUS
1990 IsThisOpcodeRequired (
1991 IN IFR_BLOCK_DATA *RequestBlockArray,
1992 IN EFI_HII_HANDLE HiiHandle,
1993 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1994 IN EFI_IFR_OP_HEADER *IfrOpHdr,
1995 IN UINT16 VarWidth,
1996 OUT IFR_BLOCK_DATA **ReturnData
1997 )
1998 {
1999 IFR_BLOCK_DATA *BlockData;
2000 UINT16 VarOffset;
2001 EFI_STRING_ID NameId;
2002 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
2003
2004 NameId = 0;
2005 VarOffset = 0;
2006 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
2007
2008 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2009 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
2010
2011 //
2012 // Check whether this question is in requested block array.
2013 //
2014 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
2015 //
2016 // This question is not in the requested string. Skip it.
2017 //
2018 return EFI_NOT_FOUND;
2019 }
2020 } else {
2021 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
2022
2023 //
2024 // Check whether this question is in requested block array.
2025 //
2026 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
2027 //
2028 // This question is not in the requested string. Skip it.
2029 //
2030 return EFI_NOT_FOUND;
2031 }
2032
2033 //
2034 // Check this var question is in the var storage
2035 //
2036 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
2037 return EFI_INVALID_PARAMETER;
2038 }
2039 }
2040
2041 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2042 if (BlockData == NULL) {
2043 return EFI_OUT_OF_RESOURCES;
2044 }
2045
2046 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2047 BlockData->Name = InternalGetString(HiiHandle, NameId);
2048 } else {
2049 BlockData->Offset = VarOffset;
2050 }
2051
2052 BlockData->Width = VarWidth;
2053 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
2054 BlockData->OpCode = IfrOpHdr->OpCode;
2055 BlockData->Scope = IfrOpHdr->Scope;
2056 InitializeListHead (&BlockData->DefaultValueEntry);
2057 //
2058 // Add Block Data into VarStorageData BlockEntry
2059 //
2060 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2061 *ReturnData = BlockData;
2062
2063 return EFI_SUCCESS;
2064 }
2065
2066 /**
2067 This function parses Form Package to get the block array and the default
2068 value array according to the request ConfigHdr.
2069
2070 @param HiiHandle Hii Handle for this hii package.
2071 @param Package Pointer to the form package data.
2072 @param PackageLength Length of the package.
2073 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2074 the first found varstore will be as ConfigHdr.
2075 @param RequestBlockArray The block array is retrieved from the request string.
2076 @param VarStorageData VarStorage structure contains the got block and default value.
2077 @param DefaultIdArray Point to the got default id and default name array.
2078
2079 @retval EFI_SUCCESS The block array and the default value array are got.
2080 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2081 are conflicted.
2082 @retval EFI_OUT_OF_RESOURCES No enough memory.
2083 **/
2084 EFI_STATUS
2085 EFIAPI
2086 ParseIfrData (
2087 IN EFI_HII_HANDLE HiiHandle,
2088 IN UINT8 *Package,
2089 IN UINT32 PackageLength,
2090 IN EFI_STRING ConfigHdr,
2091 IN IFR_BLOCK_DATA *RequestBlockArray,
2092 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
2093 OUT IFR_DEFAULT_DATA *DefaultIdArray
2094 )
2095 {
2096 EFI_STATUS Status;
2097 UINTN IfrOffset;
2098 UINTN PackageOffset;
2099 EFI_IFR_VARSTORE *IfrVarStore;
2100 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
2101 EFI_IFR_OP_HEADER *IfrOpHdr;
2102 EFI_IFR_ONE_OF *IfrOneOf;
2103 EFI_IFR_REF4 *IfrRef;
2104 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
2105 EFI_IFR_DEFAULT *IfrDefault;
2106 EFI_IFR_ORDERED_LIST *IfrOrderedList;
2107 EFI_IFR_CHECKBOX *IfrCheckBox;
2108 EFI_IFR_PASSWORD *IfrPassword;
2109 EFI_IFR_STRING *IfrString;
2110 EFI_IFR_DATE *IfrDate;
2111 EFI_IFR_TIME *IfrTime;
2112 IFR_DEFAULT_DATA DefaultData;
2113 IFR_DEFAULT_DATA *DefaultDataPtr;
2114 IFR_BLOCK_DATA *BlockData;
2115 CHAR16 *VarStoreName;
2116 UINTN NameSize;
2117 UINT16 VarWidth;
2118 UINT16 VarDefaultId;
2119 BOOLEAN FirstOneOfOption;
2120 BOOLEAN FirstOrderedList;
2121 LIST_ENTRY *LinkData;
2122 LIST_ENTRY *LinkDefault;
2123 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
2124 EFI_HII_PACKAGE_HEADER *PackageHeader;
2125 EFI_VARSTORE_ID VarStoreId;
2126 UINT16 SmallestDefaultId;
2127 BOOLEAN SmallestIdFromFlag;
2128 BOOLEAN FromOtherDefaultOpcode;
2129
2130 Status = EFI_SUCCESS;
2131 BlockData = NULL;
2132 DefaultDataPtr = NULL;
2133 FirstOneOfOption = FALSE;
2134 VarStoreId = 0;
2135 FirstOrderedList = FALSE;
2136 VarStoreName = NULL;
2137 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
2138 SmallestDefaultId = 0xFFFF;
2139 FromOtherDefaultOpcode = FALSE;
2140
2141 //
2142 // Go through the form package to parse OpCode one by one.
2143 //
2144 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2145 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
2146 IfrOffset = PackageOffset;
2147 while (IfrOffset < PackageLength) {
2148
2149 //
2150 // More than one form package found.
2151 //
2152 if (PackageOffset >= PackageHeader->Length) {
2153 //
2154 // Already found varstore for this request, break;
2155 //
2156 if (VarStoreId != 0) {
2157 VarStoreId = 0;
2158 }
2159
2160 //
2161 // Get next package header info.
2162 //
2163 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
2164 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2165 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
2166 }
2167
2168 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
2169 switch (IfrOpHdr->OpCode) {
2170 case EFI_IFR_VARSTORE_OP:
2171 //
2172 // VarStore is found. Don't need to search any more.
2173 //
2174 if (VarStoreId != 0) {
2175 break;
2176 }
2177
2178 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
2179
2180 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
2181 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2182 if (VarStoreName == NULL) {
2183 Status = EFI_OUT_OF_RESOURCES;
2184 goto Done;
2185 }
2186 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
2187
2188 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
2189 //
2190 // Find the matched VarStore
2191 //
2192 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
2193 VarStorageData->Size = IfrVarStore->Size;
2194 VarStorageData->Name = VarStoreName;
2195 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
2196 VarStoreId = IfrVarStore->VarStoreId;
2197 } else {
2198 FreePool (VarStoreName);
2199 VarStoreName = NULL;
2200 }
2201 break;
2202
2203 case EFI_IFR_VARSTORE_EFI_OP:
2204 //
2205 // VarStore is found. Don't need to search any more.
2206 //
2207 if (VarStoreId != 0) {
2208 break;
2209 }
2210
2211 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
2212
2213 //
2214 // If the length is small than the structure, this is from old efi
2215 // varstore definition. Old efi varstore get config directly from
2216 // GetVariable function.
2217 //
2218 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
2219 break;
2220 }
2221
2222 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
2223 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2224 if (VarStoreName == NULL) {
2225 Status = EFI_OUT_OF_RESOURCES;
2226 goto Done;
2227 }
2228 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
2229
2230 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
2231 //
2232 // Find the matched VarStore
2233 //
2234 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
2235 VarStorageData->Size = IfrEfiVarStore->Size;
2236 VarStorageData->Name = VarStoreName;
2237 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
2238 VarStoreId = IfrEfiVarStore->VarStoreId;
2239 } else {
2240 FreePool (VarStoreName);
2241 VarStoreName = NULL;
2242 }
2243 break;
2244
2245 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
2246 //
2247 // VarStore is found. Don't need to search any more.
2248 //
2249 if (VarStoreId != 0) {
2250 break;
2251 }
2252
2253 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
2254
2255 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
2256 //
2257 // Find the matched VarStore
2258 //
2259 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
2260 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
2261 VarStoreId = IfrNameValueVarStore->VarStoreId;
2262 }
2263 break;
2264
2265 case EFI_IFR_DEFAULTSTORE_OP:
2266 //
2267 // Add new the map between default id and default name.
2268 //
2269 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
2270 if (DefaultDataPtr == NULL) {
2271 Status = EFI_OUT_OF_RESOURCES;
2272 goto Done;
2273 }
2274 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
2275 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
2276 DefaultDataPtr = NULL;
2277 break;
2278
2279 case EFI_IFR_FORM_OP:
2280 case EFI_IFR_FORM_MAP_OP:
2281 //
2282 // No matched varstore is found and directly return.
2283 //
2284 if ( VarStoreId == 0) {
2285 Status = EFI_SUCCESS;
2286 goto Done;
2287 }
2288 break;
2289
2290 case EFI_IFR_REF_OP:
2291 //
2292 // Ref question is not in IFR Form. This IFR form is not valid.
2293 //
2294 if ( VarStoreId == 0) {
2295 Status = EFI_INVALID_PARAMETER;
2296 goto Done;
2297 }
2298 //
2299 // Check whether this question is for the requested varstore.
2300 //
2301 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
2302 if (IfrRef->Question.VarStoreId != VarStoreId) {
2303 break;
2304 }
2305 VarWidth = (UINT16) (sizeof (EFI_HII_REF));
2306
2307 //
2308 // The BlockData may allocate by other opcode,need to clean.
2309 //
2310 if (BlockData != NULL){
2311 BlockData = NULL;
2312 }
2313
2314 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2315 if (EFI_ERROR (Status)) {
2316 if (Status == EFI_NOT_FOUND){
2317 //
2318 //The opcode is not required,exit and parse other opcode.
2319 //
2320 break;
2321 }
2322 goto Done;
2323 }
2324 break;
2325
2326 case EFI_IFR_ONE_OF_OP:
2327 case EFI_IFR_NUMERIC_OP:
2328 //
2329 // Numeric and OneOf has the same opcode structure.
2330 //
2331
2332 //
2333 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2334 //
2335 if (VarStoreId == 0) {
2336 Status = EFI_INVALID_PARAMETER;
2337 goto Done;
2338 }
2339 //
2340 // Check whether this question is for the requested varstore.
2341 //
2342 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
2343 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
2344 break;
2345 }
2346 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
2347
2348 //
2349 // The BlockData may allocate by other opcode,need to clean.
2350 //
2351 if (BlockData != NULL){
2352 BlockData = NULL;
2353 }
2354
2355 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2356 if (EFI_ERROR (Status)) {
2357 if (Status == EFI_NOT_FOUND){
2358 //
2359 //The opcode is not required,exit and parse other opcode.
2360 //
2361 break;
2362 }
2363 goto Done;
2364 }
2365
2366 //
2367 //when go to there,BlockData can't be NULLL.
2368 //
2369 ASSERT (BlockData != NULL);
2370
2371 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
2372 //
2373 // Set this flag to TRUE for the first oneof option.
2374 //
2375 FirstOneOfOption = TRUE;
2376 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
2377 //
2378 // Numeric minimum value will be used as default value when no default is specified.
2379 //
2380 DefaultData.Type = DefaultValueFromDefault;
2381 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
2382 case EFI_IFR_NUMERIC_SIZE_1:
2383 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
2384 break;
2385
2386 case EFI_IFR_NUMERIC_SIZE_2:
2387 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
2388 break;
2389
2390 case EFI_IFR_NUMERIC_SIZE_4:
2391 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
2392 break;
2393
2394 case EFI_IFR_NUMERIC_SIZE_8:
2395 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
2396 break;
2397
2398 default:
2399 Status = EFI_INVALID_PARAMETER;
2400 goto Done;
2401 }
2402 //
2403 // Set default value base on the DefaultId list get from IFR data.
2404 //
2405 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2406 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2407 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2408 InsertDefaultValue (BlockData, &DefaultData);
2409 }
2410 }
2411 break;
2412
2413 case EFI_IFR_ORDERED_LIST_OP:
2414 //
2415 // offset by question header
2416 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2417 //
2418
2419 FirstOrderedList = TRUE;
2420 //
2421 // OrderedList question is not in IFR Form. This IFR form is not valid.
2422 //
2423 if (VarStoreId == 0) {
2424 Status = EFI_INVALID_PARAMETER;
2425 goto Done;
2426 }
2427 //
2428 // Check whether this question is for the requested varstore.
2429 //
2430 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
2431 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
2432 BlockData = NULL;
2433 break;
2434 }
2435 VarWidth = IfrOrderedList->MaxContainers;
2436
2437 //
2438 // The BlockData may allocate by other opcode,need to clean.
2439 //
2440 if (BlockData != NULL){
2441 BlockData = NULL;
2442 }
2443
2444 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2445 if (EFI_ERROR (Status)) {
2446 if (Status == EFI_NOT_FOUND){
2447 //
2448 //The opcode is not required,exit and parse other opcode.
2449 //
2450 break;
2451 }
2452 goto Done;
2453 }
2454 break;
2455
2456 case EFI_IFR_CHECKBOX_OP:
2457 //
2458 // EFI_IFR_DEFAULT_OP
2459 // offset by question header
2460 // width is 1 sizeof (BOOLEAN)
2461 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2462 // value by DefaultOption
2463 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2464 //
2465
2466 //
2467 // CheckBox question is not in IFR Form. This IFR form is not valid.
2468 //
2469 if (VarStoreId == 0) {
2470 Status = EFI_INVALID_PARAMETER;
2471 goto Done;
2472 }
2473 //
2474 // Check whether this question is for the requested varstore.
2475 //
2476 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
2477 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
2478 break;
2479 }
2480 VarWidth = (UINT16) sizeof (BOOLEAN);
2481
2482 //
2483 // The BlockData may allocate by other opcode,need to clean.
2484 //
2485 if (BlockData != NULL){
2486 BlockData = NULL;
2487 }
2488
2489 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2490 if (EFI_ERROR (Status)) {
2491 if (Status == EFI_NOT_FOUND){
2492 //
2493 //The opcode is not required,exit and parse other opcode.
2494 //
2495 break;
2496 }
2497 goto Done;
2498 }
2499
2500 //
2501 //when go to there,BlockData can't be NULLL.
2502 //
2503 ASSERT (BlockData != NULL);
2504
2505 SmallestIdFromFlag = FALSE;
2506
2507 //
2508 // Add default value for standard ID by CheckBox Flag
2509 //
2510 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2511 //
2512 // Prepare new DefaultValue
2513 //
2514 DefaultData.DefaultId = VarDefaultId;
2515 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
2516 //
2517 // When flag is set, default value is TRUE.
2518 //
2519 DefaultData.Type = DefaultValueFromFlag;
2520 DefaultData.Value.b = TRUE;
2521 InsertDefaultValue (BlockData, &DefaultData);
2522
2523 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
2524 //
2525 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2526 //
2527 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2528 SmallestIdFromFlag = TRUE;
2529 }
2530 }
2531
2532 //
2533 // Add default value for Manufacture ID by CheckBox Flag
2534 //
2535 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2536 //
2537 // Prepare new DefaultValue
2538 //
2539 DefaultData.DefaultId = VarDefaultId;
2540 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
2541 //
2542 // When flag is set, default value is TRUE.
2543 //
2544 DefaultData.Type = DefaultValueFromFlag;
2545 DefaultData.Value.b = TRUE;
2546 InsertDefaultValue (BlockData, &DefaultData);
2547
2548 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2549 //
2550 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2551 //
2552 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2553 SmallestIdFromFlag = TRUE;
2554 }
2555 }
2556 if (SmallestIdFromFlag) {
2557 //
2558 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2559 //
2560 DefaultData.Type = DefaultValueFromOtherDefault;
2561 DefaultData.Value.b = TRUE;
2562 //
2563 // Set default value for all the default id in the DefaultId list.
2564 //
2565 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2566 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2567 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2568 InsertDefaultValue (BlockData, &DefaultData);
2569 }
2570 } else {
2571 //
2572 // When flag is not set, default value is FASLE.
2573 //
2574 DefaultData.Type = DefaultValueFromDefault;
2575 DefaultData.Value.b = FALSE;
2576 //
2577 // Set default value for all the default id in the DefaultId list.
2578 //
2579 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2580 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2581 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2582 InsertDefaultValue (BlockData, &DefaultData);
2583 }
2584 }
2585 break;
2586
2587 case EFI_IFR_DATE_OP:
2588 //
2589 // offset by question header
2590 // width MaxSize * sizeof (CHAR16)
2591 // no default value, only block array
2592 //
2593
2594 //
2595 // Date question is not in IFR Form. This IFR form is not valid.
2596 //
2597 if (VarStoreId == 0) {
2598 Status = EFI_INVALID_PARAMETER;
2599 goto Done;
2600 }
2601 //
2602 // Check whether this question is for the requested varstore.
2603 //
2604 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
2605 if (IfrDate->Question.VarStoreId != VarStoreId) {
2606 break;
2607 }
2608
2609 //
2610 // The BlockData may allocate by other opcode,need to clean.
2611 //
2612 if (BlockData != NULL){
2613 BlockData = NULL;
2614 }
2615
2616 VarWidth = (UINT16) sizeof (EFI_HII_DATE);
2617 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2618 if (EFI_ERROR (Status)) {
2619 if (Status == EFI_NOT_FOUND){
2620 //
2621 //The opcode is not required,exit and parse other opcode.
2622 //
2623 break;
2624 }
2625 goto Done;
2626 }
2627 break;
2628
2629 case EFI_IFR_TIME_OP:
2630 //
2631 // offset by question header
2632 // width MaxSize * sizeof (CHAR16)
2633 // no default value, only block array
2634 //
2635
2636 //
2637 // Time question is not in IFR Form. This IFR form is not valid.
2638 //
2639 if (VarStoreId == 0) {
2640 Status = EFI_INVALID_PARAMETER;
2641 goto Done;
2642 }
2643 //
2644 // Check whether this question is for the requested varstore.
2645 //
2646 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
2647 if (IfrTime->Question.VarStoreId != VarStoreId) {
2648 break;
2649 }
2650
2651 //
2652 // The BlockData may allocate by other opcode,need to clean.
2653 //
2654 if (BlockData != NULL){
2655 BlockData = NULL;
2656 }
2657
2658 VarWidth = (UINT16) sizeof (EFI_HII_TIME);
2659 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2660 if (EFI_ERROR (Status)) {
2661 if (Status == EFI_NOT_FOUND){
2662 //
2663 //The opcode is not required,exit and parse other opcode.
2664 //
2665 break;
2666 }
2667 goto Done;
2668 }
2669 break;
2670
2671 case EFI_IFR_STRING_OP:
2672 //
2673 // offset by question header
2674 // width MaxSize * sizeof (CHAR16)
2675 // no default value, only block array
2676 //
2677
2678 //
2679 // String question is not in IFR Form. This IFR form is not valid.
2680 //
2681 if (VarStoreId == 0) {
2682 Status = EFI_INVALID_PARAMETER;
2683 goto Done;
2684 }
2685 //
2686 // Check whether this question is for the requested varstore.
2687 //
2688 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
2689 if (IfrString->Question.VarStoreId != VarStoreId) {
2690 break;
2691 }
2692
2693 //
2694 // The BlockData may allocate by other opcode,need to clean.
2695 //
2696 if (BlockData != NULL){
2697 BlockData = NULL;
2698 }
2699
2700 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
2701 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2702 if (EFI_ERROR (Status)) {
2703 if (Status == EFI_NOT_FOUND){
2704 //
2705 //The opcode is not required,exit and parse other opcode.
2706 //
2707 break;
2708 }
2709 goto Done;
2710 }
2711 break;
2712
2713 case EFI_IFR_PASSWORD_OP:
2714 //
2715 // offset by question header
2716 // width MaxSize * sizeof (CHAR16)
2717 // no default value, only block array
2718 //
2719
2720 //
2721 // Password question is not in IFR Form. This IFR form is not valid.
2722 //
2723 if (VarStoreId == 0) {
2724 Status = EFI_INVALID_PARAMETER;
2725 goto Done;
2726 }
2727 //
2728 // Check whether this question is for the requested varstore.
2729 //
2730 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
2731 if (IfrPassword->Question.VarStoreId != VarStoreId) {
2732 break;
2733 }
2734
2735 //
2736 // The BlockData may allocate by other opcode,need to clean.
2737 //
2738 if (BlockData != NULL){
2739 BlockData = NULL;
2740 }
2741
2742 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
2743 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2744 if (EFI_ERROR (Status)) {
2745 if (Status == EFI_NOT_FOUND){
2746 //
2747 //The opcode is not required,exit and parse other opcode.
2748 //
2749 break;
2750 }
2751 goto Done;
2752 }
2753
2754 //
2755 // No default value for string.
2756 //
2757 BlockData = NULL;
2758 break;
2759
2760 case EFI_IFR_ONE_OF_OPTION_OP:
2761 //
2762 // No matched block data is ignored.
2763 //
2764 if (BlockData == NULL || BlockData->Scope == 0) {
2765 break;
2766 }
2767
2768 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
2769 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2770
2771 if (!FirstOrderedList){
2772 break;
2773 }
2774 //
2775 // Get ordered list option data type.
2776 //
2777 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
2778 VarWidth = 1;
2779 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
2780 VarWidth = 2;
2781 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
2782 VarWidth = 4;
2783 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
2784 VarWidth = 8;
2785 } else {
2786 //
2787 // Invalid ordered list option data type.
2788 //
2789 Status = EFI_INVALID_PARAMETER;
2790 if (BlockData->Name != NULL) {
2791 FreePool (BlockData->Name);
2792 }
2793 FreePool (BlockData);
2794 goto Done;
2795 }
2796
2797 //
2798 // Calculate Ordered list QuestionId width.
2799 //
2800 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
2801 //
2802 // Check whether this question is in requested block array.
2803 //
2804 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2805 //
2806 // This question is not in the requested string. Skip it.
2807 //
2808 if (BlockData->Name != NULL) {
2809 FreePool (BlockData->Name);
2810 }
2811 FreePool (BlockData);
2812 BlockData = NULL;
2813 break;
2814 }
2815 //
2816 // Check this var question is in the var storage
2817 //
2818 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2819 Status = EFI_INVALID_PARAMETER;
2820 if (BlockData->Name != NULL) {
2821 FreePool (BlockData->Name);
2822 }
2823 FreePool (BlockData);
2824 goto Done;
2825 }
2826 //
2827 // Add Block Data into VarStorageData BlockEntry
2828 //
2829 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2830
2831 FirstOrderedList = FALSE;
2832
2833 break;
2834 }
2835
2836 //
2837 // 1. Set default value for OneOf option when flag field has default attribute.
2838 // And set the default value with the smallest default id for other default id in the DefaultId list.
2839 //
2840 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2841 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
2842 //
2843 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2844 // The first oneof option value will be used as default value when no default value is specified.
2845 //
2846 FirstOneOfOption = FALSE;
2847
2848 SmallestIdFromFlag = FALSE;
2849
2850 // Prepare new DefaultValue
2851 //
2852 DefaultData.Type = DefaultValueFromFlag;
2853 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2854 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
2855 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2856 InsertDefaultValue (BlockData, &DefaultData);
2857 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
2858 //
2859 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2860 //
2861 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2862 SmallestIdFromFlag = TRUE;
2863 }
2864 }
2865 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
2866 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2867 InsertDefaultValue (BlockData, &DefaultData);
2868 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
2869 //
2870 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2871 //
2872 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2873 SmallestIdFromFlag = TRUE;
2874 }
2875 }
2876
2877 if (SmallestIdFromFlag) {
2878 //
2879 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2880 //
2881 DefaultData.Type = DefaultValueFromOtherDefault;
2882 //
2883 // Set default value for other default id in the DefaultId list.
2884 //
2885 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2886 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2887 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2888 InsertDefaultValue (BlockData, &DefaultData);
2889 }
2890 }
2891 }
2892
2893 //
2894 // 2. Set as the default value when this is the first option.
2895 // The first oneof option value will be used as default value when no default value is specified.
2896 //
2897 if (FirstOneOfOption) {
2898 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2899 FirstOneOfOption = FALSE;
2900
2901 //
2902 // Prepare new DefaultValue
2903 //
2904 DefaultData.Type = DefaultValueFromDefault;
2905 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2906 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2907 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2908 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2909 InsertDefaultValue (BlockData, &DefaultData);
2910 }
2911 }
2912 break;
2913
2914 case EFI_IFR_DEFAULT_OP:
2915 //
2916 // Update Current BlockData to the default value.
2917 //
2918 if (BlockData == NULL || BlockData->Scope == 0) {
2919 //
2920 // No matched block data is ignored.
2921 //
2922 break;
2923 }
2924
2925 //
2926 // Get the DefaultId
2927 //
2928 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
2929 VarDefaultId = IfrDefault->DefaultId;
2930 //
2931 // Prepare new DefaultValue
2932 //
2933 DefaultData.Type = DefaultValueFromOpcode;
2934 DefaultData.DefaultId = VarDefaultId;
2935 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2936
2937 // If the value field is expression, set the cleaned flag.
2938 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
2939 DefaultData.Cleaned = TRUE;
2940 }
2941 //
2942 // Add DefaultValue into current BlockData
2943 //
2944 InsertDefaultValue (BlockData, &DefaultData);
2945
2946 //
2947 // Set default value for other default id in the DefaultId list.
2948 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
2949 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
2950 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
2951 //
2952 if ((SmallestDefaultId > VarDefaultId) || (SmallestDefaultId == VarDefaultId && !FromOtherDefaultOpcode)) {
2953 FromOtherDefaultOpcode = TRUE;
2954 SmallestDefaultId = VarDefaultId;
2955 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2956 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2957 if (DefaultDataPtr->DefaultId != DefaultData.DefaultId){
2958 DefaultData.Type = DefaultValueFromOtherDefault;
2959 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2960 InsertDefaultValue (BlockData, &DefaultData);
2961 }
2962 }
2963 }
2964
2965 //
2966 // After insert the default value, reset the cleaned value for next
2967 // time used. If not set here, need to set the value before every time.
2968 // use it.
2969 //
2970 DefaultData.Cleaned = FALSE;
2971 break;
2972
2973 case EFI_IFR_END_OP:
2974 //
2975 // End Opcode is for Var question.
2976 //
2977 if (BlockData != NULL) {
2978 if (BlockData->Scope > 0) {
2979 BlockData->Scope--;
2980 }
2981 if (BlockData->Scope == 0) {
2982 BlockData = NULL;
2983 //
2984 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
2985 //
2986 SmallestDefaultId = 0xFFFF;
2987 FromOtherDefaultOpcode = FALSE;
2988 }
2989 }
2990
2991 break;
2992
2993 default:
2994 if (BlockData != NULL) {
2995 if (BlockData->Scope > 0) {
2996 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
2997 }
2998
2999 if (BlockData->Scope == 0) {
3000 BlockData = NULL;
3001 }
3002 }
3003 break;
3004 }
3005
3006 IfrOffset += IfrOpHdr->Length;
3007 PackageOffset += IfrOpHdr->Length;
3008 }
3009
3010 //
3011 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3012 //so set the Status to EFI_SUCCESS.
3013 //
3014 if (Status == EFI_NOT_FOUND){
3015 Status = EFI_SUCCESS;
3016 }
3017
3018 Done:
3019 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3020 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3021 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
3022 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3023 LinkDefault = LinkDefault->ForwardLink;
3024 if (DefaultDataPtr->Cleaned == TRUE) {
3025 RemoveEntryList (&DefaultDataPtr->Entry);
3026 FreePool (DefaultDataPtr);
3027 }
3028 }
3029 }
3030
3031 return Status;
3032 }
3033
3034 /**
3035 parse the configrequest string, get the elements.
3036
3037 @param ConfigRequest The input configrequest string.
3038 @param Progress Return the progress data.
3039
3040 @retval Block data pointer.
3041 **/
3042 IFR_BLOCK_DATA *
3043 GetBlockElement (
3044 IN EFI_STRING ConfigRequest,
3045 OUT EFI_STRING *Progress
3046 )
3047 {
3048 EFI_STRING StringPtr;
3049 IFR_BLOCK_DATA *BlockData;
3050 IFR_BLOCK_DATA *RequestBlockArray;
3051 EFI_STATUS Status;
3052 UINT8 *TmpBuffer;
3053 UINT16 Offset;
3054 UINT16 Width;
3055 LIST_ENTRY *Link;
3056 IFR_BLOCK_DATA *NextBlockData;
3057 UINTN Length;
3058
3059 TmpBuffer = NULL;
3060
3061 //
3062 // Init RequestBlockArray
3063 //
3064 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3065 if (RequestBlockArray == NULL) {
3066 goto Done;
3067 }
3068 InitializeListHead (&RequestBlockArray->Entry);
3069
3070 //
3071 // Get the request Block array from the request string
3072 // Offset and Width
3073 //
3074
3075 //
3076 // Parse each <RequestElement> if exists
3077 // Only <BlockName> format is supported by this help function.
3078 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3079 //
3080 StringPtr = ConfigRequest;
3081 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
3082 //
3083 // Skip the OFFSET string
3084 //
3085 *Progress = StringPtr;
3086 StringPtr += StrLen (L"&OFFSET=");
3087 //
3088 // Get Offset
3089 //
3090 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3091 if (EFI_ERROR (Status)) {
3092 goto Done;
3093 }
3094 Offset = 0;
3095 CopyMem (
3096 &Offset,
3097 TmpBuffer,
3098 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
3099 );
3100 FreePool (TmpBuffer);
3101
3102 StringPtr += Length;
3103 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
3104 goto Done;
3105 }
3106 StringPtr += StrLen (L"&WIDTH=");
3107
3108 //
3109 // Get Width
3110 //
3111 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3112 if (EFI_ERROR (Status)) {
3113 goto Done;
3114 }
3115 Width = 0;
3116 CopyMem (
3117 &Width,
3118 TmpBuffer,
3119 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
3120 );
3121 FreePool (TmpBuffer);
3122
3123 StringPtr += Length;
3124 if (*StringPtr != 0 && *StringPtr != L'&') {
3125 goto Done;
3126 }
3127
3128 //
3129 // Set Block Data
3130 //
3131 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3132 if (BlockData == NULL) {
3133 goto Done;
3134 }
3135 BlockData->Offset = Offset;
3136 BlockData->Width = Width;
3137 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3138
3139 //
3140 // Skip &VALUE string if &VALUE does exists.
3141 //
3142 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
3143 StringPtr += StrLen (L"&VALUE=");
3144
3145 //
3146 // Get Value
3147 //
3148 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3149 if (EFI_ERROR (Status)) {
3150 goto Done;
3151 }
3152 FreePool (TmpBuffer);
3153 StringPtr += Length;
3154 if (*StringPtr != 0 && *StringPtr != L'&') {
3155 goto Done;
3156 }
3157 }
3158 //
3159 // If '\0', parsing is finished.
3160 //
3161 if (*StringPtr == 0) {
3162 break;
3163 }
3164 }
3165
3166 //
3167 // Merge the requested block data.
3168 //
3169 Link = RequestBlockArray->Entry.ForwardLink;
3170 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
3171 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3172 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
3173 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
3174 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
3175 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
3176 }
3177 RemoveEntryList (Link->ForwardLink);
3178 FreePool (NextBlockData);
3179 continue;
3180 }
3181 Link = Link->ForwardLink;
3182 }
3183
3184 return RequestBlockArray;
3185
3186 Done:
3187 if (RequestBlockArray != NULL) {
3188 //
3189 // Free Link Array RequestBlockArray
3190 //
3191 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3192 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3193 RemoveEntryList (&BlockData->Entry);
3194 FreePool (BlockData);
3195 }
3196
3197 FreePool (RequestBlockArray);
3198 }
3199
3200 return NULL;
3201 }
3202
3203 /**
3204 parse the configrequest string, get the elements.
3205
3206 @param ConfigRequest The input config request string.
3207 @param Progress Return the progress data.
3208
3209 @retval return data block array.
3210 **/
3211 IFR_BLOCK_DATA *
3212 GetNameElement (
3213 IN EFI_STRING ConfigRequest,
3214 OUT EFI_STRING *Progress
3215 )
3216 {
3217 EFI_STRING StringPtr;
3218 EFI_STRING NextTag;
3219 IFR_BLOCK_DATA *BlockData;
3220 IFR_BLOCK_DATA *RequestBlockArray;
3221 BOOLEAN HasValue;
3222
3223 StringPtr = ConfigRequest;
3224
3225 //
3226 // Init RequestBlockArray
3227 //
3228 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3229 if (RequestBlockArray == NULL) {
3230 goto Done;
3231 }
3232 InitializeListHead (&RequestBlockArray->Entry);
3233
3234 //
3235 // Get the request Block array from the request string
3236 //
3237
3238 //
3239 // Parse each <RequestElement> if exists
3240 // Only <BlockName> format is supported by this help function.
3241 // <BlockName> ::= &'Name***=***
3242 //
3243 while (StringPtr != NULL && *StringPtr == L'&') {
3244
3245 *Progress = StringPtr;
3246 //
3247 // Skip the L"&" string
3248 //
3249 StringPtr += 1;
3250
3251 HasValue = FALSE;
3252 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
3253 *NextTag = L'\0';
3254 HasValue = TRUE;
3255 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
3256 *NextTag = L'\0';
3257 }
3258
3259 //
3260 // Set Block Data
3261 //
3262 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3263 if (BlockData == NULL) {
3264 goto Done;
3265 }
3266
3267 //
3268 // Get Name
3269 //
3270 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
3271 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3272
3273 if (HasValue) {
3274 //
3275 // If has value, skip the value.
3276 //
3277 StringPtr = NextTag + 1;
3278 *NextTag = L'=';
3279 StringPtr = StrStr (StringPtr, L"&");
3280 } else if (NextTag != NULL) {
3281 //
3282 // restore the '&' text.
3283 //
3284 StringPtr = NextTag;
3285 *NextTag = L'&';
3286 }
3287 }
3288
3289 return RequestBlockArray;
3290
3291 Done:
3292 if (RequestBlockArray != NULL) {
3293 //
3294 // Free Link Array RequestBlockArray
3295 //
3296 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3297 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3298 RemoveEntryList (&BlockData->Entry);
3299 if (BlockData->Name != NULL) {
3300 FreePool (BlockData->Name);
3301 }
3302 FreePool (BlockData);
3303 }
3304
3305 FreePool (RequestBlockArray);
3306 }
3307
3308 return NULL;
3309 }
3310
3311 /**
3312 Generate ConfigRequest string base on the varstore info.
3313
3314 @param ConfigHdr The config header for this varstore.
3315 @param VarStorageData The varstore info.
3316 @param Status Return Status.
3317 @param ConfigRequest The ConfigRequest info may be return.
3318
3319 @retval TRUE Need to continue
3320 @retval Others NO need to continue or error occur.
3321 **/
3322 BOOLEAN
3323 GenerateConfigRequest (
3324 IN CHAR16 *ConfigHdr,
3325 IN IFR_VARSTORAGE_DATA *VarStorageData,
3326 OUT EFI_STATUS *Status,
3327 IN OUT EFI_STRING *ConfigRequest
3328 )
3329 {
3330 BOOLEAN DataExist;
3331 UINTN Length;
3332 LIST_ENTRY *Link;
3333 CHAR16 *FullConfigRequest;
3334 CHAR16 *StringPtr;
3335 IFR_BLOCK_DATA *BlockData;
3336
3337 //
3338 // Append VarStorageData BlockEntry into *Request string
3339 // Now support only one varstore in a form package.
3340 //
3341
3342 //
3343 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3344 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3345 //
3346
3347 //
3348 // Compute the length of the entire request starting with <ConfigHdr> and a
3349 // Null-terminator
3350 //
3351 DataExist = FALSE;
3352 Length = StrLen (ConfigHdr) + 1;
3353
3354 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3355 DataExist = TRUE;
3356 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3357 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3358 //
3359 // Add <BlockName> length for each Name
3360 //
3361 // <BlockName> ::= &Name1&Name2&...
3362 // |1| StrLen(Name1)
3363 //
3364 Length = Length + (1 + StrLen (BlockData->Name));
3365 } else {
3366 //
3367 // Add <BlockName> length for each Offset/Width pair
3368 //
3369 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3370 // | 8 | 4 | 7 | 4 |
3371 //
3372 Length = Length + (8 + 4 + 7 + 4);
3373 }
3374 }
3375 //
3376 // No any request block data is found. The request string can't be constructed.
3377 //
3378 if (!DataExist) {
3379 *Status = EFI_SUCCESS;
3380 return FALSE;
3381 }
3382
3383 //
3384 // Allocate buffer for the entire <ConfigRequest>
3385 //
3386 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
3387 if (FullConfigRequest == NULL) {
3388 *Status = EFI_OUT_OF_RESOURCES;
3389 return FALSE;
3390 }
3391 StringPtr = FullConfigRequest;
3392
3393 //
3394 // Start with <ConfigHdr>
3395 //
3396 StrCpyS (StringPtr, Length, ConfigHdr);
3397 StringPtr += StrLen (StringPtr);
3398
3399 //
3400 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3401 //
3402 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3403 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3404 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3405 //
3406 // Append &Name1\0
3407 //
3408 UnicodeSPrint (
3409 StringPtr,
3410 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
3411 L"&%s",
3412 BlockData->Name
3413 );
3414 } else {
3415 //
3416 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3417 //
3418 UnicodeSPrint (
3419 StringPtr,
3420 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
3421 L"&OFFSET=%04X&WIDTH=%04X",
3422 BlockData->Offset,
3423 BlockData->Width
3424 );
3425 }
3426 StringPtr += StrLen (StringPtr);
3427 }
3428 //
3429 // Set to the got full request string.
3430 //
3431 HiiToLower (FullConfigRequest);
3432
3433 if (*ConfigRequest != NULL) {
3434 FreePool (*ConfigRequest);
3435 }
3436 *ConfigRequest = FullConfigRequest;
3437
3438 return TRUE;
3439 }
3440
3441 /**
3442 Generate ConfigRequest Header base on the varstore info.
3443
3444 @param VarStorageData The varstore info.
3445 @param DevicePath Device path for this varstore.
3446 @param ConfigHdr The config header for this varstore.
3447
3448 @retval EFI_SUCCESS Generate the header success.
3449 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3450 **/
3451 EFI_STATUS
3452 GenerateHdr (
3453 IN IFR_VARSTORAGE_DATA *VarStorageData,
3454 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3455 OUT EFI_STRING *ConfigHdr
3456 )
3457 {
3458 EFI_STRING GuidStr;
3459 EFI_STRING NameStr;
3460 EFI_STRING PathStr;
3461 UINTN Length;
3462 EFI_STATUS Status;
3463
3464 Status = EFI_SUCCESS;
3465 NameStr = NULL;
3466 GuidStr = NULL;
3467 PathStr = NULL;
3468
3469 //
3470 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3471 //
3472 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
3473 if (VarStorageData->Name != NULL) {
3474 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
3475 } else {
3476 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3477 }
3478 GenerateSubStr (
3479 L"PATH=",
3480 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3481 (VOID *) DevicePath,
3482 1,
3483 &PathStr
3484 );
3485 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
3486 if (VarStorageData->Name == NULL) {
3487 Length += 1;
3488 }
3489
3490 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
3491 if (*ConfigHdr == NULL) {
3492 Status = EFI_OUT_OF_RESOURCES;
3493 goto Done;
3494 }
3495 StrCpyS (*ConfigHdr, Length, GuidStr);
3496 StrCatS (*ConfigHdr, Length, NameStr);
3497 if (VarStorageData->Name == NULL) {
3498 StrCatS (*ConfigHdr, Length, L"&");
3499 }
3500 StrCatS (*ConfigHdr, Length, PathStr);
3501
3502 //
3503 // Remove the last character L'&'
3504 //
3505 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
3506
3507 Done:
3508 if (GuidStr != NULL) {
3509 FreePool (GuidStr);
3510 }
3511
3512 if (NameStr != NULL) {
3513 FreePool (NameStr);
3514 }
3515
3516 if (PathStr != NULL) {
3517 FreePool (PathStr);
3518 }
3519
3520 return Status;
3521 }
3522
3523 /**
3524 Get Data buffer size based on data type.
3525
3526 @param ValueType The input data type.
3527
3528 @retval The data buffer size for the input type.
3529 **/
3530 UINT16
3531 GetStorageWidth (
3532 IN UINT8 ValueType
3533 )
3534 {
3535 UINT16 StorageWidth;
3536
3537 switch (ValueType) {
3538 case EFI_IFR_NUMERIC_SIZE_1:
3539 case EFI_IFR_TYPE_BOOLEAN:
3540 StorageWidth = (UINT16) sizeof (UINT8);
3541 break;
3542
3543 case EFI_IFR_NUMERIC_SIZE_2:
3544 StorageWidth = (UINT16) sizeof (UINT16);
3545 break;
3546
3547 case EFI_IFR_NUMERIC_SIZE_4:
3548 StorageWidth = (UINT16) sizeof (UINT32);
3549 break;
3550
3551 case EFI_IFR_NUMERIC_SIZE_8:
3552 StorageWidth = (UINT16) sizeof (UINT64);
3553 break;
3554
3555 case EFI_IFR_TYPE_TIME:
3556 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
3557 break;
3558
3559 case EFI_IFR_TYPE_DATE:
3560 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
3561 break;
3562
3563 default:
3564 StorageWidth = 0;
3565 break;
3566 }
3567
3568 return StorageWidth;
3569 }
3570
3571 /**
3572 Generate ConfigAltResp string base on the varstore info.
3573
3574 @param HiiHandle Hii Handle for this hii package.
3575 @param ConfigHdr The config header for this varstore.
3576 @param VarStorageData The varstore info.
3577 @param DefaultIdArray The Default id array.
3578 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3579
3580 @retval TRUE Need to continue
3581 @retval Others NO need to continue or error occur.
3582 **/
3583 EFI_STATUS
3584 GenerateAltConfigResp (
3585 IN EFI_HII_HANDLE HiiHandle,
3586 IN CHAR16 *ConfigHdr,
3587 IN IFR_VARSTORAGE_DATA *VarStorageData,
3588 IN IFR_DEFAULT_DATA *DefaultIdArray,
3589 IN OUT EFI_STRING *DefaultAltCfgResp
3590 )
3591 {
3592 BOOLEAN DataExist;
3593 UINTN Length;
3594 LIST_ENTRY *Link;
3595 LIST_ENTRY *LinkData;
3596 LIST_ENTRY *LinkDefault;
3597 LIST_ENTRY *ListEntry;
3598 CHAR16 *StringPtr;
3599 IFR_BLOCK_DATA *BlockData;
3600 IFR_DEFAULT_DATA *DefaultId;
3601 IFR_DEFAULT_DATA *DefaultValueData;
3602 UINTN Width;
3603 UINT8 *TmpBuffer;
3604 CHAR16 *DefaultString;
3605 UINTN StrSize;
3606
3607 BlockData = NULL;
3608 DataExist = FALSE;
3609 DefaultString = NULL;
3610 //
3611 // Add length for <ConfigHdr> + '\0'
3612 //
3613 Length = StrLen (ConfigHdr) + 1;
3614
3615 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3616 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3617 //
3618 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3619 // |1| StrLen (ConfigHdr) | 8 | 4 |
3620 //
3621 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
3622
3623 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3624 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3625 ListEntry = &BlockData->DefaultValueEntry;
3626 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3627 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3628 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3629 continue;
3630 }
3631 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3632 //
3633 // Add length for "&Name1=zzzzzzzzzzzz"
3634 // |1|Name|1|Value|
3635 //
3636 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
3637 } else {
3638 //
3639 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3640 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3641 //
3642 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
3643 }
3644 DataExist = TRUE;
3645 }
3646 }
3647 }
3648
3649 //
3650 // No default value is found. The default string doesn't exist.
3651 //
3652 if (!DataExist) {
3653 return EFI_SUCCESS;
3654 }
3655
3656 //
3657 // Allocate buffer for the entire <DefaultAltCfgResp>
3658 //
3659 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3660 if (*DefaultAltCfgResp == NULL) {
3661 return EFI_OUT_OF_RESOURCES;
3662 }
3663 StringPtr = *DefaultAltCfgResp;
3664
3665 //
3666 // Start with <ConfigHdr>
3667 //
3668 StrCpyS (StringPtr, Length, ConfigHdr);
3669 StringPtr += StrLen (StringPtr);
3670
3671 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3672 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3673 //
3674 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3675 // |1| StrLen (ConfigHdr) | 8 | 4 |
3676 //
3677 UnicodeSPrint (
3678 StringPtr,
3679 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
3680 L"&%s&ALTCFG=%04X",
3681 ConfigHdr,
3682 DefaultId->DefaultId
3683 );
3684 StringPtr += StrLen (StringPtr);
3685
3686 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3687 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3688 ListEntry = &BlockData->DefaultValueEntry;
3689 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3690 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3691 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3692 continue;
3693 }
3694 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3695 UnicodeSPrint (
3696 StringPtr,
3697 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
3698 L"&%s=",
3699 BlockData->Name
3700 );
3701 StringPtr += StrLen (StringPtr);
3702 } else {
3703 //
3704 // Add <BlockConfig>
3705 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3706 //
3707 UnicodeSPrint (
3708 StringPtr,
3709 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
3710 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3711 BlockData->Offset,
3712 BlockData->Width
3713 );
3714 StringPtr += StrLen (StringPtr);
3715 }
3716 Width = BlockData->Width;
3717 //
3718 // Convert Value to a hex string in "%x" format
3719 // NOTE: This is in the opposite byte that GUID and PATH use
3720 //
3721 if (BlockData->OpCode == EFI_IFR_STRING_OP){
3722 DefaultString = InternalGetString(HiiHandle, DefaultValueData->Value.string);
3723 TmpBuffer = AllocateZeroPool (Width);
3724 ASSERT (TmpBuffer != NULL);
3725 if (DefaultString != NULL) {
3726 StrSize = StrLen(DefaultString)* sizeof (CHAR16);
3727 if (StrSize > Width) {
3728 StrSize = Width;
3729 }
3730 CopyMem (TmpBuffer, (UINT8 *) DefaultString, StrSize);
3731 }
3732 } else {
3733 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
3734 }
3735 for (; Width > 0 && (TmpBuffer != NULL); Width--) {
3736 UnicodeValueToStringS (
3737 StringPtr,
3738 Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),
3739 PREFIX_ZERO | RADIX_HEX,
3740 TmpBuffer[Width - 1],
3741 2
3742 );
3743 StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));
3744 }
3745 if (DefaultString != NULL){
3746 FreePool(DefaultString);
3747 DefaultString = NULL;
3748 }
3749 if (BlockData->OpCode == EFI_IFR_STRING_OP && TmpBuffer != NULL) {
3750 FreePool(TmpBuffer);
3751 TmpBuffer = NULL;
3752 }
3753 }
3754 }
3755 }
3756
3757 HiiToLower (*DefaultAltCfgResp);
3758
3759 return EFI_SUCCESS;
3760 }
3761
3762 /**
3763 This function gets the full request string and full default value string by
3764 parsing IFR data in HII form packages.
3765
3766 When Request points to NULL string, the request string and default value string
3767 for each varstore in form package will return.
3768
3769 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3770 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3771 @param Request Pointer to a null-terminated Unicode string in
3772 <ConfigRequest> format. When it doesn't contain
3773 any RequestElement, it will be updated to return
3774 the full RequestElement retrieved from IFR data.
3775 If it points to NULL, the request string for the first
3776 varstore in form package will be merged into a
3777 <MultiConfigRequest> format string and return.
3778 @param AltCfgResp Pointer to a null-terminated Unicode string in
3779 <ConfigAltResp> format. When the pointer is to NULL,
3780 the full default value string retrieved from IFR data
3781 will return. When the pinter is to a string, the
3782 full default value string retrieved from IFR data
3783 will be merged into the input string and return.
3784 When Request points to NULL, the default value string
3785 for each varstore in form package will be merged into
3786 a <MultiConfigAltResp> format string and return.
3787 @param PointerProgress Optional parameter, it can be NULL.
3788 When it is not NULL, if Request is NULL, it returns NULL.
3789 On return, points to a character in the Request
3790 string. Points to the string's null terminator if
3791 request was successful. Points to the most recent
3792 & before the first failing name / value pair (or
3793 the beginning of the string if the failure is in
3794 the first name / value pair) if the request was
3795 not successful.
3796 @retval EFI_SUCCESS The Results string is set to the full request string.
3797 And AltCfgResp contains all default value string.
3798 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3799 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3800 can't be found in Form package.
3801 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3802 @retval EFI_INVALID_PARAMETER Request points to NULL.
3803
3804 **/
3805 EFI_STATUS
3806 EFIAPI
3807 GetFullStringFromHiiFormPackages (
3808 IN HII_DATABASE_RECORD *DataBaseRecord,
3809 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3810 IN OUT EFI_STRING *Request,
3811 IN OUT EFI_STRING *AltCfgResp,
3812 OUT EFI_STRING *PointerProgress OPTIONAL
3813 )
3814 {
3815 EFI_STATUS Status;
3816 UINT8 *HiiFormPackage;
3817 UINTN PackageSize;
3818 IFR_BLOCK_DATA *RequestBlockArray;
3819 IFR_BLOCK_DATA *BlockData;
3820 IFR_DEFAULT_DATA *DefaultValueData;
3821 IFR_DEFAULT_DATA *DefaultId;
3822 IFR_DEFAULT_DATA *DefaultIdArray;
3823 IFR_VARSTORAGE_DATA *VarStorageData;
3824 EFI_STRING DefaultAltCfgResp;
3825 EFI_STRING ConfigHdr;
3826 EFI_STRING StringPtr;
3827 EFI_STRING Progress;
3828
3829 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
3830 return EFI_INVALID_PARAMETER;
3831 }
3832
3833 //
3834 // Initialize the local variables.
3835 //
3836 RequestBlockArray = NULL;
3837 DefaultIdArray = NULL;
3838 VarStorageData = NULL;
3839 DefaultAltCfgResp = NULL;
3840 ConfigHdr = NULL;
3841 HiiFormPackage = NULL;
3842 PackageSize = 0;
3843 Progress = *Request;
3844
3845 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
3846 if (EFI_ERROR (Status)) {
3847 goto Done;
3848 }
3849
3850 //
3851 // 1. Get the request block array by Request String when Request string contains the block array.
3852 //
3853 StringPtr = NULL;
3854 if (*Request != NULL) {
3855 StringPtr = *Request;
3856 //
3857 // Jump <ConfigHdr>
3858 //
3859 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3860 Status = EFI_INVALID_PARAMETER;
3861 goto Done;
3862 }
3863 StringPtr += StrLen (L"GUID=");
3864 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3865 StringPtr++;
3866 }
3867 if (*StringPtr == L'\0') {
3868 Status = EFI_INVALID_PARAMETER;
3869 goto Done;
3870 }
3871 StringPtr += StrLen (L"&NAME=");
3872 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3873 StringPtr++;
3874 }
3875 if (*StringPtr == L'\0') {
3876 Status = EFI_INVALID_PARAMETER;
3877 goto Done;
3878 }
3879 StringPtr += StrLen (L"&PATH=");
3880 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3881 StringPtr ++;
3882 }
3883
3884 if (*StringPtr == L'\0') {
3885 //
3886 // No request block is found.
3887 //
3888 StringPtr = NULL;
3889 }
3890 }
3891
3892 //
3893 // If StringPtr != NULL, get the request elements.
3894 //
3895 if (StringPtr != NULL) {
3896 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
3897 RequestBlockArray = GetBlockElement(StringPtr, &Progress);
3898 } else {
3899 RequestBlockArray = GetNameElement(StringPtr, &Progress);
3900 }
3901
3902 if (RequestBlockArray == NULL) {
3903 Status = EFI_INVALID_PARAMETER;
3904 goto Done;
3905 }
3906 }
3907
3908 //
3909 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3910 //
3911 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
3912 if (DefaultIdArray == NULL) {
3913 Status = EFI_OUT_OF_RESOURCES;
3914 goto Done;
3915 }
3916 InitializeListHead (&DefaultIdArray->Entry);
3917
3918 //
3919 // Initialize VarStorageData to store the var store Block and Default value information.
3920 //
3921 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
3922 if (VarStorageData == NULL) {
3923 Status = EFI_OUT_OF_RESOURCES;
3924 goto Done;
3925 }
3926 InitializeListHead (&VarStorageData->Entry);
3927 InitializeListHead (&VarStorageData->BlockEntry);
3928
3929 //
3930 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3931 //
3932
3933 //
3934 // Parse the opcode in form package to get the default setting.
3935 //
3936 Status = ParseIfrData (DataBaseRecord->Handle,
3937 HiiFormPackage,
3938 (UINT32) PackageSize,
3939 *Request,
3940 RequestBlockArray,
3941 VarStorageData,
3942 DefaultIdArray);
3943 if (EFI_ERROR (Status)) {
3944 goto Done;
3945 }
3946
3947 //
3948 // No requested varstore in IFR data and directly return
3949 //
3950 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
3951 Status = EFI_SUCCESS;
3952 goto Done;
3953 }
3954
3955 //
3956 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3957 //
3958 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
3959 if (EFI_ERROR (Status)) {
3960 goto Done;
3961 }
3962
3963 if (RequestBlockArray == NULL) {
3964 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
3965 goto Done;
3966 }
3967 }
3968
3969 //
3970 // 4. Construct Default Value string in AltResp according to request element.
3971 // Go through all VarStorageData Entry and get the DefaultId array for each one
3972 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3973 //
3974 Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
3975 if (EFI_ERROR (Status)) {
3976 goto Done;
3977 }
3978
3979 //
3980 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
3981 //
3982 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
3983 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
3984 FreePool (DefaultAltCfgResp);
3985 } else if (*AltCfgResp == NULL) {
3986 *AltCfgResp = DefaultAltCfgResp;
3987 }
3988
3989 Done:
3990 if (RequestBlockArray != NULL) {
3991 //
3992 // Free Link Array RequestBlockArray
3993 //
3994 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3995 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3996 RemoveEntryList (&BlockData->Entry);
3997 if (BlockData->Name != NULL) {
3998 FreePool (BlockData->Name);
3999 }
4000 FreePool (BlockData);
4001 }
4002
4003 FreePool (RequestBlockArray);
4004 }
4005
4006 if (VarStorageData != NULL) {
4007 //
4008 // Free link array VarStorageData
4009 //
4010 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
4011 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
4012 RemoveEntryList (&BlockData->Entry);
4013 if (BlockData->Name != NULL) {
4014 FreePool (BlockData->Name);
4015 }
4016 //
4017 // Free default value link array
4018 //
4019 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
4020 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
4021 RemoveEntryList (&DefaultValueData->Entry);
4022 FreePool (DefaultValueData);
4023 }
4024 FreePool (BlockData);
4025 }
4026 if (VarStorageData ->Name != NULL) {
4027 FreePool (VarStorageData ->Name);
4028 VarStorageData ->Name = NULL;
4029 }
4030 FreePool (VarStorageData);
4031 }
4032
4033 if (DefaultIdArray != NULL) {
4034 //
4035 // Free DefaultId Array
4036 //
4037 while (!IsListEmpty (&DefaultIdArray->Entry)) {
4038 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
4039 RemoveEntryList (&DefaultId->Entry);
4040 FreePool (DefaultId);
4041 }
4042 FreePool (DefaultIdArray);
4043 }
4044
4045 //
4046 // Free the allocated string
4047 //
4048 if (ConfigHdr != NULL) {
4049 FreePool (ConfigHdr);
4050 }
4051
4052 //
4053 // Free Package data
4054 //
4055 if (HiiFormPackage != NULL) {
4056 FreePool (HiiFormPackage);
4057 }
4058
4059 if (PointerProgress != NULL) {
4060 if (*Request == NULL) {
4061 *PointerProgress = NULL;
4062 } else if (EFI_ERROR (Status)) {
4063 *PointerProgress = *Request;
4064 } else {
4065 *PointerProgress = *Request + StrLen (*Request);
4066 }
4067 }
4068
4069 return Status;
4070 }
4071
4072 /**
4073 This function gets the full request resp string by
4074 parsing IFR data in HII form packages.
4075
4076 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4077 instance.
4078 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4079 varstore data structure.
4080 @param Request Pointer to a null-terminated Unicode string in
4081 <ConfigRequest> format.
4082 @param RequestResp Pointer to a null-terminated Unicode string in
4083 <ConfigResp> format.
4084 @param AccessProgress On return, points to a character in the Request
4085 string. Points to the string's null terminator if
4086 request was successful. Points to the most recent
4087 & before the first failing name / value pair (or
4088 the beginning of the string if the failure is in
4089 the first name / value pair) if the request was
4090 not successful.
4091
4092 @retval EFI_SUCCESS The Results string is set to the full request string.
4093 And AltCfgResp contains all default value string.
4094 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4095 @retval EFI_INVALID_PARAMETER Request points to NULL.
4096
4097 **/
4098 EFI_STATUS
4099 GetConfigRespFromEfiVarStore (
4100 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4101 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4102 IN EFI_STRING Request,
4103 OUT EFI_STRING *RequestResp,
4104 OUT EFI_STRING *AccessProgress
4105 )
4106 {
4107 EFI_STATUS Status;
4108 EFI_STRING VarStoreName;
4109 UINTN NameSize;
4110 UINT8 *VarStore;
4111 UINTN BufferSize;
4112
4113 Status = EFI_SUCCESS;
4114 BufferSize = 0;
4115 VarStore = NULL;
4116 VarStoreName = NULL;
4117 *AccessProgress = Request;
4118
4119 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
4120 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
4121 if (VarStoreName == NULL) {
4122 Status = EFI_OUT_OF_RESOURCES;
4123 goto Done;
4124 }
4125 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
4126
4127
4128 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4129 if (Status != EFI_BUFFER_TOO_SMALL) {
4130 goto Done;
4131 }
4132
4133 VarStore = AllocateZeroPool (BufferSize);
4134 ASSERT (VarStore != NULL);
4135 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4136 if (EFI_ERROR (Status)) {
4137 goto Done;
4138 }
4139
4140 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
4141 if (EFI_ERROR (Status)) {
4142 goto Done;
4143 }
4144
4145 Done:
4146 if (VarStoreName != NULL) {
4147 FreePool (VarStoreName);
4148 }
4149
4150 if (VarStore != NULL) {
4151 FreePool (VarStore);
4152 }
4153
4154 return Status;
4155 }
4156
4157
4158 /**
4159 This function route the full request resp string for efi varstore.
4160
4161 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4162 instance.
4163 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4164 varstore data structure.
4165 @param RequestResp Pointer to a null-terminated Unicode string in
4166 <ConfigResp> format.
4167 @param Result Pointer to a null-terminated Unicode string in
4168 <ConfigResp> format.
4169
4170 @retval EFI_SUCCESS The Results string is set to the full request string.
4171 And AltCfgResp contains all default value string.
4172 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4173 @retval EFI_INVALID_PARAMETER Request points to NULL.
4174
4175 **/
4176 EFI_STATUS
4177 RouteConfigRespForEfiVarStore (
4178 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4179 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4180 IN EFI_STRING RequestResp,
4181 OUT EFI_STRING *Result
4182 )
4183 {
4184 EFI_STATUS Status;
4185 EFI_STRING VarStoreName;
4186 UINTN NameSize;
4187 UINT8 *VarStore;
4188 UINTN BufferSize;
4189 UINTN BlockSize;
4190
4191 Status = EFI_SUCCESS;
4192 BufferSize = 0;
4193 VarStore = NULL;
4194 VarStoreName = NULL;
4195 *Result = RequestResp;
4196
4197 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
4198 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
4199 if (VarStoreName == NULL) {
4200 Status = EFI_OUT_OF_RESOURCES;
4201 goto Done;
4202 }
4203 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
4204
4205 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4206 if (Status != EFI_BUFFER_TOO_SMALL) {
4207 DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
4208 goto Done;
4209 }
4210
4211 BlockSize = BufferSize;
4212 VarStore = AllocateZeroPool (BufferSize);
4213 ASSERT (VarStore != NULL);
4214 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4215 if (EFI_ERROR (Status)) {
4216 goto Done;
4217 }
4218
4219 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
4220 if (EFI_ERROR (Status)) {
4221 goto Done;
4222 }
4223
4224 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
4225 if (EFI_ERROR (Status)) {
4226 *Result = RequestResp;
4227 goto Done;
4228 }
4229
4230 Done:
4231 if (VarStoreName != NULL) {
4232 FreePool (VarStoreName);
4233 }
4234
4235 if (VarStore != NULL) {
4236 FreePool (VarStore);
4237 }
4238
4239 return Status;
4240 }
4241
4242 /**
4243 Validate the config request elements.
4244
4245 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4246 without configHdr field.
4247
4248 @retval CHAR16 * THE first Name/value pair not correct.
4249 @retval NULL Success parse the name/value pair
4250 **/
4251 CHAR16 *
4252 OffsetWidthValidate (
4253 CHAR16 *ConfigElements
4254 )
4255 {
4256 CHAR16 *StringPtr;
4257 CHAR16 *RetVal;
4258
4259 StringPtr = ConfigElements;
4260
4261 while (1) {
4262 RetVal = StringPtr;
4263 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4264 return RetVal;
4265 }
4266
4267 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4268 StringPtr++;
4269 }
4270 if (*StringPtr == L'\0') {
4271 return RetVal;
4272 }
4273
4274 StringPtr += StrLen (L"&WIDTH=");
4275 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4276 StringPtr ++;
4277 }
4278
4279 if (*StringPtr == L'\0') {
4280 return NULL;
4281 }
4282 }
4283 }
4284
4285 /**
4286 Validate the config request elements.
4287
4288 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4289 without configHdr field.
4290
4291 @retval CHAR16 * THE first Name/value pair not correct.
4292 @retval NULL Success parse the name/value pair
4293
4294 **/
4295 CHAR16 *
4296 NameValueValidate (
4297 CHAR16 *ConfigElements
4298 )
4299 {
4300 CHAR16 *StringPtr;
4301 CHAR16 *RetVal;
4302
4303 StringPtr = ConfigElements;
4304
4305 while (1) {
4306 RetVal = StringPtr;
4307 if (*StringPtr != L'&') {
4308 return RetVal;
4309 }
4310 StringPtr += 1;
4311
4312 StringPtr = StrStr (StringPtr, L"&");
4313
4314 if (StringPtr == NULL) {
4315 return NULL;
4316 }
4317 }
4318 }
4319
4320 /**
4321 Validate the config request string.
4322
4323 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4324
4325 @retval CHAR16 * THE first element not correct.
4326 @retval NULL Success parse the name/value pair
4327
4328 **/
4329 CHAR16 *
4330 ConfigRequestValidate (
4331 CHAR16 *ConfigRequest
4332 )
4333 {
4334 BOOLEAN HasNameField;
4335 CHAR16 *StringPtr;
4336
4337 HasNameField = TRUE;
4338 StringPtr = ConfigRequest;
4339
4340 //
4341 // Check <ConfigHdr>
4342 //
4343 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4344 return ConfigRequest;
4345 }
4346 StringPtr += StrLen (L"GUID=");
4347 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
4348 StringPtr++;
4349 }
4350 if (*StringPtr == L'\0') {
4351 return ConfigRequest;
4352 }
4353 StringPtr += StrLen (L"&NAME=");
4354 if (*StringPtr == L'&') {
4355 HasNameField = FALSE;
4356 }
4357 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
4358 StringPtr++;
4359 }
4360 if (*StringPtr == L'\0') {
4361 return ConfigRequest;
4362 }
4363 StringPtr += StrLen (L"&PATH=");
4364 while (*StringPtr != L'\0' && *StringPtr != L'&') {
4365 StringPtr ++;
4366 }
4367
4368 if (*StringPtr == L'\0') {
4369 return NULL;
4370 }
4371
4372 if (HasNameField) {
4373 //
4374 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4375 //
4376 return OffsetWidthValidate(StringPtr);
4377 } else {
4378 //
4379 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4380 //
4381 return NameValueValidate(StringPtr);
4382 }
4383 }
4384
4385 /**
4386 This function allows a caller to extract the current configuration
4387 for one or more named elements from one or more drivers.
4388
4389 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4390 instance.
4391 @param Request A null-terminated Unicode string in
4392 <MultiConfigRequest> format.
4393 @param Progress On return, points to a character in the Request
4394 string. Points to the string's null terminator if
4395 request was successful. Points to the most recent
4396 & before the first failing name / value pair (or
4397 the beginning of the string if the failure is in
4398 the first name / value pair) if the request was
4399 not successful.
4400 @param Results Null-terminated Unicode string in
4401 <MultiConfigAltResp> format which has all values
4402 filled in for the names in the Request string.
4403 String to be allocated by the called function.
4404
4405 @retval EFI_SUCCESS The Results string is filled with the values
4406 corresponding to all requested names.
4407 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4408 results that must be stored awaiting possible
4409 future protocols.
4410 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4411 Progress set to the "G" in "GUID" of the routing
4412 header that doesn't match. Note: There is no
4413 requirement that all routing data be validated
4414 before any configuration extraction.
4415 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4416 parameter would result in this type of error. The
4417 Progress parameter is set to NULL.
4418 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4419 before the error or the beginning of the string.
4420 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4421 Configuration Access Protocol returned
4422 EFI_INVALID_PARAMETER. Progress set to most recent
4423 & before the error or the beginning of the string.
4424
4425 **/
4426 EFI_STATUS
4427 EFIAPI
4428 HiiConfigRoutingExtractConfig (
4429 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4430 IN CONST EFI_STRING Request,
4431 OUT EFI_STRING *Progress,
4432 OUT EFI_STRING *Results
4433 )
4434 {
4435 HII_DATABASE_PRIVATE_DATA *Private;
4436 EFI_STRING StringPtr;
4437 EFI_STRING ConfigRequest;
4438 UINTN Length;
4439 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4440 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4441 EFI_STATUS Status;
4442 LIST_ENTRY *Link;
4443 HII_DATABASE_RECORD *Database;
4444 UINT8 *DevicePathPkg;
4445 UINT8 *CurrentDevicePath;
4446 EFI_HANDLE DriverHandle;
4447 EFI_HII_HANDLE HiiHandle;
4448 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4449 EFI_STRING AccessProgress;
4450 EFI_STRING AccessResults;
4451 EFI_STRING AccessProgressBackup;
4452 EFI_STRING AccessResultsBackup;
4453 EFI_STRING DefaultResults;
4454 BOOLEAN FirstElement;
4455 BOOLEAN IfrDataParsedFlag;
4456 BOOLEAN IsEfiVarStore;
4457 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4458 EFI_STRING ErrorPtr;
4459 UINTN DevicePathSize;
4460 UINTN ConigStringSize;
4461 UINTN ConigStringSizeNewsize;
4462 EFI_STRING ConfigStringPtr;
4463
4464 if (This == NULL || Progress == NULL || Results == NULL) {
4465 return EFI_INVALID_PARAMETER;
4466 }
4467
4468 if (Request == NULL) {
4469 *Progress = NULL;
4470 return EFI_INVALID_PARAMETER;
4471 }
4472
4473 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4474 StringPtr = Request;
4475 *Progress = StringPtr;
4476 DefaultResults = NULL;
4477 ConfigRequest = NULL;
4478 Status = EFI_SUCCESS;
4479 AccessResults = NULL;
4480 AccessProgress = NULL;
4481 AccessResultsBackup = NULL;
4482 AccessProgressBackup = NULL;
4483 DevicePath = NULL;
4484 IfrDataParsedFlag = FALSE;
4485 IsEfiVarStore = FALSE;
4486 EfiVarStoreInfo = NULL;
4487
4488 //
4489 // The first element of <MultiConfigRequest> should be
4490 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4491 //
4492 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4493 return EFI_INVALID_PARAMETER;
4494 }
4495
4496 FirstElement = TRUE;
4497
4498 //
4499 // Allocate a fix length of memory to store Results. Reallocate memory for
4500 // Results if this fix length is insufficient.
4501 //
4502 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4503 if (*Results == NULL) {
4504 return EFI_OUT_OF_RESOURCES;
4505 }
4506
4507 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4508 //
4509 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4510 // or most recent & before the error.
4511 //
4512 if (StringPtr == Request) {
4513 *Progress = StringPtr;
4514 } else {
4515 *Progress = StringPtr - 1;
4516 }
4517
4518 //
4519 // Process each <ConfigRequest> of <MultiConfigRequest>
4520 //
4521 Length = CalculateConfigStringLen (StringPtr);
4522 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4523 if (ConfigRequest == NULL) {
4524 Status = EFI_OUT_OF_RESOURCES;
4525 goto Done;
4526 }
4527 *(ConfigRequest + Length) = 0;
4528
4529 //
4530 // Get the UEFI device path
4531 //
4532 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
4533 if (EFI_ERROR (Status)) {
4534 goto Done;
4535 }
4536
4537 //
4538 // Find driver which matches the routing data.
4539 //
4540 DriverHandle = NULL;
4541 HiiHandle = NULL;
4542 Database = NULL;
4543 for (Link = Private->DatabaseList.ForwardLink;
4544 Link != &Private->DatabaseList;
4545 Link = Link->ForwardLink
4546 ) {
4547 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4548 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4549 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4550 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4551 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
4552 DriverHandle = Database->DriverHandle;
4553 HiiHandle = Database->Handle;
4554 break;
4555 }
4556 }
4557 }
4558
4559 //
4560 // Try to find driver handle by device path.
4561 //
4562 if (DriverHandle == NULL) {
4563 TempDevicePath = DevicePath;
4564 Status = gBS->LocateDevicePath (
4565 &gEfiDevicePathProtocolGuid,
4566 &TempDevicePath,
4567 &DriverHandle
4568 );
4569 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4570 //
4571 // Routing data does not match any known driver.
4572 // Set Progress to the 'G' in "GUID" of the routing header.
4573 //
4574 *Progress = StringPtr;
4575 Status = EFI_NOT_FOUND;
4576 goto Done;
4577 }
4578 }
4579
4580 //
4581 // Validate ConfigRequest String.
4582 //
4583 ErrorPtr = ConfigRequestValidate(ConfigRequest);
4584 if (ErrorPtr != NULL) {
4585 *Progress = StrStr (StringPtr, ErrorPtr);
4586 Status = EFI_INVALID_PARAMETER;
4587 goto Done;
4588 }
4589
4590 //
4591 // Check whether ConfigRequest contains request string.
4592 //
4593 IfrDataParsedFlag = FALSE;
4594 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
4595 //
4596 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4597 //
4598 IfrDataParsedFlag = TRUE;
4599 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
4600 if (EFI_ERROR (Status)) {
4601 //
4602 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4603 // Map it to the progress on <MultiConfigRequest> then return it.
4604 //
4605 ASSERT (AccessProgress != NULL);
4606 *Progress = StrStr (StringPtr, AccessProgress);
4607 goto Done;
4608 }
4609 //
4610 // Not any request block is found.
4611 //
4612 if (!GetElementsFromRequest(ConfigRequest)) {
4613 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
4614 goto NextConfigString;
4615 }
4616 }
4617
4618 //
4619 // Check whether this ConfigRequest is search from Efi varstore type storage.
4620 //
4621 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
4622 if (EFI_ERROR (Status)) {
4623 goto Done;
4624 }
4625
4626 if (IsEfiVarStore) {
4627 //
4628 // Call the GetVariable function to extract settings.
4629 //
4630 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
4631 FreePool (EfiVarStoreInfo);
4632 if (EFI_ERROR (Status)) {
4633 //
4634 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4635 // Map it to the progress on <MultiConfigRequest> then return it.
4636 //
4637 *Progress = StrStr (StringPtr, AccessProgress);
4638 goto Done;
4639 }
4640
4641 //
4642 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4643 //
4644 Status = gBS->HandleProtocol (
4645 DriverHandle,
4646 &gEfiHiiConfigAccessProtocolGuid,
4647 (VOID **) &ConfigAccess
4648 );
4649 if (EFI_ERROR (Status)) {
4650 //
4651 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4652 // So ignore the error status in this case.
4653 //
4654 Status = EFI_SUCCESS;
4655 } else {
4656 Status = ConfigAccess->ExtractConfig (
4657 ConfigAccess,
4658 ConfigRequest,
4659 &AccessProgressBackup,
4660 &AccessResultsBackup
4661 );
4662 if (!EFI_ERROR(Status)) {
4663 //
4664 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4665 //
4666 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
4667 ConigStringSize = StrSize (AccessResults);
4668 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
4669 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
4670 AccessResults = (EFI_STRING) ReallocatePool (
4671 ConigStringSize,
4672 ConigStringSizeNewsize,
4673 AccessResults);
4674 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
4675 }
4676 } else {
4677 //
4678 // In the ExtractConfig function of some driver may not support EfiVarStore,
4679 // may return error status, just ignore the error status in this case.
4680 //
4681 Status = EFI_SUCCESS;
4682 }
4683 if (AccessResultsBackup != NULL) {
4684 FreePool (AccessResultsBackup);
4685 AccessResultsBackup = NULL;
4686 }
4687 }
4688 } else {
4689 //
4690 // Call corresponding ConfigAccess protocol to extract settings
4691 //
4692 Status = gBS->HandleProtocol (
4693 DriverHandle,
4694 &gEfiHiiConfigAccessProtocolGuid,
4695 (VOID **) &ConfigAccess
4696 );
4697 if (EFI_ERROR (Status)) {
4698 goto Done;
4699 }
4700
4701 Status = ConfigAccess->ExtractConfig (
4702 ConfigAccess,
4703 ConfigRequest,
4704 &AccessProgress,
4705 &AccessResults
4706 );
4707 }
4708 if (EFI_ERROR (Status)) {
4709 //
4710 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4711 // Map it to the progress on <MultiConfigRequest> then return it.
4712 //
4713 *Progress = StrStr (StringPtr, AccessProgress);
4714 goto Done;
4715 }
4716
4717 //
4718 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4719 // which separates the first <ConfigAltResp> and the following ones.
4720 //
4721 ASSERT (*AccessProgress == 0);
4722
4723 //
4724 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4725 //
4726 if (!IfrDataParsedFlag && HiiHandle != NULL) {
4727 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4728 ASSERT_EFI_ERROR (Status);
4729 }
4730
4731 FreePool (DevicePath);
4732 DevicePath = NULL;
4733
4734 if (DefaultResults != NULL) {
4735 Status = MergeDefaultString (&AccessResults, DefaultResults);
4736 ASSERT_EFI_ERROR (Status);
4737 FreePool (DefaultResults);
4738 DefaultResults = NULL;
4739 }
4740
4741 NextConfigString:
4742 if (!FirstElement) {
4743 Status = AppendToMultiString (Results, L"&");
4744 ASSERT_EFI_ERROR (Status);
4745 }
4746
4747 Status = AppendToMultiString (Results, AccessResults);
4748 ASSERT_EFI_ERROR (Status);
4749
4750 FirstElement = FALSE;
4751
4752 FreePool (AccessResults);
4753 AccessResults = NULL;
4754 FreePool (ConfigRequest);
4755 ConfigRequest = NULL;
4756
4757 //
4758 // Go to next <ConfigRequest> (skip '&').
4759 //
4760 StringPtr += Length;
4761 if (*StringPtr == 0) {
4762 *Progress = StringPtr;
4763 break;
4764 }
4765
4766 StringPtr++;
4767 }
4768
4769 Done:
4770 if (EFI_ERROR (Status)) {
4771 FreePool (*Results);
4772 *Results = NULL;
4773 }
4774
4775 if (ConfigRequest != NULL) {
4776 FreePool (ConfigRequest);
4777 }
4778
4779 if (AccessResults != NULL) {
4780 FreePool (AccessResults);
4781 }
4782
4783 if (DefaultResults != NULL) {
4784 FreePool (DefaultResults);
4785 }
4786
4787 if (DevicePath != NULL) {
4788 FreePool (DevicePath);
4789 }
4790
4791 return Status;
4792 }
4793
4794
4795 /**
4796 This function allows the caller to request the current configuration for the
4797 entirety of the current HII database and returns the data in a
4798 null-terminated Unicode string.
4799
4800 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4801 instance.
4802 @param Results Null-terminated Unicode string in
4803 <MultiConfigAltResp> format which has all values
4804 filled in for the entirety of the current HII
4805 database. String to be allocated by the called
4806 function. De-allocation is up to the caller.
4807
4808 @retval EFI_SUCCESS The Results string is filled with the values
4809 corresponding to all requested names.
4810 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4811 results that must be stored awaiting possible
4812 future protocols.
4813 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4814 parameter would result in this type of error.
4815
4816 **/
4817 EFI_STATUS
4818 EFIAPI
4819 HiiConfigRoutingExportConfig (
4820 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4821 OUT EFI_STRING *Results
4822 )
4823 {
4824 EFI_STATUS Status;
4825 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4826 EFI_STRING AccessResults;
4827 EFI_STRING Progress;
4828 EFI_STRING StringPtr;
4829 EFI_STRING ConfigRequest;
4830 UINTN Index;
4831 EFI_HANDLE *ConfigAccessHandles;
4832 UINTN NumberConfigAccessHandles;
4833 BOOLEAN FirstElement;
4834 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4835 EFI_HII_HANDLE HiiHandle;
4836 EFI_STRING DefaultResults;
4837 HII_DATABASE_PRIVATE_DATA *Private;
4838 LIST_ENTRY *Link;
4839 HII_DATABASE_RECORD *Database;
4840 UINT8 *DevicePathPkg;
4841 UINT8 *CurrentDevicePath;
4842 BOOLEAN IfrDataParsedFlag;
4843
4844 if (This == NULL || Results == NULL) {
4845 return EFI_INVALID_PARAMETER;
4846 }
4847
4848 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4849
4850 //
4851 // Allocate a fix length of memory to store Results. Reallocate memory for
4852 // Results if this fix length is insufficient.
4853 //
4854 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4855 if (*Results == NULL) {
4856 return EFI_OUT_OF_RESOURCES;
4857 }
4858
4859 NumberConfigAccessHandles = 0;
4860 Status = gBS->LocateHandleBuffer (
4861 ByProtocol,
4862 &gEfiHiiConfigAccessProtocolGuid,
4863 NULL,
4864 &NumberConfigAccessHandles,
4865 &ConfigAccessHandles
4866 );
4867 if (EFI_ERROR (Status)) {
4868 return Status;
4869 }
4870
4871 FirstElement = TRUE;
4872
4873 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
4874 Status = gBS->HandleProtocol (
4875 ConfigAccessHandles[Index],
4876 &gEfiHiiConfigAccessProtocolGuid,
4877 (VOID **) &ConfigAccess
4878 );
4879 if (EFI_ERROR (Status)) {
4880 continue;
4881 }
4882
4883 //
4884 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4885 //
4886 IfrDataParsedFlag = FALSE;
4887 Progress = NULL;
4888 HiiHandle = NULL;
4889 DefaultResults = NULL;
4890 Database = NULL;
4891 ConfigRequest = NULL;
4892 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
4893 if (DevicePath != NULL) {
4894 for (Link = Private->DatabaseList.ForwardLink;
4895 Link != &Private->DatabaseList;
4896 Link = Link->ForwardLink
4897 ) {
4898 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4899 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4900 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4901 if (CompareMem (
4902 DevicePath,
4903 CurrentDevicePath,
4904 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
4905 ) == 0) {
4906 HiiHandle = Database->Handle;
4907 break;
4908 }
4909 }
4910 }
4911 }
4912
4913 Status = ConfigAccess->ExtractConfig (
4914 ConfigAccess,
4915 NULL,
4916 &Progress,
4917 &AccessResults
4918 );
4919 if (EFI_ERROR (Status)) {
4920 //
4921 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4922 //
4923 if (HiiHandle != NULL && DevicePath != NULL) {
4924 IfrDataParsedFlag = TRUE;
4925 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4926 //
4927 // Get the full request string to get the Current setting again.
4928 //
4929 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
4930 Status = ConfigAccess->ExtractConfig (
4931 ConfigAccess,
4932 ConfigRequest,
4933 &Progress,
4934 &AccessResults
4935 );
4936 FreePool (ConfigRequest);
4937 } else {
4938 Status = EFI_NOT_FOUND;
4939 }
4940 }
4941 }
4942
4943 if (!EFI_ERROR (Status)) {
4944 //
4945 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4946 //
4947 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
4948 StringPtr = StrStr (AccessResults, L"&GUID=");
4949 if (StringPtr != NULL) {
4950 *StringPtr = 0;
4951 }
4952 if (GetElementsFromRequest (AccessResults)) {
4953 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
4954 ASSERT_EFI_ERROR (Status);
4955 }
4956 if (StringPtr != NULL) {
4957 *StringPtr = L'&';
4958 }
4959 }
4960 //
4961 // Merge the default sting from IFR code into the got setting from driver.
4962 //
4963 if (DefaultResults != NULL) {
4964 Status = MergeDefaultString (&AccessResults, DefaultResults);
4965 ASSERT_EFI_ERROR (Status);
4966 FreePool (DefaultResults);
4967 DefaultResults = NULL;
4968 }
4969
4970 //
4971 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4972 // which separates the first <ConfigAltResp> and the following ones.
4973 //
4974 if (!FirstElement) {
4975 Status = AppendToMultiString (Results, L"&");
4976 ASSERT_EFI_ERROR (Status);
4977 }
4978
4979 Status = AppendToMultiString (Results, AccessResults);
4980 ASSERT_EFI_ERROR (Status);
4981
4982 FirstElement = FALSE;
4983
4984 FreePool (AccessResults);
4985 AccessResults = NULL;
4986 }
4987 }
4988 FreePool (ConfigAccessHandles);
4989
4990 return EFI_SUCCESS;
4991 }
4992
4993
4994 /**
4995 This function processes the results of processing forms and routes it to the
4996 appropriate handlers or storage.
4997
4998 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4999 instance.
5000 @param Configuration A null-terminated Unicode string in
5001 <MulltiConfigResp> format.
5002 @param Progress A pointer to a string filled in with the offset of
5003 the most recent & before the first failing name /
5004 value pair (or the beginning of the string if the
5005 failure is in the first name / value pair) or the
5006 terminating NULL if all was successful.
5007
5008 @retval EFI_SUCCESS The results have been distributed or are awaiting
5009 distribution.
5010 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5011 results that must be stored awaiting possible
5012 future protocols.
5013 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5014 would result in this type of error.
5015 @retval EFI_NOT_FOUND Target for the specified routing data was not
5016 found.
5017
5018 **/
5019 EFI_STATUS
5020 EFIAPI
5021 HiiConfigRoutingRouteConfig (
5022 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5023 IN CONST EFI_STRING Configuration,
5024 OUT EFI_STRING *Progress
5025 )
5026 {
5027 HII_DATABASE_PRIVATE_DATA *Private;
5028 EFI_STRING StringPtr;
5029 EFI_STRING ConfigResp;
5030 UINTN Length;
5031 EFI_STATUS Status;
5032 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
5033 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
5034 LIST_ENTRY *Link;
5035 HII_DATABASE_RECORD *Database;
5036 UINT8 *DevicePathPkg;
5037 UINT8 *CurrentDevicePath;
5038 EFI_HANDLE DriverHandle;
5039 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
5040 EFI_STRING AccessProgress;
5041 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
5042 BOOLEAN IsEfiVarstore;
5043 UINTN DevicePathSize;
5044
5045 if (This == NULL || Progress == NULL) {
5046 return EFI_INVALID_PARAMETER;
5047 }
5048
5049 if (Configuration == NULL) {
5050 *Progress = NULL;
5051 return EFI_INVALID_PARAMETER;
5052 }
5053
5054 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5055 StringPtr = Configuration;
5056 *Progress = StringPtr;
5057 Database = NULL;
5058 AccessProgress = NULL;
5059 EfiVarStoreInfo= NULL;
5060 IsEfiVarstore = FALSE;
5061
5062 //
5063 // The first element of <MultiConfigResp> should be
5064 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5065 //
5066 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5067 return EFI_INVALID_PARAMETER;
5068 }
5069
5070 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
5071 //
5072 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5073 // or most recent & before the error.
5074 //
5075 if (StringPtr == Configuration) {
5076 *Progress = StringPtr;
5077 } else {
5078 *Progress = StringPtr - 1;
5079 }
5080
5081 //
5082 // Process each <ConfigResp> of <MultiConfigResp>
5083 //
5084 Length = CalculateConfigStringLen (StringPtr);
5085 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
5086 if (ConfigResp == NULL) {
5087 return EFI_OUT_OF_RESOURCES;
5088 }
5089 //
5090 // Append '\0' to the end of ConfigRequest
5091 //
5092 *(ConfigResp + Length) = 0;
5093
5094 //
5095 // Get the UEFI device path
5096 //
5097 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
5098 if (EFI_ERROR (Status)) {
5099 FreePool (ConfigResp);
5100 return Status;
5101 }
5102
5103 //
5104 // Find driver which matches the routing data.
5105 //
5106 DriverHandle = NULL;
5107 for (Link = Private->DatabaseList.ForwardLink;
5108 Link != &Private->DatabaseList;
5109 Link = Link->ForwardLink
5110 ) {
5111 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
5112
5113 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
5114 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
5115 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
5116 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
5117 DriverHandle = Database->DriverHandle;
5118 break;
5119 }
5120 }
5121 }
5122
5123 //
5124 // Try to find driver handle by device path.
5125 //
5126 if (DriverHandle == NULL) {
5127 TempDevicePath = DevicePath;
5128 Status = gBS->LocateDevicePath (
5129 &gEfiDevicePathProtocolGuid,
5130 &TempDevicePath,
5131 &DriverHandle
5132 );
5133 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
5134 //
5135 // Routing data does not match any known driver.
5136 // Set Progress to the 'G' in "GUID" of the routing header.
5137 //
5138 FreePool (DevicePath);
5139 *Progress = StringPtr;
5140 FreePool (ConfigResp);
5141 return EFI_NOT_FOUND;
5142 }
5143 }
5144
5145 FreePool (DevicePath);
5146
5147 //
5148 // Check whether this ConfigRequest is search from Efi varstore type storage.
5149 //
5150 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
5151 if (EFI_ERROR (Status)) {
5152 return Status;
5153 }
5154
5155 if (IsEfiVarstore) {
5156 //
5157 // Call the SetVariable function to route settings.
5158 //
5159 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
5160 FreePool (EfiVarStoreInfo);
5161 } else {
5162 //
5163 // Call corresponding ConfigAccess protocol to route settings
5164 //
5165 Status = gBS->HandleProtocol (
5166 DriverHandle,
5167 &gEfiHiiConfigAccessProtocolGuid,
5168 (VOID **) &ConfigAccess
5169 );
5170 if (EFI_ERROR (Status)) {
5171 *Progress = StringPtr;
5172 FreePool (ConfigResp);
5173 return EFI_NOT_FOUND;
5174 }
5175
5176 Status = ConfigAccess->RouteConfig (
5177 ConfigAccess,
5178 ConfigResp,
5179 &AccessProgress
5180 );
5181 }
5182 if (EFI_ERROR (Status)) {
5183 ASSERT (AccessProgress != NULL);
5184 //
5185 // AccessProgress indicates the parsing progress on <ConfigResp>.
5186 // Map it to the progress on <MultiConfigResp> then return it.
5187 //
5188 *Progress = StrStr (StringPtr, AccessProgress);
5189
5190 FreePool (ConfigResp);
5191 return Status;
5192 }
5193
5194 FreePool (ConfigResp);
5195 ConfigResp = NULL;
5196
5197 //
5198 // Go to next <ConfigResp> (skip '&').
5199 //
5200 StringPtr += Length;
5201 if (*StringPtr == 0) {
5202 *Progress = StringPtr;
5203 break;
5204 }
5205
5206 StringPtr++;
5207
5208 }
5209
5210 return EFI_SUCCESS;
5211 }
5212
5213
5214 /**
5215 This helper function is to be called by drivers to map configuration data
5216 stored in byte array ("block") formats such as UEFI Variables into current
5217 configuration strings.
5218
5219 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5220 instance.
5221 @param ConfigRequest A null-terminated Unicode string in
5222 <ConfigRequest> format.
5223 @param Block Array of bytes defining the block's configuration.
5224 @param BlockSize Length in bytes of Block.
5225 @param Config Filled-in configuration string. String allocated
5226 by the function. Returned only if call is
5227 successful. It is <ConfigResp> string format.
5228 @param Progress A pointer to a string filled in with the offset of
5229 the most recent & before the first failing
5230 name/value pair (or the beginning of the string if
5231 the failure is in the first name / value pair) or
5232 the terminating NULL if all was successful.
5233
5234 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5235 terminator at the end of the ConfigRequest
5236 string.
5237 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5238 points to the first character of ConfigRequest.
5239 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5240 Block parameter would result in this type of
5241 error. Progress points to the first character of
5242 ConfigRequest.
5243 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5244 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5245 Block is left updated and Progress points at
5246 the "&" preceding the first non-<BlockName>.
5247
5248 **/
5249 EFI_STATUS
5250 EFIAPI
5251 HiiBlockToConfig (
5252 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5253 IN CONST EFI_STRING ConfigRequest,
5254 IN CONST UINT8 *Block,
5255 IN CONST UINTN BlockSize,
5256 OUT EFI_STRING *Config,
5257 OUT EFI_STRING *Progress
5258 )
5259 {
5260 HII_DATABASE_PRIVATE_DATA *Private;
5261 EFI_STRING StringPtr;
5262 UINTN Length;
5263 EFI_STATUS Status;
5264 EFI_STRING TmpPtr;
5265 UINT8 *TmpBuffer;
5266 UINTN Offset;
5267 UINTN Width;
5268 UINT8 *Value;
5269 EFI_STRING ValueStr;
5270 EFI_STRING ConfigElement;
5271 UINTN Index;
5272 UINT8 *TemBuffer;
5273 CHAR16 *TemString;
5274 CHAR16 TemChar;
5275
5276 TmpBuffer = NULL;
5277
5278 if (This == NULL || Progress == NULL || Config == NULL) {
5279 return EFI_INVALID_PARAMETER;
5280 }
5281
5282 if (Block == NULL || ConfigRequest == NULL) {
5283 *Progress = ConfigRequest;
5284 return EFI_INVALID_PARAMETER;
5285 }
5286
5287
5288 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5289 ASSERT (Private != NULL);
5290
5291 StringPtr = ConfigRequest;
5292 ValueStr = NULL;
5293 Value = NULL;
5294 ConfigElement = NULL;
5295
5296 //
5297 // Allocate a fix length of memory to store Results. Reallocate memory for
5298 // Results if this fix length is insufficient.
5299 //
5300 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
5301 if (*Config == NULL) {
5302 return EFI_OUT_OF_RESOURCES;
5303 }
5304
5305 //
5306 // Jump <ConfigHdr>
5307 //
5308 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5309 *Progress = StringPtr;
5310 Status = EFI_INVALID_PARAMETER;
5311 goto Exit;
5312 }
5313 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5314 StringPtr++;
5315 }
5316 if (*StringPtr == 0) {
5317 *Progress = StringPtr - 1;
5318 Status = EFI_INVALID_PARAMETER;
5319 goto Exit;
5320 }
5321
5322 while (*StringPtr != L'&' && *StringPtr != 0) {
5323 StringPtr++;
5324 }
5325 if (*StringPtr == 0) {
5326 *Progress = StringPtr;
5327
5328 AppendToMultiString(Config, ConfigRequest);
5329 HiiToLower (*Config);
5330
5331 return EFI_SUCCESS;
5332 }
5333 //
5334 // Skip '&'
5335 //
5336 StringPtr++;
5337
5338 //
5339 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5340 //
5341 TemChar = *StringPtr;
5342 *StringPtr = '\0';
5343 AppendToMultiString(Config, ConfigRequest);
5344 *StringPtr = TemChar;
5345
5346 //
5347 // Parse each <RequestElement> if exists
5348 // Only <BlockName> format is supported by this help function.
5349 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5350 //
5351 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
5352 //
5353 // Back up the header of one <BlockName>
5354 //
5355 TmpPtr = StringPtr;
5356
5357 StringPtr += StrLen (L"OFFSET=");
5358 //
5359 // Get Offset
5360 //
5361 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5362 if (EFI_ERROR (Status)) {
5363 *Progress = TmpPtr - 1;
5364 goto Exit;
5365 }
5366 Offset = 0;
5367 CopyMem (
5368 &Offset,
5369 TmpBuffer,
5370 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5371 );
5372 FreePool (TmpBuffer);
5373
5374 StringPtr += Length;
5375 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5376 *Progress = TmpPtr - 1;
5377 Status = EFI_INVALID_PARAMETER;
5378 goto Exit;
5379 }
5380 StringPtr += StrLen (L"&WIDTH=");
5381
5382 //
5383 // Get Width
5384 //
5385 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5386 if (EFI_ERROR (Status)) {
5387 *Progress = TmpPtr - 1;
5388 goto Exit;
5389 }
5390 Width = 0;
5391 CopyMem (
5392 &Width,
5393 TmpBuffer,
5394 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5395 );
5396 FreePool (TmpBuffer);
5397
5398 StringPtr += Length;
5399 if (*StringPtr != 0 && *StringPtr != L'&') {
5400 *Progress = TmpPtr - 1;
5401 Status = EFI_INVALID_PARAMETER;
5402 goto Exit;
5403 }
5404
5405 //
5406 // Calculate Value and convert it to hex string.
5407 //
5408 if (Offset + Width > BlockSize) {
5409 *Progress = StringPtr;
5410 Status = EFI_DEVICE_ERROR;
5411 goto Exit;
5412 }
5413
5414 Value = (UINT8 *) AllocateZeroPool (Width);
5415 if (Value == NULL) {
5416 *Progress = ConfigRequest;
5417 Status = EFI_OUT_OF_RESOURCES;
5418 goto Exit;
5419 }
5420
5421 CopyMem (Value, (UINT8 *) Block + Offset, Width);
5422
5423 Length = Width * 2 + 1;
5424 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5425 if (ValueStr == NULL) {
5426 *Progress = ConfigRequest;
5427 Status = EFI_OUT_OF_RESOURCES;
5428 goto Exit;
5429 }
5430
5431 TemString = ValueStr;
5432 TemBuffer = Value + Width - 1;
5433 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
5434 UnicodeValueToStringS (
5435 TemString,
5436 Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
5437 PREFIX_ZERO | RADIX_HEX,
5438 *TemBuffer,
5439 2
5440 );
5441 TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
5442 }
5443
5444 FreePool (Value);
5445 Value = NULL;
5446
5447 //
5448 // Build a ConfigElement
5449 //
5450 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
5451 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5452 if (ConfigElement == NULL) {
5453 Status = EFI_OUT_OF_RESOURCES;
5454 goto Exit;
5455 }
5456 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
5457 if (*StringPtr == 0) {
5458 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
5459 }
5460 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
5461 StrCatS (ConfigElement, Length, L"VALUE=");
5462 StrCatS (ConfigElement, Length, ValueStr);
5463
5464 AppendToMultiString (Config, ConfigElement);
5465
5466 FreePool (ConfigElement);
5467 FreePool (ValueStr);
5468 ConfigElement = NULL;
5469 ValueStr = NULL;
5470
5471 //
5472 // If '\0', parsing is finished. Otherwise skip '&' to continue
5473 //
5474 if (*StringPtr == 0) {
5475 break;
5476 }
5477 AppendToMultiString (Config, L"&");
5478 StringPtr++;
5479
5480 }
5481
5482 if (*StringPtr != 0) {
5483 *Progress = StringPtr - 1;
5484 Status = EFI_INVALID_PARAMETER;
5485 goto Exit;
5486 }
5487
5488 HiiToLower (*Config);
5489 *Progress = StringPtr;
5490 return EFI_SUCCESS;
5491
5492 Exit:
5493 if (*Config != NULL) {
5494 FreePool (*Config);
5495 *Config = NULL;
5496 }
5497 if (ValueStr != NULL) {
5498 FreePool (ValueStr);
5499 }
5500 if (Value != NULL) {
5501 FreePool (Value);
5502 }
5503 if (ConfigElement != NULL) {
5504 FreePool (ConfigElement);
5505 }
5506
5507 return Status;
5508
5509 }
5510
5511
5512 /**
5513 This helper function is to be called by drivers to map configuration strings
5514 to configurations stored in byte array ("block") formats such as UEFI Variables.
5515
5516 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5517 instance.
5518 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5519 format.
5520 @param Block A possibly null array of bytes representing the
5521 current block. Only bytes referenced in the
5522 ConfigResp string in the block are modified. If
5523 this parameter is null or if the *BlockSize
5524 parameter is (on input) shorter than required by
5525 the Configuration string, only the BlockSize
5526 parameter is updated and an appropriate status
5527 (see below) is returned.
5528 @param BlockSize The length of the Block in units of UINT8. On
5529 input, this is the size of the Block. On output,
5530 if successful, contains the largest index of the
5531 modified byte in the Block, or the required buffer
5532 size if the Block is not large enough.
5533 @param Progress On return, points to an element of the ConfigResp
5534 string filled in with the offset of the most
5535 recent '&' before the first failing name / value
5536 pair (or the beginning of the string if the
5537 failure is in the first name / value pair) or the
5538 terminating NULL if all was successful.
5539
5540 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5541 terminator at the end of the ConfigResp string.
5542 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5543 points to the first character of ConfigResp.
5544 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5545 Block parameter would result in this type of
5546 error. Progress points to the first character of
5547 ConfigResp.
5548 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5549 value pair. Block is left updated and
5550 Progress points at the '&' preceding the first
5551 non-<BlockName>.
5552 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5553 BlockSize is updated with the required buffer size.
5554 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5555 Progress points to the "G" in "GUID" of the errant
5556 routing data.
5557
5558 **/
5559 EFI_STATUS
5560 EFIAPI
5561 HiiConfigToBlock (
5562 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5563 IN CONST EFI_STRING ConfigResp,
5564 IN OUT UINT8 *Block,
5565 IN OUT UINTN *BlockSize,
5566 OUT EFI_STRING *Progress
5567 )
5568 {
5569 HII_DATABASE_PRIVATE_DATA *Private;
5570 EFI_STRING StringPtr;
5571 EFI_STRING TmpPtr;
5572 UINTN Length;
5573 EFI_STATUS Status;
5574 UINT8 *TmpBuffer;
5575 UINTN Offset;
5576 UINTN Width;
5577 UINT8 *Value;
5578 UINTN BufferSize;
5579 UINTN MaxBlockSize;
5580
5581 TmpBuffer = NULL;
5582
5583 if (This == NULL || BlockSize == NULL || Progress == NULL) {
5584 return EFI_INVALID_PARAMETER;
5585 }
5586
5587 *Progress = ConfigResp;
5588 if (ConfigResp == NULL) {
5589 return EFI_INVALID_PARAMETER;
5590 }
5591
5592 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5593 ASSERT (Private != NULL);
5594
5595 StringPtr = ConfigResp;
5596 BufferSize = *BlockSize;
5597 Value = NULL;
5598 MaxBlockSize = 0;
5599
5600 //
5601 // Jump <ConfigHdr>
5602 //
5603 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5604 *Progress = StringPtr;
5605 Status = EFI_INVALID_PARAMETER;
5606 goto Exit;
5607 }
5608 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5609 StringPtr++;
5610 }
5611 if (*StringPtr == 0) {
5612 *Progress = StringPtr;
5613 Status = EFI_INVALID_PARAMETER;
5614 goto Exit;
5615 }
5616
5617 while (*StringPtr != L'&' && *StringPtr != 0) {
5618 StringPtr++;
5619 }
5620 if (*StringPtr == 0) {
5621 *Progress = StringPtr;
5622 Status = EFI_INVALID_PARAMETER;
5623 goto Exit;
5624 }
5625
5626 //
5627 // Parse each <ConfigElement> if exists
5628 // Only '&'<BlockConfig> format is supported by this help function.
5629 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5630 //
5631 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
5632 TmpPtr = StringPtr;
5633 StringPtr += StrLen (L"&OFFSET=");
5634 //
5635 // Get Offset
5636 //
5637 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5638 if (EFI_ERROR (Status)) {
5639 *Progress = TmpPtr;
5640 goto Exit;
5641 }
5642 Offset = 0;
5643 CopyMem (
5644 &Offset,
5645 TmpBuffer,
5646 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5647 );
5648 FreePool (TmpBuffer);
5649
5650 StringPtr += Length;
5651 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5652 *Progress = TmpPtr;
5653 Status = EFI_INVALID_PARAMETER;
5654 goto Exit;
5655 }
5656 StringPtr += StrLen (L"&WIDTH=");
5657
5658 //
5659 // Get Width
5660 //
5661 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5662 if (EFI_ERROR (Status)) {
5663 *Progress = TmpPtr;
5664 goto Exit;
5665 }
5666 Width = 0;
5667 CopyMem (
5668 &Width,
5669 TmpBuffer,
5670 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5671 );
5672 FreePool (TmpBuffer);
5673
5674 StringPtr += Length;
5675 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
5676 *Progress = TmpPtr;
5677 Status = EFI_INVALID_PARAMETER;
5678 goto Exit;
5679 }
5680 StringPtr += StrLen (L"&VALUE=");
5681
5682 //
5683 // Get Value
5684 //
5685 Status = GetValueOfNumber (StringPtr, &Value, &Length);
5686 if (EFI_ERROR (Status)) {
5687 *Progress = TmpPtr;
5688 goto Exit;
5689 }
5690
5691 StringPtr += Length;
5692 if (*StringPtr != 0 && *StringPtr != L'&') {
5693 *Progress = TmpPtr;
5694 Status = EFI_INVALID_PARAMETER;
5695 goto Exit;
5696 }
5697
5698 //
5699 // Update the Block with configuration info
5700 //
5701 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
5702 CopyMem (Block + Offset, Value, Width);
5703 }
5704 if (Offset + Width > MaxBlockSize) {
5705 MaxBlockSize = Offset + Width;
5706 }
5707
5708 FreePool (Value);
5709 Value = NULL;
5710
5711 //
5712 // If '\0', parsing is finished.
5713 //
5714 if (*StringPtr == 0) {
5715 break;
5716 }
5717 }
5718
5719 //
5720 // The input string is not ConfigResp format, return error.
5721 //
5722 if (*StringPtr != 0) {
5723 *Progress = StringPtr;
5724 Status = EFI_INVALID_PARAMETER;
5725 goto Exit;
5726 }
5727
5728 *Progress = StringPtr + StrLen (StringPtr);
5729 *BlockSize = MaxBlockSize - 1;
5730
5731 if (MaxBlockSize > BufferSize) {
5732 *BlockSize = MaxBlockSize;
5733 if (Block != NULL) {
5734 return EFI_BUFFER_TOO_SMALL;
5735 }
5736 }
5737
5738 if (Block == NULL) {
5739 *Progress = ConfigResp;
5740 return EFI_INVALID_PARAMETER;
5741 }
5742
5743 return EFI_SUCCESS;
5744
5745 Exit:
5746
5747 if (Value != NULL) {
5748 FreePool (Value);
5749 }
5750 return Status;
5751 }
5752
5753
5754 /**
5755 This helper function is to be called by drivers to extract portions of
5756 a larger configuration string.
5757
5758 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5759 instance.
5760 @param Configuration A null-terminated Unicode string in
5761 <MultiConfigAltResp> format.
5762 @param Guid A pointer to the GUID value to search for in the
5763 routing portion of the ConfigResp string when
5764 retrieving the requested data. If Guid is NULL,
5765 then all GUID values will be searched for.
5766 @param Name A pointer to the NAME value to search for in the
5767 routing portion of the ConfigResp string when
5768 retrieving the requested data. If Name is NULL,
5769 then all Name values will be searched for.
5770 @param DevicePath A pointer to the PATH value to search for in the
5771 routing portion of the ConfigResp string when
5772 retrieving the requested data. If DevicePath is
5773 NULL, then all DevicePath values will be searched
5774 for.
5775 @param AltCfgId A pointer to the ALTCFG value to search for in the
5776 routing portion of the ConfigResp string when
5777 retrieving the requested data. If this parameter
5778 is NULL, then the current setting will be
5779 retrieved.
5780 @param AltCfgResp A pointer to a buffer which will be allocated by
5781 the function which contains the retrieved string
5782 as requested. This buffer is only allocated if
5783 the call was successful. It is <ConfigResp> format.
5784
5785 @retval EFI_SUCCESS The request succeeded. The requested data was
5786 extracted and placed in the newly allocated
5787 AltCfgResp buffer.
5788 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5789 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5790 @retval EFI_NOT_FOUND Target for the specified routing data was not
5791 found.
5792
5793 **/
5794 EFI_STATUS
5795 EFIAPI
5796 HiiGetAltCfg (
5797 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5798 IN CONST EFI_STRING Configuration,
5799 IN CONST EFI_GUID *Guid,
5800 IN CONST EFI_STRING Name,
5801 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
5802 IN CONST UINT16 *AltCfgId,
5803 OUT EFI_STRING *AltCfgResp
5804 )
5805 {
5806 EFI_STATUS Status;
5807 EFI_STRING StringPtr;
5808 EFI_STRING HdrStart;
5809 EFI_STRING HdrEnd;
5810 EFI_STRING TmpPtr;
5811 UINTN Length;
5812 EFI_STRING GuidStr;
5813 EFI_STRING NameStr;
5814 EFI_STRING PathStr;
5815 EFI_STRING AltIdStr;
5816 EFI_STRING Result;
5817 BOOLEAN GuidFlag;
5818 BOOLEAN NameFlag;
5819 BOOLEAN PathFlag;
5820
5821 HdrStart = NULL;
5822 HdrEnd = NULL;
5823 GuidStr = NULL;
5824 NameStr = NULL;
5825 PathStr = NULL;
5826 AltIdStr = NULL;
5827 Result = NULL;
5828 GuidFlag = FALSE;
5829 NameFlag = FALSE;
5830 PathFlag = FALSE;
5831
5832 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
5833 return EFI_INVALID_PARAMETER;
5834 }
5835
5836 StringPtr = Configuration;
5837 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5838 return EFI_INVALID_PARAMETER;
5839 }
5840
5841 //
5842 // Generate the sub string for later matching.
5843 //
5844 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
5845 GenerateSubStr (
5846 L"PATH=",
5847 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
5848 (VOID *) DevicePath,
5849 1,
5850 &PathStr
5851 );
5852 if (AltCfgId != NULL) {
5853 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
5854 }
5855 if (Name != NULL) {
5856 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
5857 } else {
5858 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
5859 }
5860
5861 while (*StringPtr != 0) {
5862 //
5863 // Try to match the GUID
5864 //
5865 if (!GuidFlag) {
5866 TmpPtr = StrStr (StringPtr, GuidStr);
5867 if (TmpPtr == NULL) {
5868 Status = EFI_NOT_FOUND;
5869 goto Exit;
5870 }
5871 HdrStart = TmpPtr;
5872
5873 //
5874 // Jump to <NameHdr>
5875 //
5876 if (Guid != NULL) {
5877 StringPtr = TmpPtr + StrLen (GuidStr);
5878 } else {
5879 StringPtr = StrStr (TmpPtr, L"NAME=");
5880 if (StringPtr == NULL) {
5881 Status = EFI_NOT_FOUND;
5882 goto Exit;
5883 }
5884 }
5885 GuidFlag = TRUE;
5886 }
5887
5888 //
5889 // Try to match the NAME
5890 //
5891 if (GuidFlag && !NameFlag) {
5892 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
5893 GuidFlag = FALSE;
5894 } else {
5895 //
5896 // Jump to <PathHdr>
5897 //
5898 if (Name != NULL) {
5899 StringPtr += StrLen (NameStr);
5900 } else {
5901 StringPtr = StrStr (StringPtr, L"PATH=");
5902 if (StringPtr == NULL) {
5903 Status = EFI_NOT_FOUND;
5904 goto Exit;
5905 }
5906 }
5907 NameFlag = TRUE;
5908 }
5909 }
5910
5911 //
5912 // Try to match the DevicePath
5913 //
5914 if (GuidFlag && NameFlag && !PathFlag) {
5915 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
5916 GuidFlag = FALSE;
5917 NameFlag = FALSE;
5918 } else {
5919 //
5920 // Jump to '&' before <DescHdr> or <ConfigBody>
5921 //
5922 if (DevicePath != NULL) {
5923 StringPtr += StrLen (PathStr);
5924 } else {
5925 StringPtr = StrStr (StringPtr, L"&");
5926 if (StringPtr == NULL) {
5927 Status = EFI_NOT_FOUND;
5928 goto Exit;
5929 }
5930 StringPtr ++;
5931 }
5932 PathFlag = TRUE;
5933 HdrEnd = StringPtr;
5934 }
5935 }
5936
5937 //
5938 // Try to match the AltCfgId
5939 //
5940 if (GuidFlag && NameFlag && PathFlag) {
5941 if (AltCfgId == NULL) {
5942 //
5943 // Return Current Setting when AltCfgId is NULL.
5944 //
5945 Status = OutputConfigBody (StringPtr, &Result);
5946 goto Exit;
5947 }
5948 //
5949 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5950 //
5951 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
5952 GuidFlag = FALSE;
5953 NameFlag = FALSE;
5954 PathFlag = FALSE;
5955 } else {
5956 //
5957 // Skip AltIdStr and &
5958 //
5959 StringPtr = StringPtr + StrLen (AltIdStr);
5960 Status = OutputConfigBody (StringPtr, &Result);
5961 goto Exit;
5962 }
5963 }
5964 }
5965
5966 Status = EFI_NOT_FOUND;
5967
5968 Exit:
5969 *AltCfgResp = NULL;
5970 if (!EFI_ERROR (Status) && (Result != NULL)) {
5971 //
5972 // Copy the <ConfigHdr> and <ConfigBody>
5973 //
5974 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
5975 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
5976 if (*AltCfgResp == NULL) {
5977 Status = EFI_OUT_OF_RESOURCES;
5978 } else {
5979 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
5980 StrCatS (*AltCfgResp, Length, Result);
5981 Status = EFI_SUCCESS;
5982 }
5983 }
5984
5985 if (GuidStr != NULL) {
5986 FreePool (GuidStr);
5987 }
5988 if (NameStr != NULL) {
5989 FreePool (NameStr);
5990 }
5991 if (PathStr != NULL) {
5992 FreePool (PathStr);
5993 }
5994 if (AltIdStr != NULL) {
5995 FreePool (AltIdStr);
5996 }
5997 if (Result != NULL) {
5998 FreePool (Result);
5999 }
6000
6001 return Status;
6002
6003 }
6004
6005