diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c | 1283 |
1 files changed, 1283 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c new file mode 100644 index 00000000..50406a25 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c @@ -0,0 +1,1283 @@ +/** @file + Implementation of the HII for the Opal UEFI Driver. + +Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "OpalHii.h" +// +// Character definitions +// +#define UPPER_LOWER_CASE_OFFSET 0x20 + +// +// This is the generated IFR binary Data for each formset defined in VFR. +// This Data array is ready to be used as input of HiiAddPackages() to +// create a packagelist (which contains Form packages, String packages, etc). +// +extern UINT8 OpalPasswordFormBin[]; + +// +// This is the generated String package Data for all .UNI files. +// This Data array is ready to be used as input of HiiAddPackages() to +// create a packagelist (which contains Form packages, String packages, etc). +// +extern UINT8 OpalPasswordDxeStrings[]; + +CHAR16 OpalPasswordStorageName[] = L"OpalHiiConfig"; + +EFI_HII_CONFIG_ACCESS_PROTOCOL gHiiConfigAccessProtocol; + +// +// Handle to the list of HII packages (forms and strings) for this driver +// +EFI_HII_HANDLE gHiiPackageListHandle = NULL; + +// +// Package List GUID containing all form and string packages +// +const EFI_GUID gHiiPackageListGuid = PACKAGE_LIST_GUID; +const EFI_GUID gHiiSetupVariableGuid = SETUP_VARIABLE_GUID; + +// +// Structure that contains state of the HII +// This structure is updated by Hii.cpp and its contents +// is rendered in the HII. +// +OPAL_HII_CONFIGURATION gHiiConfiguration; + +// +// The device path containing the VENDOR_DEVICE_PATH and EFI_DEVICE_PATH_PROTOCOL +// +HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8) + } + }, + OPAL_PASSWORD_CONFIG_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8)(END_DEVICE_PATH_LENGTH), + (UINT8)((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Get saved OPAL request. + + @param[in] OpalDisk The disk needs to get the saved OPAL request. + @param[out] OpalRequest OPAL request got. + +**/ +VOID +GetSavedOpalRequest ( + IN OPAL_DISK *OpalDisk, + OUT OPAL_REQUEST *OpalRequest + ) +{ + EFI_STATUS Status; + OPAL_REQUEST_VARIABLE *TempVariable; + OPAL_REQUEST_VARIABLE *Variable; + UINTN VariableSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable; + UINTN DevicePathSizeInVariable; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN DevicePathSize; + + DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__)); + + Variable = NULL; + VariableSize = 0; + + Status = GetVariable2 ( + OPAL_REQUEST_VARIABLE_NAME, + &gHiiSetupVariableGuid, + (VOID **) &Variable, + &VariableSize + ); + if (EFI_ERROR (Status) || (Variable == NULL)) { + return; + } + + TempVariable = Variable; + while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) && + (VariableSize >= TempVariable->Length) && + (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) { + DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE)); + DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable); + DevicePath = OpalDisk->OpalDevicePath; + DevicePathSize = GetDevicePathSize (DevicePath); + if ((DevicePathSize == DevicePathSizeInVariable) && + (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) { + // + // Found the node for the OPAL device. + // Get the OPAL request. + // + CopyMem (OpalRequest, &TempVariable->OpalRequest, sizeof (OPAL_REQUEST)); + DEBUG (( + DEBUG_INFO, + "OpalRequest got: 0x%x\n", + *OpalRequest + )); + break; + } + VariableSize -= TempVariable->Length; + TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length); + } + + FreePool (Variable); + + DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__)); +} + +/** + Save OPAL request. + + @param[in] OpalDisk The disk has OPAL request to save. + @param[in] OpalRequest OPAL request to save. + +**/ +VOID +SaveOpalRequest ( + IN OPAL_DISK *OpalDisk, + IN OPAL_REQUEST OpalRequest + ) +{ + EFI_STATUS Status; + OPAL_REQUEST_VARIABLE *TempVariable; + UINTN TempVariableSize; + OPAL_REQUEST_VARIABLE *Variable; + UINTN VariableSize; + OPAL_REQUEST_VARIABLE *NewVariable; + UINTN NewVariableSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable; + UINTN DevicePathSizeInVariable; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN DevicePathSize; + + DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__)); + + DEBUG (( + DEBUG_INFO, + "OpalRequest to save: 0x%x\n", + OpalRequest + )); + + Variable = NULL; + VariableSize = 0; + NewVariable = NULL; + NewVariableSize = 0; + + Status = GetVariable2 ( + OPAL_REQUEST_VARIABLE_NAME, + &gHiiSetupVariableGuid, + (VOID **) &Variable, + &VariableSize + ); + if (!EFI_ERROR (Status) && (Variable != NULL)) { + TempVariable = Variable; + TempVariableSize = VariableSize; + while ((TempVariableSize > sizeof (OPAL_REQUEST_VARIABLE)) && + (TempVariableSize >= TempVariable->Length) && + (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) { + DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE)); + DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable); + DevicePath = OpalDisk->OpalDevicePath; + DevicePathSize = GetDevicePathSize (DevicePath); + if ((DevicePathSize == DevicePathSizeInVariable) && + (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) { + // + // Found the node for the OPAL device. + // Update the OPAL request. + // + CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST)); + NewVariable = Variable; + NewVariableSize = VariableSize; + break; + } + TempVariableSize -= TempVariable->Length; + TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length); + } + if (NewVariable == NULL) { + // + // The node for the OPAL device is not found. + // Create node for the OPAL device. + // + DevicePath = OpalDisk->OpalDevicePath; + DevicePathSize = GetDevicePathSize (DevicePath); + NewVariableSize = VariableSize + sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize; + NewVariable = AllocatePool (NewVariableSize); + ASSERT (NewVariable != NULL); + CopyMem (NewVariable, Variable, VariableSize); + TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize); + TempVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize); + CopyMem (&TempVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST)); + DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE)); + CopyMem (DevicePathInVariable, DevicePath, DevicePathSize); + } + } else { + DevicePath = OpalDisk->OpalDevicePath; + DevicePathSize = GetDevicePathSize (DevicePath); + NewVariableSize = sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize; + NewVariable = AllocatePool (NewVariableSize); + ASSERT (NewVariable != NULL); + NewVariable->Length = (UINT32) (sizeof (OPAL_REQUEST_VARIABLE) + DevicePathSize); + CopyMem (&NewVariable->OpalRequest, &OpalRequest, sizeof (OPAL_REQUEST)); + DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) NewVariable + sizeof (OPAL_REQUEST_VARIABLE)); + CopyMem (DevicePathInVariable, DevicePath, DevicePathSize); + } + Status = gRT->SetVariable ( + OPAL_REQUEST_VARIABLE_NAME, + (EFI_GUID *) &gHiiSetupVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + NewVariableSize, + NewVariable + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OpalRequest variable set failed (%r)\n", Status)); + } + if (NewVariable != Variable) { + FreePool (NewVariable); + } + if (Variable != NULL) { + FreePool (Variable); + } + + DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__)); +} + +/** + Sets the current system state of global config variables. + +**/ +VOID +HiiSetCurrentConfiguration( + VOID + ) +{ + UINT32 PpStorageFlag; + EFI_STRING NewString; + + gHiiConfiguration.NumDisks = GetDeviceCount(); + + // + // Update the BlockSID status string. + // + PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags (); + + if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_ENABLED), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } else { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISABLED), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } + HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS1), NewString, NULL); + FreePool (NewString); + + if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) != 0) { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_TRUE), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } else { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID_FALSE), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } + HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS2), NewString, NULL); + FreePool (NewString); + + if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) != 0) { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_TRUE), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } else { + NewString = HiiGetString (gHiiPackageListHandle, STRING_TOKEN(STR_DISK_INFO_DISABLE_BLOCKSID_FALSE), NULL); + if (NewString == NULL) { + DEBUG ((DEBUG_INFO, "HiiSetCurrentConfiguration: HiiGetString( ) failed\n")); + return; + } + } + HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_BLOCKSID_STATUS3), NewString, NULL); + FreePool (NewString); +} + +/** + Install the HII related resources. + + @retval EFI_SUCCESS Install all the resources success. + @retval other Error occur when install the resources. +**/ +EFI_STATUS +HiiInstall( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE DriverHandle; + + // + // Clear the global configuration. + // + ZeroMem(&gHiiConfiguration, sizeof(gHiiConfiguration)); + + // + // Obtain the driver handle that the BIOS assigned us + // + DriverHandle = HiiGetDriverImageHandleCB(); + + // + // Populate the config access protocol with the three functions we are publishing + // + gHiiConfigAccessProtocol.ExtractConfig = ExtractConfig; + gHiiConfigAccessProtocol.RouteConfig = RouteConfig; + gHiiConfigAccessProtocol.Callback = DriverCallback; + + // + // Associate the required protocols with our driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces( + &DriverHandle, + &gEfiHiiConfigAccessProtocolGuid, + &gHiiConfigAccessProtocol, // HII callback + &gEfiDevicePathProtocolGuid, + &gHiiVendorDevicePath, // required for HII callback allow all disks to be shown in same hii + NULL + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + return OpalHiiAddPackages(); +} + +/** + Install the HII form and string packages. + + @retval EFI_SUCCESS Install all the resources success. + @retval EFI_OUT_OF_RESOURCES Out of resource error. +**/ +EFI_STATUS +OpalHiiAddPackages( + VOID + ) +{ + EFI_HANDLE DriverHandle; + + DriverHandle = HiiGetDriverImageHandleCB(); + + // + // Publish the HII form and HII string packages + // + gHiiPackageListHandle = HiiAddPackages( + &gHiiPackageListGuid, + DriverHandle, + OpalPasswordDxeStrings, + OpalPasswordFormBin, + (VOID*)NULL + ); + + // + // Make sure the packages installed successfully + // + if (gHiiPackageListHandle == NULL) { + DEBUG ((DEBUG_INFO, "OpalHiiAddPackages failed\n")); + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Uninstall the HII capability. + + @retval EFI_SUCCESS Uninstall all the resources success. + @retval others Other errors occur when unistall the hii resource. +**/ +EFI_STATUS +HiiUninstall( + VOID + ) +{ + EFI_STATUS Status; + + // + // Remove the packages we've provided to the BIOS + // + HiiRemovePackages(gHiiPackageListHandle); + + // + // Remove the protocols from our driver handle + // + Status = gBS->UninstallMultipleProtocolInterfaces( + HiiGetDriverImageHandleCB(), + &gEfiHiiConfigAccessProtocolGuid, + &gHiiConfigAccessProtocol, // HII callback + &gEfiDevicePathProtocolGuid, + &gHiiVendorDevicePath, // required for HII callback + NULL + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_INFO, "Cannot uninstall Hii Protocols: %r\n", Status)); + } + + return Status; +} + +/** + Updates the main menu form. + + @retval EFI_SUCCESS update the main form success. +**/ +EFI_STATUS +HiiPopulateMainMenuForm ( + VOID + ) +{ + UINT8 Index; + CHAR8 *DiskName; + EFI_STRING_ID DiskNameId; + OPAL_DISK *OpalDisk; + + HiiSetCurrentConfiguration(); + + gHiiConfiguration.SupportedDisks = 0; + + for (Index = 0; Index < gHiiConfiguration.NumDisks; Index++) { + OpalDisk = HiiGetOpalDiskCB (Index); + if ((OpalDisk != NULL) && OpalFeatureSupported (&OpalDisk->SupportedAttributes)) { + gHiiConfiguration.SupportedDisks |= (1 << Index); + DiskNameId = GetDiskNameStringId (Index); + DiskName = HiiDiskGetNameCB (Index); + if ((DiskName == NULL) || (DiskNameId == 0)) { + return EFI_UNSUPPORTED; + } + HiiSetFormString(DiskNameId, DiskName); + } + } + + OpalHiiSetBrowserData (); + return EFI_SUCCESS; +} + +/** + Get disk name string id. + + @param DiskIndex The input disk index info. + + @retval The disk name string id. + +**/ +EFI_STRING_ID +GetDiskNameStringId( + UINT8 DiskIndex + ) +{ + switch (DiskIndex) { + case 0: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0); + case 1: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1); + case 2: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2); + case 3: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3); + case 4: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4); + case 5: return STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5); + } + return 0; +} + +/** + Confirm whether user truly want to do the revert action. + + @param OpalDisk The device which need to perform data removal action. + @param ActionString Specifies the action name shown on pop up menu. + + @retval EFI_SUCCESS Confirmed user want to do the revert action. +**/ +EFI_STATUS +HiiConfirmDataRemovalAction ( + IN OPAL_DISK *OpalDisk, + IN CHAR16 *ActionString + + ) +{ + CHAR16 Unicode[512]; + EFI_INPUT_KEY Key; + CHAR16 ApproveResponse; + CHAR16 RejectResponse; + + // + // When the estimate cost time bigger than MAX_ACCEPTABLE_REVERTING_TIME, pop up dialog to let user confirm + // the revert action. + // + if (OpalDisk->EstimateTimeCost < MAX_ACCEPTABLE_REVERTING_TIME) { + return EFI_SUCCESS; + } + + ApproveResponse = L'Y'; + RejectResponse = L'N'; + + UnicodeSPrint(Unicode, StrSize(L"WARNING: ############# action needs about ####### seconds"), L"WARNING: %s action needs about %d seconds", ActionString, OpalDisk->EstimateTimeCost); + + do { + CreatePopUp( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + Unicode, + L" System should not be powered off until action completion ", + L" ", + L" Press 'Y/y' to continue, press 'N/n' to cancel ", + NULL + ); + } while ( + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (ApproveResponse | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (RejectResponse | UPPER_LOWER_CASE_OFFSET)) + ); + + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (RejectResponse | UPPER_LOWER_CASE_OFFSET)) { + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +DriverCallback( + CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + EFI_BROWSER_ACTION Action, + EFI_QUESTION_ID QuestionId, + UINT8 Type, + EFI_IFR_TYPE_VALUE *Value, + EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + HII_KEY HiiKey; + UINT8 HiiKeyId; + UINT32 PpRequest; + OPAL_DISK *OpalDisk; + + if (ActionRequest != NULL) { + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + } else { + return EFI_INVALID_PARAMETER; + } + + // + // If QuestionId is an auto-generated key (label, empty line, etc.), ignore it. + // + if ((QuestionId & HII_KEY_FLAG) == 0) { + return EFI_SUCCESS; + } + + HiiKey.Raw = QuestionId; + HiiKeyId = (UINT8) HiiKey.KeyBits.Id; + + if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { + switch (HiiKeyId) { + case HII_KEY_ID_VAR_SUPPORTED_DISKS: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_VAR_SUPPORTED_DISKS\n")); + return HiiPopulateMainMenuForm (); + + case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS\n")); + return HiiPopulateDiskInfoForm(); + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + switch (HiiKeyId) { + case HII_KEY_ID_GOTO_DISK_INFO: + return HiiSelectDisk((UINT8)HiiKey.KeyBits.Index); + + case HII_KEY_ID_REVERT: + case HII_KEY_ID_PSID_REVERT: + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + return HiiConfirmDataRemovalAction (OpalDisk, L"Revert"); + } else { + ASSERT (FALSE); + return EFI_SUCCESS; + } + + case HII_KEY_ID_SECURE_ERASE: + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + return HiiConfirmDataRemovalAction (OpalDisk, L"Secure erase"); + } else { + ASSERT (FALSE); + return EFI_SUCCESS; + } + + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (HiiKeyId) { + case HII_KEY_ID_BLOCKSID: + switch (Value->u8) { + case 0: + PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + break; + + case 1: + PpRequest = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID; + break; + + case 2: + PpRequest = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID; + break; + + case 3: + PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE; + break; + + case 4: + PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE; + break; + + case 5: + PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE; + break; + + case 6: + PpRequest = TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE; + break; + + default: + PpRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + DEBUG ((DEBUG_ERROR, "Invalid value input!\n")); + break; + } + HiiSetBlockSidAction(PpRequest); + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_SET_ADMIN_PWD: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_SET_ADMIN_PWD\n")); + gHiiConfiguration.OpalRequest.SetAdminPwd = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_SET_USER_PWD: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_SET_USER_PWD\n")); + gHiiConfiguration.OpalRequest.SetUserPwd = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_SECURE_ERASE: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_SECURE_ERASE\n")); + gHiiConfiguration.OpalRequest.SecureErase = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_REVERT: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_REVERT\n")); + gHiiConfiguration.OpalRequest.Revert = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + case HII_KEY_ID_KEEP_USER_DATA: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_KEEP_USER_DATA\n")); + gHiiConfiguration.OpalRequest.KeepUserData = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_PSID_REVERT: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_PSID_REVERT\n")); + gHiiConfiguration.OpalRequest.PsidRevert = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_DISABLE_USER: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_DISABLE_USER\n")); + gHiiConfiguration.OpalRequest.DisableUser = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + case HII_KEY_ID_ENABLE_FEATURE: + DEBUG ((DEBUG_INFO, "HII_KEY_ID_ENABLE_FEATURE\n")); + gHiiConfiguration.OpalRequest.EnableFeature = Value->b; + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + if (OpalDisk != NULL) { + SaveOpalRequest (OpalDisk, gHiiConfiguration.OpalRequest); + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + return EFI_SUCCESS; + + default: + break; + } + } + + return EFI_UNSUPPORTED; +} + +/** + Update the global Disk index info. + + @param Index The input disk index info. + + @retval EFI_SUCCESS Update the disk index info success. + +**/ +EFI_STATUS +HiiSelectDisk( + UINT8 Index + ) +{ + OpalHiiGetBrowserData(); + gHiiConfiguration.SelectedDiskIndex = Index; + OpalHiiSetBrowserData (); + + return EFI_SUCCESS; +} + +/** + Draws the disk info form. + + @retval EFI_SUCCESS Draw the disk info success. + +**/ +EFI_STATUS +HiiPopulateDiskInfoForm( + VOID + ) +{ + OPAL_DISK* OpalDisk; + OPAL_DISK_ACTIONS AvailActions; + TCG_RESULT Ret; + CHAR8 *DiskName; + + OpalHiiGetBrowserData(); + + DiskName = HiiDiskGetNameCB (gHiiConfiguration.SelectedDiskIndex); + if (DiskName == NULL) { + return EFI_UNSUPPORTED; + } + HiiSetFormString(STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME), DiskName); + + gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE; + ZeroMem (&gHiiConfiguration.OpalRequest, sizeof (OPAL_REQUEST)); + gHiiConfiguration.KeepUserDataForced = FALSE; + + OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex); + + if (OpalDisk != NULL) { + OpalDiskUpdateStatus (OpalDisk); + Ret = OpalSupportGetAvailableActions(&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions); + if (Ret == TcgResultSuccess) { + // + // Update actions, always allow PSID Revert + // + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.PsidRevert == 1) ? HII_ACTION_PSID_REVERT : HII_ACTION_NONE; + + // + // Always allow unlock to handle device migration + // + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Unlock == 1) ? HII_ACTION_UNLOCK : HII_ACTION_NONE; + + if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) { + if (OpalDisk->Owner == OpalOwnershipNobody) { + gHiiConfiguration.SelectedDiskAvailableActions |= HII_ACTION_ENABLE_FEATURE; + + // + // Update strings + // + HiiSetFormString( STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default"); + } else { + DEBUG ((DEBUG_INFO, "Feature disabled but ownership != nobody\n")); + } + } else { + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.Revert == 1) ? HII_ACTION_REVERT : HII_ACTION_NONE; + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.AdminPass == 1) ? HII_ACTION_SET_ADMIN_PWD : HII_ACTION_NONE; + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.UserPass == 1) ? HII_ACTION_SET_USER_PWD : HII_ACTION_NONE; + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.SecureErase == 1) ? HII_ACTION_SECURE_ERASE : HII_ACTION_NONE; + gHiiConfiguration.SelectedDiskAvailableActions |= (AvailActions.DisableUser == 1) ? HII_ACTION_DISABLE_USER : HII_ACTION_NONE; + + HiiSetFormString (STRING_TOKEN(STR_DISK_INFO_PSID_REVERT), "PSID Revert to factory default and Disable"); + + // + // Determine revert options for disk + // Default initialize keep user Data to be true + // + gHiiConfiguration.OpalRequest.KeepUserData = 1; + if (AvailActions.RevertKeepDataForced) { + gHiiConfiguration.KeepUserDataForced = TRUE; + } + } + } + + GetSavedOpalRequest (OpalDisk, &gHiiConfiguration.OpalRequest); + } + + // + // Pass the current configuration to the BIOS + // + OpalHiiSetBrowserData (); + + return EFI_SUCCESS; +} + +/** + Send BlockSid request through TPM physical presence module. + + @param PpRequest TPM physical presence operation request. + + @retval EFI_SUCCESS Do the required action success. + @retval Others Other error occur. + +**/ +EFI_STATUS +HiiSetBlockSidAction ( + IN UINT32 PpRequest + ) +{ + UINT32 ReturnCode; + EFI_STATUS Status; + + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (PpRequest, 0); + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in <ConfigResp> + format. + @param Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +RouteConfig( + CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + CONST EFI_STRING Configuration, + EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return (EFI_INVALID_PARAMETER); + } + + *Progress = Configuration; + if (!HiiIsConfigHdrMatch (Configuration, &gHiiSetupVariableGuid, OpalPasswordStorageName)) { + return EFI_NOT_FOUND; + } + + *Progress = Configuration + StrLen (Configuration); + + return EFI_SUCCESS; +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in + <ConfigRequest> format. + @param Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param Results A null-terminated Unicode string in + <ConfigAltResp> format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +ExtractConfig( + CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + CONST EFI_STRING Request, + EFI_STRING *Progress, + EFI_STRING *Results + ) +{ + EFI_STATUS Status; + EFI_STRING ConfigRequest; + EFI_STRING ConfigRequestHdr; + UINTN BufferSize; + UINTN Size; + BOOLEAN AllocatedRequest; + EFI_HANDLE DriverHandle; + + // + // Check for valid parameters + // + if (Progress == NULL || Results == NULL) { + return (EFI_INVALID_PARAMETER); + } + + *Progress = Request; + if ((Request != NULL) && + !HiiIsConfigHdrMatch (Request, &gHiiSetupVariableGuid, OpalPasswordStorageName)) { + return EFI_NOT_FOUND; + } + + AllocatedRequest = FALSE; + BufferSize = sizeof (OPAL_HII_CONFIGURATION); + ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + // + // Request has no request element, construct full request string. + // Allocate and fill a buffer large enough to hold the <ConfigHdr> template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator + // + DriverHandle = HiiGetDriverImageHandleCB(); + ConfigRequestHdr = HiiConstructConfigHdr (&gHiiSetupVariableGuid, OpalPasswordStorageName, DriverHandle); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + if (ConfigRequest == NULL) { + return EFI_OUT_OF_RESOURCES; + } + AllocatedRequest = TRUE; + UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); + FreePool (ConfigRequestHdr); + } + + // + // Convert Buffer Data to <ConfigResp> by helper function BlockToConfig( ) + // + Status = gHiiConfigRouting->BlockToConfig( + gHiiConfigRouting, + ConfigRequest, + (UINT8*)&gHiiConfiguration, + sizeof(OPAL_HII_CONFIGURATION), + Results, + Progress + ); + + // + // Free the allocated config request string. + // + if (AllocatedRequest) { + FreePool (ConfigRequest); + ConfigRequest = NULL; + } + + // + // Set Progress string to the original request string. + // + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr (Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen (Request); + } + + return (Status); +} + + +/** + + Pass the current system state to the bios via the hii_G_Configuration. + +**/ +VOID +OpalHiiSetBrowserData ( + VOID + ) +{ + HiiSetBrowserData( + &gHiiSetupVariableGuid, + (CHAR16*)L"OpalHiiConfig", + sizeof(gHiiConfiguration), + (UINT8*)&gHiiConfiguration, + NULL + ); +} + + +/** + + Populate the hii_g_Configuration with the browser Data. + +**/ +VOID +OpalHiiGetBrowserData ( + VOID + ) +{ + HiiGetBrowserData( + &gHiiSetupVariableGuid, + (CHAR16*)L"OpalHiiConfig", + sizeof(gHiiConfiguration), + (UINT8*)&gHiiConfiguration + ); +} + +/** + Set a string Value in a form. + + @param DestStringId The stringid which need to update. + @param SrcAsciiStr The string need to update. + + @retval EFI_SUCCESS Do the required action success. + @retval Others Other error occur. + +**/ +EFI_STATUS +HiiSetFormString( + EFI_STRING_ID DestStringId, + CHAR8 *SrcAsciiStr + ) +{ + UINT32 Len; + UINT32 UniSize; + CHAR16* UniStr; + + // + // Determine the Length of the sting + // + Len = ( UINT32 )AsciiStrLen( SrcAsciiStr ); + + // + // Allocate space for the unicode string, including terminator + // + UniSize = (Len + 1) * sizeof(CHAR16); + UniStr = (CHAR16*)AllocateZeroPool(UniSize); + + // + // Copy into unicode string, then copy into string id + // + AsciiStrToUnicodeStrS ( SrcAsciiStr, UniStr, Len + 1); + + // + // Update the string in the form + // + if (HiiSetString(gHiiPackageListHandle, DestStringId, UniStr, NULL) == 0) { + DEBUG ((DEBUG_INFO, "HiiSetFormString( ) failed\n")); + FreePool(UniStr); + return (EFI_OUT_OF_RESOURCES); + } + + // + // Free the memory + // + FreePool(UniStr); + + return (EFI_SUCCESS); +} + +/** + Initialize the Opal disk base on the hardware info get from device. + + @param Dev The Opal device. + + @retval EFI_SUCCESS Initialize the device success. + @retval EFI_DEVICE_ERROR Get info from device failed. + +**/ +EFI_STATUS +OpalDiskInitialize ( + IN OPAL_DRIVER_DEVICE *Dev + ) +{ + TCG_RESULT TcgResult; + OPAL_SESSION Session; + UINT8 ActiveDataRemovalMechanism; + UINT32 RemovalMechanishLists[ResearvedMechanism]; + + ZeroMem(&Dev->OpalDisk, sizeof(OPAL_DISK)); + Dev->OpalDisk.Sscp = Dev->Sscp; + Dev->OpalDisk.MediaId = Dev->MediaId; + Dev->OpalDisk.OpalDevicePath = Dev->OpalDevicePath; + + ZeroMem(&Session, sizeof(Session)); + Session.Sscp = Dev->Sscp; + Session.MediaId = Dev->MediaId; + + TcgResult = OpalGetSupportedAttributesInfo (&Session, &Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.OpalBaseComId); + if (TcgResult != TcgResultSuccess) { + return EFI_DEVICE_ERROR; + } + Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId; + + TcgResult = OpalUtilGetMsid (&Session, Dev->OpalDisk.Msid, OPAL_MSID_LENGTH, &Dev->OpalDisk.MsidLength); + if (TcgResult != TcgResultSuccess) { + return EFI_DEVICE_ERROR; + } + + if (Dev->OpalDisk.SupportedAttributes.DataRemoval) { + TcgResult = OpalUtilGetDataRemovalMechanismLists (&Session, RemovalMechanishLists); + if (TcgResult != TcgResultSuccess) { + return EFI_DEVICE_ERROR; + } + + TcgResult = OpalUtilGetActiveDataRemovalMechanism (&Session, Dev->OpalDisk.Msid, Dev->OpalDisk.MsidLength, &ActiveDataRemovalMechanism); + if (TcgResult != TcgResultSuccess) { + return EFI_DEVICE_ERROR; + } + + Dev->OpalDisk.EstimateTimeCost = RemovalMechanishLists[ActiveDataRemovalMechanism]; + } + + return OpalDiskUpdateStatus (&Dev->OpalDisk); +} + +/** + Update the device ownship + + @param OpalDisk The Opal device. + + @retval EFI_SUCCESS Get ownership success. + @retval EFI_ACCESS_DENIED Has send BlockSID command, can't change ownership. + @retval EFI_INVALID_PARAMETER Not get Msid info before get ownership info. + +**/ +EFI_STATUS +OpalDiskUpdateOwnerShip ( + OPAL_DISK *OpalDisk + ) +{ + OPAL_SESSION Session; + + if (OpalDisk->MsidLength == 0) { + return EFI_INVALID_PARAMETER; + } + + if (OpalDisk->SentBlockSID) { + return EFI_ACCESS_DENIED; + } + + ZeroMem(&Session, sizeof(Session)); + Session.Sscp = OpalDisk->Sscp; + Session.MediaId = OpalDisk->MediaId; + Session.OpalBaseComId = OpalDisk->OpalBaseComId; + + OpalDisk->Owner = OpalUtilDetermineOwnership(&Session, OpalDisk->Msid, OpalDisk->MsidLength); + return EFI_SUCCESS; +} + +/** + Update the device info. + + @param OpalDisk The Opal device. + + @retval EFI_SUCCESS Initialize the device success. + @retval EFI_DEVICE_ERROR Get info from device failed. + @retval EFI_INVALID_PARAMETER Not get Msid info before get ownership info. + @retval EFI_ACCESS_DENIED Has send BlockSID command, can't change ownership. + +**/ +EFI_STATUS +OpalDiskUpdateStatus ( + OPAL_DISK *OpalDisk + ) +{ + TCG_RESULT TcgResult; + OPAL_SESSION Session; + + ZeroMem(&Session, sizeof(Session)); + Session.Sscp = OpalDisk->Sscp; + Session.MediaId = OpalDisk->MediaId; + Session.OpalBaseComId = OpalDisk->OpalBaseComId; + + TcgResult = OpalGetLockingInfo(&Session, &OpalDisk->LockingFeature); + if (TcgResult != TcgResultSuccess) { + return EFI_DEVICE_ERROR; + } + + return OpalDiskUpdateOwnerShip (OpalDisk); +} + |