+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
-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
-Module Name:\r
-\r
- UefiIfrForm.c\r
-\r
-Abstract:\r
-\r
- Common Library Routines to assist handle HII elements.\r
-\r
---*/\r
-\r
-#include "UefiIfrLibrary.h"\r
-\r
-//\r
-// Fake <ConfigHdr>\r
-//\r
-UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";\r
-\r
-EFI_STATUS\r
-GetPackageDataFromPackageList (\r
- IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
- IN UINT32 PackageIndex,\r
- OUT UINT32 *BufferLen,\r
- OUT EFI_HII_PACKAGE_HEADER **Buffer\r
- )\r
-{\r
- UINT32 Index;\r
- EFI_HII_PACKAGE_HEADER *Package;\r
- UINT32 Offset;\r
- UINT32 PackageListLength;\r
- EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};\r
-\r
- ASSERT(HiiPackageList != NULL);\r
-\r
- if ((BufferLen == NULL) || (Buffer == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Package = NULL;\r
- Index = 0;\r
- Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
- EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
- while (Offset < PackageListLength) {\r
- Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
- EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
- if (Index == PackageIndex) {\r
- break;\r
- }\r
- Offset += PackageHeader.Length;\r
- Index++;\r
- }\r
- if (Offset >= PackageListLength) {\r
- //\r
- // no package found in this Package List\r
- //\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- *BufferLen = PackageHeader.Length;\r
- *Buffer = Package;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-UpdateFormPackageData (\r
- IN EFI_GUID *FormSetGuid,\r
- IN EFI_FORM_ID FormId,\r
- IN EFI_HII_PACKAGE_HEADER *Package,\r
- IN UINT32 PackageLength,\r
- IN UINT16 Label,\r
- IN BOOLEAN Insert,\r
- IN EFI_HII_UPDATE_DATA *Data,\r
- OUT UINT8 **TempBuffer,\r
- OUT UINT32 *TempBufferSize\r
- )\r
-{\r
- UINT8 *BufferPos;\r
- EFI_HII_PACKAGE_HEADER PackageHeader;\r
- UINT32 Offset;\r
- EFI_IFR_OP_HEADER *IfrOpHdr;\r
- BOOLEAN GetFormSet;\r
- BOOLEAN GetForm;\r
- UINT8 ExtendOpCode;\r
- UINT16 LabelNumber;\r
- BOOLEAN Updated;\r
-\r
- if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *TempBufferSize = PackageLength;\r
- if (Data != NULL) {\r
- *TempBufferSize += Data->Offset;\r
- }\r
- *TempBuffer = EfiLibAllocateZeroPool (*TempBufferSize);\r
- if (*TempBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- EfiCopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
- *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);\r
- BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
-\r
- EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
- IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
- Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
- GetFormSet = (BOOLEAN)((FormSetGuid == NULL) ? TRUE : FALSE);\r
- GetForm = FALSE;\r
- Updated = FALSE;\r
-\r
- while (!Updated && Offset < PackageHeader.Length) {\r
- EfiCopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
- BufferPos += IfrOpHdr->Length;\r
- *TempBufferSize += IfrOpHdr->Length;\r
-\r
- switch (IfrOpHdr->OpCode) {\r
- case EFI_IFR_FORM_SET_OP :\r
- if (FormSetGuid != NULL) {\r
- if (EfiCompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {\r
- GetFormSet = TRUE;\r
- } else {\r
- GetFormSet = FALSE;\r
- }\r
- }\r
- break;\r
-\r
- case EFI_IFR_FORM_OP:\r
- if (EfiCompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
- GetForm = TRUE;\r
- } else {\r
- GetForm = FALSE;\r
- }\r
- break;\r
-\r
- case EFI_IFR_GUID_OP :\r
- if (!GetFormSet || !GetForm) {\r
- //\r
- // Go to the next Op-Code\r
- //\r
- break;\r
- }\r
-\r
- if (!EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid)) {\r
- //\r
- // GUID mismatch, skip this op-code\r
- //\r
- break;\r
- }\r
-\r
- ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
- EfiCopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));\r
- if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {\r
- //\r
- // Go to the next Op-Code\r
- //\r
- break;\r
- }\r
-\r
- if (Insert) {\r
- //\r
- // Insert data after current Label, skip myself\r
- //\r
- Offset += IfrOpHdr->Length;\r
- IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
- } else {\r
- //\r
- // Replace data between two paired Label, try to find the next Label.\r
- //\r
- while (TRUE) {\r
- Offset += IfrOpHdr->Length;\r
- //\r
- // Search the next label and Fail if not label found.\r
- //\r
- if (Offset >= PackageHeader.Length) {\r
- goto Fail;\r
- }\r
- IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
- if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {\r
- ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
- if (EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid) && ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Fill in the update data\r
- //\r
- if (Data != NULL) {\r
- EfiCopyMem (BufferPos, Data->Data, Data->Offset);\r
- BufferPos += Data->Offset;\r
- *TempBufferSize += Data->Offset;\r
- }\r
-\r
- //\r
- // Copy the reset data\r
- //\r
- EfiCopyMem (BufferPos, IfrOpHdr, PackageHeader.Length - Offset);\r
- *TempBufferSize += PackageHeader.Length - Offset;\r
-\r
- Updated = TRUE;\r
- break;\r
- default :\r
- break;\r
- }\r
-\r
- //\r
- // Go to the next Op-Code\r
- //\r
- Offset += IfrOpHdr->Length;\r
- IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
- }\r
-\r
- //\r
- // Update the package length.\r
- //\r
- PackageHeader.Length = *TempBufferSize;\r
- EfiCopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
-\r
-Fail:\r
- if (!Updated) {\r
- gBS->FreePool (*TempBuffer);\r
- *TempBufferSize = 0;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-IfrLibInitUpdateData (\r
- IN OUT EFI_HII_UPDATE_DATA *UpdateData,\r
- IN UINT32 BufferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- This function initialize the data structure for dynamic opcode.\r
-\r
-Arguments:\r
- UpdateData - The adding data;\r
- BufferSize - Length of the buffer to fill dynamic opcodes.\r
-\r
-Returns:\r
- EFI_SUCCESS - Update data is initialized.\r
- EFI_INVALID_PARAMETER - UpdateData is NULL.\r
- EFI_OUT_OF_RESOURCES - No enough memory to allocate.\r
-\r
---*/\r
-{\r
- if (UpdateData == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- UpdateData->BufferSize = BufferSize;\r
- UpdateData->Offset = 0;\r
- UpdateData->Data = EfiLibAllocatePool (BufferSize);\r
-\r
- return (UpdateData->Data != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
-}\r
-\r
-EFI_STATUS\r
-IfrLibFreeUpdateData (\r
- IN EFI_HII_UPDATE_DATA *UpdateData\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- This function free the resource of update data.\r
-\r
-Arguments:\r
- UpdateData - The adding data;\r
-\r
-Returns:\r
- EFI_SUCCESS - Resource in UpdateData is released.\r
- EFI_INVALID_PARAMETER - UpdateData is NULL.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- if (UpdateData == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = gBS->FreePool (UpdateData->Data);\r
- UpdateData->Data = NULL;\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-IfrLibUpdateForm (\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_GUID *FormSetGuid, OPTIONAL\r
- IN EFI_FORM_ID FormId,\r
- IN UINT16 Label,\r
- IN BOOLEAN Insert,\r
- IN EFI_HII_UPDATE_DATA *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- This function allows the caller to update a form that has\r
- previously been registered with the EFI HII database.\r
-\r
-Arguments:\r
- Handle - Hii Handle\r
- FormSetGuid - The formset should be updated.\r
- FormId - The form should be updated.\r
- Label - Update information starting immediately after this label in the IFR\r
- Insert - If TRUE and Data is not NULL, insert data after Label.\r
- If FALSE, replace opcodes between two labels with Data\r
- Data - The adding data; If NULL, remove opcodes between two Label.\r
-\r
-Returns:\r
- EFI_SUCCESS - Update success.\r
- Other - Update fail.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
- EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
- UINT32 Index;\r
- EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;\r
- UINTN BufferSize;\r
- UINT8 *UpdateBufferPos;\r
- EFI_HII_PACKAGE_HEADER PackageHeader;\r
- EFI_HII_PACKAGE_HEADER *Package;\r
- UINT32 PackageLength;\r
- EFI_HII_PACKAGE_HEADER *TempBuffer;\r
- UINT32 TempBufferSize;\r
- BOOLEAN Updated;\r
-\r
- if (Data == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- LocateHiiProtocols ();\r
- HiiDatabase = gIfrLibHiiDatabase;\r
-\r
- //\r
- // Get the orginal package list\r
- //\r
- BufferSize = 0;\r
- HiiPackageList = NULL;\r
- Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- HiiPackageList = EfiLibAllocatePool (BufferSize);\r
- ASSERT (HiiPackageList != NULL);\r
-\r
- Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (HiiPackageList);\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Calculate and allocate space for retrieval of IFR data\r
- //\r
- BufferSize += Data->Offset;\r
- UpdateBuffer = EfiLibAllocateZeroPool (BufferSize);\r
- if (UpdateBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- UpdateBufferPos = (UINT8 *) UpdateBuffer;\r
-\r
- //\r
- // copy the package list header\r
- //\r
- EfiCopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
- UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
-\r
- Updated = FALSE;\r
- for (Index = 0; ; Index++) {\r
- Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);\r
- if (Status == EFI_SUCCESS) {\r
- EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
- if ((PackageHeader.Type == EFI_HII_PACKAGE_FORMS) && !Updated) {\r
- Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);\r
- if (!EFI_ERROR(Status)) {\r
- if (FormSetGuid == NULL) {\r
- Updated = TRUE;\r
- }\r
- EfiCopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);\r
- UpdateBufferPos += TempBufferSize;\r
- gBS->FreePool (TempBuffer);\r
- continue;\r
- }\r
- }\r
-\r
- EfiCopyMem (UpdateBufferPos, Package, PackageLength);\r
- UpdateBufferPos += PackageLength;\r
- } else if (Status == EFI_NOT_FOUND) {\r
- break;\r
- } else {\r
- gBS->FreePool (HiiPackageList);\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Update package list length\r
- //\r
- BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;\r
- EfiCopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));\r
-\r
- gBS->FreePool (HiiPackageList);\r
-\r
- return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);\r
-}\r
-\r
-EFI_STATUS\r
-IfrLibCreatePopUp (\r
- IN UINTN NumberOfLines,\r
- OUT EFI_INPUT_KEY *KeyValue,\r
- IN CHAR16 *String,\r
- ...\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Draw a dialog and return the selected key.\r
-\r
-Arguments:\r
- NumberOfLines - The number of lines for the dialog box\r
- KeyValue - The EFI_KEY value returned if HotKey is TRUE..\r
- String - Pointer to the first string in the list\r
- ... - A series of (quantity == NumberOfLines) text strings which\r
- will be used to construct the dialog box\r
-\r
-Returns:\r
- EFI_SUCCESS - Displayed dialog and received user interaction\r
- EFI_INVALID_PARAMETER - One of the parameters was invalid.\r
-\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
- VA_LIST Marker;\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_OUT_PROTOCOL *ConOut;\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 = EfiLibAllocateZeroPool (DimensionsWidth * sizeof (CHAR16));\r
- ASSERT (LineBuffer != NULL);\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 = EfiLibAllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));\r
- LargestString = EfiStrLen (String);\r
- StringArray[0] = String;\r
-\r
- VA_START (Marker, String);\r
- for (Index = 1; Index < NumberOfLines; Index++) {\r
- StackString = VA_ARG (Marker, CHAR16 *);\r
-\r
- if (StackString == NULL) {\r
- VA_END (Marker);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- StringArray[Index] = StackString;\r
- StringLen = EfiStrLen (StackString);\r
- if (StringLen > LargestString) {\r
- LargestString = StringLen;\r
- }\r
- }\r
- VA_END (Marker);\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 = EfiStrLen (StringArray[Index]);\r
- if (StringLen > LargestString) {\r
- StringLen = LargestString;\r
- }\r
- EfiCopyMem (\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 (EFI_EVENT_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
- EfiCopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
-\r
- ConOut->SetAttribute (ConOut, CurrentAttribute);\r
- ConOut->EnableCursor (ConOut, TRUE);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-ExtractDefault(\r
- IN VOID *Buffer,\r
- IN UINTN *BufferSize,\r
- UINTN Number,\r
- ...\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Configure the buffer accrording to ConfigBody strings.\r
-\r
- Arguments:\r
- DefaultId - the ID of default.\r
- Buffer - the start address of buffer.\r
- BufferSize - the size of buffer.\r
- Number - the number of the strings.\r
-\r
- Returns:\r
- EFI_BUFFER_TOO_SMALL - the BufferSize is too small to operate.\r
- EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0.\r
- EFI_SUCCESS - Operation successful.\r
-\r
---*/\r
-{\r
- VA_LIST Args;\r
- UINTN Index;\r
- UINT32 TotalLen;\r
- UINT8 *BufCfgArray;\r
- UINT8 *BufferPos;\r
- UINT16 Offset;\r
- UINT16 Width;\r
- UINT8 *Value;\r
-\r
- if ((Buffer == NULL) || (BufferSize == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Offset = 0;\r
- Width = 0;\r
- Value = NULL;\r
-\r
- VA_START (Args, Number);\r
- for (Index = 0; Index < Number; Index++) {\r
- BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
- EfiCopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));\r
- BufferPos = BufCfgArray + sizeof (UINT32);\r
-\r
- while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
- EfiCopyMem (&Offset, BufferPos, sizeof (UINT16));\r
- BufferPos += sizeof (UINT16);\r
- EfiCopyMem (&Width, BufferPos, sizeof (UINT16));\r
- BufferPos += sizeof (UINT16);\r
- Value = BufferPos;\r
- BufferPos += Width;\r
-\r
- if ((UINTN)(Offset + Width) > *BufferSize) {\r
- VA_END (Args);\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- EfiCopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
- }\r
- }\r
- VA_END (Args);\r
-\r
- *BufferSize = (UINTN)Offset;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-ExtractBlockName (\r
- IN UINT8 *Buffer,\r
- OUT CHAR16 **BlockName\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Extract block name from the array generated by VFR compiler. The name of\r
- this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".\r
- Format of this array is:\r
- Array length | 4-bytes\r
- Offset | 2-bytes\r
- Width | 2-bytes\r
- Offset | 2-bytes\r
- Width | 2-bytes\r
- ... ...\r
-\r
- Arguments:\r
- Buffer - Array generated by VFR compiler.\r
- BlockName - The returned <BlockName>\r
-\r
- Returns:\r
- EFI_OUT_OF_RESOURCES - Run out of memory resource.\r
- EFI_INVALID_PARAMETER - Buffer is NULL or BlockName is NULL.\r
- EFI_SUCCESS - Operation successful.\r
-\r
---*/\r
-{\r
- UINTN Index;\r
- UINT32 Length;\r
- UINT32 BlockNameNumber;\r
- UINTN HexStringBufferLen;\r
- CHAR16 *StringPtr;\r
-\r
- if ((Buffer == NULL) || (BlockName == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Calculate number of Offset/Width pair\r
- //\r
- EfiCopyMem (&Length, Buffer, sizeof (UINT32));\r
- BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2);\r
-\r
- //\r
- // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
- // | 8 | 4 | 7 | 4 |\r
- //\r
- StringPtr = EfiLibAllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));\r
- *BlockName = StringPtr;\r
- if (StringPtr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Buffer += sizeof (UINT32);\r
- for (Index = 0; Index < BlockNameNumber; Index++) {\r
- EfiStrCpy (StringPtr, L"&OFFSET=");\r
- StringPtr += 8;\r
-\r
- HexStringBufferLen = 5;\r
- BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
- Buffer += sizeof (UINT16);\r
- StringPtr += 4;\r
-\r
- EfiStrCpy (StringPtr, L"&WIDTH=");\r
- StringPtr += 7;\r
-\r
- HexStringBufferLen = 5;\r
- BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
- Buffer += sizeof (UINT16);\r
- StringPtr += 4;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-ExtractBlockConfig (\r
- IN UINT8 *Buffer,\r
- OUT CHAR16 **BlockConfig\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Extract block config from the array generated by VFR compiler. The name of\r
- this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".\r
-\r
- Arguments:\r
- Buffer - Array generated by VFR compiler.\r
- BlockConfig - The returned <BlockConfig>\r
-\r
- Returns:\r
- EFI_OUT_OF_RESOURCES - Run out of memory resource.\r
- EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.\r
- EFI_SUCCESS - Operation successful.\r
-\r
---*/\r
-{\r
- UINT32 Length;\r
- UINT16 Width;\r
- UINTN HexStringBufferLen;\r
- CHAR16 *StringPtr;\r
- UINT8 *BufferEnd;\r
- CHAR16 *StringEnd;\r
- EFI_STATUS Status;\r
-\r
- if ((Buffer == NULL) || (BlockConfig == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Calculate length of AltResp string\r
- // Format of Default value array is:\r
- // Array length | 4-bytes\r
- // Offset | 2-bytes\r
- // Width | 2-bytes\r
- // Value | Variable length\r
- // Offset | 2-bytes\r
- // Width | 2-bytes\r
- // Value | Variable length\r
- // ... ...\r
- // When value is 1 byte in length, overhead of AltResp string will be maximum,\r
- // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+\r
- // | 8 | 4 | 7 | 4 | 7 |2|\r
- // so the maximum length of BlockConfig could be calculated as:\r
- // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7\r
- //\r
- EfiCopyMem (&Length, Buffer, sizeof (UINT32));\r
- BufferEnd = Buffer + Length;\r
- StringPtr = EfiLibAllocatePool (Length * 7 * sizeof (CHAR16));\r
- *BlockConfig = StringPtr;\r
- if (StringPtr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- StringEnd = StringPtr + (Length * 7);\r
-\r
- Buffer += sizeof (UINT32);\r
- while (Buffer < BufferEnd) {\r
- EfiStrCpy (StringPtr, L"&OFFSET=");\r
- StringPtr += 8;\r
-\r
- HexStringBufferLen = 5;\r
- BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
- Buffer += sizeof (UINT16);\r
- StringPtr += 4;\r
-\r
- EfiStrCpy (StringPtr, L"&WIDTH=");\r
- StringPtr += 7;\r
-\r
- HexStringBufferLen = 5;\r
- BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
- EfiCopyMem (&Width, Buffer, sizeof (UINT16));\r
- Buffer += sizeof (UINT16);\r
- StringPtr += 4;\r
-\r
- EfiStrCpy (StringPtr, L"&VALUE=");\r
- StringPtr += 7;\r
-\r
- HexStringBufferLen = StringEnd - StringPtr;\r
- Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- Buffer += Width;\r
- StringPtr += (Width * 2);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-ConstructConfigAltResp (\r
- IN EFI_STRING ConfigRequest, OPTIONAL\r
- OUT EFI_STRING *Progress,\r
- OUT EFI_STRING *ConfigAltResp,\r
- IN EFI_GUID *Guid,\r
- IN CHAR16 *Name,\r
- IN EFI_HANDLE *DriverHandle,\r
- IN VOID *BufferStorage,\r
- IN UINTN BufferStorageSize,\r
- IN VOID *BlockNameArray, OPTIONAL\r
- IN UINTN NumberAltCfg,\r
- ...\r
-//IN UINT16 AltCfgId,\r
-//IN VOID *DefaultValueArray,\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Construct <ConfigAltResp> for a buffer storage.\r
-\r
- Arguments:\r
- ConfigRequest - The Config request string. If set to NULL, all the\r
- configurable elements will be extracted from BlockNameArray.\r
- ConfigAltResp - The returned <ConfigAltResp>.\r
- Progress - On return, points to a character in the Request.\r
- Guid - GUID of the buffer storage.\r
- Name - Name of the buffer storage.\r
- DriverHandle - The DriverHandle which is used to invoke HiiDatabase\r
- protocol interface NewPackageList().\r
- BufferStorage - Content of the buffer storage.\r
- BufferStorageSize - Length in bytes of the buffer storage.\r
- BlockNameArray - Array generated by VFR compiler.\r
- NumberAltCfg - Number of Default value array generated by VFR compiler.\r
- The sequential input parameters will be number of\r
- AltCfgId and DefaultValueArray pairs. When set to 0,\r
- there will be no <AltResp>.\r
-\r
- Returns:\r
- EFI_OUT_OF_RESOURCES - Run out of memory resource.\r
- EFI_INVALID_PARAMETER - ConfigAltResp is NULL.\r
- EFI_SUCCESS - Operation successful.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *ConfigHdr;\r
- CHAR16 *BlockName;\r
- CHAR16 *DescHdr;\r
- CHAR16 *StringPtr;\r
- CHAR16 **AltCfg;\r
- UINT16 AltCfgId;\r
- VOID *DefaultValueArray;\r
- UINTN StrBufferLen;\r
- EFI_STRING ConfigResp;\r
- EFI_STRING TempStr;\r
- VA_LIST Args;\r
- UINTN AltRespLen;\r
- UINTN Index;\r
- BOOLEAN NeedFreeConfigRequest;\r
- EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
-\r
- if (ConfigAltResp == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
- //\r
- ConfigHdr = NULL;\r
- StrBufferLen = 0;\r
- Status = ConstructConfigHdr (\r
- ConfigHdr,\r
- &StrBufferLen,\r
- Guid,\r
- Name,\r
- DriverHandle\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- ConfigHdr = EfiLibAllocateZeroPool (StrBufferLen);\r
- Status = ConstructConfigHdr (\r
- ConfigHdr,\r
- &StrBufferLen,\r
- Guid,\r
- Name,\r
- DriverHandle\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status) || (ConfigHdr == NULL)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Construct <ConfigResp>\r
- //\r
- NeedFreeConfigRequest = FALSE;\r
- if (ConfigRequest == NULL) {\r
- //\r
- // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray\r
- //\r
- Status = ExtractBlockName (BlockNameArray, &BlockName);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- StrBufferLen = EfiStrSize (ConfigHdr);\r
- StrBufferLen = StrBufferLen + EfiStrSize (BlockName) - sizeof (CHAR16);\r
- ConfigRequest = EfiLibAllocateZeroPool (StrBufferLen);\r
- EfiStrCpy (ConfigRequest, ConfigHdr);\r
- EfiStrCat (ConfigRequest, BlockName);\r
- NeedFreeConfigRequest = TRUE;\r
- }\r
-\r
- Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = HiiConfigRouting->BlockToConfig (\r
- HiiConfigRouting,\r
- ConfigRequest,\r
- BufferStorage,\r
- BufferStorageSize,\r
- &ConfigResp,\r
- (Progress == NULL) ? &TempStr : Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Construct <AltResp>\r
- //\r
- DescHdr = EfiLibAllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));\r
- StringPtr = DescHdr;\r
- AltCfg = EfiLibAllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));\r
- AltRespLen = 0;\r
- VA_START (Args, NumberAltCfg);\r
- for (Index = 0; Index < NumberAltCfg; Index++) {\r
- AltCfgId = (UINT16) VA_ARG (Args, UINT16);\r
- DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);\r
-\r
- //\r
- // '&' <ConfigHdr>\r
- //\r
- AltRespLen += (EfiStrLen (ConfigHdr) + 1);\r
-\r
- StringPtr = DescHdr + Index * 16;\r
- EfiStrCpy (StringPtr, L"&ALTCFG=");\r
- AltRespLen += (8 + sizeof (UINT16) * 2);\r
-\r
- StrBufferLen = 5;\r
- BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));\r
- Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);\r
- if (EFI_ERROR (Status)) {\r
- VA_END (Args);\r
- return Status;\r
- }\r
- AltRespLen += EfiStrLen (AltCfg[Index]);\r
- }\r
- VA_END (Args);\r
-\r
- //\r
- // Generate the final <ConfigAltResp>\r
- //\r
- StrBufferLen = (EfiStrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16);\r
- TempStr = EfiLibAllocateZeroPool (StrBufferLen);\r
- *ConfigAltResp = TempStr;\r
- if (TempStr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*\r
- //\r
- EfiStrCpy (TempStr, ConfigResp);\r
- for (Index = 0; Index < NumberAltCfg; Index++) {\r
- EfiStrCat (TempStr, L"&");\r
- EfiStrCat (TempStr, ConfigHdr);\r
- EfiStrCat (TempStr, DescHdr + Index * 16);\r
- EfiStrCat (TempStr, AltCfg[Index]);\r
-\r
- gBS->FreePool (AltCfg[Index]);\r
- }\r
-\r
- if (NeedFreeConfigRequest) {\r
- gBS->FreePool (ConfigRequest);\r
- }\r
- gBS->FreePool (ConfigHdr);\r
- gBS->FreePool (ConfigResp);\r
- gBS->FreePool (DescHdr);\r
- gBS->FreePool (AltCfg);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-SwapBuffer (\r
- IN OUT UINT8 *Buffer,\r
- IN UINTN BufferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Swap bytes in the buffer.\r
-\r
-Arguments:\r
- Buffer - Binary buffer.\r
- BufferSize - Size of the buffer in bytes.\r
-\r
-Returns:\r
- None.\r
-\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
-VOID\r
-ToLower (\r
- IN OUT CHAR16 *Str\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Converts the unicode character of the string from uppercase to lowercase.\r
-\r
-Arguments:\r
- Str - String to be converted\r
-\r
-Returns:\r
-\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
-EFI_STATUS\r
-BufferToHexString (\r
- IN OUT CHAR16 *Str,\r
- IN UINT8 *Buffer,\r
- IN UINTN BufferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Converts binary buffer to Unicode string in reversed byte order from BufToHexString().\r
-\r
-Arguments:\r
- Str - String for output\r
- Buffer - Binary buffer.\r
- BufferSize - Size of the buffer in bytes.\r
-\r
-Returns:\r
- EFI_SUCCESS - The function completed successfully.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *NewBuffer;\r
- UINTN StrBufferLen;\r
-\r
- NewBuffer = EfiLibAllocateCopyPool (BufferSize, Buffer);\r
- SwapBuffer (NewBuffer, BufferSize);\r
-\r
- StrBufferLen = BufferSize * 2 + 1;\r
- Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);\r
-\r
- gBS->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
-EFI_STATUS\r
-HexStringToBuffer (\r
- IN OUT UINT8 *Buffer,\r
- IN OUT UINTN *BufferSize,\r
- IN CHAR16 *Str\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().\r
-\r
-Arguments:\r
- Buffer - Pointer to buffer that receives the data.\r
- BufferSize - Length in bytes of the buffer to hold converted data.\r
- If routine return with EFI_SUCCESS, containing length of converted data.\r
- If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.\r
- Str - String to be converted from.\r
-\r
-Returns:\r
- EFI_SUCCESS - The function completed successfully.\r
-\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 + 1) / 2);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-ConfigStringToUnicode (\r
- IN OUT CHAR16 *UnicodeString,\r
- IN OUT UINTN *StrBufferLen,\r
- IN CHAR16 *ConfigString\r
- )\r
-/*++\r
-\r
-Routine Description:\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
-Arguments:\r
- UnicodeString - Original Unicode string.\r
- 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
- ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+\r
-\r
-Returns:\r
- EFI_SUCCESS - Routine success.\r
- EFI_BUFFER_TOO_SMALL - The string buffer is too small.\r
-\r
---*/\r
-{\r
- UINTN Index;\r
- UINTN Len;\r
- UINTN BufferSize;\r
- CHAR16 BackupChar;\r
-\r
- Len = EfiStrLen (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
-EFI_STATUS\r
-UnicodeToConfigString (\r
- IN OUT CHAR16 *ConfigString,\r
- IN OUT UINTN *StrBufferLen,\r
- IN CHAR16 *UnicodeString\r
- )\r
-/*++\r
-\r
-Routine Description:\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
-Arguments:\r
- ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+\r
- 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
- UnicodeString - Original Unicode string.\r
-\r
-Returns:\r
- EFI_SUCCESS - Routine success.\r
- EFI_BUFFER_TOO_SMALL - The string buffer is too small.\r
-\r
---*/\r
-{\r
- UINTN Index;\r
- UINTN Len;\r
- UINTN BufferSize;\r
- CHAR16 *String;\r
-\r
- Len = EfiStrLen (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
-EFI_STATUS\r
-ConstructConfigHdr (\r
- IN OUT CHAR16 *ConfigHdr,\r
- IN OUT UINTN *StrBufferLen,\r
- IN EFI_GUID *Guid,\r
- IN CHAR16 *Name, OPTIONAL\r
- IN EFI_HANDLE *DriverHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
-\r
-Arguments:\r
- ConfigHdr - Pointer to the ConfigHdr string.\r
- StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string.\r
- Includes tailing '\0' character.\r
- On output:\r
- If return EFI_SUCCESS, containing length of ConfigHdr string buffer.\r
- If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.\r
- Guid - Routing information: GUID.\r
- Name - Routing information: NAME.\r
- DriverHandle - Driver handle which contains the routing information: PATH.\r
-\r
-Returns:\r
- EFI_SUCCESS - Routine success.\r
- EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small.\r
-\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 = EfiStrLen (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 = EfiDevicePathSize (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
- if (ConfigHdr == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *StrBufferLen = BufferSize;\r
-\r
- StrPtr = ConfigHdr;\r
-\r
- EfiStrCpy (StrPtr, L"GUID=");\r
- StrPtr += 5;\r
- BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));\r
- StrPtr += 32;\r
-\r
- //\r
- // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"\r
- //\r
- EfiStrCpy (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
- EfiStrCpy (StrPtr, L"&PATH=");\r
- StrPtr += 6;\r
- BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-IsConfigHdrMatch (\r
- IN EFI_STRING ConfigString,\r
- IN EFI_GUID *StorageGuid, OPTIONAL\r
- IN CHAR16 *StorageName OPTIONAL\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.\r
-\r
-Arguments:\r
- ConfigString - Either <ConfigRequest> or <ConfigResp>.\r
- StorageGuid - GUID of the storage.\r
- StorageName - Name of the stoarge.\r
-\r
-Returns:\r
- TRUE - Routing information is correct in ConfigString.\r
- FALSE - Routing information is incorrect in ConfigString.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN Match;\r
- EFI_GUID Guid;\r
- CHAR16 *Name;\r
- CHAR16 *StrPtr;\r
- UINTN BufferSize;\r
-\r
- //\r
- // <ConfigHdr> ::=\r
- // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
- // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
- //\r
- if (EfiStrLen (ConfigString) <= (5 + 32 + 6)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Compare GUID\r
- //\r
- if (StorageGuid != NULL) {\r
-\r
- StrPtr = ConfigString + 5 + 32;\r
- if (*StrPtr != L'&') {\r
- return FALSE;\r
- }\r
- *StrPtr = L'\0';\r
-\r
- BufferSize = sizeof (EFI_GUID);\r
- Status = HexStringToBuffer (\r
- (UINT8 *) &Guid,\r
- &BufferSize,\r
- ConfigString + 5\r
- );\r
- *StrPtr = L'&';\r
-\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (!EfiCompareGuid (&Guid, StorageGuid)) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- //\r
- // Compare Name\r
- //\r
- Match = TRUE;\r
- if (StorageName != NULL) {\r
- StrPtr = ConfigString + 5 + 32 + 6;\r
- while (*StrPtr != L'\0' && *StrPtr != L'&') {\r
- StrPtr++;\r
- }\r
- if (*StrPtr != L'&') {\r
- return FALSE;\r
- }\r
-\r
- *StrPtr = L'\0';\r
- BufferSize = (EfiStrLen (ConfigString + 5 + 32 + 6) + 1) * sizeof (CHAR16);\r
- Name = EfiLibAllocatePool (BufferSize);\r
- ASSERT (Name != NULL);\r
- Status = ConfigStringToUnicode (\r
- Name,\r
- &BufferSize,\r
- ConfigString + 5 + 32 + 6\r
- );\r
- *StrPtr = L'&';\r
-\r
- if (EFI_ERROR (Status) || (EfiStrCmp (Name, StorageName) != 0)) {\r
- Match = FALSE;\r
- }\r
- gBS->FreePool (Name);\r
- }\r
-\r
- return Match;\r
-}\r
-\r
-BOOLEAN\r
-FindBlockName (\r
- IN OUT CHAR16 *String,\r
- UINTN Offset,\r
- UINTN Width\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
-\r
-Arguments:\r
- String - The string to be searched in.\r
- Offset - Offset in BlockName.\r
- Width - Width in BlockName.\r
-\r
-Returns:\r
- TRUE - Block name found.\r
- FALSE - Block name not found.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN Data;\r
- UINTN BufferSize;\r
- UINTN ConvertedStrLen;\r
-\r
- while ((String = EfiStrStr (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 (EfiStrnCmp (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
-EFI_STATUS\r
-GetBrowserData (\r
- EFI_GUID *VariableGuid, OPTIONAL\r
- CHAR16 *VariableName, OPTIONAL\r
- UINTN *BufferSize,\r
- UINT8 *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.\r
-\r
-Arguments:\r
- VariableGuid - An optional field to indicate the target variable GUID name to use.\r
- VariableName - An optional field to indicate the target human-readable variable name.\r
- BufferSize - On input: Length in bytes of buffer to hold retrived data.\r
- On output:\r
- If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired.\r
- Buffer - Buffer to hold retrived data.\r
-\r
-Returns:\r
- EFI_SUCCESS - Routine success.\r
- EFI_BUFFER_TOO_SMALL - The intput buffer is too small.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *ConfigHdr;\r
- CHAR16 *ConfigResp;\r
- CHAR16 *StringPtr;\r
- UINTN HeaderLen;\r
- UINTN BufferLen;\r
- CHAR16 *Progress;\r
- EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
- EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
-\r
- //\r
- // Locate protocols for use\r
- //\r
- Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Retrieve formset storage data from Form Browser\r
- //\r
- ConfigHdr = mFakeConfigHdr;\r
- HeaderLen = EfiStrLen (ConfigHdr);\r
-\r
- BufferLen = 0x4000;\r
- ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16));\r
-\r
- StringPtr = ConfigResp + HeaderLen;\r
- *StringPtr = L'&';\r
- StringPtr++;\r
-\r
- Status = FormBrowser2->BrowserCallback (\r
- FormBrowser2,\r
- &BufferLen,\r
- StringPtr,\r
- TRUE,\r
- VariableGuid,\r
- VariableName\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- gBS->FreePool (ConfigResp);\r
- ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16));\r
-\r
- StringPtr = ConfigResp + HeaderLen;\r
- *StringPtr = L'&';\r
- StringPtr++;\r
-\r
- Status = FormBrowser2->BrowserCallback (\r
- FormBrowser2,\r
- &BufferLen,\r
- StringPtr,\r
- TRUE,\r
- VariableGuid,\r
- VariableName\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (ConfigResp);\r
- return Status;\r
- }\r
- EfiCopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));\r
-\r
- //\r
- // Convert <ConfigResp> to buffer data\r
- //\r
- Status = HiiConfigRouting->ConfigToBlock (\r
- HiiConfigRouting,\r
- ConfigResp,\r
- Buffer,\r
- BufferSize,\r
- &Progress\r
- );\r
- gBS->FreePool (ConfigResp);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-SetBrowserData (\r
- EFI_GUID *VariableGuid, OPTIONAL\r
- CHAR16 *VariableName, OPTIONAL\r
- UINTN BufferSize,\r
- UINT8 *Buffer,\r
- CHAR16 *RequestElement OPTIONAL\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.\r
-\r
-Arguments:\r
- VariableGuid - An optional field to indicate the target variable GUID name to use.\r
- VariableName - An optional field to indicate the target human-readable variable name.\r
- BufferSize - Length in bytes of buffer to hold retrived data.\r
- Buffer - Buffer to hold retrived data.\r
- RequestElement - An optional field to specify which part of the buffer data\r
- will be send back to Browser. If NULL, the whole buffer of\r
- data will be committed to Browser.\r
- <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
-\r
-Returns:\r
- EFI_SUCCESS - Routine success.\r
- Other - Updating Browser uncommitted data failed.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *ConfigHdr;\r
- CHAR16 *ConfigResp;\r
- CHAR16 *StringPtr;\r
- UINTN HeaderLen;\r
- UINTN BufferLen;\r
- CHAR16 *Progress;\r
- EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
- EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
- CHAR16 BlockName[33];\r
- CHAR16 *ConfigRequest;\r
- CHAR16 *Request;\r
-\r
- //\r
- // Locate protocols for use\r
- //\r
- Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Prepare <ConfigRequest>\r
- //\r
- ConfigHdr = mFakeConfigHdr;\r
- HeaderLen = EfiStrLen (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
- EfiStrCpy (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) + EfiStrSize (Request);\r
- ConfigRequest = EfiLibAllocateZeroPool (BufferLen);\r
-\r
- EfiCopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));\r
- StringPtr = ConfigRequest + HeaderLen;\r
- EfiStrCpy (StringPtr, Request);\r
-\r
- //\r
- // Convert buffer to <ConfigResp>\r
- //\r
- Status = HiiConfigRouting->BlockToConfig (\r
- HiiConfigRouting,\r
- ConfigRequest,\r
- Buffer,\r
- BufferSize,\r
- &ConfigResp,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->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 = FormBrowser2->BrowserCallback (\r
- FormBrowser2,\r
- &BufferSize,\r
- StringPtr,\r
- FALSE,\r
- VariableGuid,\r
- VariableName\r
- );\r
- gBS->FreePool (ConfigResp);\r
- gBS->FreePool (ConfigRequest);\r
- return Status;\r
-}\r