2 Utility functions which helps in opcode creation, HII configuration string manipulations,
3 pop up window creations, setup browser persistence data set and get.
5 Copyright (c) 2007- 2009, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "UefiIfrLibraryInternal.h"
18 CONST EFI_FORM_BROWSER2_PROTOCOL
*mFormBrowser2
= NULL
;
19 CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*mIfrSupportLibHiiConfigRouting
= NULL
;
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mIfrSupportLibHexStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
25 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
28 This function locate FormBrowser2 protocols for later usage.
30 @return Status the status to locate protocol.
33 LocateFormBrowser2Protocols (
39 // Locate protocols for later usage
41 if (mFormBrowser2
== NULL
) {
42 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mFormBrowser2
);
43 if (EFI_ERROR (Status
)) {
48 if (mIfrSupportLibHiiConfigRouting
== NULL
) {
49 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &mIfrSupportLibHiiConfigRouting
);
50 if (EFI_ERROR (Status
)) {
59 Draw a dialog and return the selected key.
61 @param NumberOfLines The number of lines for the dialog box
62 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
63 @param String The first String to be displayed in the Pop-Up.
64 @param Marker A series of (quantity == NumberOfLines - 1) text
65 strings which will be used to construct the dialog
68 @retval EFI_SUCCESS Displayed dialog and received user interaction
69 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
70 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
76 IN UINTN NumberOfLines
,
77 OUT EFI_INPUT_KEY
*KeyValue
,
91 UINTN DimensionsWidth
;
92 UINTN DimensionsHeight
;
100 EFI_EVENT TimerEvent
;
101 EFI_EVENT WaitList
[2];
102 UINTN CurrentAttribute
;
103 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
105 if ((KeyValue
== NULL
) || (String
== NULL
)) {
106 return EFI_INVALID_PARAMETER
;
114 ConOut
= gST
->ConOut
;
115 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &RightColumn
, &BottomRow
);
117 DimensionsWidth
= RightColumn
- LeftColumn
;
118 DimensionsHeight
= BottomRow
- TopRow
;
120 CurrentAttribute
= ConOut
->Mode
->Attribute
;
122 LineBuffer
= AllocateZeroPool (DimensionsWidth
* sizeof (CHAR16
));
123 if (LineBuffer
== NULL
) {
124 return EFI_OUT_OF_RESOURCES
;
128 // Determine the largest string in the dialog box
129 // Notice we are starting with 1 since String is the first string
131 StringArray
= AllocateZeroPool (NumberOfLines
* sizeof (CHAR16
*));
132 if (StringArray
== NULL
) {
133 FreePool (LineBuffer
);
134 return EFI_OUT_OF_RESOURCES
;
136 LargestString
= StrLen (String
);
137 StringArray
[0] = String
;
139 for (Index
= 1; Index
< NumberOfLines
; Index
++) {
140 StackString
= VA_ARG (Marker
, CHAR16
*);
142 if (StackString
== NULL
) {
143 FreePool (LineBuffer
);
144 FreePool (StringArray
);
145 return EFI_INVALID_PARAMETER
;
148 StringArray
[Index
] = StackString
;
149 StringLen
= StrLen (StackString
);
150 if (StringLen
> LargestString
) {
151 LargestString
= StringLen
;
155 if ((LargestString
+ 2) > DimensionsWidth
) {
156 LargestString
= DimensionsWidth
- 2;
160 // Subtract the PopUp width from total Columns, allow for one space extra on
161 // each end plus a border.
163 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + LeftColumn
+ 1;
165 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + TopRow
- 1;
170 ConOut
->EnableCursor (ConOut
, FALSE
);
171 ConOut
->SetAttribute (ConOut
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
173 StringPtr
= &LineBuffer
[0];
174 *StringPtr
++ = BOXDRAW_DOWN_RIGHT
;
175 for (Index
= 0; Index
< LargestString
; Index
++) {
176 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
178 *StringPtr
++ = BOXDRAW_DOWN_LEFT
;
181 ConOut
->SetCursorPosition (ConOut
, Start
, Top
);
182 ConOut
->OutputString (ConOut
, LineBuffer
);
184 for (Index
= 0; Index
< NumberOfLines
; Index
++) {
185 StringPtr
= &LineBuffer
[0];
186 *StringPtr
++ = BOXDRAW_VERTICAL
;
188 for (Count
= 0; Count
< LargestString
; Count
++) {
189 StringPtr
[Count
] = L
' ';
192 StringLen
= StrLen (StringArray
[Index
]);
193 if (StringLen
> LargestString
) {
194 StringLen
= LargestString
;
197 StringPtr
+ ((LargestString
- StringLen
) / 2),
199 StringLen
* sizeof (CHAR16
)
201 StringPtr
+= LargestString
;
203 *StringPtr
++ = BOXDRAW_VERTICAL
;
206 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ 1 + Index
);
207 ConOut
->OutputString (ConOut
, LineBuffer
);
210 StringPtr
= &LineBuffer
[0];
211 *StringPtr
++ = BOXDRAW_UP_RIGHT
;
212 for (Index
= 0; Index
< LargestString
; Index
++) {
213 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
215 *StringPtr
++ = BOXDRAW_UP_LEFT
;
218 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ NumberOfLines
+ 1);
219 ConOut
->OutputString (ConOut
, LineBuffer
);
222 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
225 // Set a timer event of 1 second expiration
234 // Wait for the keystroke event or the timer
236 WaitList
[0] = gST
->ConIn
->WaitForKey
;
237 WaitList
[1] = TimerEvent
;
238 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
241 // Check for the timer expiration
243 if (!EFI_ERROR (Status
) && Index
== 1) {
244 Status
= EFI_TIMEOUT
;
247 gBS
->CloseEvent (TimerEvent
);
248 } while (Status
== EFI_TIMEOUT
);
250 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
251 CopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
253 ConOut
->SetAttribute (ConOut
, CurrentAttribute
);
254 ConOut
->EnableCursor (ConOut
, TRUE
);
256 FreePool (LineBuffer
);
257 FreePool (StringArray
);
264 Draw a dialog and return the selected key.
266 @param NumberOfLines The number of lines for the dialog box
267 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
268 @param String Pointer to the first string in the list
269 @param ... A series of (quantity == NumberOfLines - 1) text
270 strings which will be used to construct the dialog
273 @retval EFI_SUCCESS Displayed dialog and received user interaction
274 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
280 IN UINTN NumberOfLines
,
281 OUT EFI_INPUT_KEY
*KeyValue
,
289 VA_START (Marker
, String
);
291 Status
= IfrLibCreatePopUp2 (NumberOfLines
, KeyValue
, String
, Marker
);
299 Extract block name from the array generated by VFR compiler. The name of
300 this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".
301 Format of this array is:
302 Array length | 4-bytes
309 @param Buffer Array generated by VFR compiler.
310 @param BlockName The returned <BlockName>
312 @retval EFI_OUT_OF_RESOURCES Run out of memory resource.
313 @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL.
314 @retval EFI_SUCCESS Operation successful.
320 OUT CHAR16
**BlockName
326 UINT32 BlockNameNumber
;
327 UINTN HexStringBufferLen
;
330 if ((Buffer
== NULL
) || (BlockName
== NULL
)) {
331 return EFI_INVALID_PARAMETER
;
335 // Calculate number of Offset/Width pair
337 CopyMem (&Length
, Buffer
, sizeof (UINT32
));
338 BlockNameNumber
= (Length
- sizeof (UINT32
)) / (sizeof (UINT16
) * 2);
341 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
344 StringPtr
= AllocateZeroPool ((BlockNameNumber
* (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16
));
345 if (StringPtr
== NULL
) {
346 return EFI_OUT_OF_RESOURCES
;
348 *BlockName
= StringPtr
;
350 Buffer
+= sizeof (UINT32
);
351 for (Index
= 0; Index
< BlockNameNumber
; Index
++) {
352 StrCpy (StringPtr
, L
"&OFFSET=");
355 HexStringBufferLen
= 5;
356 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
357 Buffer
+= sizeof (UINT16
);
360 StrCpy (StringPtr
, L
"&WIDTH=");
363 HexStringBufferLen
= 5;
364 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
365 Buffer
+= sizeof (UINT16
);
374 Extract block config from the array generated by VFR compiler. The name of
375 this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".
377 @param Buffer - Array generated by VFR compiler.
378 @param BlockConfig - The returned <BlockConfig>
380 @retval EFI_OUT_OF_RESOURCES - Run out of memory resource.
381 @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.
382 @retval EFI_SUCCESS - Operation successful.
388 OUT CHAR16
**BlockConfig
393 UINTN HexStringBufferLen
;
399 if ((Buffer
== NULL
) || (BlockConfig
== NULL
)) {
400 return EFI_INVALID_PARAMETER
;
404 // Calculate length of AltResp string
405 // Format of Default value array is:
406 // Array length | 4-bytes
409 // Value | Variable length
412 // Value | Variable length
414 // When value is 1 byte in length, overhead of AltResp string will be maximum,
415 // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+
416 // | 8 | 4 | 7 | 4 | 7 |2|
417 // so the maximum length of BlockConfig could be calculated as:
418 // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7
420 CopyMem (&Length
, Buffer
, sizeof (UINT32
));
421 BufferEnd
= Buffer
+ Length
;
422 StringPtr
= AllocatePool (Length
* 7 * sizeof (CHAR16
));
423 *BlockConfig
= StringPtr
;
424 if (StringPtr
== NULL
) {
425 return EFI_OUT_OF_RESOURCES
;
427 StringEnd
= StringPtr
+ (Length
* 7);
429 Buffer
+= sizeof (UINT32
);
430 while (Buffer
< BufferEnd
) {
431 StrCpy (StringPtr
, L
"&OFFSET=");
434 HexStringBufferLen
= 5;
435 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
436 Buffer
+= sizeof (UINT16
);
439 StrCpy (StringPtr
, L
"&WIDTH=");
442 HexStringBufferLen
= 5;
443 BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, sizeof (UINT16
));
444 CopyMem (&Width
, Buffer
, sizeof (UINT16
));
445 Buffer
+= sizeof (UINT16
);
448 StrCpy (StringPtr
, L
"&VALUE=");
451 HexStringBufferLen
= StringEnd
- StringPtr
;
452 Status
= BufToHexString (StringPtr
, &HexStringBufferLen
, Buffer
, Width
);
453 if (EFI_ERROR (Status
)) {
457 StringPtr
+= (Width
* 2);
464 Construct <ConfigAltResp> for a buffer storage.
466 @param ConfigRequest The Config request string. If set to NULL, all the
467 configurable elements will be extracted from BlockNameArray.
468 @param ConfigAltResp The returned <ConfigAltResp>.
469 @param Progress On return, points to a character in the Request.
470 @param Guid GUID of the buffer storage.
471 @param Name Name of the buffer storage.
472 @param DriverHandle The DriverHandle which is used to invoke HiiDatabase
473 protocol interface NewPackageList().
474 @param BufferStorage Content of the buffer storage.
475 @param BufferStorageSize Length in bytes of the buffer storage.
476 @param BlockNameArray Array generated by VFR compiler.
477 @param NumberAltCfg Number of Default value array generated by VFR compiler.
478 The sequential input parameters will be number of
479 AltCfgId and DefaultValueArray pairs. When set to 0,
480 there will be no <AltResp>.
482 retval EFI_OUT_OF_RESOURCES Run out of memory resource.
483 retval EFI_INVALID_PARAMETER ConfigAltResp is NULL.
484 retval EFI_SUCCESS Operation successful.
488 ConstructConfigAltResp (
489 IN EFI_STRING ConfigRequest
, OPTIONAL
490 OUT EFI_STRING
*Progress
,
491 OUT EFI_STRING
*ConfigAltResp
,
494 IN EFI_HANDLE
*DriverHandle
,
495 IN VOID
*BufferStorage
,
496 IN UINTN BufferStorageSize
,
497 IN VOID
*BlockNameArray
, OPTIONAL
498 IN UINTN NumberAltCfg
,
500 //IN UINT16 AltCfgId,
501 //IN VOID *DefaultValueArray,
511 VOID
*DefaultValueArray
;
513 EFI_STRING ConfigResp
;
518 BOOLEAN NeedFreeConfigRequest
;
519 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
522 if (ConfigAltResp
== NULL
) {
523 return EFI_INVALID_PARAMETER
;
531 NeedFreeConfigRequest
= FALSE
;
534 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
538 Status
= ConstructConfigHdr (
545 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
546 ConfigHdr
= AllocateZeroPool (StrBufferLen
);
547 if (ConfigHdr
== NULL
) {
548 Status
= EFI_OUT_OF_RESOURCES
;
551 Status
= ConstructConfigHdr (
559 if (EFI_ERROR (Status
)) {
564 // Construct <ConfigResp>
566 if (ConfigRequest
== NULL
) {
568 // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray
570 Status
= ExtractBlockName (BlockNameArray
, &BlockName
);
571 if (EFI_ERROR (Status
)) {
575 Len
= StrSize (ConfigHdr
);
576 ConfigRequest
= AllocateZeroPool (Len
+ StrSize (BlockName
) - sizeof (CHAR16
));
577 if (ConfigRequest
== NULL
) {
578 Status
= EFI_OUT_OF_RESOURCES
;
582 StrCpy (ConfigRequest
, ConfigHdr
);
583 StrCat (ConfigRequest
, BlockName
);
584 NeedFreeConfigRequest
= TRUE
;
588 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
589 if (EFI_ERROR (Status
)) {
593 Status
= HiiConfigRouting
->BlockToConfig (
599 (Progress
== NULL
) ? &TempStr
: Progress
601 if (EFI_ERROR (Status
)) {
607 // Construct <AltResp>
609 if (NumberAltCfg
> 0) {
610 DescHdr
= AllocateZeroPool (NumberAltCfg
* 16 * sizeof (CHAR16
));
611 if (DescHdr
== NULL
) {
612 Status
= EFI_OUT_OF_RESOURCES
;
617 AltCfg
= AllocateZeroPool (NumberAltCfg
* sizeof (CHAR16
*));
618 if (AltCfg
== NULL
) {
619 Status
= EFI_OUT_OF_RESOURCES
;
623 VA_START (Args
, NumberAltCfg
);
624 for (Index
= 0; Index
< NumberAltCfg
; Index
++) {
625 AltCfgId
= (UINT16
) VA_ARG (Args
, UINT16
);
626 DefaultValueArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
631 AltRespLen
+= (StrLen (ConfigHdr
) + 1);
633 StringPtr
= DescHdr
+ Index
* 16;
634 StrCpy (StringPtr
, L
"&ALTCFG=");
635 AltRespLen
+= (8 + sizeof (UINT16
) * 2);
638 BufToHexString (StringPtr
+ 8, &StrBufferLen
, (UINT8
*) &AltCfgId
, sizeof (UINT16
));
639 Status
= ExtractBlockConfig (DefaultValueArray
, &AltCfg
[Index
]);
640 if (EFI_ERROR (Status
)) {
643 AltRespLen
+= StrLen (AltCfg
[Index
]);
649 // Generate the final <ConfigAltResp>
651 StrBufferLen
= (StrLen ((CHAR16
*) ConfigResp
) + AltRespLen
+ 1) * sizeof (CHAR16
);
652 TempStr
= AllocateZeroPool (StrBufferLen
);
653 *ConfigAltResp
= TempStr
;
654 if (TempStr
== NULL
) {
659 // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*
661 StrCpy (TempStr
, ConfigResp
);
662 for (Index
= 0; Index
< NumberAltCfg
; Index
++) {
663 StrCat (TempStr
, L
"&");
664 StrCat (TempStr
, ConfigHdr
);
665 StrCat (TempStr
, DescHdr
+ Index
* 16);
666 StrCat (TempStr
, AltCfg
[Index
]);
668 FreePool (AltCfg
[Index
]);
672 if (NeedFreeConfigRequest
) {
673 FreePool (ConfigRequest
);
675 FreePool (ConfigHdr
);
676 if (ConfigResp
!= NULL
) {
677 FreePool (ConfigResp
);
680 if (BlockName
!= NULL
) {
681 FreePool (BlockName
);
684 if (NumberAltCfg
> 0) {
693 Swap bytes in the buffer. This is a internal function.
695 @param Buffer Binary buffer.
696 @param BufferSize Size of the buffer in bytes.
703 IN OUT UINT8
*Buffer
,
711 SwapCount
= BufferSize
/ 2;
712 for (Index
= 0; Index
< SwapCount
; Index
++) {
713 Temp
= Buffer
[Index
];
714 Buffer
[Index
] = Buffer
[BufferSize
- 1 - Index
];
715 Buffer
[BufferSize
- 1 - Index
] = Temp
;
720 Converts the unicode character of the string from uppercase to lowercase.
721 This is a internal function.
723 @param Str String to be converted
734 for (Ptr
= Str
; *Ptr
!= L
'\0'; Ptr
++) {
735 if (*Ptr
>= L
'A' && *Ptr
<= L
'Z') {
736 *Ptr
= (CHAR16
) (*Ptr
- L
'A' + L
'a');
743 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
745 @param Str String for output
746 @param Buffer Binary buffer.
747 @param BufferSize Size of the buffer in bytes.
749 @retval EFI_SUCCESS The function completed successfully.
750 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
755 BufInReverseOrderToHexString (
765 NewBuffer
= AllocateCopyPool (BufferSize
, Buffer
);
766 if (NewBuffer
== NULL
) {
767 return EFI_OUT_OF_RESOURCES
;
769 SwapBuffer (NewBuffer
, BufferSize
);
771 StrBufferLen
= BufferSize
* sizeof (CHAR16
) + 1;
772 Status
= BufToHexString (Str
, &StrBufferLen
, NewBuffer
, BufferSize
);
774 FreePool (NewBuffer
);
776 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
785 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
787 @param Buffer Pointer to buffer that receives the data.
788 @param BufferSize Length in bytes of the buffer to hold converted
789 data. If routine return with EFI_SUCCESS,
790 containing length of converted data. If routine
791 return with EFI_BUFFER_TOO_SMALL, containg length
793 @param Str String to be converted from.
795 @retval EFI_SUCCESS The function completed successfully.
796 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
797 will be updated to the size required for the converstion.
802 HexStringToBufInReverseOrder (
803 IN OUT UINT8
*Buffer
,
804 IN OUT UINTN
*BufferSize
,
809 UINTN ConvertedStrLen
;
812 Status
= HexStringToBuf (Buffer
, BufferSize
, Str
, &ConvertedStrLen
);
813 if (!EFI_ERROR (Status
)) {
814 SwapBuffer (Buffer
, (ConvertedStrLen
+ 1) / 2);
821 Convert binary representation Config string (e.g. "0041004200430044") to the
822 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
823 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
825 @param UnicodeString Original Unicode string.
826 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
827 Includes tailing '\0' character.
829 If return EFI_SUCCESS, containing length of Unicode string buffer.
830 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
831 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
833 @retval EFI_SUCCESS Operation completes successfully.
834 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
839 ConfigStringToUnicode (
840 IN OUT CHAR16
*UnicodeString
,
841 IN OUT UINTN
*StrBufferLen
,
842 IN CHAR16
*ConfigString
850 Len
= StrLen (ConfigString
) / 4;
851 BufferSize
= (Len
+ 1) * sizeof (CHAR16
);
853 if (*StrBufferLen
< BufferSize
) {
854 *StrBufferLen
= BufferSize
;
855 return EFI_BUFFER_TOO_SMALL
;
858 *StrBufferLen
= BufferSize
;
860 for (Index
= 0; Index
< Len
; Index
++) {
861 BackupChar
= ConfigString
[4];
862 ConfigString
[4] = L
'\0';
864 HexStringToBuf ((UINT8
*) UnicodeString
, &BufferSize
, ConfigString
, NULL
);
866 ConfigString
[4] = BackupChar
;
873 // Add tailing '\0' character
875 *UnicodeString
= L
'\0';
881 Convert Unicode string to binary representation Config string, e.g.
882 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
883 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
885 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
886 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
887 Includes tailing '\0' character.
889 If return EFI_SUCCESS, containing length of Unicode string buffer.
890 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
891 @param UnicodeString Original Unicode string.
893 @retval EFI_SUCCESS Operation completes successfully.
894 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
899 UnicodeToConfigString (
900 IN OUT CHAR16
*ConfigString
,
901 IN OUT UINTN
*StrBufferLen
,
902 IN CHAR16
*UnicodeString
910 Len
= StrLen (UnicodeString
);
911 BufferSize
= (Len
* 4 + 1) * sizeof (CHAR16
);
913 if (*StrBufferLen
< BufferSize
) {
914 *StrBufferLen
= BufferSize
;
915 return EFI_BUFFER_TOO_SMALL
;
918 *StrBufferLen
= BufferSize
;
919 String
= ConfigString
;
921 for (Index
= 0; Index
< Len
; Index
++) {
922 BufToHexString (ConfigString
, &BufferSize
, (UINT8
*) UnicodeString
, 2);
929 // Add tailing '\0' character
931 *ConfigString
= L
'\0';
934 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
941 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
943 @param ConfigHdr Pointer to the ConfigHdr string.
944 @param StrBufferLen On input: Length in bytes of buffer to hold the
945 ConfigHdr string. Includes tailing '\0' character.
946 On output: If return EFI_SUCCESS, containing
947 length of ConfigHdr string buffer. If return
948 EFI_BUFFER_TOO_SMALL, containg length of string
950 @param Guid Routing information: GUID.
951 @param Name Routing information: NAME.
952 @param DriverHandle Driver handle which contains the routing
955 @retval EFI_SUCCESS Operation completes successfully.
956 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
962 IN OUT CHAR16
*ConfigHdr
,
963 IN OUT UINTN
*StrBufferLen
,
964 IN CONST EFI_GUID
*Guid
,
965 IN CHAR16
*Name
, OPTIONAL
966 IN EFI_HANDLE
*DriverHandle
971 UINTN DevicePathSize
;
974 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
977 // Make sure when ConfigHdr is NULL, StrBufferlen must be 0
979 ASSERT (!(ConfigHdr
== NULL
&& *StrBufferLen
!= 0));
983 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
988 // For buffer storage
990 NameStrLen
= StrLen (Name
);
994 // Retrieve DevicePath Protocol associated with this HiiPackageList
996 Status
= gBS
->HandleProtocol (
998 &gEfiDevicePathProtocolGuid
,
999 (VOID
**) &DevicePath
1001 if (EFI_ERROR (Status
)) {
1005 DevicePathSize
= GetDevicePathSize (DevicePath
);
1008 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1009 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1011 BufferSize
= (5 + 32 + 6 + NameStrLen
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
1012 if ((*StrBufferLen
== 0) || *StrBufferLen
< BufferSize
) {
1013 *StrBufferLen
= BufferSize
;
1014 return EFI_BUFFER_TOO_SMALL
;
1017 *StrBufferLen
= BufferSize
;
1021 StrCpy (StrPtr
, L
"GUID=");
1023 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
1027 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
1029 StrCpy (StrPtr
, L
"&NAME=");
1032 BufferSize
= (NameStrLen
* 4 + 1) * sizeof (CHAR16
);
1033 UnicodeToConfigString (StrPtr
, &BufferSize
, Name
);
1034 StrPtr
+= (NameStrLen
* 4);
1037 StrCpy (StrPtr
, L
"&PATH=");
1039 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
1045 Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.
1047 @param ConfigString Either <ConfigRequest> or <ConfigResp>.
1048 @param StorageGuid GUID of the storage.
1049 @param StorageName Name of the stoarge.
1051 @retval TRUE Routing information is correct in ConfigString.
1052 @retval FALSE Routing information is incorrect in ConfigString.
1058 IN EFI_STRING ConfigString
,
1059 IN EFI_GUID
*StorageGuid
, OPTIONAL
1060 IN CHAR16
*StorageName OPTIONAL
1072 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1073 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1075 if (StrLen (ConfigString
) <= (5 + 32 + 6)) {
1082 if (StorageGuid
!= NULL
) {
1084 StrPtr
= ConfigString
+ 5 + 32;
1085 if (*StrPtr
!= L
'&') {
1090 BufferSize
= sizeof (EFI_GUID
);
1091 Status
= HexStringToBufInReverseOrder (
1098 if (EFI_ERROR (Status
)) {
1102 if (!CompareGuid (&Guid
, StorageGuid
)) {
1111 if (StorageName
!= NULL
) {
1112 StrPtr
= ConfigString
+ 5 + 32 + 6;
1113 while (*StrPtr
!= L
'\0' && *StrPtr
!= L
'&') {
1116 if (*StrPtr
!= L
'&') {
1121 BufferSize
= (((UINTN
) StrPtr
) - ((UINTN
) &ConfigString
[5 + 32 + 6])) / 4 + sizeof (CHAR16
);
1122 Name
= AllocatePool (BufferSize
);
1123 ASSERT (Name
!= NULL
);
1124 Status
= ConfigStringToUnicode (
1127 ConfigString
+ 5 + 32 + 6
1131 if (EFI_ERROR (Status
) || (StrCmp (Name
, StorageName
) != 0)) {
1141 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
1143 @param String The string to be searched in.
1144 @param Offset Offset in BlockName.
1145 @param Width Width in BlockName.
1147 @retval TRUE Block name found.
1148 @retval FALSE Block name not found.
1154 IN OUT CHAR16
*String
,
1162 UINTN ConvertedStrLen
;
1164 while ((String
= StrStr (String
, L
"&OFFSET=")) != NULL
) {
1168 String
= String
+ 8;
1171 BufferSize
= sizeof (UINTN
);
1172 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1173 if (EFI_ERROR (Status
)) {
1176 String
= String
+ ConvertedStrLen
;
1178 if (Data
!= Offset
) {
1182 if (StrnCmp (String
, L
"&WIDTH=", 7) != 0) {
1185 String
= String
+ 7;
1188 BufferSize
= sizeof (UINTN
);
1189 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1190 if (EFI_ERROR (Status
)) {
1193 if (Data
== Width
) {
1197 String
= String
+ ConvertedStrLen
;
1205 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
1207 @param VariableGuid An optional field to indicate the target variable
1209 @param VariableName An optional field to indicate the target
1210 human-readable variable name.
1211 @param BufferSize On input: Length in bytes of buffer to hold
1212 retrived data. On output: If return
1213 EFI_BUFFER_TOO_SMALL, containg length of buffer
1215 @param Buffer Buffer to hold retrived data.
1217 @retval EFI_SUCCESS Operation completes successfully.
1218 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
1219 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1225 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1226 IN CONST CHAR16
*VariableName
, OPTIONAL
1227 IN OUT UINTN
*BufferSize
,
1228 IN OUT UINT8
*Buffer
1232 CONST CHAR16
*ConfigHdr
;
1240 // Locate protocols for use
1242 Status
= LocateFormBrowser2Protocols ();
1243 if (EFI_ERROR (Status
)) {
1248 // Retrive formset storage data from Form Browser
1250 ConfigHdr
= mFakeConfigHdr
;
1251 HeaderLen
= StrLen (ConfigHdr
);
1254 // First try allocate 0x4000 buffer for the formet storage data.
1257 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1258 if (ConfigResp
== NULL
) {
1259 return EFI_OUT_OF_RESOURCES
;
1262 StringPtr
= ConfigResp
+ HeaderLen
;
1266 Status
= mFormBrowser2
->BrowserCallback (
1274 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1275 FreePool (ConfigResp
);
1277 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1278 if (ConfigResp
== NULL
) {
1279 return EFI_OUT_OF_RESOURCES
;
1282 StringPtr
= ConfigResp
+ HeaderLen
;
1286 Status
= mFormBrowser2
->BrowserCallback (
1295 if (EFI_ERROR (Status
)) {
1296 FreePool (ConfigResp
);
1299 CopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
1302 // Convert <ConfigResp> to buffer data
1304 Status
= mIfrSupportLibHiiConfigRouting
->ConfigToBlock (
1305 mIfrSupportLibHiiConfigRouting
,
1311 FreePool (ConfigResp
);
1318 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
1320 @param VariableGuid An optional field to indicate the target variable
1322 @param VariableName An optional field to indicate the target
1323 human-readable variable name.
1324 @param BufferSize Length in bytes of buffer to hold retrived data.
1325 @param Buffer Buffer to hold retrived data.
1326 @param RequestElement An optional field to specify which part of the
1327 buffer data will be send back to Browser. If NULL,
1328 the whole buffer of data will be committed to
1329 Browser. <RequestElement> ::=
1330 &OFFSET=<Number>&WIDTH=<Number>*
1332 @retval EFI_SUCCESS Operation completes successfully.
1333 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1334 @retval Other Updating Browser uncommitted data failed.
1340 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1341 IN CONST CHAR16
*VariableName
, OPTIONAL
1342 IN UINTN BufferSize
,
1343 IN CONST UINT8
*Buffer
,
1344 IN CONST CHAR16
*RequestElement OPTIONAL
1348 CONST CHAR16
*ConfigHdr
;
1354 CHAR16 BlockName
[33];
1355 CHAR16
*ConfigRequest
;
1356 CONST CHAR16
*Request
;
1359 // Locate protocols for use
1361 Status
= LocateFormBrowser2Protocols ();
1362 if (EFI_ERROR (Status
)) {
1367 // Prepare <ConfigRequest>
1369 ConfigHdr
= mFakeConfigHdr
;
1370 HeaderLen
= StrLen (ConfigHdr
);
1372 if (RequestElement
== NULL
) {
1374 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
1376 BlockName
[0] = L
'\0';
1377 StrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
1380 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
1382 StringPtr
= BlockName
+ 16;
1383 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
1384 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
1386 Request
= BlockName
;
1388 Request
= RequestElement
;
1391 BufferLen
= HeaderLen
* sizeof (CHAR16
) + StrSize (Request
);
1392 ConfigRequest
= AllocateZeroPool (BufferLen
);
1393 if (ConfigRequest
== NULL
) {
1394 return EFI_OUT_OF_RESOURCES
;
1397 CopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
1398 StringPtr
= ConfigRequest
+ HeaderLen
;
1399 StrCpy (StringPtr
, Request
);
1402 // Convert buffer to <ConfigResp>
1404 Status
= mIfrSupportLibHiiConfigRouting
->BlockToConfig (
1405 mIfrSupportLibHiiConfigRouting
,
1412 if (EFI_ERROR (Status
)) {
1413 FreePool (ConfigRequest
);
1418 // Skip <ConfigHdr> and '&'
1420 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
1423 // Change uncommitted data in Browser
1425 Status
= mFormBrowser2
->BrowserCallback (
1433 FreePool (ConfigRequest
);
1438 Test if a Unicode character is a hexadecimal digit. If true, the input
1439 Unicode character is converted to a byte.
1441 This function tests if a Unicode character is a hexadecimal digit. If true, the input
1442 Unicode character is converted to a byte. For example, Unicode character
1443 L'A' will be converted to 0x0A.
1445 If Digit is NULL, then ASSERT.
1447 @param Digit The output hexadecimal digit.
1449 @param Char The input Unicode character.
1451 @retval TRUE Char is in the range of Hexadecimal number. Digit is updated
1452 to the byte value of the number.
1453 @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep
1464 ASSERT (Digit
!= NULL
);
1466 if ((Char
>= L
'0') && (Char
<= L
'9')) {
1467 *Digit
= (UINT8
) (Char
- L
'0');
1471 if ((Char
>= L
'A') && (Char
<= L
'F')) {
1472 *Digit
= (UINT8
) (Char
- L
'A' + 0x0A);
1476 if ((Char
>= L
'a') && (Char
<= L
'f')) {
1477 *Digit
= (UINT8
) (Char
- L
'a' + 0x0A);
1485 Convert binary buffer to a Unicode String in a specified sequence.
1487 This function converts bytes in the memory block pointed by Buffer to a Unicode String Str.
1488 Each byte will be represented by two Unicode characters. For example, byte 0xA1 will
1489 be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character
1490 for the Most Significant Nibble will be put before the Unicode Character for the Least Significant
1491 Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1".
1492 For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the
1493 the last character in the output string. The one next to first byte will be put into the
1494 character before the last character. This rules applies to the rest of the bytes. The Unicode
1495 character by the last byte will be put into the first character in the output string. For example,
1496 the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to
1497 a Unicode string equal to L"12345678abcdef1234".
1499 @param String On input, String is pointed to the buffer allocated for the convertion.
1500 @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.
1501 The StringLen required to convert a N bytes Buffer will be a least equal to or greater
1503 @param Buffer The pointer to a input buffer.
1504 @param BufferSizeInBytes Length in bytes of the input buffer.
1507 @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding
1508 Unicode character and placed into the right place in String.
1509 @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to
1510 complete the convertion.
1515 IN OUT CHAR16
*String
,
1516 IN OUT UINTN
*StringLen
,
1517 IN CONST UINT8
*Buffer
,
1518 IN UINTN BufferSizeInBytes
1526 // Make sure string is either passed or allocate enough.
1527 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
1528 // Plus the Unicode termination character.
1530 StrLen
= BufferSizeInBytes
* 2;
1531 if (StrLen
> ((*StringLen
) - 1)) {
1532 *StringLen
= StrLen
+ 1;
1533 return RETURN_BUFFER_TOO_SMALL
;
1536 *StringLen
= StrLen
+ 1;
1540 String
[StrLen
] = L
'\0';
1542 for (Idx
= 0; Idx
< BufferSizeInBytes
; Idx
++) {
1544 String
[StrLen
- 1 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
& 0xF];
1545 String
[StrLen
- 2 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
>> 4];
1548 return RETURN_SUCCESS
;
1553 Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.
1555 This function converts a Unicode string consisting of characters in the range of Hexadecimal
1556 character (L'0' to L'9', L'A' to L'F' and L'a' to L'f') to a output byte buffer. The function will stop
1557 at the first non-hexadecimal character or the NULL character. The convertion process can be
1558 simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be
1559 converted into one byte. The first Unicode character represents the Most Significant Nibble and the
1560 second Unicode character represents the Least Significant Nibble in the output byte.
1561 The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode
1562 characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes.
1563 The last pair represent the first byte in the output buffer.
1565 For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes
1566 (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".
1568 If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least
1569 N/2 (if N is even) or (N+1)/2 (if N if odd) bytes.
1571 If either Buffer, BufferSizeInBytes or String is NULL, then ASSERT ().
1573 @param Buffer The output buffer allocated by the caller.
1574 @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to
1575 contain the size of the Buffer which is actually used for the converstion.
1576 For Unicode string with 2*N hexadecimal characters (not including the
1577 tailing NULL character), N bytes of Buffer will be used for the output.
1578 @param String The input hexadecimal string.
1579 @param ConvertedStrLen The number of hexadecimal characters used to produce content in output
1582 @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes
1583 will be updated to the size required for the converstion.
1584 @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String
1585 is hexadecimal. If ConvertedStrLen is not NULL, it is updated
1586 to the number of hexadecimal character used for the converstion.
1592 IN OUT UINTN
*BufferSizeInBytes
,
1593 IN CONST CHAR16
*String
,
1594 OUT UINTN
*ConvertedStrLen OPTIONAL
1603 ASSERT (Buffer
!= NULL
);
1604 ASSERT (BufferSizeInBytes
!= NULL
);
1605 ASSERT (String
!= NULL
);
1608 // Find out how many hex characters the string has.
1610 for (Idx
= 0, HexCnt
= 0; IsHexDigit (&Digit
, String
[Idx
]); Idx
++, HexCnt
++);
1613 *ConvertedStrLen
= 0;
1614 return RETURN_SUCCESS
;
1617 // Two Unicode characters make up 1 buffer byte. Round up.
1619 BufferLength
= (HexCnt
+ 1) / 2;
1622 // Test if buffer is passed enough.
1624 if (BufferLength
> (*BufferSizeInBytes
)) {
1625 *BufferSizeInBytes
= BufferLength
;
1626 return RETURN_BUFFER_TOO_SMALL
;
1629 *BufferSizeInBytes
= BufferLength
;
1631 for (Idx
= 0; Idx
< HexCnt
; Idx
++) {
1633 IsHexDigit (&Digit
, String
[HexCnt
- 1 - Idx
]);
1636 // For odd charaters, write the lower nibble for each buffer byte,
1637 // and for even characters, the upper nibble.
1639 if ((Idx
& 1) == 0) {
1642 Byte
= Buffer
[Idx
/ 2];
1644 Byte
= (UINT8
) (Byte
| Digit
<< 4);
1647 Buffer
[Idx
/ 2] = Byte
;
1650 if (ConvertedStrLen
!= NULL
) {
1651 *ConvertedStrLen
= HexCnt
;
1654 return RETURN_SUCCESS
;