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