]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
057835232583db0599e9049e08826c58643bbca4
[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 UINTN NameSize;
1608 EFI_STRING GuidStr;
1609 EFI_STRING NameStr;
1610 EFI_STRING TempStr;
1611 UINTN LengthString;
1612 UINT8 *HiiFormPackage;
1613 UINTN PackageSize;
1614 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1615 EFI_HII_PACKAGE_HEADER *PackageHeader;
1616
1617 HiiFormPackage = NULL;
1618 LengthString = 0;
1619 Status = EFI_SUCCESS;
1620 GuidStr = NULL;
1621 NameStr = NULL;
1622 TempStr = NULL;
1623 *IsEfiVarstore = FALSE;
1624
1625 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1626 if (EFI_ERROR (Status)) {
1627 return Status;
1628 }
1629
1630 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1631 PackageOffset = IfrOffset;
1632 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1633
1634 while (IfrOffset < PackageSize) {
1635 //
1636 // More than one form packages exist.
1637 //
1638 if (PackageOffset >= PackageHeader->Length) {
1639 //
1640 // Process the new form package.
1641 //
1642 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1643 IfrOffset += PackageOffset;
1644 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1645 }
1646
1647 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1648 IfrOffset += IfrOpHdr->Length;
1649 PackageOffset += IfrOpHdr->Length;
1650
1651 if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
1652 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1653 //
1654 // If the length is small than the structure, this is from old efi
1655 // varstore definition. Old efi varstore get config directly from
1656 // GetVariable function.
1657 //
1658 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
1659 continue;
1660 }
1661
1662 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1663 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1664 if (VarStoreName == NULL) {
1665 Status = EFI_OUT_OF_RESOURCES;
1666 goto Done;
1667 }
1668 AsciiStrToUnicodeStrS ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName, NameSize);
1669
1670 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
1671 GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
1672 LengthString = StrLen (GuidStr);
1673 LengthString = LengthString + StrLen (NameStr) + 1;
1674 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1675 if (TempStr == NULL) {
1676 FreePool (GuidStr);
1677 FreePool (NameStr);
1678 FreePool (VarStoreName);
1679 Status = EFI_OUT_OF_RESOURCES;
1680 goto Done;
1681 }
1682 StrCpyS (TempStr, LengthString, GuidStr);
1683 StrCatS (TempStr, LengthString, NameStr);
1684 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1685 *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
1686 if (*EfiVarStore == NULL) {
1687 FreePool (VarStoreName);
1688 FreePool (GuidStr);
1689 FreePool (NameStr);
1690 FreePool (TempStr);
1691 Status = EFI_OUT_OF_RESOURCES;
1692 goto Done;
1693 }
1694 *IsEfiVarstore = TRUE;
1695 CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
1696 }
1697
1698 //
1699 // Free alllocated temp string.
1700 //
1701 FreePool (VarStoreName);
1702 FreePool (GuidStr);
1703 FreePool (NameStr);
1704 FreePool (TempStr);
1705
1706 //
1707 // Already found the varstore, break;
1708 //
1709 if (*IsEfiVarstore) {
1710 break;
1711 }
1712 }
1713 }
1714 Done:
1715 if (HiiFormPackage != NULL) {
1716 FreePool (HiiFormPackage);
1717 }
1718
1719 return Status;
1720 }
1721
1722 /**
1723 Check whether the ConfigRequest string has the request elements.
1724 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1725 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1726
1727 @param ConfigRequest The input config request string.
1728
1729 @retval TRUE The input include config request elements.
1730 @retval FALSE The input string not includes.
1731
1732 **/
1733 BOOLEAN
1734 GetElementsFromRequest (
1735 IN EFI_STRING ConfigRequest
1736 )
1737 {
1738 EFI_STRING TmpRequest;
1739
1740 TmpRequest = StrStr (ConfigRequest, L"PATH=");
1741 ASSERT (TmpRequest != NULL);
1742
1743 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
1744 return TRUE;
1745 }
1746
1747 return FALSE;
1748 }
1749
1750 /**
1751 Check whether the this varstore is the request varstore.
1752
1753 @param VarstoreGuid Varstore guid.
1754 @param Name Varstore name.
1755 @param ConfigHdr Current configRequest info.
1756
1757 @retval TRUE This varstore is the requst one.
1758 @retval FALSE This varstore is not the requst one.
1759
1760 **/
1761 BOOLEAN
1762 IsThisVarstore (
1763 IN EFI_GUID *VarstoreGuid,
1764 IN CHAR16 *Name,
1765 IN CHAR16 *ConfigHdr
1766 )
1767 {
1768 EFI_STRING GuidStr;
1769 EFI_STRING NameStr;
1770 EFI_STRING TempStr;
1771 UINTN LengthString;
1772 BOOLEAN RetVal;
1773
1774 RetVal = FALSE;
1775 GuidStr = NULL;
1776 TempStr = NULL;
1777
1778 //
1779 // If ConfigHdr has name field and varstore not has name, return FALSE.
1780 //
1781 if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
1782 return FALSE;
1783 }
1784
1785 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
1786 if (Name != NULL) {
1787 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
1788 } else {
1789 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
1790 }
1791 LengthString = StrLen (GuidStr);
1792 LengthString = LengthString + StrLen (NameStr) + 1;
1793 TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
1794 if (TempStr == NULL) {
1795 goto Done;
1796 }
1797
1798 StrCpyS (TempStr, LengthString, GuidStr);
1799 StrCatS (TempStr, LengthString, NameStr);
1800
1801 if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
1802 RetVal = TRUE;
1803 }
1804
1805 Done:
1806 if (GuidStr != NULL) {
1807 FreePool (GuidStr);
1808 }
1809
1810 if (NameStr != NULL) {
1811 FreePool (NameStr);
1812 }
1813
1814 if (TempStr != NULL) {
1815 FreePool (TempStr);
1816 }
1817
1818 return RetVal;
1819 }
1820
1821 /**
1822 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1823
1824 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1825 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1826 the first found varstore will be as ConfigHdr.
1827 @retval TRUE This hii package is the reqeust one.
1828 @retval FALSE This hii package is not the reqeust one.
1829 **/
1830 BOOLEAN
1831 IsThisPackageList (
1832 IN HII_DATABASE_RECORD *DataBaseRecord,
1833 IN EFI_STRING ConfigHdr
1834 )
1835 {
1836 EFI_STATUS Status;
1837 UINTN IfrOffset;
1838 UINTN PackageOffset;
1839 EFI_IFR_OP_HEADER *IfrOpHdr;
1840 CHAR16 *VarStoreName;
1841 UINTN NameSize;
1842 UINT8 *HiiFormPackage;
1843 UINTN PackageSize;
1844 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
1845 EFI_HII_PACKAGE_HEADER *PackageHeader;
1846 EFI_IFR_VARSTORE *IfrVarStore;
1847 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
1848 BOOLEAN FindVarstore;
1849
1850 HiiFormPackage = NULL;
1851 VarStoreName = NULL;
1852 Status = EFI_SUCCESS;
1853 FindVarstore = FALSE;
1854
1855 Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
1856 if (EFI_ERROR (Status)) {
1857 return FALSE;
1858 }
1859
1860 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1861 PackageOffset = IfrOffset;
1862 PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
1863
1864 while (IfrOffset < PackageSize) {
1865 //
1866 // More than one form packages exist.
1867 //
1868 if (PackageOffset >= PackageHeader->Length) {
1869 //
1870 // Process the new form package.
1871 //
1872 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1873 IfrOffset += PackageOffset;
1874 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
1875 }
1876
1877 IfrOpHdr = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
1878 IfrOffset += IfrOpHdr->Length;
1879 PackageOffset += IfrOpHdr->Length;
1880
1881 switch (IfrOpHdr->OpCode) {
1882
1883 case EFI_IFR_VARSTORE_OP:
1884 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
1885
1886 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
1887 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1888 if (VarStoreName == NULL) {
1889 goto Done;
1890 }
1891 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
1892
1893 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
1894 FindVarstore = TRUE;
1895 goto Done;
1896 } else {
1897 FreePool (VarStoreName);
1898 VarStoreName = NULL;
1899 }
1900 break;
1901
1902 case EFI_IFR_VARSTORE_EFI_OP:
1903 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
1904 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
1905 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
1906 if (VarStoreName == NULL) {
1907 goto Done;
1908 }
1909 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
1910
1911 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
1912 FindVarstore = TRUE;
1913 goto Done;
1914 } else {
1915 FreePool (VarStoreName);
1916 VarStoreName = NULL;
1917 }
1918 break;
1919
1920 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1921 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
1922
1923 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
1924 FindVarstore = TRUE;
1925 goto Done;
1926 }
1927 break;
1928
1929 case EFI_IFR_FORM_OP:
1930 case EFI_IFR_FORM_MAP_OP:
1931 //
1932 // No matched varstore is found and directly return.
1933 //
1934 goto Done;
1935
1936 default:
1937 break;
1938 }
1939 }
1940 Done:
1941 if (HiiFormPackage != NULL) {
1942 FreePool (HiiFormPackage);
1943 }
1944
1945 if (VarStoreName != NULL) {
1946 FreePool (VarStoreName);
1947 }
1948
1949 return FindVarstore;
1950 }
1951
1952 /**
1953 Check whether the this op code is required.
1954
1955 @param RequestBlockArray The array includes all the request info or NULL.
1956 @param HiiHandle The hii handle for this form package.
1957 @param VarStorageData The varstore data strucure.
1958 @param IfrOpHdr Ifr opcode header for this opcode.
1959 @param VarWidth The buffer width for this opcode.
1960 @param ReturnData The data block added for this opcode.
1961
1962 @retval EFI_SUCCESS This opcode is required.
1963 @retval EFI_NOT_FOUND This opcode is not required.
1964 @retval Others Contain some error.
1965
1966 **/
1967 EFI_STATUS
1968 IsThisOpcodeRequired (
1969 IN IFR_BLOCK_DATA *RequestBlockArray,
1970 IN EFI_HII_HANDLE HiiHandle,
1971 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
1972 IN EFI_IFR_OP_HEADER *IfrOpHdr,
1973 IN UINT16 VarWidth,
1974 OUT IFR_BLOCK_DATA **ReturnData
1975 )
1976 {
1977 IFR_BLOCK_DATA *BlockData;
1978 UINT16 VarOffset;
1979 EFI_STRING_ID NameId;
1980 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
1981
1982 NameId = 0;
1983 VarOffset = 0;
1984 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
1985
1986 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1987 NameId = IfrQuestionHdr->VarStoreInfo.VarName;
1988
1989 //
1990 // Check whether this question is in requested block array.
1991 //
1992 if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
1993 //
1994 // This question is not in the requested string. Skip it.
1995 //
1996 return EFI_NOT_FOUND;
1997 }
1998 } else {
1999 VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
2000
2001 //
2002 // Check whether this question is in requested block array.
2003 //
2004 if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
2005 //
2006 // This question is not in the requested string. Skip it.
2007 //
2008 return EFI_NOT_FOUND;
2009 }
2010
2011 //
2012 // Check this var question is in the var storage
2013 //
2014 if (((VarOffset + VarWidth) > VarStorageData->Size)) {
2015 return EFI_INVALID_PARAMETER;
2016 }
2017 }
2018
2019 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2020 if (BlockData == NULL) {
2021 return EFI_OUT_OF_RESOURCES;
2022 }
2023
2024 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
2025 BlockData->Name = InternalGetString(HiiHandle, NameId);
2026 } else {
2027 BlockData->Offset = VarOffset;
2028 }
2029
2030 BlockData->Width = VarWidth;
2031 BlockData->QuestionId = IfrQuestionHdr->QuestionId;
2032 BlockData->OpCode = IfrOpHdr->OpCode;
2033 BlockData->Scope = IfrOpHdr->Scope;
2034 InitializeListHead (&BlockData->DefaultValueEntry);
2035 //
2036 // Add Block Data into VarStorageData BlockEntry
2037 //
2038 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2039 *ReturnData = BlockData;
2040
2041 return EFI_SUCCESS;
2042 }
2043
2044 /**
2045 This function parses Form Package to get the block array and the default
2046 value array according to the request ConfigHdr.
2047
2048 @param HiiHandle Hii Handle for this hii package.
2049 @param Package Pointer to the form package data.
2050 @param PackageLength Length of the pacakge.
2051 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2052 the first found varstore will be as ConfigHdr.
2053 @param RequestBlockArray The block array is retrieved from the request string.
2054 @param VarStorageData VarStorage structure contains the got block and default value.
2055 @param DefaultIdArray Point to the got default id and default name array.
2056
2057 @retval EFI_SUCCESS The block array and the default value array are got.
2058 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
2059 are conflicted.
2060 @retval EFI_OUT_OF_RESOURCES No enough memory.
2061 **/
2062 EFI_STATUS
2063 EFIAPI
2064 ParseIfrData (
2065 IN EFI_HII_HANDLE HiiHandle,
2066 IN UINT8 *Package,
2067 IN UINT32 PackageLength,
2068 IN EFI_STRING ConfigHdr,
2069 IN IFR_BLOCK_DATA *RequestBlockArray,
2070 IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
2071 OUT IFR_DEFAULT_DATA *DefaultIdArray
2072 )
2073 {
2074 EFI_STATUS Status;
2075 UINTN IfrOffset;
2076 UINTN PackageOffset;
2077 EFI_IFR_VARSTORE *IfrVarStore;
2078 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
2079 EFI_IFR_OP_HEADER *IfrOpHdr;
2080 EFI_IFR_ONE_OF *IfrOneOf;
2081 EFI_IFR_REF4 *IfrRef;
2082 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
2083 EFI_IFR_DEFAULT *IfrDefault;
2084 EFI_IFR_ORDERED_LIST *IfrOrderedList;
2085 EFI_IFR_CHECKBOX *IfrCheckBox;
2086 EFI_IFR_PASSWORD *IfrPassword;
2087 EFI_IFR_STRING *IfrString;
2088 EFI_IFR_DATE *IfrDate;
2089 EFI_IFR_TIME *IfrTime;
2090 IFR_DEFAULT_DATA DefaultData;
2091 IFR_DEFAULT_DATA *DefaultDataPtr;
2092 IFR_BLOCK_DATA *BlockData;
2093 CHAR16 *VarStoreName;
2094 UINTN NameSize;
2095 UINT16 VarWidth;
2096 UINT16 VarDefaultId;
2097 BOOLEAN FirstOneOfOption;
2098 BOOLEAN FirstOrderedList;
2099 LIST_ENTRY *LinkData;
2100 LIST_ENTRY *LinkDefault;
2101 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
2102 EFI_HII_PACKAGE_HEADER *PackageHeader;
2103 EFI_VARSTORE_ID VarStoreId;
2104
2105 Status = EFI_SUCCESS;
2106 BlockData = NULL;
2107 DefaultDataPtr = NULL;
2108 FirstOneOfOption = FALSE;
2109 VarStoreId = 0;
2110 FirstOrderedList = FALSE;
2111 VarStoreName = NULL;
2112 ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
2113
2114 //
2115 // Go through the form package to parse OpCode one by one.
2116 //
2117 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2118 PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
2119 IfrOffset = PackageOffset;
2120 while (IfrOffset < PackageLength) {
2121
2122 //
2123 // More than one form package found.
2124 //
2125 if (PackageOffset >= PackageHeader->Length) {
2126 //
2127 // Already found varstore for this request, break;
2128 //
2129 if (VarStoreId != 0) {
2130 VarStoreId = 0;
2131 }
2132
2133 //
2134 // Get next package header info.
2135 //
2136 IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);
2137 PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
2138 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
2139 }
2140
2141 IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
2142 switch (IfrOpHdr->OpCode) {
2143 case EFI_IFR_VARSTORE_OP:
2144 //
2145 // VarStore is found. Don't need to search any more.
2146 //
2147 if (VarStoreId != 0) {
2148 break;
2149 }
2150
2151 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
2152
2153 NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
2154 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2155 if (VarStoreName == NULL) {
2156 Status = EFI_OUT_OF_RESOURCES;
2157 goto Done;
2158 }
2159 AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
2160
2161 if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
2162 //
2163 // Find the matched VarStore
2164 //
2165 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
2166 VarStorageData->Size = IfrVarStore->Size;
2167 VarStorageData->Name = VarStoreName;
2168 VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
2169 VarStoreId = IfrVarStore->VarStoreId;
2170 } else {
2171 FreePool (VarStoreName);
2172 VarStoreName = NULL;
2173 }
2174 break;
2175
2176 case EFI_IFR_VARSTORE_EFI_OP:
2177 //
2178 // VarStore is found. Don't need to search any more.
2179 //
2180 if (VarStoreId != 0) {
2181 break;
2182 }
2183
2184 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
2185
2186 //
2187 // If the length is small than the structure, this is from old efi
2188 // varstore definition. Old efi varstore get config directly from
2189 // GetVariable function.
2190 //
2191 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
2192 break;
2193 }
2194
2195 NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
2196 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
2197 if (VarStoreName == NULL) {
2198 Status = EFI_OUT_OF_RESOURCES;
2199 goto Done;
2200 }
2201 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
2202
2203 if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
2204 //
2205 // Find the matched VarStore
2206 //
2207 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
2208 VarStorageData->Size = IfrEfiVarStore->Size;
2209 VarStorageData->Name = VarStoreName;
2210 VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
2211 VarStoreId = IfrEfiVarStore->VarStoreId;
2212 } else {
2213 FreePool (VarStoreName);
2214 VarStoreName = NULL;
2215 }
2216 break;
2217
2218 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
2219 //
2220 // VarStore is found. Don't need to search any more.
2221 //
2222 if (VarStoreId != 0) {
2223 break;
2224 }
2225
2226 IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
2227
2228 if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
2229 //
2230 // Find the matched VarStore
2231 //
2232 CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
2233 VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
2234 VarStoreId = IfrNameValueVarStore->VarStoreId;
2235 }
2236 break;
2237
2238 case EFI_IFR_DEFAULTSTORE_OP:
2239 //
2240 // Add new the map between default id and default name.
2241 //
2242 DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
2243 if (DefaultDataPtr == NULL) {
2244 Status = EFI_OUT_OF_RESOURCES;
2245 goto Done;
2246 }
2247 DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
2248 InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
2249 DefaultDataPtr = NULL;
2250 break;
2251
2252 case EFI_IFR_FORM_OP:
2253 case EFI_IFR_FORM_MAP_OP:
2254 //
2255 // No matched varstore is found and directly return.
2256 //
2257 if ( VarStoreId == 0) {
2258 Status = EFI_SUCCESS;
2259 goto Done;
2260 }
2261 break;
2262
2263 case EFI_IFR_REF_OP:
2264 //
2265 // Ref question is not in IFR Form. This IFR form is not valid.
2266 //
2267 if ( VarStoreId == 0) {
2268 Status = EFI_INVALID_PARAMETER;
2269 goto Done;
2270 }
2271 //
2272 // Check whether this question is for the requested varstore.
2273 //
2274 IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
2275 if (IfrRef->Question.VarStoreId != VarStoreId) {
2276 break;
2277 }
2278 VarWidth = (UINT16) (sizeof (EFI_HII_REF));
2279
2280 //
2281 // The BlockData may allocate by other opcode,need to clean.
2282 //
2283 if (BlockData != NULL){
2284 BlockData = NULL;
2285 }
2286
2287 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2288 if (EFI_ERROR (Status)) {
2289 if (Status == EFI_NOT_FOUND){
2290 //
2291 //The opcode is not required,exit and parse other opcode.
2292 //
2293 break;
2294 }
2295 goto Done;
2296 }
2297 break;
2298
2299 case EFI_IFR_ONE_OF_OP:
2300 case EFI_IFR_NUMERIC_OP:
2301 //
2302 // Numeric and OneOf has the same opcode structure.
2303 //
2304
2305 //
2306 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2307 //
2308 if (VarStoreId == 0) {
2309 Status = EFI_INVALID_PARAMETER;
2310 goto Done;
2311 }
2312 //
2313 // Check whether this question is for the requested varstore.
2314 //
2315 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
2316 if (IfrOneOf->Question.VarStoreId != VarStoreId) {
2317 break;
2318 }
2319 VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
2320
2321 //
2322 // The BlockData may allocate by other opcode,need to clean.
2323 //
2324 if (BlockData != NULL){
2325 BlockData = NULL;
2326 }
2327
2328 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2329 if (EFI_ERROR (Status)) {
2330 if (Status == EFI_NOT_FOUND){
2331 //
2332 //The opcode is not required,exit and parse other opcode.
2333 //
2334 break;
2335 }
2336 goto Done;
2337 }
2338
2339 //
2340 //when go to there,BlockData can't be NULLL.
2341 //
2342 ASSERT (BlockData != NULL);
2343
2344 if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
2345 //
2346 // Set this flag to TRUE for the first oneof option.
2347 //
2348 FirstOneOfOption = TRUE;
2349 } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
2350 //
2351 // Numeric minimum value will be used as default value when no default is specified.
2352 //
2353 DefaultData.Type = DefaultValueFromDefault;
2354 switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
2355 case EFI_IFR_NUMERIC_SIZE_1:
2356 DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
2357 break;
2358
2359 case EFI_IFR_NUMERIC_SIZE_2:
2360 CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
2361 break;
2362
2363 case EFI_IFR_NUMERIC_SIZE_4:
2364 CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
2365 break;
2366
2367 case EFI_IFR_NUMERIC_SIZE_8:
2368 CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
2369 break;
2370
2371 default:
2372 Status = EFI_INVALID_PARAMETER;
2373 goto Done;
2374 }
2375 //
2376 // Set default value base on the DefaultId list get from IFR data.
2377 //
2378 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2379 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2380 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2381 InsertDefaultValue (BlockData, &DefaultData);
2382 }
2383 }
2384 break;
2385
2386 case EFI_IFR_ORDERED_LIST_OP:
2387 //
2388 // offset by question header
2389 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2390 //
2391
2392 FirstOrderedList = TRUE;
2393 //
2394 // OrderedList question is not in IFR Form. This IFR form is not valid.
2395 //
2396 if (VarStoreId == 0) {
2397 Status = EFI_INVALID_PARAMETER;
2398 goto Done;
2399 }
2400 //
2401 // Check whether this question is for the requested varstore.
2402 //
2403 IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
2404 if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
2405 BlockData = NULL;
2406 break;
2407 }
2408 VarWidth = IfrOrderedList->MaxContainers;
2409
2410 //
2411 // The BlockData may allocate by other opcode,need to clean.
2412 //
2413 if (BlockData != NULL){
2414 BlockData = NULL;
2415 }
2416
2417 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2418 if (EFI_ERROR (Status)) {
2419 if (Status == EFI_NOT_FOUND){
2420 //
2421 //The opcode is not required,exit and parse other opcode.
2422 //
2423 break;
2424 }
2425 goto Done;
2426 }
2427 break;
2428
2429 case EFI_IFR_CHECKBOX_OP:
2430 //
2431 // EFI_IFR_DEFAULT_OP
2432 // offset by question header
2433 // width is 1 sizeof (BOOLEAN)
2434 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2435 // value by DefaultOption
2436 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2437 //
2438
2439 //
2440 // CheckBox question is not in IFR Form. This IFR form is not valid.
2441 //
2442 if (VarStoreId == 0) {
2443 Status = EFI_INVALID_PARAMETER;
2444 goto Done;
2445 }
2446 //
2447 // Check whether this question is for the requested varstore.
2448 //
2449 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
2450 if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
2451 break;
2452 }
2453 VarWidth = (UINT16) sizeof (BOOLEAN);
2454
2455 //
2456 // The BlockData may allocate by other opcode,need to clean.
2457 //
2458 if (BlockData != NULL){
2459 BlockData = NULL;
2460 }
2461
2462 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2463 if (EFI_ERROR (Status)) {
2464 if (Status == EFI_NOT_FOUND){
2465 //
2466 //The opcode is not required,exit and parse other opcode.
2467 //
2468 break;
2469 }
2470 goto Done;
2471 }
2472
2473 //
2474 //when go to there,BlockData can't be NULLL.
2475 //
2476 ASSERT (BlockData != NULL);
2477
2478 //
2479 // Add default value for standard ID by CheckBox Flag
2480 //
2481 VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2482 //
2483 // Prepare new DefaultValue
2484 //
2485 DefaultData.DefaultId = VarDefaultId;
2486 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
2487 //
2488 // When flag is set, defautl value is TRUE.
2489 //
2490 DefaultData.Type = DefaultValueFromFlag;
2491 DefaultData.Value.b = TRUE;
2492 } else {
2493 //
2494 // When flag is not set, defautl value is FASLE.
2495 //
2496 DefaultData.Type = DefaultValueFromDefault;
2497 DefaultData.Value.b = FALSE;
2498 }
2499 //
2500 // Add DefaultValue into current BlockData
2501 //
2502 InsertDefaultValue (BlockData, &DefaultData);
2503
2504 //
2505 // Add default value for Manufacture ID by CheckBox Flag
2506 //
2507 VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2508 //
2509 // Prepare new DefaultValue
2510 //
2511 DefaultData.DefaultId = VarDefaultId;
2512 if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
2513 //
2514 // When flag is set, defautl value is TRUE.
2515 //
2516 DefaultData.Type = DefaultValueFromFlag;
2517 DefaultData.Value.b = TRUE;
2518 } else {
2519 //
2520 // When flag is not set, defautl value is FASLE.
2521 //
2522 DefaultData.Type = DefaultValueFromDefault;
2523 DefaultData.Value.b = FALSE;
2524 }
2525 //
2526 // Add DefaultValue into current BlockData
2527 //
2528 InsertDefaultValue (BlockData, &DefaultData);
2529 break;
2530
2531 case EFI_IFR_DATE_OP:
2532 //
2533 // offset by question header
2534 // width MaxSize * sizeof (CHAR16)
2535 // no default value, only block array
2536 //
2537
2538 //
2539 // Date question is not in IFR Form. This IFR form is not valid.
2540 //
2541 if (VarStoreId == 0) {
2542 Status = EFI_INVALID_PARAMETER;
2543 goto Done;
2544 }
2545 //
2546 // Check whether this question is for the requested varstore.
2547 //
2548 IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
2549 if (IfrDate->Question.VarStoreId != VarStoreId) {
2550 break;
2551 }
2552
2553 //
2554 // The BlockData may allocate by other opcode,need to clean.
2555 //
2556 if (BlockData != NULL){
2557 BlockData = NULL;
2558 }
2559
2560 VarWidth = (UINT16) sizeof (EFI_HII_DATE);
2561 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2562 if (EFI_ERROR (Status)) {
2563 if (Status == EFI_NOT_FOUND){
2564 //
2565 //The opcode is not required,exit and parse other opcode.
2566 //
2567 break;
2568 }
2569 goto Done;
2570 }
2571 break;
2572
2573 case EFI_IFR_TIME_OP:
2574 //
2575 // offset by question header
2576 // width MaxSize * sizeof (CHAR16)
2577 // no default value, only block array
2578 //
2579
2580 //
2581 // Time question is not in IFR Form. This IFR form is not valid.
2582 //
2583 if (VarStoreId == 0) {
2584 Status = EFI_INVALID_PARAMETER;
2585 goto Done;
2586 }
2587 //
2588 // Check whether this question is for the requested varstore.
2589 //
2590 IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
2591 if (IfrTime->Question.VarStoreId != VarStoreId) {
2592 break;
2593 }
2594
2595 //
2596 // The BlockData may allocate by other opcode,need to clean.
2597 //
2598 if (BlockData != NULL){
2599 BlockData = NULL;
2600 }
2601
2602 VarWidth = (UINT16) sizeof (EFI_HII_TIME);
2603 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2604 if (EFI_ERROR (Status)) {
2605 if (Status == EFI_NOT_FOUND){
2606 //
2607 //The opcode is not required,exit and parse other opcode.
2608 //
2609 break;
2610 }
2611 goto Done;
2612 }
2613 break;
2614
2615 case EFI_IFR_STRING_OP:
2616 //
2617 // offset by question header
2618 // width MaxSize * sizeof (CHAR16)
2619 // no default value, only block array
2620 //
2621
2622 //
2623 // String question is not in IFR Form. This IFR form is not valid.
2624 //
2625 if (VarStoreId == 0) {
2626 Status = EFI_INVALID_PARAMETER;
2627 goto Done;
2628 }
2629 //
2630 // Check whether this question is for the requested varstore.
2631 //
2632 IfrString = (EFI_IFR_STRING *) IfrOpHdr;
2633 if (IfrString->Question.VarStoreId != VarStoreId) {
2634 break;
2635 }
2636
2637 //
2638 // The BlockData may allocate by other opcode,need to clean.
2639 //
2640 if (BlockData != NULL){
2641 BlockData = NULL;
2642 }
2643
2644 VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
2645 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2646 if (EFI_ERROR (Status)) {
2647 if (Status == EFI_NOT_FOUND){
2648 //
2649 //The opcode is not required,exit and parse other opcode.
2650 //
2651 break;
2652 }
2653 goto Done;
2654 }
2655 break;
2656
2657 case EFI_IFR_PASSWORD_OP:
2658 //
2659 // offset by question header
2660 // width MaxSize * sizeof (CHAR16)
2661 // no default value, only block array
2662 //
2663
2664 //
2665 // Password question is not in IFR Form. This IFR form is not valid.
2666 //
2667 if (VarStoreId == 0) {
2668 Status = EFI_INVALID_PARAMETER;
2669 goto Done;
2670 }
2671 //
2672 // Check whether this question is for the requested varstore.
2673 //
2674 IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
2675 if (IfrPassword->Question.VarStoreId != VarStoreId) {
2676 break;
2677 }
2678
2679 //
2680 // The BlockData may allocate by other opcode,need to clean.
2681 //
2682 if (BlockData != NULL){
2683 BlockData = NULL;
2684 }
2685
2686 VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
2687 Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
2688 if (EFI_ERROR (Status)) {
2689 if (Status == EFI_NOT_FOUND){
2690 //
2691 //The opcode is not required,exit and parse other opcode.
2692 //
2693 break;
2694 }
2695 goto Done;
2696 }
2697
2698 //
2699 // No default value for string.
2700 //
2701 BlockData = NULL;
2702 break;
2703
2704 case EFI_IFR_ONE_OF_OPTION_OP:
2705 //
2706 // No matched block data is ignored.
2707 //
2708 if (BlockData == NULL || BlockData->Scope == 0) {
2709 break;
2710 }
2711
2712 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
2713 if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
2714
2715 if (!FirstOrderedList){
2716 break;
2717 }
2718 //
2719 // Get ordered list option data type.
2720 //
2721 if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
2722 VarWidth = 1;
2723 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
2724 VarWidth = 2;
2725 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
2726 VarWidth = 4;
2727 } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
2728 VarWidth = 8;
2729 } else {
2730 //
2731 // Invalid ordered list option data type.
2732 //
2733 Status = EFI_INVALID_PARAMETER;
2734 if (BlockData->Name != NULL) {
2735 FreePool (BlockData->Name);
2736 }
2737 FreePool (BlockData);
2738 goto Done;
2739 }
2740
2741 //
2742 // Calculate Ordered list QuestionId width.
2743 //
2744 BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
2745 //
2746 // Check whether this question is in requested block array.
2747 //
2748 if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
2749 //
2750 // This question is not in the requested string. Skip it.
2751 //
2752 if (BlockData->Name != NULL) {
2753 FreePool (BlockData->Name);
2754 }
2755 FreePool (BlockData);
2756 BlockData = NULL;
2757 break;
2758 }
2759 //
2760 // Check this var question is in the var storage
2761 //
2762 if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
2763 Status = EFI_INVALID_PARAMETER;
2764 if (BlockData->Name != NULL) {
2765 FreePool (BlockData->Name);
2766 }
2767 FreePool (BlockData);
2768 goto Done;
2769 }
2770 //
2771 // Add Block Data into VarStorageData BlockEntry
2772 //
2773 InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
2774
2775 FirstOrderedList = FALSE;
2776
2777 break;
2778 }
2779
2780 //
2781 // 1. Set default value for OneOf option when flag field has default attribute.
2782 //
2783 if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
2784 ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
2785 //
2786 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2787 // The first oneof option value will be used as default value when no default value is specified.
2788 //
2789 FirstOneOfOption = FALSE;
2790
2791 // Prepare new DefaultValue
2792 //
2793 DefaultData.Type = DefaultValueFromFlag;
2794 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2795 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
2796 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2797 InsertDefaultValue (BlockData, &DefaultData);
2798 }
2799 if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
2800 DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2801 InsertDefaultValue (BlockData, &DefaultData);
2802 }
2803 }
2804
2805 //
2806 // 2. Set as the default value when this is the first option.
2807 // The first oneof option value will be used as default value when no default value is specified.
2808 //
2809 if (FirstOneOfOption) {
2810 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2811 FirstOneOfOption = FALSE;
2812
2813 //
2814 // Prepare new DefaultValue
2815 //
2816 DefaultData.Type = DefaultValueFromDefault;
2817 CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2818 for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
2819 DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
2820 DefaultData.DefaultId = DefaultDataPtr->DefaultId;
2821 InsertDefaultValue (BlockData, &DefaultData);
2822 }
2823 }
2824 break;
2825
2826 case EFI_IFR_DEFAULT_OP:
2827 //
2828 // Update Current BlockData to the default value.
2829 //
2830 if (BlockData == NULL || BlockData->Scope == 0) {
2831 //
2832 // No matched block data is ignored.
2833 //
2834 break;
2835 }
2836
2837 //
2838 // Get the DefaultId
2839 //
2840 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
2841 VarDefaultId = IfrDefault->DefaultId;
2842 //
2843 // Prepare new DefaultValue
2844 //
2845 DefaultData.Type = DefaultValueFromOpcode;
2846 DefaultData.DefaultId = VarDefaultId;
2847 CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2848
2849 // If the value field is expression, set the cleaned flag.
2850 if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
2851 DefaultData.Cleaned = TRUE;
2852 }
2853 //
2854 // Add DefaultValue into current BlockData
2855 //
2856 InsertDefaultValue (BlockData, &DefaultData);
2857
2858 //
2859 // After insert the default value, reset the cleaned value for next
2860 // time used. If not set here, need to set the value before everytime
2861 // use it.
2862 //
2863 DefaultData.Cleaned = FALSE;
2864 break;
2865
2866 case EFI_IFR_END_OP:
2867 //
2868 // End Opcode is for Var question.
2869 //
2870 if (BlockData != NULL) {
2871 if (BlockData->Scope > 0) {
2872 BlockData->Scope--;
2873 }
2874 if (BlockData->Scope == 0) {
2875 BlockData = NULL;
2876 }
2877 }
2878
2879 break;
2880
2881 default:
2882 if (BlockData != NULL) {
2883 if (BlockData->Scope > 0) {
2884 BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
2885 }
2886
2887 if (BlockData->Scope == 0) {
2888 BlockData = NULL;
2889 }
2890 }
2891 break;
2892 }
2893
2894 IfrOffset += IfrOpHdr->Length;
2895 PackageOffset += IfrOpHdr->Length;
2896 }
2897
2898 //
2899 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2900 //so set the Status to EFI_SUCCESS.
2901 //
2902 if (Status == EFI_NOT_FOUND){
2903 Status = EFI_SUCCESS;
2904 }
2905
2906 Done:
2907 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
2908 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
2909 for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
2910 DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
2911 LinkDefault = LinkDefault->ForwardLink;
2912 if (DefaultDataPtr->Cleaned == TRUE) {
2913 RemoveEntryList (&DefaultDataPtr->Entry);
2914 FreePool (DefaultDataPtr);
2915 }
2916 }
2917 }
2918
2919 return Status;
2920 }
2921
2922 /**
2923 parse the configrequest string, get the elements.
2924
2925 @param ConfigRequest The input configrequest string.
2926 @param Progress Return the progress data.
2927
2928 @retval Block data pointer.
2929 **/
2930 IFR_BLOCK_DATA *
2931 GetBlockElement (
2932 IN EFI_STRING ConfigRequest,
2933 OUT EFI_STRING *Progress
2934 )
2935 {
2936 EFI_STRING StringPtr;
2937 IFR_BLOCK_DATA *BlockData;
2938 IFR_BLOCK_DATA *RequestBlockArray;
2939 EFI_STATUS Status;
2940 UINT8 *TmpBuffer;
2941 UINT16 Offset;
2942 UINT16 Width;
2943 LIST_ENTRY *Link;
2944 IFR_BLOCK_DATA *NextBlockData;
2945 UINTN Length;
2946
2947 TmpBuffer = NULL;
2948
2949 //
2950 // Init RequestBlockArray
2951 //
2952 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
2953 if (RequestBlockArray == NULL) {
2954 goto Done;
2955 }
2956 InitializeListHead (&RequestBlockArray->Entry);
2957
2958 //
2959 // Get the request Block array from the request string
2960 // Offset and Width
2961 //
2962
2963 //
2964 // Parse each <RequestElement> if exists
2965 // Only <BlockName> format is supported by this help function.
2966 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2967 //
2968 StringPtr = ConfigRequest;
2969 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
2970 //
2971 // Skip the OFFSET string
2972 //
2973 *Progress = StringPtr;
2974 StringPtr += StrLen (L"&OFFSET=");
2975 //
2976 // Get Offset
2977 //
2978 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
2979 if (EFI_ERROR (Status)) {
2980 goto Done;
2981 }
2982 Offset = 0;
2983 CopyMem (
2984 &Offset,
2985 TmpBuffer,
2986 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
2987 );
2988 FreePool (TmpBuffer);
2989
2990 StringPtr += Length;
2991 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
2992 goto Done;
2993 }
2994 StringPtr += StrLen (L"&WIDTH=");
2995
2996 //
2997 // Get Width
2998 //
2999 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3000 if (EFI_ERROR (Status)) {
3001 goto Done;
3002 }
3003 Width = 0;
3004 CopyMem (
3005 &Width,
3006 TmpBuffer,
3007 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
3008 );
3009 FreePool (TmpBuffer);
3010
3011 StringPtr += Length;
3012 if (*StringPtr != 0 && *StringPtr != L'&') {
3013 goto Done;
3014 }
3015
3016 //
3017 // Set Block Data
3018 //
3019 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3020 if (BlockData == NULL) {
3021 goto Done;
3022 }
3023 BlockData->Offset = Offset;
3024 BlockData->Width = Width;
3025 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3026
3027 //
3028 // Skip &VALUE string if &VALUE does exists.
3029 //
3030 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
3031 StringPtr += StrLen (L"&VALUE=");
3032
3033 //
3034 // Get Value
3035 //
3036 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
3037 if (EFI_ERROR (Status)) {
3038 goto Done;
3039 }
3040 FreePool (TmpBuffer);
3041 StringPtr += Length;
3042 if (*StringPtr != 0 && *StringPtr != L'&') {
3043 goto Done;
3044 }
3045 }
3046 //
3047 // If '\0', parsing is finished.
3048 //
3049 if (*StringPtr == 0) {
3050 break;
3051 }
3052 }
3053
3054 //
3055 // Merge the requested block data.
3056 //
3057 Link = RequestBlockArray->Entry.ForwardLink;
3058 while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
3059 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3060 NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
3061 if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
3062 if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
3063 BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
3064 }
3065 RemoveEntryList (Link->ForwardLink);
3066 FreePool (NextBlockData);
3067 continue;
3068 }
3069 Link = Link->ForwardLink;
3070 }
3071
3072 return RequestBlockArray;
3073
3074 Done:
3075 if (RequestBlockArray != NULL) {
3076 //
3077 // Free Link Array RequestBlockArray
3078 //
3079 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3080 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3081 RemoveEntryList (&BlockData->Entry);
3082 FreePool (BlockData);
3083 }
3084
3085 FreePool (RequestBlockArray);
3086 }
3087
3088 return NULL;
3089 }
3090
3091 /**
3092 parse the configrequest string, get the elements.
3093
3094 @param ConfigRequest The input config request string.
3095 @param Progress Return the progress data.
3096
3097 @retval return data block array.
3098 **/
3099 IFR_BLOCK_DATA *
3100 GetNameElement (
3101 IN EFI_STRING ConfigRequest,
3102 OUT EFI_STRING *Progress
3103 )
3104 {
3105 EFI_STRING StringPtr;
3106 EFI_STRING NextTag;
3107 IFR_BLOCK_DATA *BlockData;
3108 IFR_BLOCK_DATA *RequestBlockArray;
3109 BOOLEAN HasValue;
3110
3111 StringPtr = ConfigRequest;
3112
3113 //
3114 // Init RequestBlockArray
3115 //
3116 RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3117 if (RequestBlockArray == NULL) {
3118 goto Done;
3119 }
3120 InitializeListHead (&RequestBlockArray->Entry);
3121
3122 //
3123 // Get the request Block array from the request string
3124 //
3125
3126 //
3127 // Parse each <RequestElement> if exists
3128 // Only <BlockName> format is supported by this help function.
3129 // <BlockName> ::= &'Name***=***
3130 //
3131 while (StringPtr != NULL && *StringPtr == L'&') {
3132
3133 *Progress = StringPtr;
3134 //
3135 // Skip the L"&" string
3136 //
3137 StringPtr += 1;
3138
3139 HasValue = FALSE;
3140 if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
3141 *NextTag = L'\0';
3142 HasValue = TRUE;
3143 } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
3144 *NextTag = L'\0';
3145 }
3146
3147 //
3148 // Set Block Data
3149 //
3150 BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
3151 if (BlockData == NULL) {
3152 goto Done;
3153 }
3154
3155 //
3156 // Get Name
3157 //
3158 BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
3159 InsertBlockData (&RequestBlockArray->Entry, &BlockData);
3160
3161 if (HasValue) {
3162 //
3163 // If has value, skip the value.
3164 //
3165 StringPtr = NextTag + 1;
3166 *NextTag = L'=';
3167 StringPtr = StrStr (StringPtr, L"&");
3168 } else if (NextTag != NULL) {
3169 //
3170 // restore the '&' text.
3171 //
3172 StringPtr = NextTag;
3173 *NextTag = L'&';
3174 }
3175 }
3176
3177 return RequestBlockArray;
3178
3179 Done:
3180 if (RequestBlockArray != NULL) {
3181 //
3182 // Free Link Array RequestBlockArray
3183 //
3184 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3185 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3186 RemoveEntryList (&BlockData->Entry);
3187 if (BlockData->Name != NULL) {
3188 FreePool (BlockData->Name);
3189 }
3190 FreePool (BlockData);
3191 }
3192
3193 FreePool (RequestBlockArray);
3194 }
3195
3196 return NULL;
3197 }
3198
3199 /**
3200 Generate ConfigRequest string base on the varstore info.
3201
3202 @param ConfigHdr The config header for this varstore.
3203 @param VarStorageData The varstore info.
3204 @param Status Return Status.
3205 @param ConfigRequest The ConfigRequest info may be return.
3206
3207 @retval TRUE Need to continue
3208 @retval Others NO need to continue or error occur.
3209 **/
3210 BOOLEAN
3211 GenerateConfigRequest (
3212 IN CHAR16 *ConfigHdr,
3213 IN IFR_VARSTORAGE_DATA *VarStorageData,
3214 OUT EFI_STATUS *Status,
3215 IN OUT EFI_STRING *ConfigRequest
3216 )
3217 {
3218 BOOLEAN DataExist;
3219 UINTN Length;
3220 LIST_ENTRY *Link;
3221 CHAR16 *FullConfigRequest;
3222 CHAR16 *StringPtr;
3223 IFR_BLOCK_DATA *BlockData;
3224
3225 //
3226 // Append VarStorageData BlockEntry into *Request string
3227 // Now support only one varstore in a form package.
3228 //
3229
3230 //
3231 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3232 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3233 //
3234
3235 //
3236 // Compute the length of the entire request starting with <ConfigHdr> and a
3237 // Null-terminator
3238 //
3239 DataExist = FALSE;
3240 Length = StrLen (ConfigHdr) + 1;
3241
3242 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3243 DataExist = TRUE;
3244 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3245 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3246 //
3247 // Add <BlockName> length for each Name
3248 //
3249 // <BlockName> ::= &Name1&Name2&...
3250 // |1| StrLen(Name1)
3251 //
3252 Length = Length + (1 + StrLen (BlockData->Name));
3253 } else {
3254 //
3255 // Add <BlockName> length for each Offset/Width pair
3256 //
3257 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3258 // | 8 | 4 | 7 | 4 |
3259 //
3260 Length = Length + (8 + 4 + 7 + 4);
3261 }
3262 }
3263 //
3264 // No any request block data is found. The request string can't be constructed.
3265 //
3266 if (!DataExist) {
3267 *Status = EFI_SUCCESS;
3268 return FALSE;
3269 }
3270
3271 //
3272 // Allocate buffer for the entire <ConfigRequest>
3273 //
3274 FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
3275 if (FullConfigRequest == NULL) {
3276 *Status = EFI_OUT_OF_RESOURCES;
3277 return FALSE;
3278 }
3279 StringPtr = FullConfigRequest;
3280
3281 //
3282 // Start with <ConfigHdr>
3283 //
3284 StrCpyS (StringPtr, Length, ConfigHdr);
3285 StringPtr += StrLen (StringPtr);
3286
3287 //
3288 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3289 //
3290 for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
3291 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
3292 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3293 //
3294 // Append &Name1\0
3295 //
3296 UnicodeSPrint (
3297 StringPtr,
3298 (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
3299 L"&%s",
3300 BlockData->Name
3301 );
3302 } else {
3303 //
3304 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3305 //
3306 UnicodeSPrint (
3307 StringPtr,
3308 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
3309 L"&OFFSET=%04X&WIDTH=%04X",
3310 BlockData->Offset,
3311 BlockData->Width
3312 );
3313 }
3314 StringPtr += StrLen (StringPtr);
3315 }
3316 //
3317 // Set to the got full request string.
3318 //
3319 HiiToLower (FullConfigRequest);
3320
3321 if (*ConfigRequest != NULL) {
3322 FreePool (*ConfigRequest);
3323 }
3324 *ConfigRequest = FullConfigRequest;
3325
3326 return TRUE;
3327 }
3328
3329 /**
3330 Generate ConfigRequest Header base on the varstore info.
3331
3332 @param VarStorageData The varstore info.
3333 @param DevicePath Device path for this varstore.
3334 @param ConfigHdr The config header for this varstore.
3335
3336 @retval EFI_SUCCESS Generate the header success.
3337 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3338 **/
3339 EFI_STATUS
3340 GenerateHdr (
3341 IN IFR_VARSTORAGE_DATA *VarStorageData,
3342 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3343 OUT EFI_STRING *ConfigHdr
3344 )
3345 {
3346 EFI_STRING GuidStr;
3347 EFI_STRING NameStr;
3348 EFI_STRING PathStr;
3349 UINTN Length;
3350 EFI_STATUS Status;
3351
3352 Status = EFI_SUCCESS;
3353 NameStr = NULL;
3354 GuidStr = NULL;
3355 PathStr = NULL;
3356
3357 //
3358 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3359 //
3360 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
3361 if (VarStorageData->Name != NULL) {
3362 GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
3363 } else {
3364 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
3365 }
3366 GenerateSubStr (
3367 L"PATH=",
3368 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
3369 (VOID *) DevicePath,
3370 1,
3371 &PathStr
3372 );
3373 Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
3374 if (VarStorageData->Name == NULL) {
3375 Length += 1;
3376 }
3377
3378 *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
3379 if (*ConfigHdr == NULL) {
3380 Status = EFI_OUT_OF_RESOURCES;
3381 goto Done;
3382 }
3383 StrCpyS (*ConfigHdr, Length, GuidStr);
3384 StrCatS (*ConfigHdr, Length, NameStr);
3385 if (VarStorageData->Name == NULL) {
3386 StrCatS (*ConfigHdr, Length, L"&");
3387 }
3388 StrCatS (*ConfigHdr, Length, PathStr);
3389
3390 //
3391 // Remove the last character L'&'
3392 //
3393 *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
3394
3395 Done:
3396 if (GuidStr != NULL) {
3397 FreePool (GuidStr);
3398 }
3399
3400 if (NameStr != NULL) {
3401 FreePool (NameStr);
3402 }
3403
3404 if (PathStr != NULL) {
3405 FreePool (PathStr);
3406 }
3407
3408 return Status;
3409 }
3410
3411 /**
3412 Get Data buffer size based on data type.
3413
3414 @param ValueType The input data type.
3415
3416 @retval The data buffer size for the input type.
3417 **/
3418 UINT16
3419 GetStorageWidth (
3420 IN UINT8 ValueType
3421 )
3422 {
3423 UINT16 StorageWidth;
3424
3425 switch (ValueType) {
3426 case EFI_IFR_NUMERIC_SIZE_1:
3427 case EFI_IFR_TYPE_BOOLEAN:
3428 StorageWidth = (UINT16) sizeof (UINT8);
3429 break;
3430
3431 case EFI_IFR_NUMERIC_SIZE_2:
3432 StorageWidth = (UINT16) sizeof (UINT16);
3433 break;
3434
3435 case EFI_IFR_NUMERIC_SIZE_4:
3436 StorageWidth = (UINT16) sizeof (UINT32);
3437 break;
3438
3439 case EFI_IFR_NUMERIC_SIZE_8:
3440 StorageWidth = (UINT16) sizeof (UINT64);
3441 break;
3442
3443 case EFI_IFR_TYPE_TIME:
3444 StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
3445 break;
3446
3447 case EFI_IFR_TYPE_DATE:
3448 StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
3449 break;
3450
3451 default:
3452 StorageWidth = 0;
3453 break;
3454 }
3455
3456 return StorageWidth;
3457 }
3458
3459 /**
3460 Generate ConfigAltResp string base on the varstore info.
3461
3462 @param HiiHandle Hii Handle for this hii package.
3463 @param ConfigHdr The config header for this varstore.
3464 @param VarStorageData The varstore info.
3465 @param DefaultIdArray The Default id array.
3466 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3467
3468 @retval TRUE Need to continue
3469 @retval Others NO need to continue or error occur.
3470 **/
3471 EFI_STATUS
3472 GenerateAltConfigResp (
3473 IN EFI_HII_HANDLE HiiHandle,
3474 IN CHAR16 *ConfigHdr,
3475 IN IFR_VARSTORAGE_DATA *VarStorageData,
3476 IN IFR_DEFAULT_DATA *DefaultIdArray,
3477 IN OUT EFI_STRING *DefaultAltCfgResp
3478 )
3479 {
3480 BOOLEAN DataExist;
3481 UINTN Length;
3482 LIST_ENTRY *Link;
3483 LIST_ENTRY *LinkData;
3484 LIST_ENTRY *LinkDefault;
3485 LIST_ENTRY *ListEntry;
3486 CHAR16 *StringPtr;
3487 IFR_BLOCK_DATA *BlockData;
3488 IFR_DEFAULT_DATA *DefaultId;
3489 IFR_DEFAULT_DATA *DefaultValueData;
3490 UINTN Width;
3491 UINT8 *TmpBuffer;
3492 CHAR16 *DefaultString;
3493
3494 BlockData = NULL;
3495 DataExist = FALSE;
3496 DefaultString = NULL;
3497 //
3498 // Add length for <ConfigHdr> + '\0'
3499 //
3500 Length = StrLen (ConfigHdr) + 1;
3501
3502 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3503 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3504 //
3505 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3506 // |1| StrLen (ConfigHdr) | 8 | 4 |
3507 //
3508 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
3509
3510 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3511 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3512 ListEntry = &BlockData->DefaultValueEntry;
3513 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3514 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3515 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3516 continue;
3517 }
3518 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3519 //
3520 // Add length for "&Name1=zzzzzzzzzzzz"
3521 // |1|Name|1|Value|
3522 //
3523 Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
3524 } else {
3525 //
3526 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3527 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3528 //
3529 Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
3530 }
3531 DataExist = TRUE;
3532 }
3533 }
3534 }
3535
3536 //
3537 // No default value is found. The default string doesn't exist.
3538 //
3539 if (!DataExist) {
3540 return EFI_SUCCESS;
3541 }
3542
3543 //
3544 // Allocate buffer for the entire <DefaultAltCfgResp>
3545 //
3546 *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
3547 if (*DefaultAltCfgResp == NULL) {
3548 return EFI_OUT_OF_RESOURCES;
3549 }
3550 StringPtr = *DefaultAltCfgResp;
3551
3552 //
3553 // Start with <ConfigHdr>
3554 //
3555 StrCpyS (StringPtr, Length, ConfigHdr);
3556 StringPtr += StrLen (StringPtr);
3557
3558 for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
3559 DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
3560 //
3561 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3562 // |1| StrLen (ConfigHdr) | 8 | 4 |
3563 //
3564 UnicodeSPrint (
3565 StringPtr,
3566 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
3567 L"&%s&ALTCFG=%04X",
3568 ConfigHdr,
3569 DefaultId->DefaultId
3570 );
3571 StringPtr += StrLen (StringPtr);
3572
3573 for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
3574 BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
3575 ListEntry = &BlockData->DefaultValueEntry;
3576 for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
3577 DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
3578 if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
3579 continue;
3580 }
3581 if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
3582 UnicodeSPrint (
3583 StringPtr,
3584 (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
3585 L"&%s=",
3586 BlockData->Name
3587 );
3588 StringPtr += StrLen (StringPtr);
3589 } else {
3590 //
3591 // Add <BlockConfig>
3592 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3593 //
3594 UnicodeSPrint (
3595 StringPtr,
3596 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
3597 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3598 BlockData->Offset,
3599 BlockData->Width
3600 );
3601 StringPtr += StrLen (StringPtr);
3602 }
3603 Width = BlockData->Width;
3604 //
3605 // Convert Value to a hex string in "%x" format
3606 // NOTE: This is in the opposite byte that GUID and PATH use
3607 //
3608 if (BlockData->OpCode == EFI_IFR_STRING_OP){
3609 DefaultString = InternalGetString(HiiHandle, DefaultValueData->Value.string);
3610 TmpBuffer = (UINT8 *) DefaultString;
3611 } else {
3612 TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
3613 }
3614 for (; Width > 0 && (TmpBuffer != NULL); Width--) {
3615 StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
3616 }
3617 if (DefaultString != NULL){
3618 FreePool(DefaultString);
3619 DefaultString = NULL;
3620 }
3621 }
3622 }
3623 }
3624
3625 HiiToLower (*DefaultAltCfgResp);
3626
3627 return EFI_SUCCESS;
3628 }
3629
3630 /**
3631 This function gets the full request string and full default value string by
3632 parsing IFR data in HII form packages.
3633
3634 When Request points to NULL string, the request string and default value string
3635 for each varstore in form package will return.
3636
3637 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3638 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3639 @param Request Pointer to a null-terminated Unicode string in
3640 <ConfigRequest> format. When it doesn't contain
3641 any RequestElement, it will be updated to return
3642 the full RequestElement retrieved from IFR data.
3643 If it points to NULL, the request string for the first
3644 varstore in form package will be merged into a
3645 <MultiConfigRequest> format string and return.
3646 @param AltCfgResp Pointer to a null-terminated Unicode string in
3647 <ConfigAltResp> format. When the pointer is to NULL,
3648 the full default value string retrieved from IFR data
3649 will return. When the pinter is to a string, the
3650 full default value string retrieved from IFR data
3651 will be merged into the input string and return.
3652 When Request points to NULL, the default value string
3653 for each varstore in form package will be merged into
3654 a <MultiConfigAltResp> format string and return.
3655 @param PointerProgress Optional parameter, it can be be NULL.
3656 When it is not NULL, if Request is NULL, it returns NULL.
3657 On return, points to a character in the Request
3658 string. Points to the string's null terminator if
3659 request was successful. Points to the most recent
3660 & before the first failing name / value pair (or
3661 the beginning of the string if the failure is in
3662 the first name / value pair) if the request was
3663 not successful.
3664 @retval EFI_SUCCESS The Results string is set to the full request string.
3665 And AltCfgResp contains all default value string.
3666 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3667 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3668 can't be found in Form package.
3669 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3670 @retval EFI_INVALID_PARAMETER Request points to NULL.
3671
3672 **/
3673 EFI_STATUS
3674 EFIAPI
3675 GetFullStringFromHiiFormPackages (
3676 IN HII_DATABASE_RECORD *DataBaseRecord,
3677 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3678 IN OUT EFI_STRING *Request,
3679 IN OUT EFI_STRING *AltCfgResp,
3680 OUT EFI_STRING *PointerProgress OPTIONAL
3681 )
3682 {
3683 EFI_STATUS Status;
3684 UINT8 *HiiFormPackage;
3685 UINTN PackageSize;
3686 IFR_BLOCK_DATA *RequestBlockArray;
3687 IFR_BLOCK_DATA *BlockData;
3688 IFR_DEFAULT_DATA *DefaultValueData;
3689 IFR_DEFAULT_DATA *DefaultId;
3690 IFR_DEFAULT_DATA *DefaultIdArray;
3691 IFR_VARSTORAGE_DATA *VarStorageData;
3692 EFI_STRING DefaultAltCfgResp;
3693 EFI_STRING ConfigHdr;
3694 EFI_STRING StringPtr;
3695 EFI_STRING Progress;
3696
3697 if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
3698 return EFI_INVALID_PARAMETER;
3699 }
3700
3701 //
3702 // Initialize the local variables.
3703 //
3704 RequestBlockArray = NULL;
3705 DefaultIdArray = NULL;
3706 VarStorageData = NULL;
3707 DefaultAltCfgResp = NULL;
3708 ConfigHdr = NULL;
3709 HiiFormPackage = NULL;
3710 PackageSize = 0;
3711 Progress = *Request;
3712
3713 Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
3714 if (EFI_ERROR (Status)) {
3715 goto Done;
3716 }
3717
3718 //
3719 // 1. Get the request block array by Request String when Request string containts the block array.
3720 //
3721 StringPtr = NULL;
3722 if (*Request != NULL) {
3723 StringPtr = *Request;
3724 //
3725 // Jump <ConfigHdr>
3726 //
3727 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
3728 Status = EFI_INVALID_PARAMETER;
3729 goto Done;
3730 }
3731 StringPtr += StrLen (L"GUID=");
3732 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
3733 StringPtr++;
3734 }
3735 if (*StringPtr == L'\0') {
3736 Status = EFI_INVALID_PARAMETER;
3737 goto Done;
3738 }
3739 StringPtr += StrLen (L"&NAME=");
3740 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
3741 StringPtr++;
3742 }
3743 if (*StringPtr == L'\0') {
3744 Status = EFI_INVALID_PARAMETER;
3745 goto Done;
3746 }
3747 StringPtr += StrLen (L"&PATH=");
3748 while (*StringPtr != L'\0' && *StringPtr != L'&') {
3749 StringPtr ++;
3750 }
3751
3752 if (*StringPtr == L'\0') {
3753 //
3754 // No request block is found.
3755 //
3756 StringPtr = NULL;
3757 }
3758 }
3759
3760 //
3761 // If StringPtr != NULL, get the request elements.
3762 //
3763 if (StringPtr != NULL) {
3764 if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
3765 RequestBlockArray = GetBlockElement(StringPtr, &Progress);
3766 } else {
3767 RequestBlockArray = GetNameElement(StringPtr, &Progress);
3768 }
3769
3770 if (RequestBlockArray == NULL) {
3771 Status = EFI_INVALID_PARAMETER;
3772 goto Done;
3773 }
3774 }
3775
3776 //
3777 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3778 //
3779 DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
3780 if (DefaultIdArray == NULL) {
3781 Status = EFI_OUT_OF_RESOURCES;
3782 goto Done;
3783 }
3784 InitializeListHead (&DefaultIdArray->Entry);
3785
3786 //
3787 // Initialize VarStorageData to store the var store Block and Default value information.
3788 //
3789 VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
3790 if (VarStorageData == NULL) {
3791 Status = EFI_OUT_OF_RESOURCES;
3792 goto Done;
3793 }
3794 InitializeListHead (&VarStorageData->Entry);
3795 InitializeListHead (&VarStorageData->BlockEntry);
3796
3797 //
3798 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3799 //
3800
3801 //
3802 // Parse the opcode in form pacakge to get the default setting.
3803 //
3804 Status = ParseIfrData (DataBaseRecord->Handle,
3805 HiiFormPackage,
3806 (UINT32) PackageSize,
3807 *Request,
3808 RequestBlockArray,
3809 VarStorageData,
3810 DefaultIdArray);
3811 if (EFI_ERROR (Status)) {
3812 goto Done;
3813 }
3814
3815 //
3816 // No requested varstore in IFR data and directly return
3817 //
3818 if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
3819 Status = EFI_SUCCESS;
3820 goto Done;
3821 }
3822
3823 //
3824 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3825 //
3826 Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
3827 if (EFI_ERROR (Status)) {
3828 goto Done;
3829 }
3830
3831 if (RequestBlockArray == NULL) {
3832 if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
3833 goto Done;
3834 }
3835 }
3836
3837 //
3838 // 4. Construct Default Value string in AltResp according to request element.
3839 // Go through all VarStorageData Entry and get the DefaultId array for each one
3840 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3841 //
3842 Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
3843 if (EFI_ERROR (Status)) {
3844 goto Done;
3845 }
3846
3847 //
3848 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3849 //
3850 if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
3851 Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
3852 FreePool (DefaultAltCfgResp);
3853 } else if (*AltCfgResp == NULL) {
3854 *AltCfgResp = DefaultAltCfgResp;
3855 }
3856
3857 Done:
3858 if (RequestBlockArray != NULL) {
3859 //
3860 // Free Link Array RequestBlockArray
3861 //
3862 while (!IsListEmpty (&RequestBlockArray->Entry)) {
3863 BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
3864 RemoveEntryList (&BlockData->Entry);
3865 if (BlockData->Name != NULL) {
3866 FreePool (BlockData->Name);
3867 }
3868 FreePool (BlockData);
3869 }
3870
3871 FreePool (RequestBlockArray);
3872 }
3873
3874 if (VarStorageData != NULL) {
3875 //
3876 // Free link array VarStorageData
3877 //
3878 while (!IsListEmpty (&VarStorageData->BlockEntry)) {
3879 BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
3880 RemoveEntryList (&BlockData->Entry);
3881 if (BlockData->Name != NULL) {
3882 FreePool (BlockData->Name);
3883 }
3884 //
3885 // Free default value link array
3886 //
3887 while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
3888 DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3889 RemoveEntryList (&DefaultValueData->Entry);
3890 FreePool (DefaultValueData);
3891 }
3892 FreePool (BlockData);
3893 }
3894 if (VarStorageData ->Name != NULL) {
3895 FreePool (VarStorageData ->Name);
3896 VarStorageData ->Name = NULL;
3897 }
3898 FreePool (VarStorageData);
3899 }
3900
3901 if (DefaultIdArray != NULL) {
3902 //
3903 // Free DefaultId Array
3904 //
3905 while (!IsListEmpty (&DefaultIdArray->Entry)) {
3906 DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
3907 RemoveEntryList (&DefaultId->Entry);
3908 FreePool (DefaultId);
3909 }
3910 FreePool (DefaultIdArray);
3911 }
3912
3913 //
3914 // Free the allocated string
3915 //
3916 if (ConfigHdr != NULL) {
3917 FreePool (ConfigHdr);
3918 }
3919
3920 //
3921 // Free Pacakge data
3922 //
3923 if (HiiFormPackage != NULL) {
3924 FreePool (HiiFormPackage);
3925 }
3926
3927 if (PointerProgress != NULL) {
3928 if (*Request == NULL) {
3929 *PointerProgress = NULL;
3930 } else if (EFI_ERROR (Status)) {
3931 *PointerProgress = *Request;
3932 } else {
3933 *PointerProgress = *Request + StrLen (*Request);
3934 }
3935 }
3936
3937 return Status;
3938 }
3939
3940 /**
3941 This function gets the full request resp string by
3942 parsing IFR data in HII form packages.
3943
3944 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3945 instance.
3946 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3947 varstore data structure.
3948 @param Request Pointer to a null-terminated Unicode string in
3949 <ConfigRequest> format.
3950 @param RequestResp Pointer to a null-terminated Unicode string in
3951 <ConfigResp> format.
3952 @param AccessProgress On return, points to a character in the Request
3953 string. Points to the string's null terminator if
3954 request was successful. Points to the most recent
3955 & before the first failing name / value pair (or
3956 the beginning of the string if the failure is in
3957 the first name / value pair) if the request was
3958 not successful.
3959
3960 @retval EFI_SUCCESS The Results string is set to the full request string.
3961 And AltCfgResp contains all default value string.
3962 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3963 @retval EFI_INVALID_PARAMETER Request points to NULL.
3964
3965 **/
3966 EFI_STATUS
3967 GetConfigRespFromEfiVarStore (
3968 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
3969 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
3970 IN EFI_STRING Request,
3971 OUT EFI_STRING *RequestResp,
3972 OUT EFI_STRING *AccessProgress
3973 )
3974 {
3975 EFI_STATUS Status;
3976 EFI_STRING VarStoreName;
3977 UINTN NameSize;
3978 UINT8 *VarStore;
3979 UINTN BufferSize;
3980
3981 Status = EFI_SUCCESS;
3982 BufferSize = 0;
3983 VarStore = NULL;
3984 VarStoreName = NULL;
3985 *AccessProgress = Request;
3986
3987 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
3988 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
3989 if (VarStoreName == NULL) {
3990 Status = EFI_OUT_OF_RESOURCES;
3991 goto Done;
3992 }
3993 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
3994
3995
3996 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
3997 if (Status != EFI_BUFFER_TOO_SMALL) {
3998 goto Done;
3999 }
4000
4001 VarStore = AllocateZeroPool (BufferSize);
4002 ASSERT (VarStore != NULL);
4003 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4004 if (EFI_ERROR (Status)) {
4005 goto Done;
4006 }
4007
4008 Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
4009 if (EFI_ERROR (Status)) {
4010 goto Done;
4011 }
4012
4013 Done:
4014 if (VarStoreName != NULL) {
4015 FreePool (VarStoreName);
4016 }
4017
4018 if (VarStore != NULL) {
4019 FreePool (VarStore);
4020 }
4021
4022 return Status;
4023 }
4024
4025
4026 /**
4027 This function route the full request resp string for efi varstore.
4028
4029 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4030 instance.
4031 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4032 varstore data structure.
4033 @param RequestResp Pointer to a null-terminated Unicode string in
4034 <ConfigResp> format.
4035 @param Result Pointer to a null-terminated Unicode string in
4036 <ConfigResp> format.
4037
4038 @retval EFI_SUCCESS The Results string is set to the full request string.
4039 And AltCfgResp contains all default value string.
4040 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4041 @retval EFI_INVALID_PARAMETER Request points to NULL.
4042
4043 **/
4044 EFI_STATUS
4045 RouteConfigRespForEfiVarStore (
4046 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4047 IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,
4048 IN EFI_STRING RequestResp,
4049 OUT EFI_STRING *Result
4050 )
4051 {
4052 EFI_STATUS Status;
4053 EFI_STRING VarStoreName;
4054 UINTN NameSize;
4055 UINT8 *VarStore;
4056 UINTN BufferSize;
4057 UINTN BlockSize;
4058
4059 Status = EFI_SUCCESS;
4060 BufferSize = 0;
4061 VarStore = NULL;
4062 VarStoreName = NULL;
4063 *Result = RequestResp;
4064
4065 NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
4066 VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
4067 if (VarStoreName == NULL) {
4068 Status = EFI_OUT_OF_RESOURCES;
4069 goto Done;
4070 }
4071 AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
4072
4073 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
4074 if (Status != EFI_BUFFER_TOO_SMALL) {
4075 DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
4076 goto Done;
4077 }
4078
4079 BlockSize = BufferSize;
4080 VarStore = AllocateZeroPool (BufferSize);
4081 ASSERT (VarStore != NULL);
4082 Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
4083 if (EFI_ERROR (Status)) {
4084 goto Done;
4085 }
4086
4087 Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
4088 if (EFI_ERROR (Status)) {
4089 goto Done;
4090 }
4091
4092 Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
4093 if (EFI_ERROR (Status)) {
4094 *Result = RequestResp;
4095 goto Done;
4096 }
4097
4098 Done:
4099 if (VarStoreName != NULL) {
4100 FreePool (VarStoreName);
4101 }
4102
4103 if (VarStore != NULL) {
4104 FreePool (VarStore);
4105 }
4106
4107 return Status;
4108 }
4109
4110 /**
4111 Validate the config request elements.
4112
4113 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4114 without configHdr field.
4115
4116 @retval CHAR16 * THE first Name/value pair not correct.
4117 @retval NULL Success parse the name/value pair
4118 **/
4119 CHAR16 *
4120 OffsetWidthValidate (
4121 CHAR16 *ConfigElements
4122 )
4123 {
4124 CHAR16 *StringPtr;
4125 CHAR16 *RetVal;
4126
4127 StringPtr = ConfigElements;
4128
4129 while (1) {
4130 RetVal = StringPtr;
4131 if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4132 return RetVal;
4133 }
4134
4135 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
4136 StringPtr++;
4137 }
4138 if (*StringPtr == L'\0') {
4139 return RetVal;
4140 }
4141
4142 StringPtr += StrLen (L"&WIDTH=");
4143 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
4144 StringPtr ++;
4145 }
4146
4147 if (*StringPtr == L'\0') {
4148 return NULL;
4149 }
4150 }
4151 }
4152
4153 /**
4154 Validate the config request elements.
4155
4156 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4157 without configHdr field.
4158
4159 @retval CHAR16 * THE first Name/value pair not correct.
4160 @retval NULL Success parse the name/value pair
4161
4162 **/
4163 CHAR16 *
4164 NameValueValidate (
4165 CHAR16 *ConfigElements
4166 )
4167 {
4168 CHAR16 *StringPtr;
4169 CHAR16 *RetVal;
4170
4171 StringPtr = ConfigElements;
4172
4173 while (1) {
4174 RetVal = StringPtr;
4175 if (*StringPtr != L'&') {
4176 return RetVal;
4177 }
4178 StringPtr += 1;
4179
4180 StringPtr = StrStr (StringPtr, L"&");
4181
4182 if (StringPtr == NULL) {
4183 return NULL;
4184 }
4185 }
4186 }
4187
4188 /**
4189 Validate the config request string.
4190
4191 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4192
4193 @retval CHAR16 * THE first element not correct.
4194 @retval NULL Success parse the name/value pair
4195
4196 **/
4197 CHAR16 *
4198 ConfigRequestValidate (
4199 CHAR16 *ConfigRequest
4200 )
4201 {
4202 BOOLEAN HasNameField;
4203 CHAR16 *StringPtr;
4204
4205 HasNameField = TRUE;
4206 StringPtr = ConfigRequest;
4207
4208 //
4209 // Check <ConfigHdr>
4210 //
4211 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4212 return ConfigRequest;
4213 }
4214 StringPtr += StrLen (L"GUID=");
4215 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
4216 StringPtr++;
4217 }
4218 if (*StringPtr == L'\0') {
4219 return ConfigRequest;
4220 }
4221 StringPtr += StrLen (L"&NAME=");
4222 if (*StringPtr == L'&') {
4223 HasNameField = FALSE;
4224 }
4225 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
4226 StringPtr++;
4227 }
4228 if (*StringPtr == L'\0') {
4229 return ConfigRequest;
4230 }
4231 StringPtr += StrLen (L"&PATH=");
4232 while (*StringPtr != L'\0' && *StringPtr != L'&') {
4233 StringPtr ++;
4234 }
4235
4236 if (*StringPtr == L'\0') {
4237 return NULL;
4238 }
4239
4240 if (HasNameField) {
4241 //
4242 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4243 //
4244 return OffsetWidthValidate(StringPtr);
4245 } else {
4246 //
4247 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4248 //
4249 return NameValueValidate(StringPtr);
4250 }
4251 }
4252
4253 /**
4254 This function allows a caller to extract the current configuration
4255 for one or more named elements from one or more drivers.
4256
4257 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4258 instance.
4259 @param Request A null-terminated Unicode string in
4260 <MultiConfigRequest> format.
4261 @param Progress On return, points to a character in the Request
4262 string. Points to the string's null terminator if
4263 request was successful. Points to the most recent
4264 & before the first failing name / value pair (or
4265 the beginning of the string if the failure is in
4266 the first name / value pair) if the request was
4267 not successful.
4268 @param Results Null-terminated Unicode string in
4269 <MultiConfigAltResp> format which has all values
4270 filled in for the names in the Request string.
4271 String to be allocated by the called function.
4272
4273 @retval EFI_SUCCESS The Results string is filled with the values
4274 corresponding to all requested names.
4275 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4276 results that must be stored awaiting possible
4277 future protocols.
4278 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4279 Progress set to the "G" in "GUID" of the routing
4280 header that doesn't match. Note: There is no
4281 requirement that all routing data be validated
4282 before any configuration extraction.
4283 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4284 parameter would result in this type of error. The
4285 Progress parameter is set to NULL.
4286 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4287 before the error or the beginning of the string.
4288 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4289 Configuration Access Protocol returned
4290 EFI_INVALID_PARAMETER. Progress set to most recent
4291 & before the error or the beginning of the string.
4292
4293 **/
4294 EFI_STATUS
4295 EFIAPI
4296 HiiConfigRoutingExtractConfig (
4297 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4298 IN CONST EFI_STRING Request,
4299 OUT EFI_STRING *Progress,
4300 OUT EFI_STRING *Results
4301 )
4302 {
4303 HII_DATABASE_PRIVATE_DATA *Private;
4304 EFI_STRING StringPtr;
4305 EFI_STRING ConfigRequest;
4306 UINTN Length;
4307 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4308 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4309 EFI_STATUS Status;
4310 LIST_ENTRY *Link;
4311 HII_DATABASE_RECORD *Database;
4312 UINT8 *DevicePathPkg;
4313 UINT8 *CurrentDevicePath;
4314 EFI_HANDLE DriverHandle;
4315 EFI_HII_HANDLE HiiHandle;
4316 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4317 EFI_STRING AccessProgress;
4318 EFI_STRING AccessResults;
4319 EFI_STRING AccessProgressBackup;
4320 EFI_STRING AccessResultsBackup;
4321 EFI_STRING DefaultResults;
4322 BOOLEAN FirstElement;
4323 BOOLEAN IfrDataParsedFlag;
4324 BOOLEAN IsEfiVarStore;
4325 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4326 EFI_STRING ErrorPtr;
4327 UINTN DevicePathSize;
4328 UINTN ConigStringSize;
4329 UINTN ConigStringSizeNewsize;
4330 EFI_STRING ConfigStringPtr;
4331
4332 if (This == NULL || Progress == NULL || Results == NULL) {
4333 return EFI_INVALID_PARAMETER;
4334 }
4335
4336 if (Request == NULL) {
4337 *Progress = NULL;
4338 return EFI_INVALID_PARAMETER;
4339 }
4340
4341 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4342 StringPtr = Request;
4343 *Progress = StringPtr;
4344 DefaultResults = NULL;
4345 ConfigRequest = NULL;
4346 Status = EFI_SUCCESS;
4347 AccessResults = NULL;
4348 AccessProgress = NULL;
4349 AccessResultsBackup = NULL;
4350 AccessProgressBackup = NULL;
4351 DevicePath = NULL;
4352 IfrDataParsedFlag = FALSE;
4353 IsEfiVarStore = FALSE;
4354 EfiVarStoreInfo = NULL;
4355
4356 //
4357 // The first element of <MultiConfigRequest> should be
4358 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4359 //
4360 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4361 return EFI_INVALID_PARAMETER;
4362 }
4363
4364 FirstElement = TRUE;
4365
4366 //
4367 // Allocate a fix length of memory to store Results. Reallocate memory for
4368 // Results if this fix length is insufficient.
4369 //
4370 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4371 if (*Results == NULL) {
4372 return EFI_OUT_OF_RESOURCES;
4373 }
4374
4375 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4376 //
4377 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4378 // or most recent & before the error.
4379 //
4380 if (StringPtr == Request) {
4381 *Progress = StringPtr;
4382 } else {
4383 *Progress = StringPtr - 1;
4384 }
4385
4386 //
4387 // Process each <ConfigRequest> of <MultiConfigRequest>
4388 //
4389 Length = CalculateConfigStringLen (StringPtr);
4390 ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4391 if (ConfigRequest == NULL) {
4392 Status = EFI_OUT_OF_RESOURCES;
4393 goto Done;
4394 }
4395 *(ConfigRequest + Length) = 0;
4396
4397 //
4398 // Get the UEFI device path
4399 //
4400 Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
4401 if (EFI_ERROR (Status)) {
4402 goto Done;
4403 }
4404
4405 //
4406 // Find driver which matches the routing data.
4407 //
4408 DriverHandle = NULL;
4409 HiiHandle = NULL;
4410 Database = NULL;
4411 for (Link = Private->DatabaseList.ForwardLink;
4412 Link != &Private->DatabaseList;
4413 Link = Link->ForwardLink
4414 ) {
4415 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4416 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4417 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4418 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4419 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
4420 DriverHandle = Database->DriverHandle;
4421 HiiHandle = Database->Handle;
4422 break;
4423 }
4424 }
4425 }
4426
4427 //
4428 // Try to find driver handle by device path.
4429 //
4430 if (DriverHandle == NULL) {
4431 TempDevicePath = DevicePath;
4432 Status = gBS->LocateDevicePath (
4433 &gEfiDevicePathProtocolGuid,
4434 &TempDevicePath,
4435 &DriverHandle
4436 );
4437 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
4438 //
4439 // Routing data does not match any known driver.
4440 // Set Progress to the 'G' in "GUID" of the routing header.
4441 //
4442 *Progress = StringPtr;
4443 Status = EFI_NOT_FOUND;
4444 goto Done;
4445 }
4446 }
4447
4448 //
4449 // Validate ConfigRequest String.
4450 //
4451 ErrorPtr = ConfigRequestValidate(ConfigRequest);
4452 if (ErrorPtr != NULL) {
4453 *Progress = StrStr (StringPtr, ErrorPtr);
4454 Status = EFI_INVALID_PARAMETER;
4455 goto Done;
4456 }
4457
4458 //
4459 // Check whether ConfigRequest contains request string.
4460 //
4461 IfrDataParsedFlag = FALSE;
4462 if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
4463 //
4464 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4465 //
4466 IfrDataParsedFlag = TRUE;
4467 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
4468 if (EFI_ERROR (Status)) {
4469 //
4470 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4471 // Map it to the progress on <MultiConfigRequest> then return it.
4472 //
4473 ASSERT (AccessProgress != NULL);
4474 *Progress = StrStr (StringPtr, AccessProgress);
4475 goto Done;
4476 }
4477 //
4478 // Not any request block is found.
4479 //
4480 if (!GetElementsFromRequest(ConfigRequest)) {
4481 AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
4482 goto NextConfigString;
4483 }
4484 }
4485
4486 //
4487 // Check whether this ConfigRequest is search from Efi varstore type storage.
4488 //
4489 Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
4490 if (EFI_ERROR (Status)) {
4491 goto Done;
4492 }
4493
4494 if (IsEfiVarStore) {
4495 //
4496 // Call the GetVariable function to extract settings.
4497 //
4498 Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
4499 FreePool (EfiVarStoreInfo);
4500 if (EFI_ERROR (Status)) {
4501 //
4502 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4503 // Map it to the progress on <MultiConfigRequest> then return it.
4504 //
4505 *Progress = StrStr (StringPtr, AccessProgress);
4506 goto Done;
4507 }
4508
4509 //
4510 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4511 //
4512 Status = gBS->HandleProtocol (
4513 DriverHandle,
4514 &gEfiHiiConfigAccessProtocolGuid,
4515 (VOID **) &ConfigAccess
4516 );
4517 if (EFI_ERROR (Status)) {
4518 //
4519 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4520 // So ignore the error status in this case.
4521 //
4522 Status = EFI_SUCCESS;
4523 } else {
4524 Status = ConfigAccess->ExtractConfig (
4525 ConfigAccess,
4526 ConfigRequest,
4527 &AccessProgressBackup,
4528 &AccessResultsBackup
4529 );
4530 if (!EFI_ERROR(Status)) {
4531 //
4532 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4533 //
4534 if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
4535 ConigStringSize = StrSize (AccessResults);
4536 ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
4537 ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
4538 AccessResults = (EFI_STRING) ReallocatePool (
4539 ConigStringSize,
4540 ConigStringSizeNewsize,
4541 AccessResults);
4542 StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
4543 }
4544 } else {
4545 //
4546 // In the ExtractConfig function of some driver may not support EfiVarStore,
4547 // may return error status, just ignore the error status in this case.
4548 //
4549 Status = EFI_SUCCESS;
4550 }
4551 if (AccessResultsBackup != NULL) {
4552 FreePool (AccessResultsBackup);
4553 AccessResultsBackup = NULL;
4554 }
4555 }
4556 } else {
4557 //
4558 // Call corresponding ConfigAccess protocol to extract settings
4559 //
4560 Status = gBS->HandleProtocol (
4561 DriverHandle,
4562 &gEfiHiiConfigAccessProtocolGuid,
4563 (VOID **) &ConfigAccess
4564 );
4565 if (EFI_ERROR (Status)) {
4566 goto Done;
4567 }
4568
4569 Status = ConfigAccess->ExtractConfig (
4570 ConfigAccess,
4571 ConfigRequest,
4572 &AccessProgress,
4573 &AccessResults
4574 );
4575 }
4576 if (EFI_ERROR (Status)) {
4577 //
4578 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4579 // Map it to the progress on <MultiConfigRequest> then return it.
4580 //
4581 *Progress = StrStr (StringPtr, AccessProgress);
4582 goto Done;
4583 }
4584
4585 //
4586 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4587 // which seperates the first <ConfigAltResp> and the following ones.
4588 //
4589 ASSERT (*AccessProgress == 0);
4590
4591 //
4592 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4593 //
4594 if (!IfrDataParsedFlag && HiiHandle != NULL) {
4595 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4596 ASSERT_EFI_ERROR (Status);
4597 }
4598
4599 FreePool (DevicePath);
4600 DevicePath = NULL;
4601
4602 if (DefaultResults != NULL) {
4603 Status = MergeDefaultString (&AccessResults, DefaultResults);
4604 ASSERT_EFI_ERROR (Status);
4605 FreePool (DefaultResults);
4606 DefaultResults = NULL;
4607 }
4608
4609 NextConfigString:
4610 if (!FirstElement) {
4611 Status = AppendToMultiString (Results, L"&");
4612 ASSERT_EFI_ERROR (Status);
4613 }
4614
4615 Status = AppendToMultiString (Results, AccessResults);
4616 ASSERT_EFI_ERROR (Status);
4617
4618 FirstElement = FALSE;
4619
4620 FreePool (AccessResults);
4621 AccessResults = NULL;
4622 FreePool (ConfigRequest);
4623 ConfigRequest = NULL;
4624
4625 //
4626 // Go to next <ConfigRequest> (skip '&').
4627 //
4628 StringPtr += Length;
4629 if (*StringPtr == 0) {
4630 *Progress = StringPtr;
4631 break;
4632 }
4633
4634 StringPtr++;
4635 }
4636
4637 Done:
4638 if (EFI_ERROR (Status)) {
4639 FreePool (*Results);
4640 *Results = NULL;
4641 }
4642
4643 if (ConfigRequest != NULL) {
4644 FreePool (ConfigRequest);
4645 }
4646
4647 if (AccessResults != NULL) {
4648 FreePool (AccessResults);
4649 }
4650
4651 if (DefaultResults != NULL) {
4652 FreePool (DefaultResults);
4653 }
4654
4655 if (DevicePath != NULL) {
4656 FreePool (DevicePath);
4657 }
4658
4659 return Status;
4660 }
4661
4662
4663 /**
4664 This function allows the caller to request the current configuration for the
4665 entirety of the current HII database and returns the data in a
4666 null-terminated Unicode string.
4667
4668 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4669 instance.
4670 @param Results Null-terminated Unicode string in
4671 <MultiConfigAltResp> format which has all values
4672 filled in for the entirety of the current HII
4673 database. String to be allocated by the called
4674 function. De-allocation is up to the caller.
4675
4676 @retval EFI_SUCCESS The Results string is filled with the values
4677 corresponding to all requested names.
4678 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4679 results that must be stored awaiting possible
4680 future protocols.
4681 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4682 parameter would result in this type of error.
4683
4684 **/
4685 EFI_STATUS
4686 EFIAPI
4687 HiiConfigRoutingExportConfig (
4688 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4689 OUT EFI_STRING *Results
4690 )
4691 {
4692 EFI_STATUS Status;
4693 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4694 EFI_STRING AccessResults;
4695 EFI_STRING Progress;
4696 EFI_STRING StringPtr;
4697 EFI_STRING ConfigRequest;
4698 UINTN Index;
4699 EFI_HANDLE *ConfigAccessHandles;
4700 UINTN NumberConfigAccessHandles;
4701 BOOLEAN FirstElement;
4702 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4703 EFI_HII_HANDLE HiiHandle;
4704 EFI_STRING DefaultResults;
4705 HII_DATABASE_PRIVATE_DATA *Private;
4706 LIST_ENTRY *Link;
4707 HII_DATABASE_RECORD *Database;
4708 UINT8 *DevicePathPkg;
4709 UINT8 *CurrentDevicePath;
4710 BOOLEAN IfrDataParsedFlag;
4711
4712 if (This == NULL || Results == NULL) {
4713 return EFI_INVALID_PARAMETER;
4714 }
4715
4716 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4717
4718 //
4719 // Allocate a fix length of memory to store Results. Reallocate memory for
4720 // Results if this fix length is insufficient.
4721 //
4722 *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
4723 if (*Results == NULL) {
4724 return EFI_OUT_OF_RESOURCES;
4725 }
4726
4727 NumberConfigAccessHandles = 0;
4728 Status = gBS->LocateHandleBuffer (
4729 ByProtocol,
4730 &gEfiHiiConfigAccessProtocolGuid,
4731 NULL,
4732 &NumberConfigAccessHandles,
4733 &ConfigAccessHandles
4734 );
4735 if (EFI_ERROR (Status)) {
4736 return Status;
4737 }
4738
4739 FirstElement = TRUE;
4740
4741 for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
4742 Status = gBS->HandleProtocol (
4743 ConfigAccessHandles[Index],
4744 &gEfiHiiConfigAccessProtocolGuid,
4745 (VOID **) &ConfigAccess
4746 );
4747 if (EFI_ERROR (Status)) {
4748 continue;
4749 }
4750
4751 //
4752 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4753 //
4754 IfrDataParsedFlag = FALSE;
4755 Progress = NULL;
4756 HiiHandle = NULL;
4757 DefaultResults = NULL;
4758 Database = NULL;
4759 ConfigRequest = NULL;
4760 DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);
4761 if (DevicePath != NULL) {
4762 for (Link = Private->DatabaseList.ForwardLink;
4763 Link != &Private->DatabaseList;
4764 Link = Link->ForwardLink
4765 ) {
4766 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4767 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4768 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4769 if (CompareMem (
4770 DevicePath,
4771 CurrentDevicePath,
4772 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
4773 ) == 0) {
4774 HiiHandle = Database->Handle;
4775 break;
4776 }
4777 }
4778 }
4779 }
4780
4781 Status = ConfigAccess->ExtractConfig (
4782 ConfigAccess,
4783 NULL,
4784 &Progress,
4785 &AccessResults
4786 );
4787 if (EFI_ERROR (Status)) {
4788 //
4789 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4790 //
4791 if (HiiHandle != NULL && DevicePath != NULL) {
4792 IfrDataParsedFlag = TRUE;
4793 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
4794 //
4795 // Get the full request string to get the Current setting again.
4796 //
4797 if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
4798 Status = ConfigAccess->ExtractConfig (
4799 ConfigAccess,
4800 ConfigRequest,
4801 &Progress,
4802 &AccessResults
4803 );
4804 FreePool (ConfigRequest);
4805 } else {
4806 Status = EFI_NOT_FOUND;
4807 }
4808 }
4809 }
4810
4811 if (!EFI_ERROR (Status)) {
4812 //
4813 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4814 //
4815 if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
4816 StringPtr = StrStr (AccessResults, L"&GUID=");
4817 if (StringPtr != NULL) {
4818 *StringPtr = 0;
4819 }
4820 if (GetElementsFromRequest (AccessResults)) {
4821 Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
4822 ASSERT_EFI_ERROR (Status);
4823 }
4824 if (StringPtr != NULL) {
4825 *StringPtr = L'&';
4826 }
4827 }
4828 //
4829 // Merge the default sting from IFR code into the got setting from driver.
4830 //
4831 if (DefaultResults != NULL) {
4832 Status = MergeDefaultString (&AccessResults, DefaultResults);
4833 ASSERT_EFI_ERROR (Status);
4834 FreePool (DefaultResults);
4835 DefaultResults = NULL;
4836 }
4837
4838 //
4839 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4840 // which seperates the first <ConfigAltResp> and the following ones.
4841 //
4842 if (!FirstElement) {
4843 Status = AppendToMultiString (Results, L"&");
4844 ASSERT_EFI_ERROR (Status);
4845 }
4846
4847 Status = AppendToMultiString (Results, AccessResults);
4848 ASSERT_EFI_ERROR (Status);
4849
4850 FirstElement = FALSE;
4851
4852 FreePool (AccessResults);
4853 AccessResults = NULL;
4854 }
4855 }
4856 FreePool (ConfigAccessHandles);
4857
4858 return EFI_SUCCESS;
4859 }
4860
4861
4862 /**
4863 This function processes the results of processing forms and routes it to the
4864 appropriate handlers or storage.
4865
4866 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4867 instance.
4868 @param Configuration A null-terminated Unicode string in
4869 <MulltiConfigResp> format.
4870 @param Progress A pointer to a string filled in with the offset of
4871 the most recent & before the first failing name /
4872 value pair (or the beginning of the string if the
4873 failure is in the first name / value pair) or the
4874 terminating NULL if all was successful.
4875
4876 @retval EFI_SUCCESS The results have been distributed or are awaiting
4877 distribution.
4878 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4879 results that must be stored awaiting possible
4880 future protocols.
4881 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4882 would result in this type of error.
4883 @retval EFI_NOT_FOUND Target for the specified routing data was not
4884 found.
4885
4886 **/
4887 EFI_STATUS
4888 EFIAPI
4889 HiiConfigRoutingRouteConfig (
4890 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
4891 IN CONST EFI_STRING Configuration,
4892 OUT EFI_STRING *Progress
4893 )
4894 {
4895 HII_DATABASE_PRIVATE_DATA *Private;
4896 EFI_STRING StringPtr;
4897 EFI_STRING ConfigResp;
4898 UINTN Length;
4899 EFI_STATUS Status;
4900 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4901 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4902 LIST_ENTRY *Link;
4903 HII_DATABASE_RECORD *Database;
4904 UINT8 *DevicePathPkg;
4905 UINT8 *CurrentDevicePath;
4906 EFI_HANDLE DriverHandle;
4907 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
4908 EFI_STRING AccessProgress;
4909 EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
4910 BOOLEAN IsEfiVarstore;
4911 UINTN DevicePathSize;
4912
4913 if (This == NULL || Progress == NULL) {
4914 return EFI_INVALID_PARAMETER;
4915 }
4916
4917 if (Configuration == NULL) {
4918 *Progress = NULL;
4919 return EFI_INVALID_PARAMETER;
4920 }
4921
4922 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4923 StringPtr = Configuration;
4924 *Progress = StringPtr;
4925 Database = NULL;
4926 AccessProgress = NULL;
4927 EfiVarStoreInfo= NULL;
4928 IsEfiVarstore = FALSE;
4929
4930 //
4931 // The first element of <MultiConfigResp> should be
4932 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4933 //
4934 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
4935 return EFI_INVALID_PARAMETER;
4936 }
4937
4938 while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
4939 //
4940 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4941 // or most recent & before the error.
4942 //
4943 if (StringPtr == Configuration) {
4944 *Progress = StringPtr;
4945 } else {
4946 *Progress = StringPtr - 1;
4947 }
4948
4949 //
4950 // Process each <ConfigResp> of <MultiConfigResp>
4951 //
4952 Length = CalculateConfigStringLen (StringPtr);
4953 ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
4954 if (ConfigResp == NULL) {
4955 return EFI_OUT_OF_RESOURCES;
4956 }
4957 //
4958 // Append '\0' to the end of ConfigRequest
4959 //
4960 *(ConfigResp + Length) = 0;
4961
4962 //
4963 // Get the UEFI device path
4964 //
4965 Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
4966 if (EFI_ERROR (Status)) {
4967 FreePool (ConfigResp);
4968 return Status;
4969 }
4970
4971 //
4972 // Find driver which matches the routing data.
4973 //
4974 DriverHandle = NULL;
4975 for (Link = Private->DatabaseList.ForwardLink;
4976 Link != &Private->DatabaseList;
4977 Link = Link->ForwardLink
4978 ) {
4979 Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4980
4981 if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
4982 CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
4983 DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
4984 if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
4985 DriverHandle = Database->DriverHandle;
4986 break;
4987 }
4988 }
4989 }
4990
4991 //
4992 // Try to find driver handle by device path.
4993 //
4994 if (DriverHandle == NULL) {
4995 TempDevicePath = DevicePath;
4996 Status = gBS->LocateDevicePath (
4997 &gEfiDevicePathProtocolGuid,
4998 &TempDevicePath,
4999 &DriverHandle
5000 );
5001 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
5002 //
5003 // Routing data does not match any known driver.
5004 // Set Progress to the 'G' in "GUID" of the routing header.
5005 //
5006 FreePool (DevicePath);
5007 *Progress = StringPtr;
5008 FreePool (ConfigResp);
5009 return EFI_NOT_FOUND;
5010 }
5011 }
5012
5013 FreePool (DevicePath);
5014
5015 //
5016 // Check whether this ConfigRequest is search from Efi varstore type storage.
5017 //
5018 Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
5019 if (EFI_ERROR (Status)) {
5020 return Status;
5021 }
5022
5023 if (IsEfiVarstore) {
5024 //
5025 // Call the SetVariable function to route settings.
5026 //
5027 Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
5028 FreePool (EfiVarStoreInfo);
5029 } else {
5030 //
5031 // Call corresponding ConfigAccess protocol to route settings
5032 //
5033 Status = gBS->HandleProtocol (
5034 DriverHandle,
5035 &gEfiHiiConfigAccessProtocolGuid,
5036 (VOID **) &ConfigAccess
5037 );
5038 if (EFI_ERROR (Status)) {
5039 *Progress = StringPtr;
5040 FreePool (ConfigResp);
5041 return EFI_NOT_FOUND;
5042 }
5043
5044 Status = ConfigAccess->RouteConfig (
5045 ConfigAccess,
5046 ConfigResp,
5047 &AccessProgress
5048 );
5049 }
5050 if (EFI_ERROR (Status)) {
5051 ASSERT (AccessProgress != NULL);
5052 //
5053 // AccessProgress indicates the parsing progress on <ConfigResp>.
5054 // Map it to the progress on <MultiConfigResp> then return it.
5055 //
5056 *Progress = StrStr (StringPtr, AccessProgress);
5057
5058 FreePool (ConfigResp);
5059 return Status;
5060 }
5061
5062 FreePool (ConfigResp);
5063 ConfigResp = NULL;
5064
5065 //
5066 // Go to next <ConfigResp> (skip '&').
5067 //
5068 StringPtr += Length;
5069 if (*StringPtr == 0) {
5070 *Progress = StringPtr;
5071 break;
5072 }
5073
5074 StringPtr++;
5075
5076 }
5077
5078 return EFI_SUCCESS;
5079 }
5080
5081
5082 /**
5083 This helper function is to be called by drivers to map configuration data
5084 stored in byte array ("block") formats such as UEFI Variables into current
5085 configuration strings.
5086
5087 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5088 instance.
5089 @param ConfigRequest A null-terminated Unicode string in
5090 <ConfigRequest> format.
5091 @param Block Array of bytes defining the block's configuration.
5092 @param BlockSize Length in bytes of Block.
5093 @param Config Filled-in configuration string. String allocated
5094 by the function. Returned only if call is
5095 successful. It is <ConfigResp> string format.
5096 @param Progress A pointer to a string filled in with the offset of
5097 the most recent & before the first failing
5098 name/value pair (or the beginning of the string if
5099 the failure is in the first name / value pair) or
5100 the terminating NULL if all was successful.
5101
5102 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5103 terminator at the end of the ConfigRequest
5104 string.
5105 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5106 points to the first character of ConfigRequest.
5107 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5108 Block parameter would result in this type of
5109 error. Progress points to the first character of
5110 ConfigRequest.
5111 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5112 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5113 Block is left updated and Progress points at
5114 the "&" preceding the first non-<BlockName>.
5115
5116 **/
5117 EFI_STATUS
5118 EFIAPI
5119 HiiBlockToConfig (
5120 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5121 IN CONST EFI_STRING ConfigRequest,
5122 IN CONST UINT8 *Block,
5123 IN CONST UINTN BlockSize,
5124 OUT EFI_STRING *Config,
5125 OUT EFI_STRING *Progress
5126 )
5127 {
5128 HII_DATABASE_PRIVATE_DATA *Private;
5129 EFI_STRING StringPtr;
5130 UINTN Length;
5131 EFI_STATUS Status;
5132 EFI_STRING TmpPtr;
5133 UINT8 *TmpBuffer;
5134 UINTN Offset;
5135 UINTN Width;
5136 UINT8 *Value;
5137 EFI_STRING ValueStr;
5138 EFI_STRING ConfigElement;
5139 UINTN Index;
5140 UINT8 *TemBuffer;
5141 CHAR16 *TemString;
5142 CHAR16 TemChar;
5143
5144 TmpBuffer = NULL;
5145
5146 if (This == NULL || Progress == NULL || Config == NULL) {
5147 return EFI_INVALID_PARAMETER;
5148 }
5149
5150 if (Block == NULL || ConfigRequest == NULL) {
5151 *Progress = ConfigRequest;
5152 return EFI_INVALID_PARAMETER;
5153 }
5154
5155
5156 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5157 ASSERT (Private != NULL);
5158
5159 StringPtr = ConfigRequest;
5160 ValueStr = NULL;
5161 Value = NULL;
5162 ConfigElement = NULL;
5163
5164 //
5165 // Allocate a fix length of memory to store Results. Reallocate memory for
5166 // Results if this fix length is insufficient.
5167 //
5168 *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
5169 if (*Config == NULL) {
5170 return EFI_OUT_OF_RESOURCES;
5171 }
5172
5173 //
5174 // Jump <ConfigHdr>
5175 //
5176 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5177 *Progress = StringPtr;
5178 Status = EFI_INVALID_PARAMETER;
5179 goto Exit;
5180 }
5181 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5182 StringPtr++;
5183 }
5184 if (*StringPtr == 0) {
5185 *Progress = StringPtr - 1;
5186 Status = EFI_INVALID_PARAMETER;
5187 goto Exit;
5188 }
5189
5190 while (*StringPtr != L'&' && *StringPtr != 0) {
5191 StringPtr++;
5192 }
5193 if (*StringPtr == 0) {
5194 *Progress = StringPtr;
5195
5196 AppendToMultiString(Config, ConfigRequest);
5197 HiiToLower (*Config);
5198
5199 return EFI_SUCCESS;
5200 }
5201 //
5202 // Skip '&'
5203 //
5204 StringPtr++;
5205
5206 //
5207 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5208 //
5209 TemChar = *StringPtr;
5210 *StringPtr = '\0';
5211 AppendToMultiString(Config, ConfigRequest);
5212 *StringPtr = TemChar;
5213
5214 //
5215 // Parse each <RequestElement> if exists
5216 // Only <BlockName> format is supported by this help function.
5217 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5218 //
5219 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
5220 //
5221 // Back up the header of one <BlockName>
5222 //
5223 TmpPtr = StringPtr;
5224
5225 StringPtr += StrLen (L"OFFSET=");
5226 //
5227 // Get Offset
5228 //
5229 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5230 if (EFI_ERROR (Status)) {
5231 *Progress = TmpPtr - 1;
5232 goto Exit;
5233 }
5234 Offset = 0;
5235 CopyMem (
5236 &Offset,
5237 TmpBuffer,
5238 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5239 );
5240 FreePool (TmpBuffer);
5241
5242 StringPtr += Length;
5243 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5244 *Progress = TmpPtr - 1;
5245 Status = EFI_INVALID_PARAMETER;
5246 goto Exit;
5247 }
5248 StringPtr += StrLen (L"&WIDTH=");
5249
5250 //
5251 // Get Width
5252 //
5253 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5254 if (EFI_ERROR (Status)) {
5255 *Progress = TmpPtr - 1;
5256 goto Exit;
5257 }
5258 Width = 0;
5259 CopyMem (
5260 &Width,
5261 TmpBuffer,
5262 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5263 );
5264 FreePool (TmpBuffer);
5265
5266 StringPtr += Length;
5267 if (*StringPtr != 0 && *StringPtr != L'&') {
5268 *Progress = TmpPtr - 1;
5269 Status = EFI_INVALID_PARAMETER;
5270 goto Exit;
5271 }
5272
5273 //
5274 // Calculate Value and convert it to hex string.
5275 //
5276 if (Offset + Width > BlockSize) {
5277 *Progress = StringPtr;
5278 Status = EFI_DEVICE_ERROR;
5279 goto Exit;
5280 }
5281
5282 Value = (UINT8 *) AllocateZeroPool (Width);
5283 if (Value == NULL) {
5284 *Progress = ConfigRequest;
5285 Status = EFI_OUT_OF_RESOURCES;
5286 goto Exit;
5287 }
5288
5289 CopyMem (Value, (UINT8 *) Block + Offset, Width);
5290
5291 Length = Width * 2 + 1;
5292 ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5293 if (ValueStr == NULL) {
5294 *Progress = ConfigRequest;
5295 Status = EFI_OUT_OF_RESOURCES;
5296 goto Exit;
5297 }
5298
5299 TemString = ValueStr;
5300 TemBuffer = Value + Width - 1;
5301 for (Index = 0; Index < Width; Index ++, TemBuffer --) {
5302 TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
5303 }
5304
5305 FreePool (Value);
5306 Value = NULL;
5307
5308 //
5309 // Build a ConfigElement
5310 //
5311 Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
5312 ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
5313 if (ConfigElement == NULL) {
5314 Status = EFI_OUT_OF_RESOURCES;
5315 goto Exit;
5316 }
5317 CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
5318 if (*StringPtr == 0) {
5319 *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
5320 }
5321 *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
5322 StrCatS (ConfigElement, Length, L"VALUE=");
5323 StrCatS (ConfigElement, Length, ValueStr);
5324
5325 AppendToMultiString (Config, ConfigElement);
5326
5327 FreePool (ConfigElement);
5328 FreePool (ValueStr);
5329 ConfigElement = NULL;
5330 ValueStr = NULL;
5331
5332 //
5333 // If '\0', parsing is finished. Otherwise skip '&' to continue
5334 //
5335 if (*StringPtr == 0) {
5336 break;
5337 }
5338 AppendToMultiString (Config, L"&");
5339 StringPtr++;
5340
5341 }
5342
5343 if (*StringPtr != 0) {
5344 *Progress = StringPtr - 1;
5345 Status = EFI_INVALID_PARAMETER;
5346 goto Exit;
5347 }
5348
5349 HiiToLower (*Config);
5350 *Progress = StringPtr;
5351 return EFI_SUCCESS;
5352
5353 Exit:
5354 if (*Config != NULL) {
5355 FreePool (*Config);
5356 *Config = NULL;
5357 }
5358 if (ValueStr != NULL) {
5359 FreePool (ValueStr);
5360 }
5361 if (Value != NULL) {
5362 FreePool (Value);
5363 }
5364 if (ConfigElement != NULL) {
5365 FreePool (ConfigElement);
5366 }
5367
5368 return Status;
5369
5370 }
5371
5372
5373 /**
5374 This helper function is to be called by drivers to map configuration strings
5375 to configurations stored in byte array ("block") formats such as UEFI Variables.
5376
5377 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5378 instance.
5379 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5380 format.
5381 @param Block A possibly null array of bytes representing the
5382 current block. Only bytes referenced in the
5383 ConfigResp string in the block are modified. If
5384 this parameter is null or if the *BlockSize
5385 parameter is (on input) shorter than required by
5386 the Configuration string, only the BlockSize
5387 parameter is updated and an appropriate status
5388 (see below) is returned.
5389 @param BlockSize The length of the Block in units of UINT8. On
5390 input, this is the size of the Block. On output,
5391 if successful, contains the largest index of the
5392 modified byte in the Block, or the required buffer
5393 size if the Block is not large enough.
5394 @param Progress On return, points to an element of the ConfigResp
5395 string filled in with the offset of the most
5396 recent '&' before the first failing name / value
5397 pair (or the beginning of the string if the
5398 failure is in the first name / value pair) or the
5399 terminating NULL if all was successful.
5400
5401 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5402 terminator at the end of the ConfigResp string.
5403 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5404 points to the first character of ConfigResp.
5405 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5406 Block parameter would result in this type of
5407 error. Progress points to the first character of
5408 ConfigResp.
5409 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5410 value pair. Block is left updated and
5411 Progress points at the '&' preceding the first
5412 non-<BlockName>.
5413 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5414 BlockSize is updated with the required buffer size.
5415 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5416 Progress points to the "G" in "GUID" of the errant
5417 routing data.
5418
5419 **/
5420 EFI_STATUS
5421 EFIAPI
5422 HiiConfigToBlock (
5423 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5424 IN CONST EFI_STRING ConfigResp,
5425 IN OUT UINT8 *Block,
5426 IN OUT UINTN *BlockSize,
5427 OUT EFI_STRING *Progress
5428 )
5429 {
5430 HII_DATABASE_PRIVATE_DATA *Private;
5431 EFI_STRING StringPtr;
5432 EFI_STRING TmpPtr;
5433 UINTN Length;
5434 EFI_STATUS Status;
5435 UINT8 *TmpBuffer;
5436 UINTN Offset;
5437 UINTN Width;
5438 UINT8 *Value;
5439 UINTN BufferSize;
5440 UINTN MaxBlockSize;
5441
5442 TmpBuffer = NULL;
5443
5444 if (This == NULL || BlockSize == NULL || Progress == NULL) {
5445 return EFI_INVALID_PARAMETER;
5446 }
5447
5448 *Progress = ConfigResp;
5449 if (ConfigResp == NULL) {
5450 return EFI_INVALID_PARAMETER;
5451 }
5452
5453 Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
5454 ASSERT (Private != NULL);
5455
5456 StringPtr = ConfigResp;
5457 BufferSize = *BlockSize;
5458 Value = NULL;
5459 MaxBlockSize = 0;
5460
5461 //
5462 // Jump <ConfigHdr>
5463 //
5464 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5465 *Progress = StringPtr;
5466 Status = EFI_INVALID_PARAMETER;
5467 goto Exit;
5468 }
5469 while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
5470 StringPtr++;
5471 }
5472 if (*StringPtr == 0) {
5473 *Progress = StringPtr;
5474 Status = EFI_INVALID_PARAMETER;
5475 goto Exit;
5476 }
5477
5478 while (*StringPtr != L'&' && *StringPtr != 0) {
5479 StringPtr++;
5480 }
5481 if (*StringPtr == 0) {
5482 *Progress = StringPtr;
5483 Status = EFI_INVALID_PARAMETER;
5484 goto Exit;
5485 }
5486
5487 //
5488 // Parse each <ConfigElement> if exists
5489 // Only '&'<BlockConfig> format is supported by this help function.
5490 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5491 //
5492 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
5493 TmpPtr = StringPtr;
5494 StringPtr += StrLen (L"&OFFSET=");
5495 //
5496 // Get Offset
5497 //
5498 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5499 if (EFI_ERROR (Status)) {
5500 *Progress = TmpPtr;
5501 goto Exit;
5502 }
5503 Offset = 0;
5504 CopyMem (
5505 &Offset,
5506 TmpBuffer,
5507 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5508 );
5509 FreePool (TmpBuffer);
5510
5511 StringPtr += Length;
5512 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
5513 *Progress = TmpPtr;
5514 Status = EFI_INVALID_PARAMETER;
5515 goto Exit;
5516 }
5517 StringPtr += StrLen (L"&WIDTH=");
5518
5519 //
5520 // Get Width
5521 //
5522 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
5523 if (EFI_ERROR (Status)) {
5524 *Progress = TmpPtr;
5525 goto Exit;
5526 }
5527 Width = 0;
5528 CopyMem (
5529 &Width,
5530 TmpBuffer,
5531 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
5532 );
5533 FreePool (TmpBuffer);
5534
5535 StringPtr += Length;
5536 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
5537 *Progress = TmpPtr;
5538 Status = EFI_INVALID_PARAMETER;
5539 goto Exit;
5540 }
5541 StringPtr += StrLen (L"&VALUE=");
5542
5543 //
5544 // Get Value
5545 //
5546 Status = GetValueOfNumber (StringPtr, &Value, &Length);
5547 if (EFI_ERROR (Status)) {
5548 *Progress = TmpPtr;
5549 goto Exit;
5550 }
5551
5552 StringPtr += Length;
5553 if (*StringPtr != 0 && *StringPtr != L'&') {
5554 *Progress = TmpPtr;
5555 Status = EFI_INVALID_PARAMETER;
5556 goto Exit;
5557 }
5558
5559 //
5560 // Update the Block with configuration info
5561 //
5562 if ((Block != NULL) && (Offset + Width <= BufferSize)) {
5563 CopyMem (Block + Offset, Value, Width);
5564 }
5565 if (Offset + Width > MaxBlockSize) {
5566 MaxBlockSize = Offset + Width;
5567 }
5568
5569 FreePool (Value);
5570 Value = NULL;
5571
5572 //
5573 // If '\0', parsing is finished.
5574 //
5575 if (*StringPtr == 0) {
5576 break;
5577 }
5578 }
5579
5580 //
5581 // The input string is not ConfigResp format, return error.
5582 //
5583 if (*StringPtr != 0) {
5584 *Progress = StringPtr;
5585 Status = EFI_INVALID_PARAMETER;
5586 goto Exit;
5587 }
5588
5589 *Progress = StringPtr + StrLen (StringPtr);
5590 *BlockSize = MaxBlockSize - 1;
5591
5592 if (MaxBlockSize > BufferSize) {
5593 *BlockSize = MaxBlockSize;
5594 if (Block != NULL) {
5595 return EFI_BUFFER_TOO_SMALL;
5596 }
5597 }
5598
5599 if (Block == NULL) {
5600 *Progress = ConfigResp;
5601 return EFI_INVALID_PARAMETER;
5602 }
5603
5604 return EFI_SUCCESS;
5605
5606 Exit:
5607
5608 if (Value != NULL) {
5609 FreePool (Value);
5610 }
5611 return Status;
5612 }
5613
5614
5615 /**
5616 This helper function is to be called by drivers to extract portions of
5617 a larger configuration string.
5618
5619 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5620 instance.
5621 @param Configuration A null-terminated Unicode string in
5622 <MultiConfigAltResp> format.
5623 @param Guid A pointer to the GUID value to search for in the
5624 routing portion of the ConfigResp string when
5625 retrieving the requested data. If Guid is NULL,
5626 then all GUID values will be searched for.
5627 @param Name A pointer to the NAME value to search for in the
5628 routing portion of the ConfigResp string when
5629 retrieving the requested data. If Name is NULL,
5630 then all Name values will be searched for.
5631 @param DevicePath A pointer to the PATH value to search for in the
5632 routing portion of the ConfigResp string when
5633 retrieving the requested data. If DevicePath is
5634 NULL, then all DevicePath values will be searched
5635 for.
5636 @param AltCfgId A pointer to the ALTCFG value to search for in the
5637 routing portion of the ConfigResp string when
5638 retrieving the requested data. If this parameter
5639 is NULL, then the current setting will be
5640 retrieved.
5641 @param AltCfgResp A pointer to a buffer which will be allocated by
5642 the function which contains the retrieved string
5643 as requested. This buffer is only allocated if
5644 the call was successful. It is <ConfigResp> format.
5645
5646 @retval EFI_SUCCESS The request succeeded. The requested data was
5647 extracted and placed in the newly allocated
5648 AltCfgResp buffer.
5649 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5650 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5651 @retval EFI_NOT_FOUND Target for the specified routing data was not
5652 found.
5653
5654 **/
5655 EFI_STATUS
5656 EFIAPI
5657 HiiGetAltCfg (
5658 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
5659 IN CONST EFI_STRING Configuration,
5660 IN CONST EFI_GUID *Guid,
5661 IN CONST EFI_STRING Name,
5662 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
5663 IN CONST UINT16 *AltCfgId,
5664 OUT EFI_STRING *AltCfgResp
5665 )
5666 {
5667 EFI_STATUS Status;
5668 EFI_STRING StringPtr;
5669 EFI_STRING HdrStart;
5670 EFI_STRING HdrEnd;
5671 EFI_STRING TmpPtr;
5672 UINTN Length;
5673 EFI_STRING GuidStr;
5674 EFI_STRING NameStr;
5675 EFI_STRING PathStr;
5676 EFI_STRING AltIdStr;
5677 EFI_STRING Result;
5678 BOOLEAN GuidFlag;
5679 BOOLEAN NameFlag;
5680 BOOLEAN PathFlag;
5681
5682 HdrStart = NULL;
5683 HdrEnd = NULL;
5684 GuidStr = NULL;
5685 NameStr = NULL;
5686 PathStr = NULL;
5687 AltIdStr = NULL;
5688 Result = NULL;
5689 GuidFlag = FALSE;
5690 NameFlag = FALSE;
5691 PathFlag = FALSE;
5692
5693 if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
5694 return EFI_INVALID_PARAMETER;
5695 }
5696
5697 StringPtr = Configuration;
5698 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
5699 return EFI_INVALID_PARAMETER;
5700 }
5701
5702 //
5703 // Generate the sub string for later matching.
5704 //
5705 GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
5706 GenerateSubStr (
5707 L"PATH=",
5708 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
5709 (VOID *) DevicePath,
5710 1,
5711 &PathStr
5712 );
5713 if (AltCfgId != NULL) {
5714 GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
5715 }
5716 if (Name != NULL) {
5717 GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
5718 } else {
5719 GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
5720 }
5721
5722 while (*StringPtr != 0) {
5723 //
5724 // Try to match the GUID
5725 //
5726 if (!GuidFlag) {
5727 TmpPtr = StrStr (StringPtr, GuidStr);
5728 if (TmpPtr == NULL) {
5729 Status = EFI_NOT_FOUND;
5730 goto Exit;
5731 }
5732 HdrStart = TmpPtr;
5733
5734 //
5735 // Jump to <NameHdr>
5736 //
5737 if (Guid != NULL) {
5738 StringPtr = TmpPtr + StrLen (GuidStr);
5739 } else {
5740 StringPtr = StrStr (TmpPtr, L"NAME=");
5741 if (StringPtr == NULL) {
5742 Status = EFI_NOT_FOUND;
5743 goto Exit;
5744 }
5745 }
5746 GuidFlag = TRUE;
5747 }
5748
5749 //
5750 // Try to match the NAME
5751 //
5752 if (GuidFlag && !NameFlag) {
5753 if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
5754 GuidFlag = FALSE;
5755 } else {
5756 //
5757 // Jump to <PathHdr>
5758 //
5759 if (Name != NULL) {
5760 StringPtr += StrLen (NameStr);
5761 } else {
5762 StringPtr = StrStr (StringPtr, L"PATH=");
5763 if (StringPtr == NULL) {
5764 Status = EFI_NOT_FOUND;
5765 goto Exit;
5766 }
5767 }
5768 NameFlag = TRUE;
5769 }
5770 }
5771
5772 //
5773 // Try to match the DevicePath
5774 //
5775 if (GuidFlag && NameFlag && !PathFlag) {
5776 if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
5777 GuidFlag = FALSE;
5778 NameFlag = FALSE;
5779 } else {
5780 //
5781 // Jump to '&' before <DescHdr> or <ConfigBody>
5782 //
5783 if (DevicePath != NULL) {
5784 StringPtr += StrLen (PathStr);
5785 } else {
5786 StringPtr = StrStr (StringPtr, L"&");
5787 if (StringPtr == NULL) {
5788 Status = EFI_NOT_FOUND;
5789 goto Exit;
5790 }
5791 StringPtr ++;
5792 }
5793 PathFlag = TRUE;
5794 HdrEnd = StringPtr;
5795 }
5796 }
5797
5798 //
5799 // Try to match the AltCfgId
5800 //
5801 if (GuidFlag && NameFlag && PathFlag) {
5802 if (AltCfgId == NULL) {
5803 //
5804 // Return Current Setting when AltCfgId is NULL.
5805 //
5806 Status = OutputConfigBody (StringPtr, &Result);
5807 goto Exit;
5808 }
5809 //
5810 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5811 //
5812 if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
5813 GuidFlag = FALSE;
5814 NameFlag = FALSE;
5815 PathFlag = FALSE;
5816 } else {
5817 //
5818 // Skip AltIdStr and &
5819 //
5820 StringPtr = StringPtr + StrLen (AltIdStr);
5821 Status = OutputConfigBody (StringPtr, &Result);
5822 goto Exit;
5823 }
5824 }
5825 }
5826
5827 Status = EFI_NOT_FOUND;
5828
5829 Exit:
5830 *AltCfgResp = NULL;
5831 if (!EFI_ERROR (Status) && (Result != NULL)) {
5832 //
5833 // Copy the <ConfigHdr> and <ConfigBody>
5834 //
5835 Length = HdrEnd - HdrStart + StrLen (Result) + 1;
5836 *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
5837 if (*AltCfgResp == NULL) {
5838 Status = EFI_OUT_OF_RESOURCES;
5839 } else {
5840 StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
5841 StrCatS (*AltCfgResp, Length, Result);
5842 Status = EFI_SUCCESS;
5843 }
5844 }
5845
5846 if (GuidStr != NULL) {
5847 FreePool (GuidStr);
5848 }
5849 if (NameStr != NULL) {
5850 FreePool (NameStr);
5851 }
5852 if (PathStr != NULL) {
5853 FreePool (PathStr);
5854 }
5855 if (AltIdStr != NULL) {
5856 FreePool (AltIdStr);
5857 }
5858 if (Result != NULL) {
5859 FreePool (Result);
5860 }
5861
5862 return Status;
5863
5864 }
5865
5866