/** @file Implementation of the HII for the Opal UEFI Driver. Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
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; const EFI_GUID gOpalSetupFormSetGuid = SETUP_FORMSET_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", __func__)); 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", __func__)); } /** 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", __func__)); 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", __func__)); } /** 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; EFI_STATUS Status; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; 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_RETRIEVE) { if ((HiiKeyId == HII_KEY_ID_VAR_SUPPORTED_DISKS) || (HiiKeyId == HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS)) { // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); if (StartOpCodeHandle == NULL) { return EFI_OUT_OF_RESOURCES; } EndOpCodeHandle = HiiAllocateOpCodeHandle (); if (EndOpCodeHandle == NULL) { return EFI_OUT_OF_RESOURCES; } // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; switch (HiiKeyId) { case HII_KEY_ID_VAR_SUPPORTED_DISKS: DEBUG ((DEBUG_INFO, "HII_KEY_ID_VAR_SUPPORTED_DISKS\n")); Status = HiiPopulateMainMenuForm (); StartLabel->Number = OPAL_MAIN_MENU_LABEL_START; EndLabel->Number = OPAL_MAIN_MENU_LABEL_END; HiiUpdateForm ( gHiiPackageListHandle, (EFI_GUID *)&gOpalSetupFormSetGuid, FORMID_VALUE_MAIN_MENU, StartOpCodeHandle, EndOpCodeHandle ); break; case HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS: DEBUG ((DEBUG_INFO, "HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS\n")); Status = HiiPopulateDiskInfoForm (); StartLabel->Number = OPAL_DISK_INFO_LABEL_START; EndLabel->Number = OPAL_DISK_INFO_LABEL_END; HiiUpdateForm ( gHiiPackageListHandle, (EFI_GUID *)&gOpalSetupFormSetGuid, FORMID_VALUE_DISK_INFO_FORM_MAIN, StartOpCodeHandle, EndOpCodeHandle ); break; } HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); return Status; } } 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 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 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 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 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 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); }