3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Common Library Routines to assist handle HII elements.
22 #include "UefiIfrLibrary.h"
27 UINT16 mFakeConfigHdr
[] = L
"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
31 GetPackageDataFromPackageList (
32 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
33 IN UINT32 PackageIndex
,
34 OUT UINT32
*BufferLen
,
35 OUT EFI_HII_PACKAGE_HEADER
**Buffer
39 EFI_HII_PACKAGE_HEADER
*Package
;
41 UINT32 PackageListLength
;
42 EFI_HII_PACKAGE_HEADER PackageHeader
= {0, 0};
44 ASSERT(HiiPackageList
!= NULL
);
46 if ((BufferLen
== NULL
) || (Buffer
== NULL
)) {
47 return EFI_INVALID_PARAMETER
;
52 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
53 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
54 while (Offset
< PackageListLength
) {
55 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
56 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
57 if (Index
== PackageIndex
) {
60 Offset
+= PackageHeader
.Length
;
63 if (Offset
>= PackageListLength
) {
65 // no package found in this Package List
70 *BufferLen
= PackageHeader
.Length
;
77 UpdateFormPackageData (
78 IN EFI_GUID
*FormSetGuid
,
79 IN EFI_FORM_ID FormId
,
80 IN EFI_HII_PACKAGE_HEADER
*Package
,
81 IN UINT32 PackageLength
,
84 IN EFI_HII_UPDATE_DATA
*Data
,
85 OUT UINT8
**TempBuffer
,
86 OUT UINT32
*TempBufferSize
91 EFI_HII_PACKAGE_HEADER PackageHeader
;
93 EFI_IFR_OP_HEADER
*IfrOpHdr
;
99 EFI_IFR_OP_HEADER
*AddOpCode
;
101 if ((TempBuffer
== NULL
) || (TempBufferSize
== NULL
)) {
102 return EFI_INVALID_PARAMETER
;
105 *TempBufferSize
= PackageLength
;
107 *TempBufferSize
+= Data
->Offset
;
109 *TempBuffer
= EfiLibAllocateZeroPool (*TempBufferSize
);
110 if (*TempBuffer
== NULL
) {
111 return EFI_OUT_OF_RESOURCES
;
114 EfiCopyMem (*TempBuffer
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
115 *TempBufferSize
= sizeof (EFI_HII_PACKAGE_HEADER
);
116 BufferPos
= *TempBuffer
+ sizeof (EFI_HII_PACKAGE_HEADER
);
118 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
119 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
120 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
121 GetFormSet
= (BOOLEAN
)((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
125 while (Offset
< PackageHeader
.Length
) {
126 EfiCopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
127 BufferPos
+= IfrOpHdr
->Length
;
128 *TempBufferSize
+= IfrOpHdr
->Length
;
130 switch (IfrOpHdr
->OpCode
) {
131 case EFI_IFR_FORM_SET_OP
:
132 if (FormSetGuid
!= NULL
) {
133 if (EfiCompareMem (&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
, sizeof (EFI_GUID
)) == 0) {
139 case EFI_IFR_FORM_OP
:
140 if (EfiCompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
145 case EFI_IFR_GUID_OP
:
146 if (!GetFormSet
|| !GetForm
|| Updated
) {
148 // Go to the next Op-Code
150 Offset
+= IfrOpHdr
->Length
;
151 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
155 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
156 EfiCopyMem (&LabelNumber
, &((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Number
, sizeof (UINT16
));
157 if ((ExtendOpCode
!= EFI_IFR_EXTEND_OP_LABEL
) || (LabelNumber
!= Label
)) {
159 // Go to the next Op-Code
161 Offset
+= IfrOpHdr
->Length
;
162 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
166 if (Insert
&& (Data
!= NULL
)) {
168 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
169 // DataCount amount of opcodes unless runing into a label.
171 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
173 while (AddSize
< Data
->Offset
) {
174 EfiCopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
175 BufferPos
+= AddOpCode
->Length
;
176 *TempBufferSize
+= AddOpCode
->Length
;
178 AddSize
+= AddOpCode
->Length
;
179 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
183 // Search the next Label.
186 Offset
+= IfrOpHdr
->Length
;
188 // Search the next label and Fail if not label found.
190 if (Offset
>= PackageHeader
.Length
) {
193 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
194 if (IfrOpHdr
->OpCode
== EFI_IFR_GUID_OP
) {
195 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
196 if (ExtendOpCode
== EFI_IFR_EXTEND_OP_LABEL
) {
203 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
205 while (AddSize
< Data
->Offset
) {
206 EfiCopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
207 BufferPos
+= AddOpCode
->Length
;
208 *TempBufferSize
+= AddOpCode
->Length
;
210 AddSize
+= AddOpCode
->Length
;
211 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
216 // copy the next label
218 EfiCopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
219 BufferPos
+= IfrOpHdr
->Length
;
220 *TempBufferSize
+= IfrOpHdr
->Length
;
230 // Go to the next Op-Code
232 Offset
+= IfrOpHdr
->Length
;
233 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
237 // Update the package length.
239 PackageHeader
.Length
= *TempBufferSize
;
240 EfiCopyMem (*TempBuffer
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
244 gBS
->FreePool (*TempBuffer
);
246 return EFI_NOT_FOUND
;
254 IN EFI_HII_HANDLE Handle
,
255 IN EFI_GUID
*FormSetGuid
, OPTIONAL
256 IN EFI_FORM_ID FormId
,
259 IN EFI_HII_UPDATE_DATA
*Data
264 This function allows the caller to update a form that has
265 previously been registered with the EFI HII database.
269 FormSetGuid - The formset should be updated.
270 FormId - The form should be updated.
271 Label - Update information starting immediately after this label in the IFR
272 Insert - If TRUE and Data is not NULL, insert data after Label.
273 If FALSE, replace opcodes between two labels with Data
274 Data - The adding data; If NULL, remove opcodes between two Label.
277 EFI_SUCCESS - Update success.
283 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
284 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
286 EFI_HII_PACKAGE_LIST_HEADER
*UpdateBuffer
;
288 UINT8
*UpdateBufferPos
;
289 EFI_HII_PACKAGE_HEADER PackageHeader
;
290 EFI_HII_PACKAGE_HEADER
*Package
;
291 UINT32 PackageLength
;
292 EFI_HII_PACKAGE_HEADER
*TempBuffer
;
293 UINT32 TempBufferSize
;
297 return EFI_INVALID_PARAMETER
;
300 LocateHiiProtocols ();
301 HiiDatabase
= gIfrLibHiiDatabase
;
304 // Get the orginal package list
307 HiiPackageList
= NULL
;
308 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
309 if (Status
== EFI_BUFFER_TOO_SMALL
) {
310 HiiPackageList
= EfiLibAllocatePool (BufferSize
);
311 ASSERT (HiiPackageList
!= NULL
);
313 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
314 if (EFI_ERROR (Status
)) {
315 gBS
->FreePool (HiiPackageList
);
321 // Calculate and allocate space for retrieval of IFR data
323 BufferSize
+= Data
->Offset
;
324 UpdateBuffer
= EfiLibAllocateZeroPool (BufferSize
);
325 if (UpdateBuffer
== NULL
) {
326 return EFI_OUT_OF_RESOURCES
;
329 UpdateBufferPos
= (UINT8
*) UpdateBuffer
;
332 // copy the package list header
334 EfiCopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
335 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
338 for (Index
= 0; ; Index
++) {
339 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
340 if (Status
== EFI_SUCCESS
) {
341 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
342 if ((PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) && !Updated
) {
343 Status
= UpdateFormPackageData (FormSetGuid
, FormId
, Package
, PackageLength
, Label
, Insert
, Data
, (UINT8
**)&TempBuffer
, &TempBufferSize
);
344 if (!EFI_ERROR(Status
)) {
345 if (FormSetGuid
== NULL
) {
348 EfiCopyMem (UpdateBufferPos
, TempBuffer
, TempBufferSize
);
349 UpdateBufferPos
+= TempBufferSize
;
350 gBS
->FreePool (TempBuffer
);
355 EfiCopyMem (UpdateBufferPos
, Package
, PackageLength
);
356 UpdateBufferPos
+= PackageLength
;
357 } else if (Status
== EFI_NOT_FOUND
) {
360 gBS
->FreePool (HiiPackageList
);
366 // Update package list length
368 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdateBuffer
;
369 EfiCopyMem (&UpdateBuffer
->PackageLength
, &BufferSize
, sizeof (UINT32
));
371 gBS
->FreePool (HiiPackageList
);
373 return HiiDatabase
->UpdatePackageList (HiiDatabase
, Handle
, UpdateBuffer
);
378 IN UINTN NumberOfLines
,
379 OUT EFI_INPUT_KEY
*KeyValue
,
386 Draw a dialog and return the selected key.
389 NumberOfLines - The number of lines for the dialog box
390 KeyValue - The EFI_KEY value returned if HotKey is TRUE..
391 String - Pointer to the first string in the list
392 ... - A series of (quantity == NumberOfLines) text strings which
393 will be used to construct the dialog box
396 EFI_SUCCESS - Displayed dialog and received user interaction
397 EFI_INVALID_PARAMETER - One of the parameters was invalid.
412 UINTN DimensionsWidth
;
413 UINTN DimensionsHeight
;
421 CHAR16
**StringArray
;
422 EFI_EVENT TimerEvent
;
423 EFI_EVENT WaitList
[2];
424 UINTN CurrentAttribute
;
425 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*ConOut
;
427 if ((KeyValue
== NULL
) || (String
== NULL
)) {
428 return EFI_INVALID_PARAMETER
;
436 ConOut
= gST
->ConOut
;
437 ConOut
->QueryMode (ConOut
, ConOut
->Mode
->Mode
, &RightColumn
, &BottomRow
);
439 DimensionsWidth
= RightColumn
- LeftColumn
;
440 DimensionsHeight
= BottomRow
- TopRow
;
442 CurrentAttribute
= ConOut
->Mode
->Attribute
;
444 LineBuffer
= EfiLibAllocateZeroPool (DimensionsWidth
* sizeof (CHAR16
));
445 ASSERT (LineBuffer
!= NULL
);
448 // Determine the largest string in the dialog box
449 // Notice we are starting with 1 since String is the first string
451 StringArray
= EfiLibAllocateZeroPool (NumberOfLines
* sizeof (CHAR16
*));
452 LargestString
= EfiStrLen (String
);
453 StringArray
[0] = String
;
455 VA_START (Marker
, String
);
456 for (Index
= 1; Index
< NumberOfLines
; Index
++) {
457 StackString
= VA_ARG (Marker
, CHAR16
*);
459 if (StackString
== NULL
) {
460 return EFI_INVALID_PARAMETER
;
463 StringArray
[Index
] = StackString
;
464 StringLen
= EfiStrLen (StackString
);
465 if (StringLen
> LargestString
) {
466 LargestString
= StringLen
;
470 if ((LargestString
+ 2) > DimensionsWidth
) {
471 LargestString
= DimensionsWidth
- 2;
475 // Subtract the PopUp width from total Columns, allow for one space extra on
476 // each end plus a border.
478 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + LeftColumn
+ 1;
479 End
= Start
+ LargestString
+ 1;
481 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + TopRow
- 1;
482 Bottom
= Top
+ NumberOfLines
+ 2;
487 ConOut
->EnableCursor (ConOut
, FALSE
);
488 ConOut
->SetAttribute (ConOut
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
490 StringPtr
= &LineBuffer
[0];
491 *StringPtr
++ = BOXDRAW_DOWN_RIGHT
;
492 for (Index
= 0; Index
< LargestString
; Index
++) {
493 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
495 *StringPtr
++ = BOXDRAW_DOWN_LEFT
;
498 ConOut
->SetCursorPosition (ConOut
, Start
, Top
);
499 ConOut
->OutputString (ConOut
, LineBuffer
);
501 for (Index
= 0; Index
< NumberOfLines
; Index
++) {
502 StringPtr
= &LineBuffer
[0];
503 *StringPtr
++ = BOXDRAW_VERTICAL
;
505 for (Count
= 0; Count
< LargestString
; Count
++) {
506 StringPtr
[Count
] = L
' ';
509 StringLen
= EfiStrLen (StringArray
[Index
]);
510 if (StringLen
> LargestString
) {
511 StringLen
= LargestString
;
514 StringPtr
+ ((LargestString
- StringLen
) / 2),
516 StringLen
* sizeof (CHAR16
)
518 StringPtr
+= LargestString
;
520 *StringPtr
++ = BOXDRAW_VERTICAL
;
523 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ 1 + Index
);
524 ConOut
->OutputString (ConOut
, LineBuffer
);
527 StringPtr
= &LineBuffer
[0];
528 *StringPtr
++ = BOXDRAW_UP_RIGHT
;
529 for (Index
= 0; Index
< LargestString
; Index
++) {
530 *StringPtr
++ = BOXDRAW_HORIZONTAL
;
532 *StringPtr
++ = BOXDRAW_UP_LEFT
;
535 ConOut
->SetCursorPosition (ConOut
, Start
, Top
+ NumberOfLines
+ 1);
536 ConOut
->OutputString (ConOut
, LineBuffer
);
539 Status
= gBS
->CreateEvent (EFI_EVENT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
542 // Set a timer event of 1 second expiration
551 // Wait for the keystroke event or the timer
553 WaitList
[0] = gST
->ConIn
->WaitForKey
;
554 WaitList
[1] = TimerEvent
;
555 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
558 // Check for the timer expiration
560 if (!EFI_ERROR (Status
) && Index
== 1) {
561 Status
= EFI_TIMEOUT
;
564 gBS
->CloseEvent (TimerEvent
);
565 } while (Status
== EFI_TIMEOUT
);
567 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
568 EfiCopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
570 ConOut
->SetAttribute (ConOut
, CurrentAttribute
);
571 ConOut
->EnableCursor (ConOut
, TRUE
);
579 IN UINTN
*BufferSize
,
587 Configure the buffer accrording to ConfigBody strings.
590 DefaultId - the ID of default.
591 Buffer - the start address of buffer.
592 BufferSize - the size of buffer.
593 Number - the number of the strings.
596 EFI_BUFFER_TOO_SMALL - the BufferSize is too small to operate.
597 EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0.
598 EFI_SUCCESS - Operation successful.
611 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
612 return EFI_INVALID_PARAMETER
;
619 VA_START (Args
, Number
);
620 for (Index
= 0; Index
< Number
; Index
++) {
621 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
622 EfiCopyMem (&TotalLen
, BufCfgArray
, sizeof (UINT32
));
623 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
625 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
626 EfiCopyMem (&Offset
, BufferPos
, sizeof (UINT16
));
627 BufferPos
+= sizeof (UINT16
);
628 EfiCopyMem (&Width
, BufferPos
, sizeof (UINT16
));
629 BufferPos
+= sizeof (UINT16
);
633 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
634 return EFI_BUFFER_TOO_SMALL
;
637 EfiCopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
642 *BufferSize
= (UINTN
)Offset
;
650 IN OUT UINT8
*Buffer
,
656 Swap bytes in the buffer.
659 Buffer - Binary buffer.
660 BufferSize - Size of the buffer in bytes.
671 SwapCount
= (BufferSize
- 1) / 2;
672 for (Index
= 0; Index
< SwapCount
; Index
++) {
673 Temp
= Buffer
[Index
];
674 Buffer
[Index
] = Buffer
[BufferSize
- 1 - Index
];
675 Buffer
[BufferSize
- 1 - Index
] = Temp
;
688 Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
691 Str - String for output
692 Buffer - Binary buffer.
693 BufferSize - Size of the buffer in bytes.
696 EFI_SUCCESS - The function completed successfully.
704 NewBuffer
= EfiLibAllocateCopyPool (BufferSize
, Buffer
);
705 SwapBuffer (NewBuffer
, BufferSize
);
707 StrBufferLen
= (BufferSize
+ 1) * sizeof (CHAR16
);
708 Status
= BufToHexString (Str
, &StrBufferLen
, NewBuffer
, BufferSize
);
710 gBS
->FreePool (NewBuffer
);
717 IN OUT UINT8
*Buffer
,
718 IN OUT UINTN
*BufferSize
,
724 Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
727 Buffer - Pointer to buffer that receives the data.
728 BufferSize - Length in bytes of the buffer to hold converted data.
729 If routine return with EFI_SUCCESS, containing length of converted data.
730 If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
731 Str - String to be converted from.
734 EFI_SUCCESS - The function completed successfully.
739 UINTN ConvertedStrLen
;
742 Status
= HexStringToBuf (Buffer
, BufferSize
, Str
, &ConvertedStrLen
);
743 if (!EFI_ERROR (Status
)) {
744 SwapBuffer (Buffer
, ConvertedStrLen
);
752 IN OUT CHAR16
*ConfigHdr
,
753 IN OUT UINTN
*StrBufferLen
,
755 IN CHAR16
*Name
, OPTIONAL
756 IN EFI_HANDLE
*DriverHandle
761 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
764 ConfigHdr - Pointer to the ConfigHdr string.
765 StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string.
766 Includes tailing '\0' character.
768 If return EFI_SUCCESS, containing length of ConfigHdr string buffer.
769 If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
770 Guid - Routing information: GUID.
771 Name - Routing information: NAME.
772 DriverHandle - Driver handle which contains the routing information: PATH.
775 EFI_SUCCESS - Routine success.
776 EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small.
782 UINTN DevicePathSize
;
785 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
789 // There will be no "NAME" in <ConfigHdr> for Name/Value storage
794 // For buffer storage
796 NameStrLen
= EfiStrLen (Name
);
800 // Retrieve DevicePath Protocol associated with this HiiPackageList
802 Status
= gBS
->HandleProtocol (
804 &gEfiDevicePathProtocolGuid
,
805 (VOID
**) &DevicePath
807 if (EFI_ERROR (Status
)) {
811 DevicePathSize
= EfiDevicePathSize (DevicePath
);
814 // GUID=<HexCh>32&NAME=<Alpha>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
815 // | 5 | 32 | 6 | NameStrLen | 6 | DevicePathStrLen |
817 BufferSize
= (5 + 32 + 6 + NameStrLen
+ 6 + DevicePathSize
* 2 + 1) * sizeof (CHAR16
);
818 if (*StrBufferLen
< BufferSize
) {
819 *StrBufferLen
= BufferSize
;
820 return EFI_BUFFER_TOO_SMALL
;
823 *StrBufferLen
= BufferSize
;
827 EfiStrCpy (StrPtr
, L
"GUID=");
829 BufferToHexString (StrPtr
, (UINT8
*) Guid
, sizeof (EFI_GUID
));
832 EfiStrCpy (StrPtr
, L
"&NAME=");
835 EfiStrCpy (StrPtr
, Name
);
836 StrPtr
+= NameStrLen
;
839 EfiStrCpy (StrPtr
, L
"&PATH=");
841 BufferToHexString (StrPtr
, (UINT8
*) DevicePath
, DevicePathSize
);
848 IN OUT CHAR16
*String
,
855 Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
858 String - The string to be searched in.
859 Offset - Offset in BlockName.
860 Width - Width in BlockName.
863 TRUE - Block name found.
864 FALSE - Block name not found.
871 UINTN ConvertedStrLen
;
873 while ((String
= EfiStrStr (String
, L
"&OFFSET=")) != NULL
) {
880 BufferSize
= sizeof (UINTN
);
881 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
882 if (EFI_ERROR (Status
)) {
885 String
= String
+ ConvertedStrLen
;
887 if (Data
!= Offset
) {
891 if (EfiStrnCmp (String
, L
"&WIDTH=", 7) != 0) {
897 BufferSize
= sizeof (UINTN
);
898 Status
= HexStringToBuf ((UINT8
*) &Data
, &BufferSize
, String
, &ConvertedStrLen
);
899 if (EFI_ERROR (Status
)) {
906 String
= String
+ ConvertedStrLen
;
914 EFI_GUID
*VariableGuid
, OPTIONAL
915 CHAR16
*VariableName
, OPTIONAL
922 This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
925 VariableGuid - An optional field to indicate the target variable GUID name to use.
926 VariableName - An optional field to indicate the target human-readable variable name.
927 BufferSize - On input: Length in bytes of buffer to hold retrived data.
929 If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
930 Buffer - Buffer to hold retrived data.
933 EFI_SUCCESS - Routine success.
934 EFI_BUFFER_TOO_SMALL - The intput buffer is too small.
945 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
946 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
949 // Locate protocols for use
951 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
952 if (EFI_ERROR (Status
)) {
956 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
957 if (EFI_ERROR (Status
)) {
962 // Retrive formset storage data from Form Browser
964 ConfigHdr
= mFakeConfigHdr
;
965 HeaderLen
= EfiStrLen (ConfigHdr
);
968 ConfigResp
= EfiLibAllocateZeroPool (BufferLen
+ HeaderLen
);
970 StringPtr
= ConfigResp
+ HeaderLen
;
974 Status
= FormBrowser2
->BrowserCallback (
982 if (Status
== EFI_BUFFER_TOO_SMALL
) {
983 gBS
->FreePool (ConfigResp
);
984 ConfigResp
= EfiLibAllocateZeroPool (BufferLen
+ HeaderLen
);
986 StringPtr
= ConfigResp
+ HeaderLen
;
990 Status
= FormBrowser2
->BrowserCallback (
999 if (EFI_ERROR (Status
)) {
1000 gBS
->FreePool (ConfigResp
);
1003 EfiCopyMem (ConfigResp
, ConfigHdr
, HeaderLen
* sizeof (UINT16
));
1006 // Convert <ConfigResp> to buffer data
1008 Status
= HiiConfigRouting
->ConfigToBlock (
1015 gBS
->FreePool (ConfigResp
);
1022 EFI_GUID
*VariableGuid
, OPTIONAL
1023 CHAR16
*VariableName
, OPTIONAL
1026 CHAR16
*RequestElement OPTIONAL
1030 Routine Description:
1031 This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
1034 VariableGuid - An optional field to indicate the target variable GUID name to use.
1035 VariableName - An optional field to indicate the target human-readable variable name.
1036 BufferSize - Length in bytes of buffer to hold retrived data.
1037 Buffer - Buffer to hold retrived data.
1038 RequestElement - An optional field to specify which part of the buffer data
1039 will be send back to Browser. If NULL, the whole buffer of
1040 data will be committed to Browser.
1041 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
1044 EFI_SUCCESS - Routine success.
1045 Other - Updating Browser uncommitted data failed.
1056 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
1057 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1058 CHAR16 BlockName
[33];
1059 CHAR16
*ConfigRequest
;
1063 // Locate protocols for use
1065 Status
= gBS
->LocateProtocol (&gEfiFormBrowser2ProtocolGuid
, NULL
, (VOID
**) &FormBrowser2
);
1066 if (EFI_ERROR (Status
)) {
1070 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &HiiConfigRouting
);
1071 if (EFI_ERROR (Status
)) {
1076 // Prepare <ConfigRequest>
1078 ConfigHdr
= mFakeConfigHdr
;
1079 HeaderLen
= EfiStrLen (ConfigHdr
);
1081 if (RequestElement
== NULL
) {
1083 // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
1085 BlockName
[0] = L
'\0';
1086 EfiStrCpy (BlockName
, L
"&OFFSET=0&WIDTH=");
1089 // String lenghth of L"&OFFSET=0&WIDTH=" is 16
1091 StringPtr
= BlockName
+ 16;
1092 BufferLen
= sizeof (BlockName
) - (16 * sizeof (CHAR16
));
1093 BufToHexString (StringPtr
, &BufferLen
, (UINT8
*) &BufferSize
, sizeof (UINTN
));
1095 Request
= BlockName
;
1097 Request
= RequestElement
;
1100 BufferLen
= HeaderLen
* sizeof (CHAR16
) + EfiStrSize (Request
);
1101 ConfigRequest
= EfiLibAllocateZeroPool (BufferLen
);
1103 EfiCopyMem (ConfigRequest
, ConfigHdr
, HeaderLen
* sizeof (CHAR16
));
1104 StringPtr
= ConfigRequest
+ HeaderLen
;
1105 EfiStrCpy (StringPtr
, Request
);
1108 // Convert buffer to <ConfigResp>
1110 Status
= HiiConfigRouting
->BlockToConfig (
1118 if (EFI_ERROR (Status
)) {
1119 gBS
->FreePool (ConfigResp
);
1124 // Skip <ConfigHdr> and '&'
1126 StringPtr
= ConfigResp
+ HeaderLen
+ 1;
1129 // Change uncommitted data in Browser
1131 Status
= FormBrowser2
->BrowserCallback (
1139 gBS
->FreePool (ConfigResp
);