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
;
22 This function locate FormBrowser2 protocols for later usage.
24 @return Status the status to locate protocol.
27 LocateFormBrowser2Protocols (
33 // Locate protocols for later usage
35 if (mFormBrowser2
== NULL
) {
36 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &mFormBrowser2
);
37 if (EFI_ERROR (Status
)) {
42 if (mIfrSupportLibHiiConfigRouting
== NULL
) {
43 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &mIfrSupportLibHiiConfigRouting
);
44 if (EFI_ERROR (Status
)) {
55 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
58 Draw a dialog and return the selected key.
60 @param NumberOfLines The number of lines for the dialog box
61 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
62 @param Marker A series of (quantity == NumberOfLines - 1) text
63 strings which will be used to construct the dialog
66 @retval EFI_SUCCESS Displayed dialog and received user interaction
67 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
68 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
74 IN UINTN NumberOfLines
,
75 OUT EFI_INPUT_KEY
*KeyValue
,
88 UINTN DimensionsWidth
;
89 UINTN DimensionsHeight
;
98 EFI_EVENT WaitList
[2];
99 UINTN CurrentAttribute
;
100 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
103 String
= VA_ARG (Marker
, CHAR16
*);
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
, KeyValue
);
291 Status
= IfrLibCreatePopUp2 (NumberOfLines
, KeyValue
, Marker
);
299 Swap bytes in the buffer. This is a internal function.
301 @param Buffer Binary buffer.
302 @param BufferSize Size of the buffer in bytes.
309 IN OUT UINT8
*Buffer
,
317 SwapCount
= BufferSize
/ 2;
318 for (Index
= 0; Index
< SwapCount
; Index
++) {
319 Temp
= Buffer
[Index
];
320 Buffer
[Index
] = Buffer
[BufferSize
- 1 - Index
];
321 Buffer
[BufferSize
- 1 - Index
] = Temp
;
326 Converts the unicode character of the string from uppercase to lowercase.
327 This is a internal function.
329 @param Str String to be converted
340 for (Ptr
= Str
; *Ptr
!= L
'\0'; Ptr
++) {
341 if (*Ptr
>= L
'A' && *Ptr
<= L
'Z') {
342 *Ptr
= (CHAR16
) (*Ptr
- L
'A' + L
'a');
349 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
351 @param Str String for output
352 @param Buffer Binary buffer.
353 @param BufferSize Size of the buffer in bytes.
355 @retval EFI_SUCCESS The function completed successfully.
356 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
361 BufInReverseOrderToHexString (
371 NewBuffer
= AllocateCopyPool (BufferSize
, Buffer
);
372 if (NewBuffer
== NULL
) {
373 return EFI_OUT_OF_RESOURCES
;
375 SwapBuffer (NewBuffer
, BufferSize
);
377 StrBufferLen
= BufferSize
* sizeof (CHAR16
) + 1;
378 Status
= BufToHexString (Str
, &StrBufferLen
, NewBuffer
, BufferSize
);
380 FreePool (NewBuffer
);
382 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
391 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
393 @param Buffer Pointer to buffer that receives the data.
394 @param BufferSize Length in bytes of the buffer to hold converted
395 data. If routine return with EFI_SUCCESS,
396 containing length of converted data. If routine
397 return with EFI_BUFFER_TOO_SMALL, containg length
399 @param Str String to be converted from.
401 @retval EFI_SUCCESS The function completed successfully.
402 @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
403 will be updated to the size required for the converstion.
408 HexStringToBufInReverseOrder (
409 IN OUT UINT8
*Buffer
,
410 IN OUT UINTN
*BufferSize
,
415 UINTN ConvertedStrLen
;
418 Status
= HexStringToBuf (Buffer
, BufferSize
, Str
, &ConvertedStrLen
);
419 if (!EFI_ERROR (Status
)) {
420 SwapBuffer (Buffer
, ConvertedStrLen
);
427 Convert binary representation Config string (e.g. "0041004200430044") to the
428 original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
429 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
431 @param UnicodeString Original Unicode string.
432 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
433 Includes tailing '\0' character.
435 If return EFI_SUCCESS, containing length of Unicode string buffer.
436 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
437 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
439 @retval EFI_SUCCESS Operation completes successfully.
440 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
445 ConfigStringToUnicode (
446 IN OUT CHAR16
*UnicodeString
,
447 IN OUT UINTN
*StrBufferLen
,
448 IN CHAR16
*ConfigString
456 Len
= StrLen (ConfigString
) / 4;
457 BufferSize
= (Len
+ 1) * sizeof (CHAR16
);
459 if (*StrBufferLen
< BufferSize
) {
460 *StrBufferLen
= BufferSize
;
461 return EFI_BUFFER_TOO_SMALL
;
464 *StrBufferLen
= BufferSize
;
466 for (Index
= 0; Index
< Len
; Index
++) {
467 BackupChar
= ConfigString
[4];
468 ConfigString
[4] = L
'\0';
470 HexStringToBuf ((UINT8
*) UnicodeString
, &BufferSize
, ConfigString
, NULL
);
472 ConfigString
[4] = BackupChar
;
479 // Add tailing '\0' character
481 *UnicodeString
= L
'\0';
487 Convert Unicode string to binary representation Config string, e.g.
488 "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
489 "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
491 @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
492 @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
493 Includes tailing '\0' character.
495 If return EFI_SUCCESS, containing length of Unicode string buffer.
496 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
497 @param UnicodeString Original Unicode string.
499 @retval EFI_SUCCESS Operation completes successfully.
500 @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
505 UnicodeToConfigString (
506 IN OUT CHAR16
*ConfigString
,
507 IN OUT UINTN
*StrBufferLen
,
508 IN CHAR16
*UnicodeString
516 Len
= StrLen (UnicodeString
);
517 BufferSize
= (Len
* 4 + 1) * sizeof (CHAR16
);
519 if (*StrBufferLen
< BufferSize
) {
520 *StrBufferLen
= BufferSize
;
521 return EFI_BUFFER_TOO_SMALL
;
524 *StrBufferLen
= BufferSize
;
525 String
= ConfigString
;
527 for (Index
= 0; Index
< Len
; Index
++) {
528 BufToHexString (ConfigString
, &BufferSize
, (UINT8
*) UnicodeString
, 2);
535 // Add tailing '\0' character
537 *ConfigString
= L
'\0';
540 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
547 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
549 @param ConfigHdr Pointer to the ConfigHdr string.
550 @param StrBufferLen On input: Length in bytes of buffer to hold the
551 ConfigHdr string. Includes tailing '\0' character.
552 On output: If return EFI_SUCCESS, containing
553 length of ConfigHdr string buffer. If return
554 EFI_BUFFER_TOO_SMALL, containg length of string
556 @param Guid Routing information: GUID.
557 @param Name Routing information: NAME.
558 @param DriverHandle Driver handle which contains the routing
561 @retval EFI_SUCCESS Operation completes successfully.
562 @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
568 IN OUT CHAR16
*ConfigHdr
,
569 IN OUT UINTN
*StrBufferLen
,
570 IN CONST EFI_GUID
*Guid
,
571 IN CHAR16
*Name
, OPTIONAL
572 IN EFI_HANDLE
*DriverHandle
577 UINTN DevicePathSize
;
580 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
584 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
589 // For buffer storage
591 NameStrLen
= StrLen (Name
);
595 // Retrieve DevicePath Protocol associated with this HiiPackageList
597 Status
= gBS
->HandleProtocol (
599 &gEfiDevicePathProtocolGuid
,
600 (VOID
**) &DevicePath
602 if (EFI_ERROR (Status
)) {
606 DevicePathSize
= GetDevicePathSize (DevicePath
);
609 // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
610 // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
612 BufferSize
= (5 + 32 + 6 + NameStrLen
* 4 + 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
613 if (*StrBufferLen
< BufferSize
) {
614 *StrBufferLen
= BufferSize
;
615 return EFI_BUFFER_TOO_SMALL
;
618 *StrBufferLen
= BufferSize
;
622 StrCpy (StrPtr
, L
"GUID=");
624 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
628 // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
630 StrCpy (StrPtr
, L
"&NAME=");
633 BufferSize
= (NameStrLen
* 4 + 1) * sizeof (CHAR16
);
634 UnicodeToConfigString (StrPtr
, &BufferSize
, Name
);
635 StrPtr
+= (NameStrLen
* 4);
638 StrCpy (StrPtr
, L
"&PATH=");
640 BufInReverseOrderToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
647 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
649 @param String The string to be searched in.
650 @param Offset Offset in BlockName.
651 @param Width Width in BlockName.
653 @retval TRUE Block name found.
654 @retval FALSE Block name not found.
660 IN OUT CHAR16
*String
,
668 UINTN ConvertedStrLen
;
670 while ((String
= StrStr (String
, L
"&OFFSET=")) != NULL
) {
677 BufferSize
= sizeof (UINTN
);
678 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
679 if (EFI_ERROR (Status
)) {
682 String
= String
+ ConvertedStrLen
;
684 if (Data
!= Offset
) {
688 if (StrnCmp (String
, L
"&WIDTH=", 7) != 0) {
694 BufferSize
= sizeof (UINTN
);
695 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
696 if (EFI_ERROR (Status
)) {
703 String
= String
+ ConvertedStrLen
;
711 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
713 @param VariableGuid An optional field to indicate the target variable
715 @param VariableName An optional field to indicate the target
716 human-readable variable name.
717 @param BufferSize On input: Length in bytes of buffer to hold
718 retrived data. On output: If return
719 EFI_BUFFER_TOO_SMALL, containg length of buffer
721 @param Buffer Buffer to hold retrived data.
723 @retval EFI_SUCCESS Operation completes successfully.
724 @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
725 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
731 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
732 IN CONST CHAR16
*VariableName
, OPTIONAL
733 IN OUT UINTN
*BufferSize
,
738 CONST CHAR16
*ConfigHdr
;
746 // Locate protocols for use
748 Status
= LocateFormBrowser2Protocols ();
749 if (EFI_ERROR (Status
)) {
754 // Retrive formset storage data from Form Browser
756 ConfigHdr
= mFakeConfigHdr
;
757 HeaderLen
= StrLen (ConfigHdr
);
760 // First try allocate 0x4000 buffer for the formet storage data.
763 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
764 if (ConfigResp
== NULL
) {
768 StringPtr
= ConfigResp
+ HeaderLen
;
772 Status
= mFormBrowser2
->BrowserCallback (
780 if (Status
== EFI_BUFFER_TOO_SMALL
) {
781 if (ConfigResp
!= NULL
) {
782 FreePool (ConfigResp
);
785 ConfigResp
= AllocateZeroPool (BufferLen
+ HeaderLen
);
786 if (ConfigResp
== NULL
) {
787 return EFI_OUT_OF_RESOURCES
;
790 StringPtr
= ConfigResp
+ HeaderLen
;
794 Status
= mFormBrowser2
->BrowserCallback (
803 if (EFI_ERROR (Status
)) {
804 FreePool (ConfigResp
);
807 CopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
810 // Convert <ConfigResp> to buffer data
812 Status
= mIfrSupportLibHiiConfigRouting
->ConfigToBlock (
813 mIfrSupportLibHiiConfigRouting
,
819 FreePool (ConfigResp
);
826 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
828 @param VariableGuid An optional field to indicate the target variable
830 @param VariableName An optional field to indicate the target
831 human-readable variable name.
832 @param BufferSize Length in bytes of buffer to hold retrived data.
833 @param Buffer Buffer to hold retrived data.
834 @param RequestElement An optional field to specify which part of the
835 buffer data will be send back to Browser. If NULL,
836 the whole buffer of data will be committed to
837 Browser. <RequestElement> ::=
838 &OFFSET=<Number>&WIDTH=<Number>*
840 @retval EFI_SUCCESS Operation completes successfully.
841 @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
842 @retval Other Updating Browser uncommitted data failed.
848 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
849 IN CONST CHAR16
*VariableName
, OPTIONAL
851 IN CONST UINT8
*Buffer
,
852 IN CONST CHAR16
*RequestElement OPTIONAL
856 CONST CHAR16
*ConfigHdr
;
862 CHAR16 BlockName
[33];
863 CHAR16
*ConfigRequest
;
864 CONST CHAR16
*Request
;
867 // Locate protocols for use
869 Status
= LocateFormBrowser2Protocols ();
870 if (EFI_ERROR (Status
)) {
875 // Prepare <ConfigRequest>
877 ConfigHdr
= mFakeConfigHdr
;
878 HeaderLen
= StrLen (ConfigHdr
);
880 if (RequestElement
== NULL
) {
882 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
884 BlockName
[0] = L
'\0';
885 StrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
888 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
890 StringPtr
= BlockName
+ 16;
891 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
892 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
896 Request
= RequestElement
;
899 BufferLen
= HeaderLen
* sizeof (CHAR16
) + StrSize (Request
);
900 ConfigRequest
= AllocateZeroPool (BufferLen
);
901 if (ConfigRequest
== NULL
) {
902 return EFI_OUT_OF_RESOURCES
;
905 CopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
906 StringPtr
= ConfigRequest
+ HeaderLen
;
907 StrCpy (StringPtr
, Request
);
910 // Convert buffer to <ConfigResp>
912 Status
= mIfrSupportLibHiiConfigRouting
->BlockToConfig (
913 mIfrSupportLibHiiConfigRouting
,
920 if (EFI_ERROR (Status
)) {
921 FreePool (ConfigRequest
);
926 // Skip <ConfigHdr> and '&'
928 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
931 // Change uncommitted data in Browser
933 Status
= mFormBrowser2
->BrowserCallback (
941 FreePool (ConfigRequest
);