-/*++\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
- IfrCommon.c\r
-\r
-Abstract:\r
-\r
- Common Library Routines to assist in IFR creation on-the-fly\r
-\r
-Revision History:\r
-\r
---*/\r
-\r
-//\r
-// Include common header file for this module.\r
-//\r
-#include "CommonHeader.h"\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-IfrLibConstruct (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetCurrentLanguage (\r
- OUT CHAR16 *Lang\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Determine what is the current language setting\r
-\r
-Arguments:\r
-\r
- Lang - Pointer of system language\r
-\r
-Returns:\r
-\r
- Status code\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- UINTN Index;\r
- CHAR8 Language[4];\r
-\r
- //\r
- // Getting the system language and placing it into our Global Data\r
- //\r
- Size = sizeof (Language);\r
-\r
- Status = gRT->GetVariable (\r
- (CHAR16 *) L"Lang",\r
- &gEfiGlobalVariableGuid,\r
- NULL,\r
- &Size,\r
- Language\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- AsciiStrCpy (Language, "eng");\r
- }\r
-\r
- for (Index = 0; Index < 3; Index++) {\r
- //\r
- // Bitwise AND ascii value with 0xDF yields an uppercase value.\r
- // Sign extend into a unicode value\r
- //\r
- Lang[Index] = (CHAR16) (Language[Index] & 0xDF);\r
- }\r
-\r
- //\r
- // Null-terminate the value\r
- //\r
- Lang[3] = (CHAR16) 0;\r
-\r
- return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-AddString (\r
- IN VOID *StringBuffer,\r
- IN CHAR16 *Language,\r
- IN CHAR16 *String,\r
- IN OUT STRING_REF *StringToken\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Add a string to the incoming buffer and return the token and offset data\r
-\r
-Arguments:\r
-\r
- StringBuffer - The incoming buffer\r
-\r
- Language - Currrent language\r
-\r
- String - The string to be added\r
-\r
- StringToken - The index where the string placed\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
-\r
- EFI_SUCCESS - String successfully added to the incoming buffer\r
-\r
---*/\r
-{\r
- EFI_HII_STRING_PACK *StringPack;\r
- EFI_HII_STRING_PACK *StringPackBuffer;\r
- VOID *NewBuffer;\r
- RELOFST *PackSource;\r
- RELOFST *PackDestination;\r
- UINT8 *Source;\r
- UINT8 *Destination;\r
- UINTN Index;\r
- BOOLEAN Finished;\r
- UINTN SizeofLanguage;\r
- UINTN SizeofString;\r
-\r
- StringPack = (EFI_HII_STRING_PACK *) StringBuffer;\r
- Finished = FALSE;\r
-\r
- //\r
- // Pre-allocate a buffer sufficient for us to work on.\r
- // We will use it as a destination scratch pad to build data on\r
- // and when complete shift the data back to the original buffer\r
- //\r
- NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);\r
- if (NewBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;\r
-\r
- //\r
- // StringPack is terminated with a length 0 entry\r
- //\r
- for (; StringPack->Header.Length != 0;) {\r
- //\r
- // If this stringpack's language is same as CurrentLanguage, use it\r
- //\r
- if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {\r
- //\r
- // We have some data in this string pack, copy the string package up to the string data\r
- //\r
- CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));\r
-\r
- //\r
- // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer\r
- //\r
- StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));\r
- StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));\r
-\r
- PackSource = (RELOFST *) (StringPack + 1);\r
- PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
- for (Index = 0; PackSource[Index] != 0x0000; Index++) {\r
- //\r
- // Copy the stringpointers from old to new buffer\r
- // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)\r
- //\r
- PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));\r
- }\r
-\r
- //\r
- // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it\r
- //\r
- PackDestination[Index] = (UINT16)(PackDestination[Index-1] +\r
- StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1])));\r
- PackDestination[Index + 1] = (UINT16) 0;\r
-\r
- //\r
- // Index is the token value for the new string\r
- //\r
- *StringToken = (UINT16) Index;\r
-\r
- //\r
- // Source now points to the beginning of the old buffer strings\r
- // Destination now points to the beginning of the new buffer strings\r
- //\r
- Source = (UINT8 *) &PackSource[Index + 1];\r
- Destination = (UINT8 *) &PackDestination[Index + 2];\r
-\r
- //\r
- // This should copy all the strings from the old buffer to the new buffer\r
- //\r
- for (; Index != 0; Index--) {\r
- //\r
- // Copy Source string to destination buffer\r
- //\r
- StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);\r
-\r
- //\r
- // Adjust the source/destination to the next string location\r
- //\r
- Destination = Destination + StrSize ((CHAR16 *) Source);\r
- Source = Source + StrSize ((CHAR16 *) Source);\r
- }\r
-\r
- //\r
- // This copies the new string to the destination buffer\r
- //\r
- StrCpy ((CHAR16 *) Destination, (CHAR16 *) String);\r
-\r
- //\r
- // Adjust the size of the changed string pack by adding the size of the new string\r
- // along with the size of the additional offset entry for the new string\r
- //\r
- StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST));\r
-\r
- //\r
- // Advance the buffers to point to the next spots.\r
- //\r
- StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);\r
- StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
- Finished = TRUE;\r
- continue;\r
- }\r
- //\r
- // This isn't the language of the stringpack we were asked to add a string to\r
- // so we need to copy it to the new buffer.\r
- //\r
- CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);\r
-\r
- //\r
- // Advance the buffers to point to the next spots.\r
- //\r
- StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);\r
- StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
- }\r
-\r
- //\r
- // If we didn't copy the new data to a stringpack yet\r
- //\r
- if (!Finished) {\r
- PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
- //\r
- // Pointing to a new string pack location\r
- //\r
- SizeofLanguage = StrSize (Language);\r
- SizeofString = StrSize (String);\r
- StringPackBuffer->Header.Length = (UINT32)\r
- (\r
- sizeof (EFI_HII_STRING_PACK) -\r
- sizeof (EFI_STRING) +\r
- sizeof (RELOFST) +\r
- sizeof (RELOFST) +\r
- SizeofLanguage +\r
- SizeofString\r
- );\r
- StringPackBuffer->Header.Type = EFI_HII_STRING;\r
- StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
- StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
- StringPackBuffer->Attributes = 0;\r
- PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
- PackDestination[1] = (UINT16) (PackDestination[0] + StrSize (Language));\r
- PackDestination[2] = (UINT16) 0;\r
-\r
- //\r
- // The first string location will be set to destination. The minimum number of strings\r
- // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)\r
- // and token 1 as the new string being added and and null entry for the stringpointers\r
- //\r
- Destination = (UINT8 *) &PackDestination[3];\r
-\r
- //\r
- // Copy the language name string to the new buffer\r
- //\r
- StrCpy ((CHAR16 *) Destination, Language);\r
-\r
- //\r
- // Advance the destination to the new empty spot\r
- //\r
- Destination = Destination + StrSize (Language);\r
-\r
- //\r
- // Copy the string to the new buffer\r
- //\r
- StrCpy ((CHAR16 *) Destination, String);\r
-\r
- //\r
- // Since we are starting with a new string pack - we know the new string is token 1\r
- //\r
- *StringToken = (UINT16) 1;\r
- }\r
-\r
- //\r
- // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
- //\r
- ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
- CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
-\r
- //\r
- // Free the newly created buffer since we don't need it anymore\r
- //\r
- gBS->FreePool (NewBuffer);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-AddOpCode (\r
- IN VOID *FormBuffer,\r
- IN OUT VOID *OpCodeData\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Add op-code data to the FormBuffer\r
-\r
-Arguments:\r
-\r
- FormBuffer - Form buffer to be inserted to\r
-\r
- OpCodeData - Op-code data to be inserted\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
-\r
- EFI_SUCCESS - Op-code data successfully inserted\r
-\r
---*/\r
-{\r
- EFI_HII_PACK_HEADER *NewBuffer;\r
- UINT8 *Source;\r
- UINT8 *Destination;\r
-\r
- //\r
- // Pre-allocate a buffer sufficient for us to work on.\r
- // We will use it as a destination scratch pad to build data on\r
- // and when complete shift the data back to the original buffer\r
- //\r
- NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);\r
- if (NewBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Source = (UINT8 *) FormBuffer;\r
- Destination = (UINT8 *) NewBuffer;\r
-\r
- //\r
- // Copy the IFR Package header to the new buffer\r
- //\r
- CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));\r
-\r
- //\r
- // Advance Source and Destination to next op-code\r
- //\r
- Source = Source + sizeof (EFI_HII_PACK_HEADER);\r
- Destination = Destination + sizeof (EFI_HII_PACK_HEADER);\r
-\r
- //\r
- // Copy data to the new buffer until we run into the end_form\r
- //\r
- for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) {\r
- //\r
- // If the this opcode is an end_form_set we better be creating and endform\r
- // Nonetheless, we will add data before the end_form_set. This also provides\r
- // for interesting behavior in the code we will run, but has no bad side-effects\r
- // since we will possibly do a 0 byte copy in this particular end-case.\r
- //\r
- if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) {\r
- break;\r
- }\r
-\r
- //\r
- // Copy data to new buffer\r
- //\r
- CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
-\r
- //\r
- // Adjust Source/Destination to next op-code location\r
- //\r
- Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
- Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
- }\r
-\r
- //\r
- // Prior to the end_form is where we insert the new op-code data\r
- //\r
- CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
- Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
-\r
- NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length));\r
-\r
- //\r
- // Copy end-form data to new buffer\r
- //\r
- CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
-\r
- //\r
- // Adjust Source/Destination to next op-code location\r
- //\r
- Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
- Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
-\r
- //\r
- // Copy end-formset data to new buffer\r
- //\r
- CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
-\r
- //\r
- // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
- //\r
- ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
- CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
-\r
- //\r
- // Free the newly created buffer since we don't need it anymore\r
- //\r
- gBS->FreePool (NewBuffer);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-GetHiiInterface (\r
- OUT EFI_HII_PROTOCOL **Hii\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get the HII protocol interface\r
-\r
-Arguments:\r
-\r
- Hii - HII protocol interface\r
-\r
-Returns:\r
-\r
- Status code\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // There should only be one HII protocol\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiHiiProtocolGuid,\r
- NULL,\r
- (VOID **) Hii\r
- );\r
-\r
- return Status;;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-ExtractDataFromHiiHandle (\r
- IN EFI_HII_HANDLE HiiHandle,\r
- IN OUT UINT16 *ImageLength,\r
- OUT UINT8 *DefaultImage,\r
- OUT EFI_GUID *Guid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Extract information pertaining to the HiiHandle\r
-\r
-Arguments:\r
-\r
- HiiHandle - Hii handle\r
-\r
- ImageLength - For input, length of DefaultImage;\r
- For output, length of actually required\r
-\r
- DefaultImage - Image buffer prepared by caller\r
-\r
- Guid - Guid information about the form\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
-\r
- EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength\r
-\r
- EFI_SUCCESS - Successfully extract data from Hii database.\r
-\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_HII_PROTOCOL *Hii;\r
- UINTN DataLength;\r
- UINT8 *RawData;\r
- UINT8 *OldData;\r
- UINTN Index;\r
- UINTN Temp;\r
- UINTN SizeOfNvStore;\r
- UINTN CachedStart;\r
-\r
- DataLength = DEFAULT_FORM_BUFFER_SIZE;\r
- SizeOfNvStore = 0;\r
- CachedStart = 0;\r
-\r
- Status = GetHiiInterface (&Hii);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Allocate space for retrieval of IFR data\r
- //\r
- RawData = AllocateZeroPool (DataLength);\r
- if (RawData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Get all the forms associated with this HiiHandle\r
- //\r
- Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (RawData);\r
-\r
- //\r
- // Allocate space for retrieval of IFR data\r
- //\r
- RawData = AllocateZeroPool (DataLength);\r
- if (RawData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Get all the forms associated with this HiiHandle\r
- //\r
- Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
- }\r
-\r
- OldData = RawData;\r
-\r
- //\r
- // Point RawData to the beginning of the form data\r
- //\r
- RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
-\r
- for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
- switch (RawData[Index]) {\r
- case EFI_IFR_FORM_SET_OP:\r
- //\r
- // Copy the GUID information from this handle\r
- //\r
- CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OP:\r
- case EFI_IFR_CHECKBOX_OP:\r
- case EFI_IFR_NUMERIC_OP:\r
- case EFI_IFR_DATE_OP:\r
- case EFI_IFR_TIME_OP:\r
- case EFI_IFR_PASSWORD_OP:\r
- case EFI_IFR_STRING_OP:\r
- //\r
- // Remember, multiple op-codes may reference the same item, so let's keep a running\r
- // marker of what the highest QuestionId that wasn't zero length. This will accurately\r
- // maintain the Size of the NvStore\r
- //\r
- if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
- Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
- if (SizeOfNvStore < Temp) {\r
- SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
- }\r
- }\r
- }\r
-\r
- Index = RawData[Index + 1] + Index;\r
- }\r
-\r
- //\r
- // Return an error if buffer is too small\r
- //\r
- if (SizeOfNvStore > *ImageLength) {\r
- gBS->FreePool (OldData);\r
- *ImageLength = (UINT16) SizeOfNvStore;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- if (DefaultImage != NULL) {\r
- ZeroMem (DefaultImage, SizeOfNvStore);\r
- }\r
-\r
- //\r
- // Copy the default image information to the user's buffer\r
- //\r
- for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
- switch (RawData[Index]) {\r
- case EFI_IFR_ONE_OF_OP:\r
- CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OPTION_OP:\r
- if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) {\r
- CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);\r
- }\r
- break;\r
-\r
- case EFI_IFR_CHECKBOX_OP:\r
- DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags;\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_OP:\r
- CopyMem (\r
- &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],\r
- &((EFI_IFR_NUMERIC *) &RawData[Index])->Default,\r
- 2\r
- );\r
- break;\r
-\r
- }\r
-\r
- Index = RawData[Index + 1] + Index;\r
- }\r
-\r
- *ImageLength = (UINT16) SizeOfNvStore;\r
-\r
- //\r
- // Free our temporary repository of form data\r
- //\r
- gBS->FreePool (OldData);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_HII_HANDLE\r
-FindHiiHandle (\r
- IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL\r
- IN EFI_GUID *Guid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Finds HII handle for given pack GUID previously registered with the HII.\r
-\r
-Arguments:\r
- HiiProtocol - pointer to pointer to HII protocol interface.\r
- If NULL, the interface will be found but not returned.\r
- If it points to NULL, the interface will be found and\r
- written back to the pointer that is pointed to.\r
- Guid - The GUID of the pack that registered with the HII.\r
-\r
-Returns:\r
- Handle to the HII pack previously registered by the memory driver.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- EFI_HII_HANDLE *HiiHandleBuffer;\r
- EFI_HII_HANDLE HiiHandle;\r
- UINT16 HiiHandleBufferLength;\r
- UINT32 NumberOfHiiHandles;\r
- EFI_GUID HiiGuid;\r
- EFI_HII_PROTOCOL *HiiProt;\r
- UINT32 Index;\r
- UINT16 Length;\r
-\r
- HiiHandle = 0;\r
- if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {\r
- //\r
- // The protocol has been passed in\r
- //\r
- HiiProt = *HiiProtocol;\r
- } else {\r
- gBS->LocateProtocol (\r
- &gEfiHiiProtocolGuid,\r
- NULL,\r
- (VOID **) &HiiProt\r
- );\r
- if (HiiProt == NULL) {\r
- return HiiHandle;\r
- }\r
-\r
- if (HiiProtocol != NULL) {\r
- //\r
- // Return back the HII protocol for the caller as promissed\r
- //\r
- *HiiProtocol = HiiProt;\r
- }\r
- }\r
- //\r
- // Allocate buffer\r
- //\r
- HiiHandleBufferLength = 10;\r
- HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);\r
- ASSERT (HiiHandleBuffer != NULL);\r
-\r
- //\r
- // Get the Handles of the packages that were registered with Hii\r
- //\r
- Status = HiiProt->FindHandles (\r
- HiiProt,\r
- &HiiHandleBufferLength,\r
- HiiHandleBuffer\r
- );\r
-\r
- //\r
- // Get a bigger bugffer if this one is to small, and try again\r
- //\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
-\r
- gBS->FreePool (HiiHandleBuffer);\r
-\r
- HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);\r
- ASSERT (HiiHandleBuffer != NULL);\r
-\r
- Status = HiiProt->FindHandles (\r
- HiiProt,\r
- &HiiHandleBufferLength,\r
- HiiHandleBuffer\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto lbl_exit;\r
- }\r
-\r
- NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE);\r
-\r
- //\r
- // Iterate Hii handles and look for the one that matches our Guid\r
- //\r
- for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
-\r
- Length = 0;\r
- ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);\r
-\r
- if (CompareGuid (&HiiGuid, Guid)) {\r
-\r
- HiiHandle = HiiHandleBuffer[Index];\r
- break;\r
- }\r
- }\r
-\r
-lbl_exit:\r
- gBS->FreePool (HiiHandleBuffer);\r
- return HiiHandle;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-ValidateDataFromHiiHandle (\r
- IN EFI_HII_HANDLE HiiHandle,\r
- OUT BOOLEAN *Results\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Validate that the data associated with the HiiHandle in NVRAM is within\r
- the reasonable parameters for that FormSet. Values for strings and passwords\r
- are not verified due to their not having the equivalent of valid range settings.\r
-\r
-Arguments:\r
-\r
- HiiHandle - Handle of the HII database entry to query\r
-\r
- Results - If return Status is EFI_SUCCESS, Results provides valid data\r
- TRUE = NVRAM Data is within parameters\r
- FALSE = NVRAM Data is NOT within parameters\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
-\r
- EFI_SUCCESS - Data successfully validated\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_HII_PROTOCOL *Hii;\r
- EFI_GUID Guid;\r
- UINT8 *RawData;\r
- UINT8 *OldData;\r
- UINTN RawDataLength;\r
- UINT8 *VariableData;\r
- UINTN Index;\r
- UINTN Temp;\r
- UINTN SizeOfNvStore;\r
- UINTN CachedStart;\r
- BOOLEAN GotMatch;\r
-\r
- RawDataLength = DEFAULT_FORM_BUFFER_SIZE;\r
- SizeOfNvStore = 0;\r
- CachedStart = 0;\r
- GotMatch = FALSE;\r
- *Results = TRUE;\r
-\r
- Status = GetHiiInterface (&Hii);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Allocate space for retrieval of IFR data\r
- //\r
- RawData = AllocateZeroPool (RawDataLength);\r
- if (RawData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Get all the forms associated with this HiiHandle\r
- //\r
- Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (RawData);\r
-\r
- //\r
- // Allocate space for retrieval of IFR data\r
- //\r
- RawData = AllocateZeroPool (RawDataLength);\r
- if (RawData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Get all the forms associated with this HiiHandle\r
- //\r
- Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
- }\r
-\r
- OldData = RawData;\r
-\r
- //\r
- // Point RawData to the beginning of the form data\r
- //\r
- RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
-\r
- for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
- if (RawData[Index] == EFI_IFR_FORM_SET_OP) {\r
- CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
- break;\r
- }\r
-\r
- Index = RawData[Index + 1] + Index;\r
- }\r
-\r
- for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
- switch (RawData[Index]) {\r
- case EFI_IFR_FORM_SET_OP:\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OP:\r
- case EFI_IFR_CHECKBOX_OP:\r
- case EFI_IFR_NUMERIC_OP:\r
- case EFI_IFR_DATE_OP:\r
- case EFI_IFR_TIME_OP:\r
- case EFI_IFR_PASSWORD_OP:\r
- case EFI_IFR_STRING_OP:\r
- //\r
- // Remember, multiple op-codes may reference the same item, so let's keep a running\r
- // marker of what the highest QuestionId that wasn't zero length. This will accurately\r
- // maintain the Size of the NvStore\r
- //\r
- if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
- Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
- if (SizeOfNvStore < Temp) {\r
- SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
- }\r
- }\r
- }\r
-\r
- Index = RawData[Index + 1] + Index;\r
- }\r
-\r
- //\r
- // Allocate memory for our File Form Tags\r
- //\r
- VariableData = AllocateZeroPool (SizeOfNvStore);\r
- if (VariableData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = gRT->GetVariable (\r
- (CHAR16 *) L"Setup",\r
- &Guid,\r
- NULL,\r
- &SizeOfNvStore,\r
- (VOID *) VariableData\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
-\r
- //\r
- // If there is a variable that exists already and it is larger than what we calculated the\r
- // storage needs to be, we must assume the variable size from GetVariable is correct and not\r
- // allow the truncation of the variable. It is very possible that the user who created the IFR\r
- // we are cracking is not referring to a variable that was in a previous map, however we cannot\r
- // allow it's truncation.\r
- //\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- //\r
- // Free the buffer that was allocated that was too small\r
- //\r
- gBS->FreePool (VariableData);\r
-\r
- VariableData = AllocatePool (SizeOfNvStore);\r
- if (VariableData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = gRT->GetVariable (\r
- (CHAR16 *) L"Setup",\r
- &Guid,\r
- NULL,\r
- &SizeOfNvStore,\r
- (VOID *) VariableData\r
- );\r
- }\r
- }\r
-\r
- //\r
- // Walk through the form and see that the variable data it refers to is ok.\r
- // This allows for the possibility of stale (obsoleted) data in the variable\r
- // can be overlooked without causing an error\r
- //\r
- for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
- switch (RawData[Index]) {\r
- case EFI_IFR_ONE_OF_OP:\r
- //\r
- // A one_of has no data, its the option that does - cache the storage Id\r
- //\r
- CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OPTION_OP:\r
- //\r
- // A one_of_option can be any value\r
- //\r
- if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {\r
- GotMatch = TRUE;\r
- }\r
- break;\r
-\r
- case EFI_IFR_END_ONE_OF_OP:\r
- //\r
- // At this point lets make sure that the data value in the NVRAM matches one of the options\r
- //\r
- if (!GotMatch) {\r
- *Results = FALSE;\r
- return EFI_SUCCESS;\r
- }\r
- break;\r
-\r
- case EFI_IFR_CHECKBOX_OP:\r
- //\r
- // A checkbox is a boolean, so 0 and 1 are valid\r
- // Remember, QuestionId corresponds to the offset location of the data in the variable\r
- //\r
- if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) {\r
- *Results = FALSE;\r
- return EFI_SUCCESS;\r
- }\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_OP:\r
- if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||\r
- (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {\r
- *Results = FALSE;\r
- return EFI_SUCCESS;\r
- }\r
- break;\r
-\r
- }\r
-\r
- Index = RawData[Index + 1] + Index;\r
- }\r
-\r
- //\r
- // Free our temporary repository of form data\r
- //\r
- gBS->FreePool (OldData);\r
- gBS->FreePool (VariableData);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r