-/** @file
-Utility functions which helps in opcode creation, HII configuration string manipulations,
-pop up window creations, setup browser persistence data set and get.
-
-Copyright (c) 2007- 2008, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "UefiIfrLibraryInternal.h"
-
-CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;
-CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mIfrSupportLibHiiConfigRouting = NULL;
-
-/**
- This function locate FormBrowser2 protocols for later usage.
-
- @return Status the status to locate protocol.
-**/
-EFI_STATUS
-LocateFormBrowser2Protocols (
- VOID
- )
-{
- EFI_STATUS Status;
- //
- // Locate protocols for later usage
- //
- if (mFormBrowser2 == NULL) {
- Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- if (mIfrSupportLibHiiConfigRouting == NULL) {
- Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mIfrSupportLibHiiConfigRouting);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// Fake <ConfigHdr>
-//
-GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
-
-/**
- Draw a dialog and return the selected key.
-
- @param NumberOfLines The number of lines for the dialog box
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
- @param Marker A series of (quantity == NumberOfLines - 1) text
- strings which will be used to construct the dialog
- box
-
- @retval EFI_SUCCESS Displayed dialog and received user interaction
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
- @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
-
-**/
-EFI_STATUS
-EFIAPI
-IfrLibCreatePopUp2 (
- IN UINTN NumberOfLines,
- OUT EFI_INPUT_KEY *KeyValue,
- IN VA_LIST Marker
- )
-{
- UINTN Index;
- UINTN Count;
- UINTN Start;
- UINTN Top;
- CHAR16 *StringPtr;
- UINTN LeftColumn;
- UINTN RightColumn;
- UINTN TopRow;
- UINTN BottomRow;
- UINTN DimensionsWidth;
- UINTN DimensionsHeight;
- EFI_INPUT_KEY Key;
- UINTN LargestString;
- CHAR16 *StackString;
- EFI_STATUS Status;
- UINTN StringLen;
- CHAR16 *LineBuffer;
- CHAR16 **StringArray;
- EFI_EVENT TimerEvent;
- EFI_EVENT WaitList[2];
- UINTN CurrentAttribute;
- EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
- CHAR16 *String;
-
- String = VA_ARG (Marker, CHAR16 *);
-
- if ((KeyValue == NULL) || (String == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- TopRow = 0;
- BottomRow = 0;
- LeftColumn = 0;
- RightColumn = 0;
-
- ConOut = gST->ConOut;
- ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
-
- DimensionsWidth = RightColumn - LeftColumn;
- DimensionsHeight = BottomRow - TopRow;
-
- CurrentAttribute = ConOut->Mode->Attribute;
-
- LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
- if (LineBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Determine the largest string in the dialog box
- // Notice we are starting with 1 since String is the first string
- //
- StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
- if (StringArray == NULL) {
- FreePool (LineBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
- LargestString = StrLen (String);
- StringArray[0] = String;
-
- for (Index = 1; Index < NumberOfLines; Index++) {
- StackString = VA_ARG (Marker, CHAR16 *);
-
- if (StackString == NULL) {
- FreePool (LineBuffer);
- FreePool (StringArray);
- return EFI_INVALID_PARAMETER;
- }
-
- StringArray[Index] = StackString;
- StringLen = StrLen (StackString);
- if (StringLen > LargestString) {
- LargestString = StringLen;
- }
- }
-
- if ((LargestString + 2) > DimensionsWidth) {
- LargestString = DimensionsWidth - 2;
- }
-
- //
- // Subtract the PopUp width from total Columns, allow for one space extra on
- // each end plus a border.
- //
- Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
-
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
-
- //
- // Disable cursor
- //
- ConOut->EnableCursor (ConOut, FALSE);
- ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
-
- StringPtr = &LineBuffer[0];
- *StringPtr++ = BOXDRAW_DOWN_RIGHT;
- for (Index = 0; Index < LargestString; Index++) {
- *StringPtr++ = BOXDRAW_HORIZONTAL;
- }
- *StringPtr++ = BOXDRAW_DOWN_LEFT;
- *StringPtr = L'\0';
-
- ConOut->SetCursorPosition (ConOut, Start, Top);
- ConOut->OutputString (ConOut, LineBuffer);
-
- for (Index = 0; Index < NumberOfLines; Index++) {
- StringPtr = &LineBuffer[0];
- *StringPtr++ = BOXDRAW_VERTICAL;
-
- for (Count = 0; Count < LargestString; Count++) {
- StringPtr[Count] = L' ';
- }
-
- StringLen = StrLen (StringArray[Index]);
- if (StringLen > LargestString) {
- StringLen = LargestString;
- }
- CopyMem (
- StringPtr + ((LargestString - StringLen) / 2),
- StringArray[Index],
- StringLen * sizeof (CHAR16)
- );
- StringPtr += LargestString;
-
- *StringPtr++ = BOXDRAW_VERTICAL;
- *StringPtr = L'\0';
-
- ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
- ConOut->OutputString (ConOut, LineBuffer);
- }
-
- StringPtr = &LineBuffer[0];
- *StringPtr++ = BOXDRAW_UP_RIGHT;
- for (Index = 0; Index < LargestString; Index++) {
- *StringPtr++ = BOXDRAW_HORIZONTAL;
- }
- *StringPtr++ = BOXDRAW_UP_LEFT;
- *StringPtr = L'\0';
-
- ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
- ConOut->OutputString (ConOut, LineBuffer);
-
- do {
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
-
- //
- // Set a timer event of 1 second expiration
- //
- gBS->SetTimer (
- TimerEvent,
- TimerRelative,
- 10000000
- );
-
- //
- // Wait for the keystroke event or the timer
- //
- WaitList[0] = gST->ConIn->WaitForKey;
- WaitList[1] = TimerEvent;
- Status = gBS->WaitForEvent (2, WaitList, &Index);
-
- //
- // Check for the timer expiration
- //
- if (!EFI_ERROR (Status) && Index == 1) {
- Status = EFI_TIMEOUT;
- }
-
- gBS->CloseEvent (TimerEvent);
- } while (Status == EFI_TIMEOUT);
-
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
-
- ConOut->SetAttribute (ConOut, CurrentAttribute);
- ConOut->EnableCursor (ConOut, TRUE);
-
- FreePool (LineBuffer);
- FreePool (StringArray);
-
- return Status;
-}
-
-
-/**
- Draw a dialog and return the selected key.
-
- @param NumberOfLines The number of lines for the dialog box
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
- @param String Pointer to the first string in the list
- @param ... A series of (quantity == NumberOfLines - 1) text
- strings which will be used to construct the dialog
- box
-
- @retval EFI_SUCCESS Displayed dialog and received user interaction
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-IfrLibCreatePopUp (
- IN UINTN NumberOfLines,
- OUT EFI_INPUT_KEY *KeyValue,
- IN CHAR16 *String,
- ...
- )
-{
- EFI_STATUS Status;
- VA_LIST Marker;
-
- VA_START (Marker, KeyValue);
-
- Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, Marker);
-
- VA_END (Marker);
-
- return Status;
-}
-
-/**
- Swap bytes in the buffer. This is a internal function.
-
- @param Buffer Binary buffer.
- @param BufferSize Size of the buffer in bytes.
-
- @return None.
-
-**/
-VOID
-SwapBuffer (
- IN OUT UINT8 *Buffer,
- IN UINTN BufferSize
- )
-{
- UINTN Index;
- UINT8 Temp;
- UINTN SwapCount;
-
- SwapCount = BufferSize / 2;
- for (Index = 0; Index < SwapCount; Index++) {
- Temp = Buffer[Index];
- Buffer[Index] = Buffer[BufferSize - 1 - Index];
- Buffer[BufferSize - 1 - Index] = Temp;
- }
-}
-
-/**
- Converts the unicode character of the string from uppercase to lowercase.
- This is a internal function.
-
- @param Str String to be converted
-
-**/
-VOID
-EFIAPI
-ToLower (
- IN OUT CHAR16 *Str
- )
-{
- CHAR16 *Ptr;
-
- for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
- if (*Ptr >= L'A' && *Ptr <= L'Z') {
- *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
- }
- }
-}
-
-
-/**
- Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
-
- @param Str String for output
- @param Buffer Binary buffer.
- @param BufferSize Size of the buffer in bytes.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
-
-**/
-EFI_STATUS
-EFIAPI
-BufInReverseOrderToHexString (
- IN OUT CHAR16 *Str,
- IN UINT8 *Buffer,
- IN UINTN BufferSize
- )
-{
- EFI_STATUS Status;
- UINT8 *NewBuffer;
- UINTN StrBufferLen;
-
- NewBuffer = AllocateCopyPool (BufferSize, Buffer);
- if (NewBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- SwapBuffer (NewBuffer, BufferSize);
-
- StrBufferLen = BufferSize * sizeof (CHAR16) + 1;
- Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
-
- FreePool (NewBuffer);
- //
- // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
- //
- ToLower (Str);
-
- return Status;
-}
-
-
-/**
- Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
-
- @param Buffer Pointer to buffer that receives the data.
- @param BufferSize Length in bytes of the buffer to hold converted
- data. If routine return with EFI_SUCCESS,
- containing length of converted data. If routine
- return with EFI_BUFFER_TOO_SMALL, containg length
- of buffer desired.
- @param Str String to be converted from.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize
- will be updated to the size required for the converstion.
-
-**/
-EFI_STATUS
-EFIAPI
-HexStringToBufInReverseOrder (
- IN OUT UINT8 *Buffer,
- IN OUT UINTN *BufferSize,
- IN CHAR16 *Str
- )
-{
- EFI_STATUS Status;
- UINTN ConvertedStrLen;
-
- ConvertedStrLen = 0;
- Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
- if (!EFI_ERROR (Status)) {
- SwapBuffer (Buffer, ConvertedStrLen);
- }
-
- return Status;
-}
-
-/**
- Convert binary representation Config string (e.g. "0041004200430044") to the
- original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
- "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
-
- @param UnicodeString Original Unicode string.
- @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
- Includes tailing '\0' character.
- On output:
- If return EFI_SUCCESS, containing length of Unicode string buffer.
- If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
- @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
-
- @retval EFI_SUCCESS Operation completes successfully.
- @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-ConfigStringToUnicode (
- IN OUT CHAR16 *UnicodeString,
- IN OUT UINTN *StrBufferLen,
- IN CHAR16 *ConfigString
- )
-{
- UINTN Index;
- UINTN Len;
- UINTN BufferSize;
- CHAR16 BackupChar;
-
- Len = StrLen (ConfigString) / 4;
- BufferSize = (Len + 1) * sizeof (CHAR16);
-
- if (*StrBufferLen < BufferSize) {
- *StrBufferLen = BufferSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *StrBufferLen = BufferSize;
-
- for (Index = 0; Index < Len; Index++) {
- BackupChar = ConfigString[4];
- ConfigString[4] = L'\0';
-
- HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
-
- ConfigString[4] = BackupChar;
-
- ConfigString += 4;
- UnicodeString += 1;
- }
-
- //
- // Add tailing '\0' character
- //
- *UnicodeString = L'\0';
-
- return EFI_SUCCESS;
-}
-
-/**
- Convert Unicode string to binary representation Config string, e.g.
- "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
- "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
-
- @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+
- @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.
- Includes tailing '\0' character.
- On output:
- If return EFI_SUCCESS, containing length of Unicode string buffer.
- If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
- @param UnicodeString Original Unicode string.
-
- @retval EFI_SUCCESS Operation completes successfully.
- @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-UnicodeToConfigString (
- IN OUT CHAR16 *ConfigString,
- IN OUT UINTN *StrBufferLen,
- IN CHAR16 *UnicodeString
- )
-{
- UINTN Index;
- UINTN Len;
- UINTN BufferSize;
- CHAR16 *String;
-
- Len = StrLen (UnicodeString);
- BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
-
- if (*StrBufferLen < BufferSize) {
- *StrBufferLen = BufferSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *StrBufferLen = BufferSize;
- String = ConfigString;
-
- for (Index = 0; Index < Len; Index++) {
- BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
-
- ConfigString += 4;
- UnicodeString += 1;
- }
-
- //
- // Add tailing '\0' character
- //
- *ConfigString = L'\0';
-
- //
- // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
- //
- ToLower (String);
- return EFI_SUCCESS;
-}
-
-/**
- Construct <ConfigHdr> using routing information GUID/NAME/PATH.
-
- @param ConfigHdr Pointer to the ConfigHdr string.
- @param StrBufferLen On input: Length in bytes of buffer to hold the
- ConfigHdr string. Includes tailing '\0' character.
- On output: If return EFI_SUCCESS, containing
- length of ConfigHdr string buffer. If return
- EFI_BUFFER_TOO_SMALL, containg length of string
- buffer desired.
- @param Guid Routing information: GUID.
- @param Name Routing information: NAME.
- @param DriverHandle Driver handle which contains the routing
- information: PATH.
-
- @retval EFI_SUCCESS Operation completes successfully.
- @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-ConstructConfigHdr (
- IN OUT CHAR16 *ConfigHdr,
- IN OUT UINTN *StrBufferLen,
- IN CONST EFI_GUID *Guid,
- IN CHAR16 *Name, OPTIONAL
- IN EFI_HANDLE *DriverHandle
- )
-{
- EFI_STATUS Status;
- UINTN NameStrLen;
- UINTN DevicePathSize;
- UINTN BufferSize;
- CHAR16 *StrPtr;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- if (Name == NULL) {
- //
- // There will be no "NAME" in <ConfigHdr> for Name/Value storage
- //
- NameStrLen = 0;
- } else {
- //
- // For buffer storage
- //
- NameStrLen = StrLen (Name);
- }
-
- //
- // Retrieve DevicePath Protocol associated with this HiiPackageList
- //
- Status = gBS->HandleProtocol (
- DriverHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &DevicePath
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- DevicePathSize = GetDevicePathSize (DevicePath);
-
- //
- // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
- // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
- //
- BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
- if (*StrBufferLen < BufferSize) {
- *StrBufferLen = BufferSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *StrBufferLen = BufferSize;
-
- StrPtr = ConfigHdr;
-
- StrCpy (StrPtr, L"GUID=");
- StrPtr += 5;
- BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
- StrPtr += 32;
-
- //
- // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
- //
- StrCpy (StrPtr, L"&NAME=");
- StrPtr += 6;
- if (Name != NULL) {
- BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
- UnicodeToConfigString (StrPtr, &BufferSize, Name);
- StrPtr += (NameStrLen * 4);
- }
-
- StrCpy (StrPtr, L"&PATH=");
- StrPtr += 6;
- BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
-
- @param String The string to be searched in.
- @param Offset Offset in BlockName.
- @param Width Width in BlockName.
-
- @retval TRUE Block name found.
- @retval FALSE Block name not found.
-
-**/
-BOOLEAN
-EFIAPI
-FindBlockName (
- IN OUT CHAR16 *String,
- IN UINTN Offset,
- IN UINTN Width
- )
-{
- EFI_STATUS Status;
- UINTN Data;
- UINTN BufferSize;
- UINTN ConvertedStrLen;
-
- while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
- //
- // Skip '&OFFSET='
- //
- String = String + 8;
-
- Data = 0;
- BufferSize = sizeof (UINTN);
- Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- String = String + ConvertedStrLen;
-
- if (Data != Offset) {
- continue;
- }
-
- if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
- return FALSE;
- }
- String = String + 7;
-
- Data = 0;
- BufferSize = sizeof (UINTN);
- Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- if (Data == Width) {
- return TRUE;
- }
-
- String = String + ConvertedStrLen;
- }
-
- return FALSE;
-}
-
-
-/**
- This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
-
- @param VariableGuid An optional field to indicate the target variable
- GUID name to use.
- @param VariableName An optional field to indicate the target
- human-readable variable name.
- @param BufferSize On input: Length in bytes of buffer to hold
- retrived data. On output: If return
- EFI_BUFFER_TOO_SMALL, containg length of buffer
- desired.
- @param Buffer Buffer to hold retrived data.
-
- @retval EFI_SUCCESS Operation completes successfully.
- @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.
- @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
-
-**/
-EFI_STATUS
-EFIAPI
-GetBrowserData (
- IN CONST EFI_GUID *VariableGuid, OPTIONAL
- IN CONST CHAR16 *VariableName, OPTIONAL
- IN OUT UINTN *BufferSize,
- IN OUT UINT8 *Buffer
- )
-{
- EFI_STATUS Status;
- CONST CHAR16 *ConfigHdr;
- CHAR16 *ConfigResp;
- CHAR16 *StringPtr;
- UINTN HeaderLen;
- UINTN BufferLen;
- CHAR16 *Progress;
-
- //
- // Locate protocols for use
- //
- Status = LocateFormBrowser2Protocols ();
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Retrive formset storage data from Form Browser
- //
- ConfigHdr = mFakeConfigHdr;
- HeaderLen = StrLen (ConfigHdr);
-
- //
- // First try allocate 0x4000 buffer for the formet storage data.
- //
- BufferLen = 0x4000;
- ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
- if (ConfigResp == NULL) {
- BufferLen = 0;
- }
-
- StringPtr = ConfigResp + HeaderLen;
- *StringPtr = L'&';
- StringPtr++;
-
- Status = mFormBrowser2->BrowserCallback (
- mFormBrowser2,
- &BufferLen,
- StringPtr,
- TRUE,
- VariableGuid,
- VariableName
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- if (ConfigResp != NULL) {
- FreePool (ConfigResp);
- }
-
- ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
- if (ConfigResp == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StringPtr = ConfigResp + HeaderLen;
- *StringPtr = L'&';
- StringPtr++;
-
- Status = mFormBrowser2->BrowserCallback (
- mFormBrowser2,
- &BufferLen,
- StringPtr,
- TRUE,
- VariableGuid,
- VariableName
- );
- }
- if (EFI_ERROR (Status)) {
- FreePool (ConfigResp);
- return Status;
- }
- CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
-
- //
- // Convert <ConfigResp> to buffer data
- //
- Status = mIfrSupportLibHiiConfigRouting->ConfigToBlock (
- mIfrSupportLibHiiConfigRouting,
- ConfigResp,
- Buffer,
- BufferSize,
- &Progress
- );
- FreePool (ConfigResp);
-
- return Status;
-}
-
-
-/**
- This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
-
- @param VariableGuid An optional field to indicate the target variable
- GUID name to use.
- @param VariableName An optional field to indicate the target
- human-readable variable name.
- @param BufferSize Length in bytes of buffer to hold retrived data.
- @param Buffer Buffer to hold retrived data.
- @param RequestElement An optional field to specify which part of the
- buffer data will be send back to Browser. If NULL,
- the whole buffer of data will be committed to
- Browser. <RequestElement> ::=
- &OFFSET=<Number>&WIDTH=<Number>*
-
- @retval EFI_SUCCESS Operation completes successfully.
- @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.
- @retval Other Updating Browser uncommitted data failed.
-
-**/
-EFI_STATUS
-EFIAPI
-SetBrowserData (
- IN CONST EFI_GUID *VariableGuid, OPTIONAL
- IN CONST CHAR16 *VariableName, OPTIONAL
- IN UINTN BufferSize,
- IN CONST UINT8 *Buffer,
- IN CONST CHAR16 *RequestElement OPTIONAL
- )
-{
- EFI_STATUS Status;
- CONST CHAR16 *ConfigHdr;
- CHAR16 *ConfigResp;
- CHAR16 *StringPtr;
- UINTN HeaderLen;
- UINTN BufferLen;
- CHAR16 *Progress;
- CHAR16 BlockName[33];
- CHAR16 *ConfigRequest;
- CONST CHAR16 *Request;
-
- //
- // Locate protocols for use
- //
- Status = LocateFormBrowser2Protocols ();
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Prepare <ConfigRequest>
- //
- ConfigHdr = mFakeConfigHdr;
- HeaderLen = StrLen (ConfigHdr);
-
- if (RequestElement == NULL) {
- //
- // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
- //
- BlockName[0] = L'\0';
- StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
-
- //
- // String lenghth of L"&OFFSET=0&WIDTH=" is 16
- //
- StringPtr = BlockName + 16;
- BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
- BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
-
- Request = BlockName;
- } else {
- Request = RequestElement;
- }
-
- BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
- ConfigRequest = AllocateZeroPool (BufferLen);
- if (ConfigRequest == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
- StringPtr = ConfigRequest + HeaderLen;
- StrCpy (StringPtr, Request);
-
- //
- // Convert buffer to <ConfigResp>
- //
- Status = mIfrSupportLibHiiConfigRouting->BlockToConfig (
- mIfrSupportLibHiiConfigRouting,
- ConfigRequest,
- Buffer,
- BufferSize,
- &ConfigResp,
- &Progress
- );
- if (EFI_ERROR (Status)) {
- FreePool (ConfigRequest);
- return Status;
- }
-
- //
- // Skip <ConfigHdr> and '&'
- //
- StringPtr = ConfigResp + HeaderLen + 1;
-
- //
- // Change uncommitted data in Browser
- //
- Status = mFormBrowser2->BrowserCallback (
- mFormBrowser2,
- &BufferSize,
- StringPtr,
- FALSE,
- NULL,
- NULL
- );
- FreePool (ConfigRequest);
- return Status;
-}
+/** @file\r
+Utility functions which helps in opcode creation, HII configuration string manipulations, \r
+pop up window creations, setup browser persistence data set and get.\r
+\r
+Copyright (c) 2007- 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UefiIfrLibraryInternal.h"\r
+\r
+CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL;\r
+CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mIfrSupportLibHiiConfigRouting = NULL;\r
+\r
+/**\r
+ This function locate FormBrowser2 protocols for later usage.\r
+\r
+ @return Status the status to locate protocol.\r
+**/\r
+EFI_STATUS\r
+LocateFormBrowser2Protocols (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ //\r
+ // Locate protocols for later usage\r
+ //\r
+ if (mFormBrowser2 == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ if (mIfrSupportLibHiiConfigRouting == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mIfrSupportLibHiiConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Fake <ConfigHdr>\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
+\r
+/**\r
+ Draw a dialog and return the selected key.\r
+\r
+ @param NumberOfLines The number of lines for the dialog box\r
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
+ @param Marker A series of (quantity == NumberOfLines - 1) text\r
+ strings which will be used to construct the dialog\r
+ box\r
+\r
+ @retval EFI_SUCCESS Displayed dialog and received user interaction\r
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.\r
+ @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IfrLibCreatePopUp2 (\r
+ IN UINTN NumberOfLines,\r
+ OUT EFI_INPUT_KEY *KeyValue,\r
+ IN VA_LIST Marker\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN Start;\r
+ UINTN Top;\r
+ CHAR16 *StringPtr;\r
+ UINTN LeftColumn;\r
+ UINTN RightColumn;\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN LargestString;\r
+ CHAR16 *StackString;\r
+ EFI_STATUS Status;\r
+ UINTN StringLen;\r
+ CHAR16 *LineBuffer;\r
+ CHAR16 **StringArray;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[2];\r
+ UINTN CurrentAttribute;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
+ CHAR16 *String;\r
+\r
+ String = VA_ARG (Marker, CHAR16 *);\r
+ \r
+ if ((KeyValue == NULL) || (String == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TopRow = 0;\r
+ BottomRow = 0;\r
+ LeftColumn = 0;\r
+ RightColumn = 0;\r
+\r
+ ConOut = gST->ConOut;\r
+ ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);\r
+\r
+ DimensionsWidth = RightColumn - LeftColumn;\r
+ DimensionsHeight = BottomRow - TopRow;\r
+\r
+ CurrentAttribute = ConOut->Mode->Attribute;\r
+\r
+ LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));\r
+ if (LineBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Determine the largest string in the dialog box\r
+ // Notice we are starting with 1 since String is the first string\r
+ //\r
+ StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));\r
+ if (StringArray == NULL) {\r
+ FreePool (LineBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ LargestString = StrLen (String);\r
+ StringArray[0] = String;\r
+\r
+ for (Index = 1; Index < NumberOfLines; Index++) {\r
+ StackString = VA_ARG (Marker, CHAR16 *);\r
+\r
+ if (StackString == NULL) {\r
+ FreePool (LineBuffer);\r
+ FreePool (StringArray);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringArray[Index] = StackString;\r
+ StringLen = StrLen (StackString);\r
+ if (StringLen > LargestString) {\r
+ LargestString = StringLen;\r
+ }\r
+ }\r
+\r
+ if ((LargestString + 2) > DimensionsWidth) {\r
+ LargestString = DimensionsWidth - 2;\r
+ }\r
+\r
+ //\r
+ // Subtract the PopUp width from total Columns, allow for one space extra on\r
+ // each end plus a border.\r
+ //\r
+ Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;\r
+\r
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;\r
+\r
+ //\r
+ // Disable cursor\r
+ //\r
+ ConOut->EnableCursor (ConOut, FALSE);\r
+ ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);\r
+\r
+ StringPtr = &LineBuffer[0];\r
+ *StringPtr++ = BOXDRAW_DOWN_RIGHT;\r
+ for (Index = 0; Index < LargestString; Index++) {\r
+ *StringPtr++ = BOXDRAW_HORIZONTAL;\r
+ }\r
+ *StringPtr++ = BOXDRAW_DOWN_LEFT;\r
+ *StringPtr = L'\0';\r
+\r
+ ConOut->SetCursorPosition (ConOut, Start, Top);\r
+ ConOut->OutputString (ConOut, LineBuffer);\r
+\r
+ for (Index = 0; Index < NumberOfLines; Index++) {\r
+ StringPtr = &LineBuffer[0];\r
+ *StringPtr++ = BOXDRAW_VERTICAL;\r
+\r
+ for (Count = 0; Count < LargestString; Count++) {\r
+ StringPtr[Count] = L' ';\r
+ }\r
+\r
+ StringLen = StrLen (StringArray[Index]);\r
+ if (StringLen > LargestString) {\r
+ StringLen = LargestString;\r
+ }\r
+ CopyMem (\r
+ StringPtr + ((LargestString - StringLen) / 2),\r
+ StringArray[Index],\r
+ StringLen * sizeof (CHAR16)\r
+ );\r
+ StringPtr += LargestString;\r
+\r
+ *StringPtr++ = BOXDRAW_VERTICAL;\r
+ *StringPtr = L'\0';\r
+\r
+ ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);\r
+ ConOut->OutputString (ConOut, LineBuffer);\r
+ }\r
+\r
+ StringPtr = &LineBuffer[0];\r
+ *StringPtr++ = BOXDRAW_UP_RIGHT;\r
+ for (Index = 0; Index < LargestString; Index++) {\r
+ *StringPtr++ = BOXDRAW_HORIZONTAL;\r
+ }\r
+ *StringPtr++ = BOXDRAW_UP_LEFT;\r
+ *StringPtr = L'\0';\r
+\r
+ ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);\r
+ ConOut->OutputString (ConOut, LineBuffer);\r
+\r
+ do {\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+\r
+ //\r
+ // Set a timer event of 1 second expiration\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ 10000000\r
+ );\r
+\r
+ //\r
+ // Wait for the keystroke event or the timer\r
+ //\r
+ WaitList[0] = gST->ConIn->WaitForKey;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+\r
+ //\r
+ // Check for the timer expiration\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+\r
+ gBS->CloseEvent (TimerEvent);\r
+ } while (Status == EFI_TIMEOUT);\r
+\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ ConOut->SetAttribute (ConOut, CurrentAttribute);\r
+ ConOut->EnableCursor (ConOut, TRUE);\r
+\r
+ FreePool (LineBuffer);\r
+ FreePool (StringArray);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Draw a dialog and return the selected key.\r
+\r
+ @param NumberOfLines The number of lines for the dialog box\r
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
+ @param String Pointer to the first string in the list\r
+ @param ... A series of (quantity == NumberOfLines - 1) text\r
+ strings which will be used to construct the dialog\r
+ box\r
+\r
+ @retval EFI_SUCCESS Displayed dialog and received user interaction\r
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IfrLibCreatePopUp (\r
+ IN UINTN NumberOfLines,\r
+ OUT EFI_INPUT_KEY *KeyValue,\r
+ IN CHAR16 *String,\r
+ ...\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VA_LIST Marker;\r
+\r
+ VA_START (Marker, KeyValue);\r
+\r
+ Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, Marker);\r
+\r
+ VA_END (Marker);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Swap bytes in the buffer. This is a internal function.\r
+\r
+ @param Buffer Binary buffer.\r
+ @param BufferSize Size of the buffer in bytes.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+SwapBuffer (\r
+ IN OUT UINT8 *Buffer,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 Temp;\r
+ UINTN SwapCount;\r
+\r
+ SwapCount = BufferSize / 2;\r
+ for (Index = 0; Index < SwapCount; Index++) {\r
+ Temp = Buffer[Index];\r
+ Buffer[Index] = Buffer[BufferSize - 1 - Index];\r
+ Buffer[BufferSize - 1 - Index] = Temp;\r
+ }\r
+}\r
+\r
+/**\r
+ Converts the unicode character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
+\r
+ @param Str String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ToLower (\r
+ IN OUT CHAR16 *Str\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+ \r
+ for (Ptr = Str; *Ptr != L'\0'; Ptr++) {\r
+ if (*Ptr >= L'A' && *Ptr <= L'Z') {\r
+ *Ptr = (CHAR16) (*Ptr - L'A' + L'a');\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Converts binary buffer to Unicode string in reversed byte order from BufToHexString().\r
+\r
+ @param Str String for output\r
+ @param Buffer Binary buffer.\r
+ @param BufferSize Size of the buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BufInReverseOrderToHexString (\r
+ IN OUT CHAR16 *Str,\r
+ IN UINT8 *Buffer,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *NewBuffer;\r
+ UINTN StrBufferLen;\r
+\r
+ NewBuffer = AllocateCopyPool (BufferSize, Buffer);\r
+ if (NewBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ SwapBuffer (NewBuffer, BufferSize);\r
+\r
+ StrBufferLen = BufferSize * sizeof (CHAR16) + 1;\r
+ Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);\r
+\r
+ FreePool (NewBuffer);\r
+ //\r
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
+ //\r
+ ToLower (Str);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().\r
+\r
+ @param Buffer Pointer to buffer that receives the data.\r
+ @param BufferSize Length in bytes of the buffer to hold converted\r
+ data. If routine return with EFI_SUCCESS,\r
+ containing length of converted data. If routine\r
+ return with EFI_BUFFER_TOO_SMALL, containg length\r
+ of buffer desired.\r
+ @param Str String to be converted from.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize\r
+ will be updated to the size required for the converstion.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HexStringToBufInReverseOrder (\r
+ IN OUT UINT8 *Buffer,\r
+ IN OUT UINTN *BufferSize,\r
+ IN CHAR16 *Str\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ConvertedStrLen;\r
+\r
+ ConvertedStrLen = 0;\r
+ Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);\r
+ if (!EFI_ERROR (Status)) {\r
+ SwapBuffer (Buffer, ConvertedStrLen);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert binary representation Config string (e.g. "0041004200430044") to the\r
+ original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.\r
+ "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").\r
+\r
+ @param UnicodeString Original Unicode string.\r
+ @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.\r
+ Includes tailing '\0' character.\r
+ On output:\r
+ If return EFI_SUCCESS, containing length of Unicode string buffer.\r
+ If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
+ @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+\r
+\r
+ @retval EFI_SUCCESS Operation completes successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConfigStringToUnicode (\r
+ IN OUT CHAR16 *UnicodeString,\r
+ IN OUT UINTN *StrBufferLen,\r
+ IN CHAR16 *ConfigString\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Len;\r
+ UINTN BufferSize;\r
+ CHAR16 BackupChar;\r
+\r
+ Len = StrLen (ConfigString) / 4;\r
+ BufferSize = (Len + 1) * sizeof (CHAR16);\r
+\r
+ if (*StrBufferLen < BufferSize) {\r
+ *StrBufferLen = BufferSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *StrBufferLen = BufferSize;\r
+\r
+ for (Index = 0; Index < Len; Index++) {\r
+ BackupChar = ConfigString[4];\r
+ ConfigString[4] = L'\0';\r
+\r
+ HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);\r
+\r
+ ConfigString[4] = BackupChar;\r
+\r
+ ConfigString += 4;\r
+ UnicodeString += 1;\r
+ }\r
+\r
+ //\r
+ // Add tailing '\0' character\r
+ //\r
+ *UnicodeString = L'\0';\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Convert Unicode string to binary representation Config string, e.g.\r
+ "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.\r
+ "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").\r
+\r
+ @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+\r
+ @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string.\r
+ Includes tailing '\0' character.\r
+ On output:\r
+ If return EFI_SUCCESS, containing length of Unicode string buffer.\r
+ If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
+ @param UnicodeString Original Unicode string.\r
+\r
+ @retval EFI_SUCCESS Operation completes successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The string buffer is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnicodeToConfigString (\r
+ IN OUT CHAR16 *ConfigString,\r
+ IN OUT UINTN *StrBufferLen,\r
+ IN CHAR16 *UnicodeString\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Len;\r
+ UINTN BufferSize;\r
+ CHAR16 *String;\r
+\r
+ Len = StrLen (UnicodeString);\r
+ BufferSize = (Len * 4 + 1) * sizeof (CHAR16);\r
+\r
+ if (*StrBufferLen < BufferSize) {\r
+ *StrBufferLen = BufferSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *StrBufferLen = BufferSize;\r
+ String = ConfigString;\r
+\r
+ for (Index = 0; Index < Len; Index++) {\r
+ BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);\r
+\r
+ ConfigString += 4;\r
+ UnicodeString += 1;\r
+ }\r
+\r
+ //\r
+ // Add tailing '\0' character\r
+ //\r
+ *ConfigString = L'\0';\r
+\r
+ //\r
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
+ //\r
+ ToLower (String); \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
+\r
+ @param ConfigHdr Pointer to the ConfigHdr string.\r
+ @param StrBufferLen On input: Length in bytes of buffer to hold the\r
+ ConfigHdr string. Includes tailing '\0' character.\r
+ On output: If return EFI_SUCCESS, containing\r
+ length of ConfigHdr string buffer. If return\r
+ EFI_BUFFER_TOO_SMALL, containg length of string\r
+ buffer desired.\r
+ @param Guid Routing information: GUID.\r
+ @param Name Routing information: NAME.\r
+ @param DriverHandle Driver handle which contains the routing\r
+ information: PATH.\r
+\r
+ @retval EFI_SUCCESS Operation completes successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConstructConfigHdr (\r
+ IN OUT CHAR16 *ConfigHdr,\r
+ IN OUT UINTN *StrBufferLen,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN CHAR16 *Name, OPTIONAL\r
+ IN EFI_HANDLE *DriverHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NameStrLen;\r
+ UINTN DevicePathSize;\r
+ UINTN BufferSize;\r
+ CHAR16 *StrPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ if (Name == NULL) {\r
+ //\r
+ // There will be no "NAME" in <ConfigHdr> for Name/Value storage\r
+ //\r
+ NameStrLen = 0;\r
+ } else {\r
+ //\r
+ // For buffer storage\r
+ //\r
+ NameStrLen = StrLen (Name);\r
+ }\r
+\r
+ //\r
+ // Retrieve DevicePath Protocol associated with this HiiPackageList\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+\r
+ //\r
+ // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
+ // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
+ //\r
+ BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);\r
+ if (*StrBufferLen < BufferSize) {\r
+ *StrBufferLen = BufferSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *StrBufferLen = BufferSize;\r
+\r
+ StrPtr = ConfigHdr;\r
+\r
+ StrCpy (StrPtr, L"GUID=");\r
+ StrPtr += 5;\r
+ BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));\r
+ StrPtr += 32;\r
+\r
+ //\r
+ // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"\r
+ //\r
+ StrCpy (StrPtr, L"&NAME=");\r
+ StrPtr += 6;\r
+ if (Name != NULL) {\r
+ BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);\r
+ UnicodeToConfigString (StrPtr, &BufferSize, Name);\r
+ StrPtr += (NameStrLen * 4);\r
+ }\r
+\r
+ StrCpy (StrPtr, L"&PATH=");\r
+ StrPtr += 6;\r
+ BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
+\r
+ @param String The string to be searched in.\r
+ @param Offset Offset in BlockName.\r
+ @param Width Width in BlockName.\r
+\r
+ @retval TRUE Block name found.\r
+ @retval FALSE Block name not found.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+FindBlockName (\r
+ IN OUT CHAR16 *String,\r
+ IN UINTN Offset,\r
+ IN UINTN Width\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Data;\r
+ UINTN BufferSize;\r
+ UINTN ConvertedStrLen;\r
+\r
+ while ((String = StrStr (String, L"&OFFSET=")) != NULL) {\r
+ //\r
+ // Skip '&OFFSET='\r
+ //\r
+ String = String + 8;\r
+\r
+ Data = 0;\r
+ BufferSize = sizeof (UINTN);\r
+ Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ String = String + ConvertedStrLen;\r
+\r
+ if (Data != Offset) {\r
+ continue;\r
+ }\r
+\r
+ if (StrnCmp (String, L"&WIDTH=", 7) != 0) {\r
+ return FALSE;\r
+ }\r
+ String = String + 7;\r
+\r
+ Data = 0;\r
+ BufferSize = sizeof (UINTN);\r
+ Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ if (Data == Width) {\r
+ return TRUE;\r
+ }\r
+\r
+ String = String + ConvertedStrLen;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.\r
+\r
+ @param VariableGuid An optional field to indicate the target variable\r
+ GUID name to use.\r
+ @param VariableName An optional field to indicate the target\r
+ human-readable variable name.\r
+ @param BufferSize On input: Length in bytes of buffer to hold\r
+ retrived data. On output: If return\r
+ EFI_BUFFER_TOO_SMALL, containg length of buffer\r
+ desired.\r
+ @param Buffer Buffer to hold retrived data.\r
+\r
+ @retval EFI_SUCCESS Operation completes successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small.\r
+ @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetBrowserData (\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName, OPTIONAL\r
+ IN OUT UINTN *BufferSize,\r
+ IN OUT UINT8 *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CONST CHAR16 *ConfigHdr;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *StringPtr;\r
+ UINTN HeaderLen;\r
+ UINTN BufferLen;\r
+ CHAR16 *Progress;\r
+\r
+ //\r
+ // Locate protocols for use\r
+ //\r
+ Status = LocateFormBrowser2Protocols ();\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Retrive formset storage data from Form Browser\r
+ //\r
+ ConfigHdr = mFakeConfigHdr;\r
+ HeaderLen = StrLen (ConfigHdr);\r
+ \r
+ //\r
+ // First try allocate 0x4000 buffer for the formet storage data.\r
+ //\r
+ BufferLen = 0x4000;\r
+ ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
+ if (ConfigResp == NULL) {\r
+ BufferLen = 0;\r
+ }\r
+\r
+ StringPtr = ConfigResp + HeaderLen;\r
+ *StringPtr = L'&';\r
+ StringPtr++;\r
+\r
+ Status = mFormBrowser2->BrowserCallback (\r
+ mFormBrowser2,\r
+ &BufferLen,\r
+ StringPtr,\r
+ TRUE,\r
+ VariableGuid,\r
+ VariableName\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
+\r
+ ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);\r
+ if (ConfigResp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StringPtr = ConfigResp + HeaderLen;\r
+ *StringPtr = L'&';\r
+ StringPtr++;\r
+\r
+ Status = mFormBrowser2->BrowserCallback (\r
+ mFormBrowser2,\r
+ &BufferLen,\r
+ StringPtr,\r
+ TRUE,\r
+ VariableGuid,\r
+ VariableName\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+ CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));\r
+\r
+ //\r
+ // Convert <ConfigResp> to buffer data\r
+ //\r
+ Status = mIfrSupportLibHiiConfigRouting->ConfigToBlock (\r
+ mIfrSupportLibHiiConfigRouting,\r
+ ConfigResp,\r
+ Buffer,\r
+ BufferSize,\r
+ &Progress\r
+ );\r
+ FreePool (ConfigResp);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.\r
+\r
+ @param VariableGuid An optional field to indicate the target variable\r
+ GUID name to use.\r
+ @param VariableName An optional field to indicate the target\r
+ human-readable variable name.\r
+ @param BufferSize Length in bytes of buffer to hold retrived data.\r
+ @param Buffer Buffer to hold retrived data.\r
+ @param RequestElement An optional field to specify which part of the\r
+ buffer data will be send back to Browser. If NULL,\r
+ the whole buffer of data will be committed to\r
+ Browser. <RequestElement> ::=\r
+ &OFFSET=<Number>&WIDTH=<Number>*\r
+\r
+ @retval EFI_SUCCESS Operation completes successfully.\r
+ @retval EFI_OUT_OF_RESOURCES There is no enough available memory space.\r
+ @retval Other Updating Browser uncommitted data failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBrowserData (\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName, OPTIONAL\r
+ IN UINTN BufferSize,\r
+ IN CONST UINT8 *Buffer,\r
+ IN CONST CHAR16 *RequestElement OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CONST CHAR16 *ConfigHdr;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *StringPtr;\r
+ UINTN HeaderLen;\r
+ UINTN BufferLen;\r
+ CHAR16 *Progress;\r
+ CHAR16 BlockName[33];\r
+ CHAR16 *ConfigRequest;\r
+ CONST CHAR16 *Request;\r
+\r
+ //\r
+ // Locate protocols for use\r
+ //\r
+ Status = LocateFormBrowser2Protocols ();\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Prepare <ConfigRequest>\r
+ //\r
+ ConfigHdr = mFakeConfigHdr;\r
+ HeaderLen = StrLen (ConfigHdr);\r
+\r
+ if (RequestElement == NULL) {\r
+ //\r
+ // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>\r
+ //\r
+ BlockName[0] = L'\0';\r
+ StrCpy (BlockName, L"&OFFSET=0&WIDTH=");\r
+\r
+ //\r
+ // String lenghth of L"&OFFSET=0&WIDTH=" is 16\r
+ //\r
+ StringPtr = BlockName + 16;\r
+ BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));\r
+ BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));\r
+\r
+ Request = BlockName;\r
+ } else {\r
+ Request = RequestElement;\r
+ }\r
+\r
+ BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);\r
+ ConfigRequest = AllocateZeroPool (BufferLen);\r
+ if (ConfigRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));\r
+ StringPtr = ConfigRequest + HeaderLen;\r
+ StrCpy (StringPtr, Request);\r
+\r
+ //\r
+ // Convert buffer to <ConfigResp>\r
+ //\r
+ Status = mIfrSupportLibHiiConfigRouting->BlockToConfig (\r
+ mIfrSupportLibHiiConfigRouting,\r
+ ConfigRequest,\r
+ Buffer,\r
+ BufferSize,\r
+ &ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigRequest);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigHdr> and '&'\r
+ //\r
+ StringPtr = ConfigResp + HeaderLen + 1;\r
+\r
+ //\r
+ // Change uncommitted data in Browser\r
+ //\r
+ Status = mFormBrowser2->BrowserCallback (\r
+ mFormBrowser2,\r
+ &BufferSize,\r
+ StringPtr,\r
+ FALSE,\r
+ NULL,\r
+ NULL\r
+ );\r
+ FreePool (ConfigRequest);\r
+ return Status;\r
+}\r
-/** @file
- Library Routines to create IFR independent of string data - assume tokens already exist
- Primarily to be used for exporting op-codes at a label in pre-defined forms.
-
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-
-**/
-
-#include "UefiIfrLibraryInternal.h"
-
-/**
- Check if the input question flags is a valid value.
- The valid combination of question flags includes
- EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY.
-
- @param Flags The question flags to check.
-
- @retval TRUE If the question flag is a valid combination.
- @retval FALSE If the question flag is an invalid combination.
-
-**/
-BOOLEAN
-IsValidQuestionFlags (
- IN UINT8 Flags
- )
-{
- return (BOOLEAN) (((Flags & (~QUESTION_FLAGS)) != 0) ? FALSE : TRUE);
-}
-
-/**
- Check if the input value type is a valid type.
- The valid value type is smaller or equal than EFI_IFR_TYPE_OTHER.
-
- @param Type The value type to check.
-
- @retval TRUE If the value type is valid.
- @retval FALSE If the value type is invalid.
-
-**/
-BOOLEAN
-IsValidValueType (
- IN UINT8 Type
- )
-{
- return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE);
-}
-
-/**
- Check if the input numeric flags is a valid value.
-
- @param Flags The numeric flags to check.
-
- @retval TRUE If the numeric flags is valid.
- @retval FALSE If the numeric flags is invalid.
-
-**/
-BOOLEAN
-IsValidNumricFlags (
- IN UINT8 Flags
- )
-{
- if ((Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) != 0) {
- return FALSE;
- }
-
- if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- Check if the checkbox flags is a valid value.
-
- @param Flags The checkbox flags to check.
-
- @retval TRUE If the checkbox flags is valid.
- @retval FALSE If the checkbox flags is invalid.
-
-**/
-BOOLEAN
-IsValidCheckboxFlags (
- IN UINT8 Flags
- )
-{
- return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE);
-}
-
-/**
- Create EFI_IFR_END_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateEndOpCode (
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_END End;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- End.Header.Length = sizeof (EFI_IFR_END);
- End.Header.OpCode = EFI_IFR_END_OP;
- End.Header.Scope = 0;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_END to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END));
- Data->Offset += sizeof (EFI_IFR_END);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_DEFAULT_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param Value Value for the default
- @param Type Type for the default
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER The type is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateDefaultOpCode (
- IN EFI_IFR_TYPE_VALUE *Value,
- IN UINT8 Type,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_DEFAULT Default;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if ((Value == NULL) || !IsValidValueType (Type)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Default.Header.OpCode = EFI_IFR_DEFAULT_OP;
- Default.Header.Length = sizeof (EFI_IFR_DEFAULT);
- Default.Header.Scope = 0;
- Default.Type = Type;
- Default.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE));
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_DEFAULT to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT));
- Data->Offset += sizeof (EFI_IFR_DEFAULT);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_ACTION_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param QuestionConfig String ID for configuration
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateActionOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN EFI_STRING_ID QuestionConfig,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_ACTION Action;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Action.Header.OpCode = EFI_IFR_ACTION_OP;
- Action.Header.Length = sizeof (EFI_IFR_ACTION);
- Action.Header.Scope = 0;
- Action.Question.QuestionId = QuestionId;
- Action.Question.Header.Prompt = Prompt;
- Action.Question.Header.Help = Help;
- Action.Question.VarStoreId = INVALID_VARSTORE_ID;
- Action.Question.Flags = QuestionFlags;
- Action.QuestionConfig = QuestionConfig;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_ACTION to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION));
- Data->Offset += sizeof (EFI_IFR_ACTION);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_SUBTITLE_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param Flags Subtitle opcode flags
- @param Scope Subtitle Scope bit
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateSubTitleOpCode (
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 Flags,
- IN UINT8 Scope,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_SUBTITLE Subtitle;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;
- Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);
- Subtitle.Header.Scope = Scope;
- Subtitle.Statement.Prompt = Prompt;
- Subtitle.Statement.Help = Help;
- Subtitle.Flags = Flags;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_SUBTITLE to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));
- Data->Offset += sizeof (EFI_IFR_SUBTITLE);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Create EFI_IFR_TEXT_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param TextTwo String ID for text two
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateTextOpCode (
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN EFI_STRING_ID TextTwo,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_TEXT Text;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Text.Header.OpCode = EFI_IFR_TEXT_OP;
- Text.Header.Length = sizeof (EFI_IFR_TEXT);
- Text.Header.Scope = 0;
- Text.Statement.Prompt = Prompt;
- Text.Statement.Help = Help;
- Text.TextTwo = TextTwo;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_TEXT to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT));
- Data->Offset += sizeof (EFI_IFR_TEXT);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_REF_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param FormId Destination Form ID
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param QuestionId Question ID
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateGotoOpCode (
- IN EFI_FORM_ID FormId,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN EFI_QUESTION_ID QuestionId,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_REF Goto;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Goto.Header.OpCode = EFI_IFR_REF_OP;
- Goto.Header.Length = sizeof (EFI_IFR_REF);
- Goto.Header.Scope = 0;
- Goto.Question.Header.Prompt = Prompt;
- Goto.Question.Header.Help = Help;
- Goto.Question.VarStoreId = INVALID_VARSTORE_ID;
- Goto.Question.QuestionId = QuestionId;
- Goto.Question.Flags = QuestionFlags;
- Goto.FormId = FormId;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_REF to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF));
- Data->Offset += sizeof (EFI_IFR_REF);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_ONE_OF_OPTION_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param OptionCount The number of options.
- @param OptionsList The list of Options.
- @param Type The data type.
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If OptionCount is not zero but OptionsList is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateOneOfOptionOpCode (
- IN UINTN OptionCount,
- IN IFR_OPTION *OptionsList,
- IN UINT8 Type,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- UINTN Index;
- UINT8 *LocalBuffer;
- EFI_IFR_ONE_OF_OPTION OneOfOption;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if ((OptionCount != 0) && (OptionsList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- for (Index = 0; Index < OptionCount; Index++) {
- OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
- OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
- OneOfOption.Header.Scope = 0;
-
- OneOfOption.Option = OptionsList[Index].StringToken;
- OneOfOption.Value = OptionsList[Index].Value;
- OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
- OneOfOption.Type = Type;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_ONF_OF_OPTION to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));
- Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_ONE_OF_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param VarStoreId Storage ID
- @param VarOffset Offset in Storage
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param OneOfFlags Flags for oneof opcode
- @param OptionsList List of options
- @param OptionCount Number of options in option list
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateOneOfOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_VARSTORE_ID VarStoreId,
- IN UINT16 VarOffset,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN UINT8 OneOfFlags,
- IN IFR_OPTION *OptionsList,
- IN UINTN OptionCount,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- UINTN Length;
- EFI_IFR_ONE_OF OneOf;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidNumricFlags (OneOfFlags) ||
- !IsValidQuestionFlags (QuestionFlags) ||
- ((OptionCount != 0) && (OptionsList == NULL))) {
- return EFI_INVALID_PARAMETER;
- }
-
- Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
- if (Data->Offset + Length > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;
- OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);
- OneOf.Header.Scope = 1;
- OneOf.Question.Header.Prompt = Prompt;
- OneOf.Question.Header.Help = Help;
- OneOf.Question.QuestionId = QuestionId;
- OneOf.Question.VarStoreId = VarStoreId;
- OneOf.Question.VarStoreInfo.VarOffset = VarOffset;
- OneOf.Question.Flags = QuestionFlags;
- OneOf.Flags = OneOfFlags;
- ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA));
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_ONF_OF to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));
- Data->Offset += sizeof (EFI_IFR_ONE_OF);
-
- CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data);
-
- CreateEndOpCode (Data);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_ORDERED_LIST_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param VarStoreId Storage ID
- @param VarOffset Offset in Storage
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param OrderedListFlags Flags for ordered list opcode
- @param DataType Type for option value
- @param MaxContainers Maximum count for options in this ordered list
- @param OptionsList List of options
- @param OptionCount Number of options in option list
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateOrderedListOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_VARSTORE_ID VarStoreId,
- IN UINT16 VarOffset,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN UINT8 OrderedListFlags,
- IN UINT8 DataType,
- IN UINT8 MaxContainers,
- IN IFR_OPTION *OptionsList,
- IN UINTN OptionCount,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- UINTN Length;
- EFI_IFR_ORDERED_LIST OrderedList;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags) ||
- ((OptionCount != 0) && (OptionsList == NULL))) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((OrderedListFlags != 0) &&
- (OrderedListFlags != EFI_IFR_UNIQUE_SET) &&
- (OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
- if (Data->Offset + Length > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
- OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);
- OrderedList.Header.Scope = 1;
- OrderedList.Question.Header.Prompt = Prompt;
- OrderedList.Question.Header.Help = Help;
- OrderedList.Question.QuestionId = QuestionId;
- OrderedList.Question.VarStoreId = VarStoreId;
- OrderedList.Question.VarStoreInfo.VarOffset = VarOffset;
- OrderedList.Question.Flags = QuestionFlags;
- OrderedList.MaxContainers = MaxContainers;
- OrderedList.Flags = OrderedListFlags;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_ORDERED_LIST to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));
- Data->Offset += sizeof (EFI_IFR_ORDERED_LIST);
-
- CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data);
-
- CreateEndOpCode (Data);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_CHECKBOX_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param VarStoreId Storage ID
- @param VarOffset Offset in Storage
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param CheckBoxFlags Flags for checkbox opcode
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateCheckBoxOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_VARSTORE_ID VarStoreId,
- IN UINT16 VarOffset,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN UINT8 CheckBoxFlags,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_CHECKBOX CheckBox;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP;
- CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX);
- CheckBox.Header.Scope = 0;
- CheckBox.Question.QuestionId = QuestionId;
- CheckBox.Question.VarStoreId = VarStoreId;
- CheckBox.Question.VarStoreInfo.VarOffset = VarOffset;
- CheckBox.Question.Header.Prompt = Prompt;
- CheckBox.Question.Header.Help = Help;
- CheckBox.Question.Flags = QuestionFlags;
- CheckBox.Flags = CheckBoxFlags;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_CHECKBOX to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));
- Data->Offset += sizeof (EFI_IFR_CHECKBOX);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_NUMERIC_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param VarStoreId Storage ID
- @param VarOffset Offset in Storage
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param NumericFlags Flags for numeric opcode
- @param Minimum Numeric minimum value
- @param Maximum Numeric maximum value
- @param Step Numeric step for edit
- @param Default Numeric default value
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateNumericOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_VARSTORE_ID VarStoreId,
- IN UINT16 VarOffset,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN UINT8 NumericFlags,
- IN UINT64 Minimum,
- IN UINT64 Maximum,
- IN UINT64 Step,
- IN UINT64 Default,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_STATUS Status;
- EFI_IFR_NUMERIC Numeric;
- MINMAXSTEP_DATA MinMaxStep;
- EFI_IFR_TYPE_VALUE DefaultValue;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;
- Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);
- Numeric.Header.Scope = 1;
- Numeric.Question.QuestionId = QuestionId;
- Numeric.Question.VarStoreId = VarStoreId;
- Numeric.Question.VarStoreInfo.VarOffset = VarOffset;
- Numeric.Question.Header.Prompt = Prompt;
- Numeric.Question.Header.Help = Help;
- Numeric.Question.Flags = QuestionFlags;
- Numeric.Flags = NumericFlags;
-
- switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
- case EFI_IFR_NUMERIC_SIZE_1:
- MinMaxStep.u8.MinValue = (UINT8) Minimum;
- MinMaxStep.u8.MaxValue = (UINT8) Maximum;
- MinMaxStep.u8.Step = (UINT8) Step;
- break;
-
- case EFI_IFR_NUMERIC_SIZE_2:
- MinMaxStep.u16.MinValue = (UINT16) Minimum;
- MinMaxStep.u16.MaxValue = (UINT16) Maximum;
- MinMaxStep.u16.Step = (UINT16) Step;
- break;
-
- case EFI_IFR_NUMERIC_SIZE_4:
- MinMaxStep.u32.MinValue = (UINT32) Minimum;
- MinMaxStep.u32.MaxValue = (UINT32) Maximum;
- MinMaxStep.u32.Step = (UINT32) Step;
- break;
-
- case EFI_IFR_NUMERIC_SIZE_8:
- MinMaxStep.u64.MinValue = Minimum;
- MinMaxStep.u64.MaxValue = Maximum;
- MinMaxStep.u64.Step = Step;
- break;
- }
-
- CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA));
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_NUMERIC to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));
- Data->Offset += sizeof (EFI_IFR_NUMERIC);
-
- DefaultValue.u64 = Default;
- Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- CreateEndOpCode (Data);
-
- return EFI_SUCCESS;
-}
-
-/**
- Create EFI_IFR_STRING_OP opcode.
-
- If Data is NULL or Data->Data is NULL, then ASSERT.
-
- @param QuestionId Question ID
- @param VarStoreId Storage ID
- @param VarOffset Offset in Storage
- @param Prompt String ID for Prompt
- @param Help String ID for Help
- @param QuestionFlags Flags in Question Header
- @param StringFlags Flags for string opcode
- @param MinSize String minimum length
- @param MaxSize String maximum length
- @param Data Destination for the created opcode binary
-
- @retval EFI_SUCCESS Opcode is created successfully.
- @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
- @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateStringOpCode (
- IN EFI_QUESTION_ID QuestionId,
- IN EFI_VARSTORE_ID VarStoreId,
- IN UINT16 VarOffset,
- IN EFI_STRING_ID Prompt,
- IN EFI_STRING_ID Help,
- IN UINT8 QuestionFlags,
- IN UINT8 StringFlags,
- IN UINT8 MinSize,
- IN UINT8 MaxSize,
- IN OUT EFI_HII_UPDATE_DATA *Data
- )
-{
- EFI_IFR_STRING String;
- UINT8 *LocalBuffer;
-
- ASSERT (Data != NULL && Data->Data != NULL);
-
- if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & ~EFI_IFR_STRING_MULTI_LINE) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- String.Header.OpCode = EFI_IFR_STRING_OP;
- String.Header.Length = sizeof (EFI_IFR_STRING);
- String.Header.Scope = 0;
- String.Question.Header.Prompt = Prompt;
- String.Question.Header.Help = Help;
- String.Question.QuestionId = QuestionId;
- String.Question.VarStoreId = VarStoreId;
- String.Question.VarStoreInfo.VarOffset = VarOffset;
- String.Question.Flags = QuestionFlags;
- String.MinSize = MinSize;
- String.MaxSize = MaxSize;
- String.Flags = StringFlags;
-
- LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
- //
- // CopyMem is used for EFI_IFR_STRING to cover the unaligned address access.
- //
- CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING));
- Data->Offset += sizeof (EFI_IFR_STRING);
-
- return EFI_SUCCESS;
-}
-
-
+/** @file\r
+ Library Routines to create IFR independent of string data - assume tokens already exist\r
+ Primarily to be used for exporting op-codes at a label in pre-defined forms.\r
+\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "UefiIfrLibraryInternal.h"\r
+\r
+/**\r
+ Check if the input question flags is a valid value.\r
+ The valid combination of question flags includes\r
+ EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY.\r
+\r
+ @param Flags The question flags to check.\r
+\r
+ @retval TRUE If the question flag is a valid combination.\r
+ @retval FALSE If the question flag is an invalid combination.\r
+ \r
+**/\r
+BOOLEAN\r
+IsValidQuestionFlags (\r
+ IN UINT8 Flags\r
+ )\r
+{\r
+ return (BOOLEAN) (((Flags & (~QUESTION_FLAGS)) != 0) ? FALSE : TRUE);\r
+}\r
+\r
+/**\r
+ Check if the input value type is a valid type.\r
+ The valid value type is smaller or equal than EFI_IFR_TYPE_OTHER.\r
+\r
+ @param Type The value type to check.\r
+\r
+ @retval TRUE If the value type is valid.\r
+ @retval FALSE If the value type is invalid.\r
+ \r
+**/\r
+BOOLEAN\r
+IsValidValueType (\r
+ IN UINT8 Type\r
+ )\r
+{\r
+ return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE);\r
+}\r
+\r
+/**\r
+ Check if the input numeric flags is a valid value.\r
+\r
+ @param Flags The numeric flags to check.\r
+\r
+ @retval TRUE If the numeric flags is valid.\r
+ @retval FALSE If the numeric flags is invalid.\r
+ \r
+**/\r
+BOOLEAN\r
+IsValidNumricFlags (\r
+ IN UINT8 Flags\r
+ )\r
+{\r
+ if ((Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check if the checkbox flags is a valid value.\r
+\r
+ @param Flags The checkbox flags to check.\r
+\r
+ @retval TRUE If the checkbox flags is valid.\r
+ @retval FALSE If the checkbox flags is invalid.\r
+ \r
+**/\r
+BOOLEAN\r
+IsValidCheckboxFlags (\r
+ IN UINT8 Flags\r
+ )\r
+{\r
+ return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE);\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_END_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateEndOpCode (\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_END End;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ End.Header.Length = sizeof (EFI_IFR_END);\r
+ End.Header.OpCode = EFI_IFR_END_OP;\r
+ End.Header.Scope = 0;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_END to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END));\r
+ Data->Offset += sizeof (EFI_IFR_END);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_DEFAULT_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param Value Value for the default\r
+ @param Type Type for the default\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER The type is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateDefaultOpCode (\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ IN UINT8 Type,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_DEFAULT Default;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if ((Value == NULL) || !IsValidValueType (Type)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Default.Header.OpCode = EFI_IFR_DEFAULT_OP;\r
+ Default.Header.Length = sizeof (EFI_IFR_DEFAULT);\r
+ Default.Header.Scope = 0;\r
+ Default.Type = Type;\r
+ Default.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE));\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_DEFAULT to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT));\r
+ Data->Offset += sizeof (EFI_IFR_DEFAULT);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ACTION_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param QuestionConfig String ID for configuration\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateActionOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN EFI_STRING_ID QuestionConfig,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_ACTION Action;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Action.Header.OpCode = EFI_IFR_ACTION_OP;\r
+ Action.Header.Length = sizeof (EFI_IFR_ACTION);\r
+ Action.Header.Scope = 0;\r
+ Action.Question.QuestionId = QuestionId;\r
+ Action.Question.Header.Prompt = Prompt;\r
+ Action.Question.Header.Help = Help;\r
+ Action.Question.VarStoreId = INVALID_VARSTORE_ID;\r
+ Action.Question.Flags = QuestionFlags;\r
+ Action.QuestionConfig = QuestionConfig;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_ACTION to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION));\r
+ Data->Offset += sizeof (EFI_IFR_ACTION);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_SUBTITLE_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param Flags Subtitle opcode flags\r
+ @param Scope Subtitle Scope bit\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateSubTitleOpCode (\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 Flags,\r
+ IN UINT8 Scope,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_SUBTITLE Subtitle;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;\r
+ Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);\r
+ Subtitle.Header.Scope = Scope;\r
+ Subtitle.Statement.Prompt = Prompt;\r
+ Subtitle.Statement.Help = Help;\r
+ Subtitle.Flags = Flags;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_SUBTITLE to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));\r
+ Data->Offset += sizeof (EFI_IFR_SUBTITLE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Create EFI_IFR_TEXT_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param TextTwo String ID for text two\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateTextOpCode (\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN EFI_STRING_ID TextTwo,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_TEXT Text;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Text.Header.OpCode = EFI_IFR_TEXT_OP;\r
+ Text.Header.Length = sizeof (EFI_IFR_TEXT);\r
+ Text.Header.Scope = 0;\r
+ Text.Statement.Prompt = Prompt;\r
+ Text.Statement.Help = Help;\r
+ Text.TextTwo = TextTwo;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_TEXT to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT));\r
+ Data->Offset += sizeof (EFI_IFR_TEXT);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_REF_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param FormId Destination Form ID\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param QuestionId Question ID\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateGotoOpCode (\r
+ IN EFI_FORM_ID FormId,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_REF Goto;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Goto.Header.OpCode = EFI_IFR_REF_OP;\r
+ Goto.Header.Length = sizeof (EFI_IFR_REF);\r
+ Goto.Header.Scope = 0;\r
+ Goto.Question.Header.Prompt = Prompt;\r
+ Goto.Question.Header.Help = Help;\r
+ Goto.Question.VarStoreId = INVALID_VARSTORE_ID;\r
+ Goto.Question.QuestionId = QuestionId;\r
+ Goto.Question.Flags = QuestionFlags;\r
+ Goto.FormId = FormId;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_REF to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF));\r
+ Data->Offset += sizeof (EFI_IFR_REF);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param OptionCount The number of options.\r
+ @param OptionsList The list of Options.\r
+ @param Type The data type.\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If OptionCount is not zero but OptionsList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateOneOfOptionOpCode (\r
+ IN UINTN OptionCount,\r
+ IN IFR_OPTION *OptionsList,\r
+ IN UINT8 Type,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 *LocalBuffer;\r
+ EFI_IFR_ONE_OF_OPTION OneOfOption;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if ((OptionCount != 0) && (OptionsList == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
+ OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);\r
+ OneOfOption.Header.Scope = 0;\r
+\r
+ OneOfOption.Option = OptionsList[Index].StringToken;\r
+ OneOfOption.Value = OptionsList[Index].Value;\r
+ OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
+ OneOfOption.Type = Type;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_ONF_OF_OPTION to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));\r
+ Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ONE_OF_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param VarStoreId Storage ID\r
+ @param VarOffset Offset in Storage\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param OneOfFlags Flags for oneof opcode\r
+ @param OptionsList List of options\r
+ @param OptionCount Number of options in option list\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateOneOfOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 OneOfFlags,\r
+ IN IFR_OPTION *OptionsList,\r
+ IN UINTN OptionCount,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ UINTN Length;\r
+ EFI_IFR_ONE_OF OneOf;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidNumricFlags (OneOfFlags) ||\r
+ !IsValidQuestionFlags (QuestionFlags) ||\r
+ ((OptionCount != 0) && (OptionsList == NULL))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);\r
+ if (Data->Offset + Length > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;\r
+ OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);\r
+ OneOf.Header.Scope = 1;\r
+ OneOf.Question.Header.Prompt = Prompt;\r
+ OneOf.Question.Header.Help = Help;\r
+ OneOf.Question.QuestionId = QuestionId;\r
+ OneOf.Question.VarStoreId = VarStoreId;\r
+ OneOf.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OneOf.Question.Flags = QuestionFlags;\r
+ OneOf.Flags = OneOfFlags;\r
+ ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA));\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_ONF_OF to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));\r
+ Data->Offset += sizeof (EFI_IFR_ONE_OF);\r
+\r
+ CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data);\r
+\r
+ CreateEndOpCode (Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ORDERED_LIST_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param VarStoreId Storage ID\r
+ @param VarOffset Offset in Storage\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param OrderedListFlags Flags for ordered list opcode\r
+ @param DataType Type for option value\r
+ @param MaxContainers Maximum count for options in this ordered list\r
+ @param OptionsList List of options\r
+ @param OptionCount Number of options in option list\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateOrderedListOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 OrderedListFlags,\r
+ IN UINT8 DataType,\r
+ IN UINT8 MaxContainers,\r
+ IN IFR_OPTION *OptionsList,\r
+ IN UINTN OptionCount,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ UINTN Length;\r
+ EFI_IFR_ORDERED_LIST OrderedList;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags) ||\r
+ ((OptionCount != 0) && (OptionsList == NULL))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((OrderedListFlags != 0) &&\r
+ (OrderedListFlags != EFI_IFR_UNIQUE_SET) &&\r
+ (OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);\r
+ if (Data->Offset + Length > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;\r
+ OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);\r
+ OrderedList.Header.Scope = 1;\r
+ OrderedList.Question.Header.Prompt = Prompt;\r
+ OrderedList.Question.Header.Help = Help;\r
+ OrderedList.Question.QuestionId = QuestionId;\r
+ OrderedList.Question.VarStoreId = VarStoreId;\r
+ OrderedList.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OrderedList.Question.Flags = QuestionFlags;\r
+ OrderedList.MaxContainers = MaxContainers;\r
+ OrderedList.Flags = OrderedListFlags;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_ORDERED_LIST to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));\r
+ Data->Offset += sizeof (EFI_IFR_ORDERED_LIST);\r
+\r
+ CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data);\r
+\r
+ CreateEndOpCode (Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_CHECKBOX_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param VarStoreId Storage ID\r
+ @param VarOffset Offset in Storage\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param CheckBoxFlags Flags for checkbox opcode\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateCheckBoxOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 CheckBoxFlags,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_CHECKBOX CheckBox;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP;\r
+ CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX);\r
+ CheckBox.Header.Scope = 0;\r
+ CheckBox.Question.QuestionId = QuestionId;\r
+ CheckBox.Question.VarStoreId = VarStoreId;\r
+ CheckBox.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ CheckBox.Question.Header.Prompt = Prompt;\r
+ CheckBox.Question.Header.Help = Help;\r
+ CheckBox.Question.Flags = QuestionFlags;\r
+ CheckBox.Flags = CheckBoxFlags;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_CHECKBOX to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));\r
+ Data->Offset += sizeof (EFI_IFR_CHECKBOX);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_NUMERIC_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param VarStoreId Storage ID\r
+ @param VarOffset Offset in Storage\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param NumericFlags Flags for numeric opcode\r
+ @param Minimum Numeric minimum value\r
+ @param Maximum Numeric maximum value\r
+ @param Step Numeric step for edit\r
+ @param Default Numeric default value\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateNumericOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 NumericFlags,\r
+ IN UINT64 Minimum,\r
+ IN UINT64 Maximum,\r
+ IN UINT64 Step,\r
+ IN UINT64 Default,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IFR_NUMERIC Numeric;\r
+ MINMAXSTEP_DATA MinMaxStep;\r
+ EFI_IFR_TYPE_VALUE DefaultValue;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;\r
+ Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);\r
+ Numeric.Header.Scope = 1;\r
+ Numeric.Question.QuestionId = QuestionId;\r
+ Numeric.Question.VarStoreId = VarStoreId;\r
+ Numeric.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ Numeric.Question.Header.Prompt = Prompt;\r
+ Numeric.Question.Header.Help = Help;\r
+ Numeric.Question.Flags = QuestionFlags;\r
+ Numeric.Flags = NumericFlags;\r
+\r
+ switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ MinMaxStep.u8.MinValue = (UINT8) Minimum;\r
+ MinMaxStep.u8.MaxValue = (UINT8) Maximum;\r
+ MinMaxStep.u8.Step = (UINT8) Step;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ MinMaxStep.u16.MinValue = (UINT16) Minimum;\r
+ MinMaxStep.u16.MaxValue = (UINT16) Maximum;\r
+ MinMaxStep.u16.Step = (UINT16) Step;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ MinMaxStep.u32.MinValue = (UINT32) Minimum;\r
+ MinMaxStep.u32.MaxValue = (UINT32) Maximum;\r
+ MinMaxStep.u32.Step = (UINT32) Step;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ MinMaxStep.u64.MinValue = Minimum;\r
+ MinMaxStep.u64.MaxValue = Maximum;\r
+ MinMaxStep.u64.Step = Step;\r
+ break;\r
+ }\r
+\r
+ CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA));\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_NUMERIC to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));\r
+ Data->Offset += sizeof (EFI_IFR_NUMERIC);\r
+\r
+ DefaultValue.u64 = Default;\r
+ Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CreateEndOpCode (Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_STRING_OP opcode.\r
+\r
+ If Data is NULL or Data->Data is NULL, then ASSERT.\r
+\r
+ @param QuestionId Question ID\r
+ @param VarStoreId Storage ID\r
+ @param VarOffset Offset in Storage\r
+ @param Prompt String ID for Prompt\r
+ @param Help String ID for Help\r
+ @param QuestionFlags Flags in Question Header\r
+ @param StringFlags Flags for string opcode\r
+ @param MinSize String minimum length\r
+ @param MaxSize String maximum length\r
+ @param Data Destination for the created opcode binary\r
+\r
+ @retval EFI_SUCCESS Opcode is created successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.\r
+ @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateStringOpCode (\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 StringFlags,\r
+ IN UINT8 MinSize,\r
+ IN UINT8 MaxSize,\r
+ IN OUT EFI_HII_UPDATE_DATA *Data\r
+ )\r
+{\r
+ EFI_IFR_STRING String;\r
+ UINT8 *LocalBuffer;\r
+\r
+ ASSERT (Data != NULL && Data->Data != NULL);\r
+\r
+ if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & ~EFI_IFR_STRING_MULTI_LINE) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ String.Header.OpCode = EFI_IFR_STRING_OP;\r
+ String.Header.Length = sizeof (EFI_IFR_STRING);\r
+ String.Header.Scope = 0;\r
+ String.Question.Header.Prompt = Prompt;\r
+ String.Question.Header.Help = Help;\r
+ String.Question.QuestionId = QuestionId;\r
+ String.Question.VarStoreId = VarStoreId;\r
+ String.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ String.Question.Flags = QuestionFlags;\r
+ String.MinSize = MinSize;\r
+ String.MaxSize = MaxSize;\r
+ String.Flags = StringFlags;\r
+\r
+ LocalBuffer = (UINT8 *) Data->Data + Data->Offset;\r
+ //\r
+ // CopyMem is used for EFI_IFR_STRING to cover the unaligned address access.\r
+ //\r
+ CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING));\r
+ Data->Offset += sizeof (EFI_IFR_STRING);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r