diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h new file mode 100644 index 0000000000..552000f857 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h @@ -0,0 +1,39 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 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. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c new file mode 100644 index 0000000000..69764f7c6e --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c @@ -0,0 +1,1005 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrCommon.c + +Abstract: + + Common Library Routines to assist in IFR creation on-the-fly + +Revision History: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +EFI_STATUS +EFIAPI +IfrLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +GetCurrentLanguage ( + OUT CHAR16 *Lang + ) +/*++ + +Routine Description: + + Determine what is the current language setting + +Arguments: + + Lang - Pointer of system language + +Returns: + + Status code + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + UINTN Index; + CHAR8 Language[4]; + + // + // Getting the system language and placing it into our Global Data + // + Size = sizeof (Language); + + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + Language + ); + + if (EFI_ERROR (Status)) { + AsciiStrCpy (Language, "eng"); + } + + for (Index = 0; Index < 3; Index++) { + // + // Bitwise AND ascii value with 0xDF yields an uppercase value. + // Sign extend into a unicode value + // + Lang[Index] = (CHAR16) (Language[Index] & 0xDF); + } + + // + // Null-terminate the value + // + Lang[3] = (CHAR16) 0; + + return Status; +} + + +EFI_STATUS +AddString ( + IN VOID *StringBuffer, + IN CHAR16 *Language, + IN CHAR16 *String, + IN OUT STRING_REF *StringToken + ) +/*++ + +Routine Description: + + Add a string to the incoming buffer and return the token and offset data + +Arguments: + + StringBuffer - The incoming buffer + + Language - Currrent language + + String - The string to be added + + StringToken - The index where the string placed + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - String successfully added to the incoming buffer + +--*/ +{ + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *StringPackBuffer; + VOID *NewBuffer; + RELOFST *PackSource; + RELOFST *PackDestination; + UINT8 *Source; + UINT8 *Destination; + UINTN Index; + BOOLEAN Finished; + UINTN SizeofLanguage; + UINTN SizeofString; + + StringPack = (EFI_HII_STRING_PACK *) StringBuffer; + Finished = FALSE; + + // + // Pre-allocate a buffer sufficient for us to work on. + // We will use it as a destination scratch pad to build data on + // and when complete shift the data back to the original buffer + // + NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer; + + // + // StringPack is terminated with a length 0 entry + // + for (; StringPack->Header.Length != 0;) { + // + // If this stringpack's language is same as CurrentLanguage, use it + // + if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) { + // + // We have some data in this string pack, copy the string package up to the string data + // + CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack)); + + // + // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer + // + StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST)); + StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST)); + + PackSource = (RELOFST *) (StringPack + 1); + PackDestination = (RELOFST *) (StringPackBuffer + 1); + for (Index = 0; PackSource[Index] != 0x0000; Index++) { + // + // Copy the stringpointers from old to new buffer + // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST) + // + PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST)); + } + + // + // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it + // + PackDestination[Index] = (UINT16)(PackDestination[Index-1] + + StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1]))); + PackDestination[Index + 1] = (UINT16) 0; + + // + // Index is the token value for the new string + // + *StringToken = (UINT16) Index; + + // + // Source now points to the beginning of the old buffer strings + // Destination now points to the beginning of the new buffer strings + // + Source = (UINT8 *) &PackSource[Index + 1]; + Destination = (UINT8 *) &PackDestination[Index + 2]; + + // + // This should copy all the strings from the old buffer to the new buffer + // + for (; Index != 0; Index--) { + // + // Copy Source string to destination buffer + // + StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source); + + // + // Adjust the source/destination to the next string location + // + Destination = Destination + StrSize ((CHAR16 *) Source); + Source = Source + StrSize ((CHAR16 *) Source); + } + + // + // This copies the new string to the destination buffer + // + StrCpy ((CHAR16 *) Destination, (CHAR16 *) String); + + // + // Adjust the size of the changed string pack by adding the size of the new string + // along with the size of the additional offset entry for the new string + // + StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST)); + + // + // Advance the buffers to point to the next spots. + // + StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + Finished = TRUE; + continue; + } + // + // This isn't the language of the stringpack we were asked to add a string to + // so we need to copy it to the new buffer. + // + CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length); + + // + // Advance the buffers to point to the next spots. + // + StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + } + + // + // If we didn't copy the new data to a stringpack yet + // + if (!Finished) { + PackDestination = (RELOFST *) (StringPackBuffer + 1); + // + // Pointing to a new string pack location + // + SizeofLanguage = StrSize (Language); + SizeofString = StrSize (String); + StringPackBuffer->Header.Length = (UINT32) + ( + sizeof (EFI_HII_STRING_PACK) - + sizeof (EFI_STRING) + + sizeof (RELOFST) + + sizeof (RELOFST) + + SizeofLanguage + + SizeofString + ); + StringPackBuffer->Header.Type = EFI_HII_STRING; + StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + StringPackBuffer->Attributes = 0; + PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + PackDestination[1] = (UINT16) (PackDestination[0] + StrSize (Language)); + PackDestination[2] = (UINT16) 0; + + // + // The first string location will be set to destination. The minimum number of strings + // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc) + // and token 1 as the new string being added and and null entry for the stringpointers + // + Destination = (UINT8 *) &PackDestination[3]; + + // + // Copy the language name string to the new buffer + // + StrCpy ((CHAR16 *) Destination, Language); + + // + // Advance the destination to the new empty spot + // + Destination = Destination + StrSize (Language); + + // + // Copy the string to the new buffer + // + StrCpy ((CHAR16 *) Destination, String); + + // + // Since we are starting with a new string pack - we know the new string is token 1 + // + *StringToken = (UINT16) 1; + } + + // + // Zero out the original buffer and copy the updated data in the new buffer to the old buffer + // + ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE); + CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE); + + // + // Free the newly created buffer since we don't need it anymore + // + gBS->FreePool (NewBuffer); + return EFI_SUCCESS; +} + + +EFI_STATUS +AddOpCode ( + IN VOID *FormBuffer, + IN OUT VOID *OpCodeData + ) +/*++ + +Routine Description: + + Add op-code data to the FormBuffer + +Arguments: + + FormBuffer - Form buffer to be inserted to + + OpCodeData - Op-code data to be inserted + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Op-code data successfully inserted + +--*/ +{ + EFI_HII_PACK_HEADER *NewBuffer; + UINT8 *Source; + UINT8 *Destination; + + // + // Pre-allocate a buffer sufficient for us to work on. + // We will use it as a destination scratch pad to build data on + // and when complete shift the data back to the original buffer + // + NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Source = (UINT8 *) FormBuffer; + Destination = (UINT8 *) NewBuffer; + + // + // Copy the IFR Package header to the new buffer + // + CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER)); + + // + // Advance Source and Destination to next op-code + // + Source = Source + sizeof (EFI_HII_PACK_HEADER); + Destination = Destination + sizeof (EFI_HII_PACK_HEADER); + + // + // Copy data to the new buffer until we run into the end_form + // + for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) { + // + // If the this opcode is an end_form_set we better be creating and endform + // Nonetheless, we will add data before the end_form_set. This also provides + // for interesting behavior in the code we will run, but has no bad side-effects + // since we will possibly do a 0 byte copy in this particular end-case. + // + if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) { + break; + } + + // + // Copy data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Adjust Source/Destination to next op-code location + // + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + } + + // + // Prior to the end_form is where we insert the new op-code data + // + CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length); + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + + NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length)); + + // + // Copy end-form data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Adjust Source/Destination to next op-code location + // + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + + // + // Copy end-formset data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Zero out the original buffer and copy the updated data in the new buffer to the old buffer + // + ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE); + CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE); + + // + // Free the newly created buffer since we don't need it anymore + // + gBS->FreePool (NewBuffer); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetHiiInterface ( + OUT EFI_HII_PROTOCOL **Hii + ) +/*++ + +Routine Description: + + Get the HII protocol interface + +Arguments: + + Hii - HII protocol interface + +Returns: + + Status code + +--*/ +{ + EFI_STATUS Status; + + // + // There should only be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) Hii + ); + + return Status;; +} + + +EFI_STATUS +ExtractDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN OUT UINT16 *ImageLength, + OUT UINT8 *DefaultImage, + OUT EFI_GUID *Guid + ) +/*++ + +Routine Description: + + Extract information pertaining to the HiiHandle + +Arguments: + + HiiHandle - Hii handle + + ImageLength - For input, length of DefaultImage; + For output, length of actually required + + DefaultImage - Image buffer prepared by caller + + Guid - Guid information about the form + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength + + EFI_SUCCESS - Successfully extract data from Hii database. + + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PROTOCOL *Hii; + UINTN DataLength; + UINT8 *RawData; + UINT8 *OldData; + UINTN Index; + UINTN Temp; + UINTN SizeOfNvStore; + UINTN CachedStart; + + DataLength = DEFAULT_FORM_BUFFER_SIZE; + SizeOfNvStore = 0; + CachedStart = 0; + + Status = GetHiiInterface (&Hii); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (DataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData); + + if (EFI_ERROR (Status)) { + gBS->FreePool (RawData); + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (DataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData); + } + + OldData = RawData; + + // + // Point RawData to the beginning of the form data + // + RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER)); + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_FORM_SET_OP: + // + // Copy the GUID information from this handle + // + CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // Remember, multiple op-codes may reference the same item, so let's keep a running + // marker of what the highest QuestionId that wasn't zero length. This will accurately + // maintain the Size of the NvStore + // + if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) { + Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + if (SizeOfNvStore < Temp) { + SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + } + } + } + + Index = RawData[Index + 1] + Index; + } + + // + // Return an error if buffer is too small + // + if (SizeOfNvStore > *ImageLength) { + gBS->FreePool (OldData); + *ImageLength = (UINT16) SizeOfNvStore; + return EFI_BUFFER_TOO_SMALL; + } + + if (DefaultImage != NULL) { + ZeroMem (DefaultImage, SizeOfNvStore); + } + + // + // Copy the default image information to the user's buffer + // + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_ONE_OF_OP: + CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) { + CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2); + } + break; + + case EFI_IFR_CHECKBOX_OP: + DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags; + break; + + case EFI_IFR_NUMERIC_OP: + CopyMem ( + &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId], + &((EFI_IFR_NUMERIC *) &RawData[Index])->Default, + 2 + ); + break; + + } + + Index = RawData[Index + 1] + Index; + } + + *ImageLength = (UINT16) SizeOfNvStore; + + // + // Free our temporary repository of form data + // + gBS->FreePool (OldData); + + return EFI_SUCCESS; +} + + +EFI_HII_HANDLE +FindHiiHandle ( + IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + Finds HII handle for given pack GUID previously registered with the HII. + +Arguments: + HiiProtocol - pointer to pointer to HII protocol interface. + If NULL, the interface will be found but not returned. + If it points to NULL, the interface will be found and + written back to the pointer that is pointed to. + Guid - The GUID of the pack that registered with the HII. + +Returns: + Handle to the HII pack previously registered by the memory driver. + +--*/ +{ + EFI_STATUS Status; + + EFI_HII_HANDLE *HiiHandleBuffer; + EFI_HII_HANDLE HiiHandle; + UINT16 HiiHandleBufferLength; + UINT32 NumberOfHiiHandles; + EFI_GUID HiiGuid; + EFI_HII_PROTOCOL *HiiProt; + UINT32 Index; + UINT16 Length; + + HiiHandle = 0; + if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) { + // + // The protocol has been passed in + // + HiiProt = *HiiProtocol; + } else { + gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) &HiiProt + ); + if (HiiProt == NULL) { + return HiiHandle; + } + + if (HiiProtocol != NULL) { + // + // Return back the HII protocol for the caller as promissed + // + *HiiProtocol = HiiProt; + } + } + // + // Allocate buffer + // + HiiHandleBufferLength = 10; + HiiHandleBuffer = AllocatePool (HiiHandleBufferLength); + ASSERT (HiiHandleBuffer != NULL); + + // + // Get the Handles of the packages that were registered with Hii + // + Status = HiiProt->FindHandles ( + HiiProt, + &HiiHandleBufferLength, + HiiHandleBuffer + ); + + // + // Get a bigger bugffer if this one is to small, and try again + // + if (Status == EFI_BUFFER_TOO_SMALL) { + + gBS->FreePool (HiiHandleBuffer); + + HiiHandleBuffer = AllocatePool (HiiHandleBufferLength); + ASSERT (HiiHandleBuffer != NULL); + + Status = HiiProt->FindHandles ( + HiiProt, + &HiiHandleBufferLength, + HiiHandleBuffer + ); + } + + if (EFI_ERROR (Status)) { + goto lbl_exit; + } + + NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE); + + // + // Iterate Hii handles and look for the one that matches our Guid + // + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + + Length = 0; + ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid); + + if (CompareGuid (&HiiGuid, Guid)) { + + HiiHandle = HiiHandleBuffer[Index]; + break; + } + } + +lbl_exit: + gBS->FreePool (HiiHandleBuffer); + return HiiHandle; +} + + +EFI_STATUS +ValidateDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + OUT BOOLEAN *Results + ) +/*++ + +Routine Description: + + Validate that the data associated with the HiiHandle in NVRAM is within + the reasonable parameters for that FormSet. Values for strings and passwords + are not verified due to their not having the equivalent of valid range settings. + +Arguments: + + HiiHandle - Handle of the HII database entry to query + + Results - If return Status is EFI_SUCCESS, Results provides valid data + TRUE = NVRAM Data is within parameters + FALSE = NVRAM Data is NOT within parameters + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Data successfully validated +--*/ +{ + EFI_STATUS Status; + EFI_HII_PROTOCOL *Hii; + EFI_GUID Guid; + UINT8 *RawData; + UINT8 *OldData; + UINTN RawDataLength; + UINT8 *VariableData; + UINTN Index; + UINTN Temp; + UINTN SizeOfNvStore; + UINTN CachedStart; + BOOLEAN GotMatch; + + RawDataLength = DEFAULT_FORM_BUFFER_SIZE; + SizeOfNvStore = 0; + CachedStart = 0; + GotMatch = FALSE; + *Results = TRUE; + + Status = GetHiiInterface (&Hii); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (RawDataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData); + + if (EFI_ERROR (Status)) { + gBS->FreePool (RawData); + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (RawDataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData); + } + + OldData = RawData; + + // + // Point RawData to the beginning of the form data + // + RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER)); + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + if (RawData[Index] == EFI_IFR_FORM_SET_OP) { + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + } + + Index = RawData[Index + 1] + Index; + } + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_FORM_SET_OP: + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // Remember, multiple op-codes may reference the same item, so let's keep a running + // marker of what the highest QuestionId that wasn't zero length. This will accurately + // maintain the Size of the NvStore + // + if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) { + Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + if (SizeOfNvStore < Temp) { + SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + } + } + } + + Index = RawData[Index + 1] + Index; + } + + // + // Allocate memory for our File Form Tags + // + VariableData = AllocateZeroPool (SizeOfNvStore); + if (VariableData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable ( + (CHAR16 *) L"Setup", + &Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableData + ); + + if (EFI_ERROR (Status)) { + + // + // If there is a variable that exists already and it is larger than what we calculated the + // storage needs to be, we must assume the variable size from GetVariable is correct and not + // allow the truncation of the variable. It is very possible that the user who created the IFR + // we are cracking is not referring to a variable that was in a previous map, however we cannot + // allow it's truncation. + // + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Free the buffer that was allocated that was too small + // + gBS->FreePool (VariableData); + + VariableData = AllocatePool (SizeOfNvStore); + if (VariableData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable ( + (CHAR16 *) L"Setup", + &Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableData + ); + } + } + + // + // Walk through the form and see that the variable data it refers to is ok. + // This allows for the possibility of stale (obsoleted) data in the variable + // can be overlooked without causing an error + // + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_ONE_OF_OP: + // + // A one_of has no data, its the option that does - cache the storage Id + // + CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + // + // A one_of_option can be any value + // + if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) { + GotMatch = TRUE; + } + break; + + case EFI_IFR_END_ONE_OF_OP: + // + // At this point lets make sure that the data value in the NVRAM matches one of the options + // + if (!GotMatch) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + case EFI_IFR_CHECKBOX_OP: + // + // A checkbox is a boolean, so 0 and 1 are valid + // Remember, QuestionId corresponds to the offset location of the data in the variable + // + if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + case EFI_IFR_NUMERIC_OP: + if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) || + (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + } + + Index = RawData[Index + 1] + Index; + } + + // + // Free our temporary repository of form data + // + gBS->FreePool (OldData); + gBS->FreePool (VariableData); + + return EFI_SUCCESS; +} + diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c new file mode 100644 index 0000000000..ee99bfafe4 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c @@ -0,0 +1,977 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrOnTheFly.c + +Abstract: + + Library Routines to create IFR on-the-fly + +Revision History: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +EFI_STATUS +CreateFormSet ( + IN CHAR16 *FormSetTitle, + IN EFI_GUID *Guid, + IN UINT8 Class, + IN UINT8 SubClass, + IN OUT VOID **FormBuffer, + IN OUT VOID **StringBuffer + ) +/*++ + +Routine Description: + + Create a formset + +Arguments: + + FormSetTitle - Title of formset + + Guid - Guid of formset + + Class - Class of formset + + SubClass - Sub class of formset + + FormBuffer - Pointer of the formset created + + StringBuffer - Pointer of FormSetTitile string created + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Formset successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_HII_IFR_PACK IfrPack; + EFI_IFR_FORM_SET FormSet; + EFI_IFR_END_FORM_SET EndFormSet; + UINT8 *Destination; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Pre-allocate a buffer sufficient for us to work from. + // + FormBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE); + if (FormBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Pre-allocate a buffer sufficient for us to work from. + // + StringBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE); + if (StringBuffer == NULL) { + gBS->FreePool (FormBuffer); + return EFI_OUT_OF_RESOURCES; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add the FormSetTitle to the string buffer and get the StringToken + // + Status = AddString (*StringBuffer, CurrentLanguage, FormSetTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Initialize the Ifr Package header data + // + IfrPack.Header.Length = sizeof (EFI_HII_PACK_HEADER) + sizeof (EFI_IFR_FORM_SET) + sizeof (EFI_IFR_END_FORM_SET); + IfrPack.Header.Type = EFI_HII_IFR; + + // + // Initialize FormSet with the appropriate information + // + FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP; + FormSet.Header.Length = sizeof (EFI_IFR_FORM_SET); + FormSet.FormSetTitle = StringToken; + FormSet.Class = Class; + FormSet.SubClass = SubClass; + CopyMem (&FormSet.Guid, Guid, sizeof (EFI_GUID)); + + // + // Initialize the end formset data + // + EndFormSet.Header.Length = sizeof (EFI_IFR_END_FORM_SET); + EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP; + + Destination = (UINT8 *) *FormBuffer; + + // + // Copy the formset/endformset data to the form buffer + // + CopyMem (Destination, &IfrPack, sizeof (EFI_HII_PACK_HEADER)); + + Destination = Destination + sizeof (EFI_HII_PACK_HEADER); + + CopyMem (Destination, &FormSet, sizeof (EFI_IFR_FORM_SET)); + + Destination = Destination + sizeof (EFI_IFR_FORM_SET); + + CopyMem (Destination, &EndFormSet, sizeof (EFI_IFR_END_FORM_SET)); + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateForm ( + IN CHAR16 *FormTitle, + IN UINT16 FormId, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a form + +Arguments: + + FormTitle - Title of the form + + FormId - Id of the form + + FormBuffer - Pointer of the form created + + StringBuffer - Pointer of FormTitil string created + +Returns: + + EFI_SUCCESS - Form successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_FORM Form; + EFI_IFR_END_FORM EndForm; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, FormTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Form.Header.OpCode = EFI_IFR_FORM_OP; + Form.Header.Length = sizeof (EFI_IFR_FORM); + Form.FormId = FormId; + Form.FormTitle = StringToken; + + Status = AddOpCode (FormBuffer, &Form); + + if (EFI_ERROR (Status)) { + return Status; + } + + EndForm.Header.OpCode = EFI_IFR_END_FORM_OP; + EndForm.Header.Length = sizeof (EFI_IFR_END_FORM); + + Status = AddOpCode (FormBuffer, &EndForm); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateSubTitle ( + IN CHAR16 *SubTitle, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle + +Arguments: + + SubTitle - Sub title to be created + + FormBuffer - Where this subtitle to add to + + StringBuffer - String buffer created for subtitle + +Returns: + + EFI_SUCCESS - Subtitle successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_SUBTITLE Subtitle; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, SubTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; + Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); + Subtitle.SubTitle = StringToken; + + Status = AddOpCode (FormBuffer, &Subtitle); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateText ( + IN CHAR16 *String, + IN CHAR16 *String2, + IN CHAR16 *String3, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a line of text + +Arguments: + + String - First string of the text + + String2 - Second string of the text + + String3 - Help string of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - The form where this text adds to + + StringBuffer - String buffer created for String, String2 and String3 + +Returns: + + EFI_SUCCESS - Text successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_TEXT Text; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.Header.OpCode = EFI_IFR_TEXT_OP; + Text.Header.Length = sizeof (EFI_IFR_TEXT); + Text.Text = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String2, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.TextTwo = StringToken; + + Text.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + Text.Key = Key; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String3, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.Help = StringToken; + + Status = AddOpCode (FormBuffer, &Text); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateGoto ( + IN UINT16 FormId, + IN CHAR16 *Prompt, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink + +Arguments: + + FormId - Form ID of the hyperlink + + Prompt - Prompt of the hyperlink + + FormBuffer - The form where this hyperlink adds to + + StringBuffer - String buffer created for Prompt + +Returns: + + EFI_SUCCESS - Hyperlink successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_REF Hyperlink; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Hyperlink.Header.OpCode = EFI_IFR_REF_OP; + Hyperlink.Header.Length = sizeof (EFI_IFR_REF); + Hyperlink.FormId = FormId; + Hyperlink.Prompt = StringToken; + + Status = AddOpCode (FormBuffer, &Hyperlink); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateOneOf ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + Prompt - Prompt of the one-of box + + Help - Help of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - The form where this one-of box adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - One-Of box successfully created. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_IFR_ONE_OF OneOf; + EFI_IFR_ONE_OF_OPTION OneOfOption; + EFI_IFR_END_ONE_OF EndOneOf; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for one-of in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; + OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); + OneOf.QuestionId = QuestionId; + OneOf.Width = DataWidth; + OneOf.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OneOf.Help = StringToken; + + Status = AddOpCode (FormBuffer, &OneOf); + + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + // + // Add string and get token back + // + Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken); + + OneOfOption.Option = StringToken; + OneOfOption.Value = OptionsList[Index].Value; + OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED); + OneOfOption.Key = OptionsList[Index].Key; + + Status = AddOpCode (FormBuffer, &OneOfOption); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + Status = AddOpCode (FormBuffer, &EndOneOf); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOrderedList ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + Prompt - Prompt of the ordered list + + Help - Help of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - The form where this ordered list adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_SUCCESS - Ordered list successfully created. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_IFR_ORDERED_LIST OrderedList; + EFI_IFR_ONE_OF_OPTION OrderedListOption; + EFI_IFR_END_ONE_OF EndOrderedList; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; + OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); + OrderedList.QuestionId = QuestionId; + OrderedList.MaxEntries = MaxEntries; + OrderedList.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OrderedList.Help = StringToken; + + Status = AddOpCode (FormBuffer, &OrderedList); + + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < OptionCount; Index++) { + OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + // + // Add string and get token back + // + Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken); + + OrderedListOption.Option = StringToken; + OrderedListOption.Value = OptionsList[Index].Value; + OrderedListOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED); + OrderedListOption.Key = OptionsList[Index].Key; + + Status = AddOpCode (FormBuffer, &OrderedListOption); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + Status = AddOpCode (FormBuffer, &EndOrderedList); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateCheckBox ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 Flags, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a checkbox + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + Prompt - Prompt of the check box + + Help - Help of the check box + + Flags - Flags of the check box + + FormBuffer - The form where this check box adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 1 + + EFI_SUCCESS - Check box successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_CHECKBOX CheckBox; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for checkbox in excess of 8 bits for now + // + if (DataWidth > 1) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; + CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); + CheckBox.QuestionId = QuestionId; + CheckBox.Width = DataWidth; + CheckBox.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + CheckBox.Help = StringToken; + CheckBox.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + + Status = AddOpCode (FormBuffer, &CheckBox); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateNumeric ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a numeric + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + Prompt - Prompt of the numeric + + Help - Help of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - The form where this numeric adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - Numeric is successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_NUMERIC Numeric; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for numerics in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; + Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); + Numeric.QuestionId = QuestionId; + Numeric.Width = DataWidth; + Numeric.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Numeric.Help = StringToken; + Numeric.Minimum = Minimum; + Numeric.Maximum = Maximum; + Numeric.Step = Step; + Numeric.Default = Default; + Numeric.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + Numeric.Key = Key; + + Status = AddOpCode (FormBuffer, &Numeric); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateString ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a string + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + Prompt - Prompt of the string + + Help - Help of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - The form where this string adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_SUCCESS - String successfully created. + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_STRING String; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + String.Header.OpCode = EFI_IFR_STRING_OP; + String.Header.Length = sizeof (EFI_IFR_STRING); + String.QuestionId = QuestionId; + String.Width = DataWidth; + String.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + String.Help = StringToken; + String.MinSize = MinSize; + String.MaxSize = MaxSize; + String.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + String.Key = Key; + + Status = AddOpCode (FormBuffer, &String); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c new file mode 100644 index 0000000000..7bcb453777 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c @@ -0,0 +1,618 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrOpCodeCreation.c + +Abstract: + + 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. + +Revision History: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +EFI_STATUS +CreateSubTitleOpCode ( + IN STRING_REF StringToken, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - StringToken of the subtitle + + FormBuffer - Output of subtitle as a form + +Returns: + + EFI_SUCCESS - Subtitle created to be a form + +--*/ +{ + EFI_IFR_SUBTITLE Subtitle; + + Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; + Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); + Subtitle.SubTitle = StringToken; + + CopyMem (FormBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE)); + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateTextOpCode ( + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN STRING_REF StringTokenThree, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a Text opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - First string token of the text + + StringTokenTwo - Second string token of the text + + StringTokenThree - Help string token of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - Output of text as a form + +Returns: + + EFI_SUCCESS - Text created to be a form + +--*/ +{ + EFI_IFR_TEXT Text; + + Text.Header.OpCode = EFI_IFR_TEXT_OP; + Text.Header.Length = sizeof (EFI_IFR_TEXT); + Text.Text = StringToken; + + Text.TextTwo = StringTokenTwo; + Text.Help = StringTokenThree; + Text.Flags = Flags; + Text.Key = Key; + + CopyMem (FormBuffer, &Text, sizeof (EFI_IFR_TEXT)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateGotoOpCode ( + IN UINT16 FormId, + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + FormId - Form ID of the hyperlink + + StringToken - Prompt string token of the hyperlink + + StringTokenTwo - Help string token of the hyperlink + + Flags - Flags of the hyperlink + + Key - Key of the hyperlink + + FormBuffer - Output of hyperlink as a form + +Returns: + + EFI_SUCCESS - Hyperlink created to be a form + +--*/ +{ + EFI_IFR_REF Hyperlink; + + Hyperlink.Header.OpCode = EFI_IFR_REF_OP; + Hyperlink.Header.Length = sizeof (EFI_IFR_REF); + Hyperlink.FormId = FormId; + Hyperlink.Prompt = StringToken; + Hyperlink.Help = StringTokenTwo; + Hyperlink.Key = Key; + Hyperlink.Flags = Flags; + + CopyMem (FormBuffer, &Hyperlink, sizeof (EFI_IFR_REF)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateOneOfOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a one-of opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + PromptToken - Prompt string token of the one-of box + + HelpToken - Help string token of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - Output of One-Of box as a form + +Returns: + + EFI_SUCCESS - One-Of box created to be a form + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +{ + UINTN Index; + EFI_IFR_ONE_OF OneOf; + EFI_IFR_ONE_OF_OPTION OneOfOption; + EFI_IFR_END_ONE_OF EndOneOf; + UINT8 *LocalBuffer; + + // + // We do not create op-code storage widths for one-of in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; + OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); + OneOf.QuestionId = QuestionId; + OneOf.Width = DataWidth; + OneOf.Prompt = PromptToken; + + OneOf.Help = HelpToken; + + LocalBuffer = (UINT8 *) FormBuffer; + + CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF)); + + 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.Option = OptionsList[Index].StringToken; + OneOfOption.Value = OptionsList[Index].Value; + OneOfOption.Flags = OptionsList[Index].Flags; + OneOfOption.Key = OptionsList[Index].Key; + + CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION)); + } + + EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + CopyMem (LocalBuffer, &EndOneOf, sizeof (EFI_IFR_END_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF)); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOrderedListOpCode ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a ordered list opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + PromptToken - Prompt string token of the ordered list + + HelpToken - Help string token of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - Output of ordered list as a form + +Returns: + + EFI_SUCCESS - Ordered list created to be a form + +--*/ +{ + UINTN Index; + EFI_IFR_ORDERED_LIST OrderedList; + EFI_IFR_ONE_OF_OPTION OrderedListOption; + EFI_IFR_END_ONE_OF EndOrderedList; + UINT8 *LocalBuffer; + + OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; + OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); + OrderedList.QuestionId = QuestionId; + OrderedList.MaxEntries = MaxEntries; + OrderedList.Prompt = PromptToken; + + OrderedList.Help = HelpToken; + + LocalBuffer = (UINT8 *) FormBuffer; + + CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ORDERED_LIST)); + + for (Index = 0; Index < OptionCount; Index++) { + OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + OrderedListOption.Option = OptionsList[Index].StringToken; + OrderedListOption.Value = OptionsList[Index].Value; + OrderedListOption.Flags = OptionsList[Index].Flags; + OrderedListOption.Key = OptionsList[Index].Key; + + CopyMem (LocalBuffer, &OrderedListOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION)); + } + + EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + CopyMem (LocalBuffer, &EndOrderedList, sizeof (EFI_IFR_END_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF)); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateCheckBoxOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a checkbox opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + PromptToken - Prompt string token of the check box + + HelpToken - Help string token of the check box + + Flags - Flags of the check box + + Key - Key of the check box + + FormBuffer - Output of the check box as a form + +Returns: + + EFI_SUCCESS - Checkbox created to be a form + + EFI_DEVICE_ERROR - DataWidth > 1 + +--*/ +{ + EFI_IFR_CHECKBOX CheckBox; + + // + // We do not create op-code storage widths for checkbox in excess of 8 bits for now + // + if (DataWidth > 1) { + return EFI_DEVICE_ERROR; + } + + CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; + CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); + CheckBox.QuestionId = QuestionId; + CheckBox.Width = DataWidth; + CheckBox.Prompt = PromptToken; + + CheckBox.Help = HelpToken; + CheckBox.Flags = Flags; + CheckBox.Key = Key; + + CopyMem (FormBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateNumericOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + PromptToken - Prompt string token of the numeric + + HelpToken - Help string token of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value of the numeric + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - Output of the numeric as a form + +Returns: + + EFI_SUCCESS - The numeric created to be a form. + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +{ + EFI_IFR_NUMERIC Numeric; + + // + // We do not create op-code storage widths for numerics in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; + Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); + Numeric.QuestionId = QuestionId; + Numeric.Width = DataWidth; + Numeric.Prompt = PromptToken; + + Numeric.Help = HelpToken; + Numeric.Minimum = Minimum; + Numeric.Maximum = Maximum; + Numeric.Step = Step; + Numeric.Default = Default; + Numeric.Flags = Flags; + Numeric.Key = Key; + + CopyMem (FormBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateStringOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + PromptToken - Prompt token of the string + + HelpToken - Help token of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - Output of the string as a form + +Returns: + + EFI_SUCCESS - String created to be a form. + +--*/ +{ + EFI_IFR_STRING String; + + String.Header.OpCode = EFI_IFR_STRING_OP; + String.Header.Length = sizeof (EFI_IFR_STRING); + String.QuestionId = QuestionId; + String.Width = DataWidth; + String.Prompt = PromptToken; + + String.Help = HelpToken; + String.MinSize = MinSize; + String.MaxSize = MaxSize; + String.Flags = Flags; + String.Key = Key; + + CopyMem (FormBuffer, &String, sizeof (EFI_IFR_STRING)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateBannerOpCode ( + IN UINT16 Title, + IN UINT16 LineNumber, + IN UINT8 Alignment, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a banner opcode. This is primarily used by the FrontPage implementation from BDS. + +Arguments: + + Title - Title of the banner + + LineNumber - LineNumber of the banner + + Alignment - Alignment of the banner + + FormBuffer - Output of banner as a form + +Returns: + + EFI_SUCCESS - Banner created to be a form. + +--*/ +{ + EFI_IFR_BANNER Banner; + + Banner.Header.OpCode = EFI_IFR_BANNER_OP; + Banner.Header.Length = sizeof (EFI_IFR_BANNER); + CopyMem (&Banner.Title, &Title, sizeof (UINT16)); + CopyMem (&Banner.LineNumber, &LineNumber, sizeof (UINT16)); + Banner.Alignment = Alignment; + + CopyMem (FormBuffer, &Banner, sizeof (EFI_IFR_BANNER)); + + return EFI_SUCCESS; +} diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf new file mode 100644 index 0000000000..3fa870c7c7 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf @@ -0,0 +1,104 @@ +#/** @file +# EDK Internal Form Refresentation Support Library Instance. +# +# The library instance provides common library routines help in +# IFR creation on-the-fly, HII variable access, HII database access, multi language supports. +# Copyright (c) 2006 - 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. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FrameworkIfrSupportLib + FILE_GUID = ea55bada-d488-427b-9d2d-227e0aaa3707 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FrameworkIfrSupportLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + CONSTRUCTOR = IfrLibConstruct + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# Variable Guid C Name: gLanGuid Variable Name: L"Lan" +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + IfrVariable.c + IfrOpCodeCreation.c + IfrOnTheFly.c + IfrCommon.c + CommonHeader.h + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiGlobalVariableGuid # ALWAYS_CONSUMED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiHiiProtocolGuid # PROTOCOL ALWAYS_CONSUMED + diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa new file mode 100644 index 0000000000..87f4f7411a --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa @@ -0,0 +1,81 @@ + + + + EdkIfrSupportLib + DXE_DRIVER + ea55bada-d488-427b-9d2d-227e0aaa3707 + 1.0 + EDK Internal Form Refresentation Support Library Instance. + The library instance provides common library routines help in + IFR creation on-the-fly, HII variable access, HII database access, multi language supports. + Copyright (c) 2006 - 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + EdkIfrSupportLib + + + + EdkIfrSupportLib + + + DebugLib + + + BaseLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + UefiRuntimeServicesTableLib + + + + IfrCommon.c + IfrOnTheFly.c + IfrOpCodeCreation.c + IfrVariable.c + + + + + + + + gEfiHiiProtocolGuid + + + + + 0x004C 0x0061 0x006E + gLanGuid + + + + + gEfiGlobalVariableGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + IfrLibConstruct + + + \ No newline at end of file diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c new file mode 100644 index 0000000000..e48adbd325 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c @@ -0,0 +1,493 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + IfrVariable.c + +Abstract: + Variable/Map manipulations routines + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +VOID +EfiLibHiiVariablePackGetMap ( + IN EFI_HII_VARIABLE_PACK *Pack, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, OPTIONAL + OUT UINTN *Size OPTIONAL + ) +/*++ + +Routine Description: + + Extracts a variable form a Pack. + +Arguments: + + Pack - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + VOID + +--*/ +{ + if (NULL != Name) { + *Name = (VOID *) (Pack + 1); + } + + if (NULL != Guid) { + *Guid = (EFI_GUID *)(UINTN)&Pack->VariableGuid; + } + + + if (NULL != Id) { + *Id = Pack->VariableId; + } + + if (NULL != Var) { + *Var = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength); + } + + if (NULL != Size) { + *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength; + } +} + + +UINTN +EfiLibHiiVariablePackListGetMapCnt ( + IN EFI_HII_VARIABLE_PACK_LIST *List + ) + +/*++ + +Routine Description: + + Finds a count of the variables/maps in the List. + +Arguments: + + List - List of variables + +Returns: + + UINTN - The number of map count. + +--*/ + +{ + UINTN Cnt = 0; + while (NULL != List) { + Cnt++; + List = List->NextVariablePack; + } + return Cnt; +} + + +VOID +EfiLibHiiVariablePackListForEachVar ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK *Callback + ) +/*++ + +Routine Description: + + Will iterate all variable/maps as appearing + in List and for each, it will call the Callback. + +Arguments: + + List - List of variables + Callback - Routine to be called for each iterated variable. + +Returns: + + VOID + +--*/ + +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + // + // call the callback + // + Callback (MapName, MapGuid, MapId, Map, MapSize); + List = List->NextVariablePack; + } +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMapByIdx ( + IN UINTN Idx, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form List given + the order number as appears in the List. + +Arguments: + + Idx - The index of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if (0 == Idx--) { + *Var = Map; + *Size = MapSize; + + if (NULL != Name) { + *Name = MapName; + } + + if (NULL != Guid) { + *Guid = MapGuid; + } + + if (NULL != Id) { + *Id = MapId; + } + + return EFI_SUCCESS; // Map found + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMapById ( + IN UINT16 Id, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form List given the + order number as appears in the List. + +Arguments: + + Id - The ID of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ + +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if (MapId == Id) { + *Var = Map; + *Size = MapSize; + if (NULL != Name) { + *Name = MapName; + } + if (NULL != Guid) { + *Guid = MapGuid; + } + // + // Map found + // + return EFI_SUCCESS; + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMap ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + OUT UINT16 *Id, + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID. + +Arguments: + + List - List of variables + Name - Name of the variable/map to be found + Guid - GUID of the variable/map to be found + Var - Pointer to the variable/map found + Size - Size of the variable/map in bytes found + +Returns: + + EFI_SUCCESS - variable is found, OUT parameters are valid + EFI_NOT_FOUND - variable is not found, OUT parameters are not valid + +--*/ + +{ + VOID *Map; + UINTN MapSize; + UINT16 MapId; + CHAR16 *MapName; + EFI_GUID *MapGuid; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if ((0 == StrCmp (Name, MapName)) && CompareGuid (Guid, MapGuid)) { + *Id = MapId; + *Var = Map; + *Size = MapSize; + return EFI_SUCCESS; + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiLibHiiVariableRetrieveFromNv ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID **Var + ) +/*++ + +Routine Description: + Finds out if a variable of specific Name/Guid/Size exists in NV. + If it does, it will retrieve it into the Var. + +Arguments: + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into buffer pointed by this pointer. + If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer. +Returns: + EFI_SUCCESS - The variable of exact Name/Guid/Size parameters was retrieved and written to Var. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + EFI_STATUS Status; + UINTN SizeNv; + + // + // Test for existence of the variable. + // + SizeNv = 0; + Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL); + if (EFI_BUFFER_TOO_SMALL != Status) { + ASSERT (EFI_SUCCESS != Status); + return EFI_NOT_FOUND; + } + if (SizeNv != Size) { + // + // The variable is considered corrupt, as it has different size from expected. + // + return EFI_LOAD_ERROR; + } + + if (NULL == *Var) { + *Var = AllocatePool (Size); + ASSERT (NULL != *Var); + } + SizeNv = Size; + // + // Final read into the Var + // + Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var); + // + // No tolerance for random failures. Such behavior is undetermined and not validated. + // + ASSERT_EFI_ERROR (Status); + ASSERT (SizeNv == Size); + return EFI_SUCCESS; +} + + + +EFI_STATUS +EfiLibHiiVariableOverrideIfSuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the Name ends with specified Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride", + the Suffix matches the end of Name, so the variable will be loaded from NV + provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the Name should end with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_INVALID_PARAMETER - The name of the variable does not end with . + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + UINTN StrLength; + UINTN StrLenSuffix; + + StrLength = StrLen (Name); + StrLenSuffix = StrLen (Suffix); + if ((StrLength <= StrLenSuffix) || (0 != StrCmp (Suffix, &Name[StrLength - StrLenSuffix]))) { + // + // Not ending with . + // + return EFI_INVALID_PARAMETER; + } + return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var); +} + +EFI_STATUS +EfiLibHiiVariableOverrideBySuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the NV contains the same variable with Name is appended with Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetup", + the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride" + will be loaded from NV provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the variable will be appended with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. + +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + EFI_STATUS Status; + CHAR16 *NameSuffixed; + UINTN NameLength; + UINTN SuffixLength; + + // + // enough to concatenate both strings. + // + NameLength = StrLen (Name); + SuffixLength = StrLen (Suffix); + NameSuffixed = AllocateZeroPool ((NameLength + SuffixLength + 1) * sizeof (CHAR16)); + + StrCpy (NameSuffixed, Name); + StrCat (NameSuffixed, Suffix); + + Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var); + gBS->FreePool (NameSuffixed); + + return Status; +} +