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- 2008, 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
;
978 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
983 // For buffer storage
985 NameStrLen
= StrLen (Name
);
989 // Retrieve DevicePath Protocol associated with this HiiPackageList
991 Status
= gBS
->HandleProtocol (
993 &gEfiDevicePathProtocolGuid
,
994 (VOID
**) &DevicePath
996 if (EFI_ERROR (Status
)) {
1000 DevicePathSize
= GetDevicePathSize (DevicePath
);
1003 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1004 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1006 BufferSize
= (5 + 32 + 6 + NameStrLen
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
1007 if (*StrBufferLen
< BufferSize
) {
1008 *StrBufferLen
= BufferSize
;
1009 return EFI_BUFFER_TOO_SMALL
;
1012 *StrBufferLen
= BufferSize
;
1016 StrCpy (StrPtr
, L
"GUID=");
1018 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
1022 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
1024 StrCpy (StrPtr
, L
"&NAME=");
1027 BufferSize
= (NameStrLen
* 4 + 1) * sizeof (CHAR16
);
1028 UnicodeToConfigString (StrPtr
, &BufferSize
, Name
);
1029 StrPtr
+= (NameStrLen
* 4);
1032 StrCpy (StrPtr
, L
"&PATH=");
1034 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
1040 Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.
1042 @param ConfigString Either <ConfigRequest> or <ConfigResp>.
1043 @param StorageGuid GUID of the storage.
1044 @param StorageName Name of the stoarge.
1046 @retval TRUE Routing information is correct in ConfigString.
1047 @retval FALSE Routing information is incorrect in ConfigString.
1052 IN EFI_STRING ConfigString
,
1053 IN EFI_GUID
*StorageGuid
, OPTIONAL
1054 IN CHAR16
*StorageName OPTIONAL
1066 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
1067 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
1069 if (StrLen (ConfigString
) <= (5 + 32 + 6)) {
1076 if (StorageGuid
!= NULL
) {
1078 StrPtr
= ConfigString
+ 5 + 32;
1079 if (*StrPtr
!= L
'&') {
1084 BufferSize
= sizeof (EFI_GUID
);
1085 Status
= HexStringToBufInReverseOrder (
1092 if (EFI_ERROR (Status
)) {
1096 if (!CompareGuid (&Guid
, StorageGuid
)) {
1105 if (StorageName
!= NULL
) {
1106 StrPtr
= ConfigString
+ 5 + 32 + 6;
1107 while (*StrPtr
!= L
'\0' && *StrPtr
!= L
'&') {
1110 if (*StrPtr
!= L
'&') {
1115 BufferSize
= (((UINTN
) StrPtr
) - ((UINTN
) &ConfigString
[5 + 32 + 6])) / 4 + sizeof (CHAR16
);
1116 Name
= AllocatePool (BufferSize
);
1117 ASSERT (Name
!= NULL
);
1118 Status
= ConfigStringToUnicode (
1121 ConfigString
+ 5 + 32 + 6
1125 if (EFI_ERROR (Status
) || (StrCmp (Name
, StorageName
) != 0)) {
1135 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
1137 @param String The string to be searched in.
1138 @param Offset Offset in BlockName.
1139 @param Width Width in BlockName.
1141 @retval TRUE Block name found.
1142 @retval FALSE Block name not found.
1148 IN OUT CHAR16
*String
,
1156 UINTN ConvertedStrLen
;
1158 while ((String
= StrStr (String
, L
"&OFFSET=")) != NULL
) {
1162 String
= String
+ 8;
1165 BufferSize
= sizeof (UINTN
);
1166 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1167 if (EFI_ERROR (Status
)) {
1170 String
= String
+ ConvertedStrLen
;
1172 if (Data
!= Offset
) {
1176 if (StrnCmp (String
, L
"&WIDTH=", 7) != 0) {
1179 String
= String
+ 7;
1182 BufferSize
= sizeof (UINTN
);
1183 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
1184 if (EFI_ERROR (Status
)) {
1187 if (Data
== Width
) {
1191 String
= String
+ ConvertedStrLen
;
1199 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
1201 @param VariableGuid An optional field to indicate the target variable
1203 @param VariableName An optional field to indicate the target
1204 human-readable variable name.
1205 @param BufferSize On input: Length in bytes of buffer to hold
1206 retrived data. On output: If return
1207 EFI_BUFFER_TOO_SMALL, containg length of buffer
1209 @param Buffer Buffer to hold retrived data.
1211 @retval EFI_SUCCESS Operation completes successfully.
1212 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
1213 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1219 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1220 IN CONST CHAR16
*VariableName
, OPTIONAL
1221 IN OUT UINTN
*BufferSize
,
1222 IN OUT UINT8
*Buffer
1226 CONST CHAR16
*ConfigHdr
;
1234 // Locate protocols for use
1236 Status
= LocateFormBrowser2Protocols ();
1237 if (EFI_ERROR (Status
)) {
1242 // Retrive formset storage data from Form Browser
1244 ConfigHdr
= mFakeConfigHdr
;
1245 HeaderLen
= StrLen (ConfigHdr
);
1248 // First try allocate 0x4000 buffer for the formet storage data.
1251 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1252 if (ConfigResp
== NULL
) {
1253 return EFI_OUT_OF_RESOURCES
;
1256 StringPtr
= ConfigResp
+ HeaderLen
;
1260 Status
= mFormBrowser2
->BrowserCallback (
1268 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1269 FreePool (ConfigResp
);
1271 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
1272 if (ConfigResp
== NULL
) {
1273 return EFI_OUT_OF_RESOURCES
;
1276 StringPtr
= ConfigResp
+ HeaderLen
;
1280 Status
= mFormBrowser2
->BrowserCallback (
1289 if (EFI_ERROR (Status
)) {
1290 FreePool (ConfigResp
);
1293 CopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
1296 // Convert <ConfigResp> to buffer data
1298 Status
= mIfrSupportLibHiiConfigRouting
->ConfigToBlock (
1299 mIfrSupportLibHiiConfigRouting
,
1305 FreePool (ConfigResp
);
1312 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
1314 @param VariableGuid An optional field to indicate the target variable
1316 @param VariableName An optional field to indicate the target
1317 human-readable variable name.
1318 @param BufferSize Length in bytes of buffer to hold retrived data.
1319 @param Buffer Buffer to hold retrived data.
1320 @param RequestElement An optional field to specify which part of the
1321 buffer data will be send back to Browser. If NULL,
1322 the whole buffer of data will be committed to
1323 Browser. <RequestElement> ::=
1324 &OFFSET=<Number>&WIDTH=<Number>*
1326 @retval EFI_SUCCESS Operation completes successfully.
1327 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
1328 @retval Other Updating Browser uncommitted data failed.
1334 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
1335 IN CONST CHAR16
*VariableName
, OPTIONAL
1336 IN UINTN BufferSize
,
1337 IN CONST UINT8
*Buffer
,
1338 IN CONST CHAR16
*RequestElement OPTIONAL
1342 CONST CHAR16
*ConfigHdr
;
1348 CHAR16 BlockName
[33];
1349 CHAR16
*ConfigRequest
;
1350 CONST CHAR16
*Request
;
1353 // Locate protocols for use
1355 Status
= LocateFormBrowser2Protocols ();
1356 if (EFI_ERROR (Status
)) {
1361 // Prepare <ConfigRequest>
1363 ConfigHdr
= mFakeConfigHdr
;
1364 HeaderLen
= StrLen (ConfigHdr
);
1366 if (RequestElement
== NULL
) {
1368 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
1370 BlockName
[0] = L
'\0';
1371 StrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
1374 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
1376 StringPtr
= BlockName
+ 16;
1377 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
1378 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
1380 Request
= BlockName
;
1382 Request
= RequestElement
;
1385 BufferLen
= HeaderLen
* sizeof (CHAR16
) + StrSize (Request
);
1386 ConfigRequest
= AllocateZeroPool (BufferLen
);
1387 if (ConfigRequest
== NULL
) {
1388 return EFI_OUT_OF_RESOURCES
;
1391 CopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
1392 StringPtr
= ConfigRequest
+ HeaderLen
;
1393 StrCpy (StringPtr
, Request
);
1396 // Convert buffer to <ConfigResp>
1398 Status
= mIfrSupportLibHiiConfigRouting
->BlockToConfig (
1399 mIfrSupportLibHiiConfigRouting
,
1406 if (EFI_ERROR (Status
)) {
1407 FreePool (ConfigRequest
);
1412 // Skip <ConfigHdr> and '&'
1414 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
1417 // Change uncommitted data in Browser
1419 Status
= mFormBrowser2
->BrowserCallback (
1427 FreePool (ConfigRequest
);
1432 Test if a Unicode character is a hexadecimal digit. If true, the input
1433 Unicode character is converted to a byte.
1435 This function tests if a Unicode character is a hexadecimal digit. If true, the input
1436 Unicode character is converted to a byte. For example, Unicode character
1437 L'A' will be converted to 0x0A.
1439 If Digit is NULL, then ASSERT.
1441 @param Digit The output hexadecimal digit.
1443 @param Char The input Unicode character.
1445 @retval TRUE Char is in the range of Hexadecimal number. Digit is updated
1446 to the byte value of the number.
1447 @retval FALSE Char is not in the range of Hexadecimal number. Digit is keep
1458 ASSERT (Digit
!= NULL
);
1460 if ((Char
>= L
'0') && (Char
<= L
'9')) {
1461 *Digit
= (UINT8
) (Char
- L
'0');
1465 if ((Char
>= L
'A') && (Char
<= L
'F')) {
1466 *Digit
= (UINT8
) (Char
- L
'A' + 0x0A);
1470 if ((Char
>= L
'a') && (Char
<= L
'f')) {
1471 *Digit
= (UINT8
) (Char
- L
'a' + 0x0A);
1479 Convert binary buffer to a Unicode String in a specified sequence.
1481 This function converts bytes in the memory block pointed by Buffer to a Unicode String Str.
1482 Each byte will be represented by two Unicode characters. For example, byte 0xA1 will
1483 be converted into two Unicode character L'A' and L'1'. In the output String, the Unicode Character
1484 for the Most Significant Nibble will be put before the Unicode Character for the Least Significant
1485 Nibble. The output string for the buffer containing a single byte 0xA1 will be L"A1".
1486 For a buffer with multiple bytes, the Unicode character produced by the first byte will be put into the
1487 the last character in the output string. The one next to first byte will be put into the
1488 character before the last character. This rules applies to the rest of the bytes. The Unicode
1489 character by the last byte will be put into the first character in the output string. For example,
1490 the input buffer for a 64-bits unsigned integer 0x12345678abcdef1234 will be converted to
1491 a Unicode string equal to L"12345678abcdef1234".
1493 @param String On input, String is pointed to the buffer allocated for the convertion.
1494 @param StringLen The Length of String buffer to hold the output String. The length must include the tailing '\0' character.
1495 The StringLen required to convert a N bytes Buffer will be a least equal to or greater
1497 @param Buffer The pointer to a input buffer.
1498 @param BufferSizeInBytes Length in bytes of the input buffer.
1501 @retval EFI_SUCCESS The convertion is successful. All bytes in Buffer has been convert to the corresponding
1502 Unicode character and placed into the right place in String.
1503 @retval EFI_BUFFER_TOO_SMALL StringSizeInBytes is smaller than 2 * N + 1the number of bytes required to
1504 complete the convertion.
1509 IN OUT CHAR16
*String
,
1510 IN OUT UINTN
*StringLen
,
1511 IN CONST UINT8
*Buffer
,
1512 IN UINTN BufferSizeInBytes
1520 // Make sure string is either passed or allocate enough.
1521 // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
1522 // Plus the Unicode termination character.
1524 StrLen
= BufferSizeInBytes
* 2;
1525 if (StrLen
> ((*StringLen
) - 1)) {
1526 *StringLen
= StrLen
+ 1;
1527 return RETURN_BUFFER_TOO_SMALL
;
1530 *StringLen
= StrLen
+ 1;
1534 String
[StrLen
] = L
'\0';
1536 for (Idx
= 0; Idx
< BufferSizeInBytes
; Idx
++) {
1538 String
[StrLen
- 1 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
& 0xF];
1539 String
[StrLen
- 2 - Idx
* 2] = mIfrSupportLibHexStr
[Byte
>> 4];
1542 return RETURN_SUCCESS
;
1547 Convert a Unicode string consisting of hexadecimal characters to a output byte buffer.
1549 This function converts a Unicode string consisting of characters in the range of Hexadecimal
1550 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
1551 at the first non-hexadecimal character or the NULL character. The convertion process can be
1552 simply viewed as the reverse operations defined by BufToHexString. Two Unicode characters will be
1553 converted into one byte. The first Unicode character represents the Most Significant Nibble and the
1554 second Unicode character represents the Least Significant Nibble in the output byte.
1555 The first pair of Unicode characters represents the last byte in the output buffer. The second pair of Unicode
1556 characters represent the the byte preceding the last byte. This rule applies to the rest pairs of bytes.
1557 The last pair represent the first byte in the output buffer.
1559 For example, a Unciode String L"12345678" will be converted into a buffer wil the following bytes
1560 (first byte is the byte in the lowest memory address): "0x78, 0x56, 0x34, 0x12".
1562 If String has N valid hexadecimal characters for conversion, the caller must make sure Buffer is at least
1563 N/2 (if N is even) or (N+1)/2 (if N if odd) bytes.
1565 @param Buffer The output buffer allocated by the caller.
1566 @param BufferSizeInBytes On input, the size in bytes of Buffer. On output, it is updated to
1567 contain the size of the Buffer which is actually used for the converstion.
1568 For Unicode string with 2*N hexadecimal characters (not including the
1569 tailing NULL character), N bytes of Buffer will be used for the output.
1570 @param String The input hexadecimal string.
1571 @param ConvertedStrLen The number of hexadecimal characters used to produce content in output
1574 @retval RETURN_BUFFER_TOO_SMALL The input BufferSizeInBytes is too small to hold the output. BufferSizeInBytes
1575 will be updated to the size required for the converstion.
1576 @retval RETURN_SUCCESS The convertion is successful or the first Unicode character from String
1577 is hexadecimal. If ConvertedStrLen is not NULL, it is updated
1578 to the number of hexadecimal character used for the converstion.
1584 IN OUT UINTN
*BufferSizeInBytes
,
1585 IN CONST CHAR16
*String
,
1586 OUT UINTN
*ConvertedStrLen OPTIONAL
1596 // Find out how many hex characters the string has.
1598 for (Idx
= 0, HexCnt
= 0; IsHexDigit (&Digit
, String
[Idx
]); Idx
++, HexCnt
++);
1601 *ConvertedStrLen
= 0;
1602 return RETURN_SUCCESS
;
1605 // Two Unicode characters make up 1 buffer byte. Round up.
1607 BufferLength
= (HexCnt
+ 1) / 2;
1610 // Test if buffer is passed enough.
1612 if (BufferLength
> (*BufferSizeInBytes
)) {
1613 *BufferSizeInBytes
= BufferLength
;
1614 return RETURN_BUFFER_TOO_SMALL
;
1617 *BufferSizeInBytes
= BufferLength
;
1619 for (Idx
= 0; Idx
< HexCnt
; Idx
++) {
1621 IsHexDigit (&Digit
, String
[HexCnt
- 1 - Idx
]);
1624 // For odd charaters, write the lower nibble for each buffer byte,
1625 // and for even characters, the upper nibble.
1627 if ((Idx
& 1) == 0) {
1630 Byte
= Buffer
[Idx
/ 2];
1632 Byte
= (UINT8
) (Byte
| Digit
<< 4);
1635 Buffer
[Idx
/ 2] = Byte
;
1638 if (ConvertedStrLen
!= NULL
) {
1639 *ConvertedStrLen
= HexCnt
;
1642 return RETURN_SUCCESS
;