+/**@file\r
+ This file contains functions related to Config Access Protocols installed by\r
+ by HII Thunk Modules which is used to thunk UEFI Config Access Callback to \r
+ Framework HII Callback.\r
+ \r
+Copyright (c) 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HiiDatabase.h"\r
+\r
+HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate = {\r
+ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_SIGNATURE,\r
+ {\r
+ ThunkExtractConfig,\r
+ ThunkRouteConfig,\r
+ ThunkCallback\r
+ }, //ConfigAccessProtocol\r
+ NULL, //FrameworkFormCallbackProtocol\r
+ {NULL, NULL} //ConfigAccessStorageListHead\r
+};\r
+\r
+EFI_HII_PACKAGE_HEADER *\r
+GetIfrFormSet (\r
+ IN CONST EFI_HII_PACKAGES *Packages\r
+ )\r
+{\r
+ TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
+ EFI_HII_PACKAGE_HEADER *IfrPackage;\r
+ UINTN Index;\r
+\r
+ ASSERT (Packages != NULL);\r
+\r
+ IfrPackage = NULL;\r
+\r
+ TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
+ for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
+ //\r
+ // BugBug: The current UEFI HII build tool generate a binary in the format defined in: \r
+ // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
+ // this binary is with same package type. So the returned IfrPackNum and StringPackNum\r
+ // may not be the exact number of valid package number in the binary generated \r
+ // by HII Build tool.\r
+ //\r
+ switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {\r
+ case EFI_HII_PACKAGE_FORM:\r
+ return &TianoAutogenPackageHdrArray[Index]->PackageHeader;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_STRINGS:\r
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+ break;\r
+\r
+ //\r
+ // The following fonts are invalid for a module that using Framework to UEFI thunk layer.\r
+ //\r
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+ case EFI_HII_PACKAGE_FONTS:\r
+ case EFI_HII_PACKAGE_IMAGES:\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ }\r
+\r
+ return (EFI_HII_PACKAGE_HEADER *) NULL;\r
+}\r
+\r
+EFI_STATUS\r
+GetBufferStorage (\r
+ IN CONST EFI_HII_PACKAGE_HEADER *FormSetPackage,\r
+ OUT LIST_ENTRY *BufferStorageListHead\r
+ )\r
+{\r
+ UINTN OpCodeOffset;\r
+ UINTN OpCodeLength;\r
+ UINT8 *OpCodeData;\r
+ UINT8 Operand;\r
+ EFI_IFR_VARSTORE *VarStoreOpCode;\r
+ HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+\r
+ OpCodeOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (OpCodeOffset < FormSetPackage->Length) {\r
+ OpCodeData = (UINT8 *) FormSetPackage + OpCodeOffset;\r
+\r
+ OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ OpCodeOffset += OpCodeLength;\r
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
+\r
+ if (Operand == EFI_IFR_VARSTORE_OP) {\r
+ VarStoreOpCode = (EFI_IFR_VARSTORE *)OpCodeData;\r
+ BufferStorageKey = AllocateZeroPool (sizeof (*BufferStorageKey));\r
+ if (BufferStorageKey == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyGuid (&BufferStorageKey->Guid, &VarStoreOpCode->Guid);\r
+\r
+ BufferStorageKey->Name = AllocateZeroPool (AsciiStrSize (VarStoreOpCode->Name) * 2);\r
+ AsciiStrToUnicodeStr (VarStoreOpCode->Name, BufferStorageKey->Name);\r
+\r
+ BufferStorageKey->VarStoreId = VarStoreOpCode->VarStoreId;\r
+\r
+ BufferStorageKey->Size = VarStoreOpCode->Size;\r
+ BufferStorageKey->Signature = HII_TRHUNK_BUFFER_STORAGE_KEY_SIGNATURE;\r
+\r
+ InsertTailList (BufferStorageListHead, &BufferStorageKey->List);\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+ \r
+\r
+EFI_STATUS\r
+InstallDefaultUefiConfigAccessProtocol (\r
+ IN CONST EFI_HII_PACKAGES *Packages,\r
+ OUT EFI_HANDLE *Handle,\r
+ IN OUT HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *MapEntry\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_HEADER *FormSetPackage;\r
+ EFI_STATUS Status;\r
+ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigAccessInstance;\r
+\r
+ Status = HiiLibCreateHiiDriverHandle (Handle);\r
+ ConfigAccessInstance = AllocateCopyPool (\r
+ sizeof (HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE), \r
+ &ConfigAccessProtocolInstanceTempate\r
+ );\r
+ InitializeListHead (&ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
+\r
+ //\r
+ // We assume there is only one formset package in each Forms Package\r
+ //\r
+ FormSetPackage = GetIfrFormSet (Packages);\r
+ Status = GetBufferStorage (FormSetPackage, &ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigAccessInstance);\r
+ ASSERT (FALSE);\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ Handle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ &ConfigAccessInstance->ConfigAccessProtocol,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigAccessInstance);\r
+ return Status;\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RouteConfigToFrameworkFormCallBack (\r
+ IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
+ IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN ResetRequired;\r
+\r
+ Status = FrameworkFormCallBack->NvWrite (\r
+ FrameworkFormCallBack, \r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize,\r
+ Data,\r
+ &ResetRequired\r
+ );\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ExtractConfigFromFrameworkFormCallBack (\r
+ IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
+ IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
+ OUT VOID **Data,\r
+ OUT UINTN *DataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ *DataSize = 0;\r
+ *Data = NULL;\r
+ \r
+ Status = FrameworkFormCallBack->NvRead (\r
+ FrameworkFormCallBack, \r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ NULL,\r
+ DataSize,\r
+ *Data\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (BufferStorageKey->Size != *DataSize) {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Data = AllocateZeroPool (*DataSize);\r
+ if (Data == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FrameworkFormCallBack->NvRead (\r
+ FrameworkFormCallBack, \r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ NULL,\r
+ DataSize,\r
+ *Data\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+RouteConfigToUefiVariable (\r
+ IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ return gRT->SetVariable (\r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize,\r
+ Data\r
+ );\r
+ \r
+}\r
+EFI_STATUS\r
+ExtractConfigFromUefiVariable (\r
+ IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
+ OUT VOID **Data,\r
+ OUT UINTN *DataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ *DataSize = 0;\r
+ *Data = NULL;\r
+ Status = gRT->GetVariable (\r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ NULL,\r
+ DataSize,\r
+ *Data\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+ if (BufferStorageKey->Size != *DataSize) {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Data = AllocateZeroPool (*DataSize);\r
+ if (Data == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gRT->GetVariable (\r
+ BufferStorageKey->Name,\r
+ &BufferStorageKey->Guid,\r
+ NULL,\r
+ DataSize,\r
+ *Data\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ThunkExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
+ LIST_ENTRY *ListEntry;\r
+ HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
+\r
+ Data = NULL;\r
+ ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+ ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
+ if (ListEntry == NULL) {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
+\r
+ if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
+ ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
+ Status = ExtractConfigFromUefiVariable (\r
+ BufferStorageKey,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ } else {\r
+ Status = ExtractConfigFromFrameworkFormCallBack (\r
+ BufferStorageKey,\r
+ ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ }\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ Status = mUefiConfigRoutingProtocol->BlockToConfig (\r
+ mUefiConfigRoutingProtocol,\r
+ Request,\r
+ Data,\r
+ DataSize,\r
+ Results,\r
+ Progress\r
+ );\r
+ }\r
+\r
+ SafeFreePool (Data);\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ThunkRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
+ LIST_ENTRY *ListEntry;\r
+ HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
+ UINTN LastModifiedByteIndex;\r
+\r
+ Data = NULL;\r
+ ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+ ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
+ if (ListEntry == NULL) {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
+\r
+ Data = AllocateZeroPool (BufferStorageKey->Size);\r
+ if (Data == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Status = mUefiConfigRoutingProtocol->ConfigToBlock (\r
+ mUefiConfigRoutingProtocol,\r
+ Configuration,\r
+ Data,\r
+ &LastModifiedByteIndex,\r
+ Progress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ DataSize = BufferStorageKey->Size;\r
+ if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
+ ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
+ Status = RouteConfigToUefiVariable (\r
+ BufferStorageKey,\r
+ Data,\r
+ DataSize\r
+ );\r
+ } else {\r
+ Status = RouteConfigToFrameworkFormCallBack (\r
+ BufferStorageKey,\r
+ ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
+ Data,\r
+ DataSize\r
+ );\r
+ }\r
+\r
+Done: \r
+ SafeFreePool (Data);\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ThunkCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
+ EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallbackProtocol;\r
+ EFI_HII_CALLBACK_PACKET *Packet;\r
+ FRAMEWORK_EFI_IFR_DATA_ARRAY Data;\r
+ FRAMEWORK_EFI_IFR_DATA_ENTRY *DataEntry;\r
+ EFI_FORM_CALLBACK Callback; \r
+\r
+ ASSERT (This != NULL);\r
+ ASSERT (Value != NULL);\r
+ ASSERT (ActionRequest != NULL);\r
+\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+ FrameworkFormCallbackProtocol = ConfigaAccessInstance->FrameworkFormCallbackProtocol;\r
+ if (FrameworkFormCallbackProtocol == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Callback = FrameworkFormCallbackProtocol->Callback;\r
+\r
+ Status = Callback (\r
+ FrameworkFormCallbackProtocol,\r
+ QuestionId,\r
+ &Data,\r
+ &Packet\r
+ );\r
+\r
+ //\r
+ // Callback require browser to perform action\r
+ //\r
+ if (Packet != NULL) {\r
+ if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
+ DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));\r
+ switch (DataEntry->Flags) {\r
+ case EXIT_REQUIRED:\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+ case SAVE_REQUIRED:\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+ case RESET_REQUIRED:\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
+ break;\r
+ default:\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ break; \r
+ }\r
+ }\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r