diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c
new file mode 100644
index 0000000000..ef963d0e0b
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/ComponentName.c
@@ -0,0 +1,398 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for Opal driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalDriver.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gOpalComponentName = {
+ OpalEfiDriverComponentNameGetDriverName,
+ OpalEfiDriverComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOpalComponentName2 = {
+ OpalEfiDriverComponentName2GetDriverName,
+ OpalEfiDriverComponentName2GetControllerName,
+ "en"
+};
+
+
+/// The name of the driver in all the languages we support.
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOpalDriverNameTable[] = {
+ { LANGUAGE_RFC_3066_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
+ { LANGUAGE_ISO_639_2_ENGLISH, (CHAR16*)EFI_DRIVER_NAME_UNICODE },
+ { 0, 0 }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetDriverName(
+ EFI_COMPONENT_NAME_PROTOCOL* This,
+ CHAR8* Language,
+ CHAR16** DriverName
+ )
+{
+ return LookupUnicodeString2(
+ Language,
+ This->SupportedLanguages,
+ mOpalDriverNameTable,
+ DriverName,
+ TRUE
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetDriverName(
+ EFI_COMPONENT_NAME2_PROTOCOL* This,
+ CHAR8* Language,
+ CHAR16** DriverName
+ )
+{
+ return LookupUnicodeString2(
+ Language,
+ This->SupportedLanguages,
+ mOpalDriverNameTable,
+ DriverName,
+ FALSE
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+GetControllerName(
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ CHAR8* Language,
+ CHAR16** ControllerName
+ )
+{
+ if (Language == NULL || ControllerName == NULL || ControllerHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // don't support any controller or children names
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetControllerName(
+ EFI_COMPONENT_NAME_PROTOCOL* This,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ CHAR8* Language,
+ CHAR16** ControllerName
+ )
+{
+ return (GetControllerName( ControllerHandle, ChildHandle, Language, ControllerName));
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetControllerName(
+ EFI_COMPONENT_NAME2_PROTOCOL* This,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ CHAR8* Language,
+ CHAR16** ControllerName
+ )
+{
+ return (GetControllerName(ControllerHandle, ChildHandle, Language, ControllerName));
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
new file mode 100644
index 0000000000..e06ce4a6a1
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
@@ -0,0 +1,1083 @@
+/** @file
+ Entrypoint of Opal UEFI Driver and contains all the logic to
+ register for new Opal device instances.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an
+// HII GUI to manage Opal features if the device is Opal capable
+// If the Opal device is being managed by the UEFI Driver, it shall provide a popup
+// window during boot requesting a user password
+
+#include "OpalDriver.h"
+#include "OpalDriverPrivate.h"
+#include "OpalHii.h"
+
+OPAL_DRIVER mOpalDriver;
+
+// flag to track hii installation
+BOOLEAN gHiiInstalled = FALSE;
+
+
+#define MAX_PASSWORD_SIZE 32
+#define MAX_PASSWORD_TRY_COUNT 5
+
+//
+// Globals
+//
+EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
+ OpalEfiDriverBindingSupported,
+ OpalEfiDriverBindingStart,
+ OpalEfiDriverBindingStop,
+ 0x1b,
+ NULL,
+ NULL
+};
+
+
+/**
+ Add new device to the global device list.
+
+ @param Dev New create device.
+
+**/
+VOID
+AddDeviceToTail(
+ IN OPAL_DRIVER_DEVICE *Dev
+ )
+{
+ OPAL_DRIVER_DEVICE *TmpDev;
+
+ if (mOpalDriver.DeviceList == NULL) {
+ mOpalDriver.DeviceList = Dev;
+ } else {
+ TmpDev = mOpalDriver.DeviceList;
+ while (TmpDev->Next != NULL) {
+ TmpDev = TmpDev->Next;
+ }
+
+ TmpDev->Next = Dev;
+ }
+}
+
+/**
+ Remove one device in the global device list.
+
+ @param Dev The device need to be removed.
+
+**/
+VOID
+RemoveDevice (
+ IN OPAL_DRIVER_DEVICE *Dev
+ )
+{
+ OPAL_DRIVER_DEVICE *TmpDev;
+
+ if (mOpalDriver.DeviceList == NULL) {
+ return;
+ }
+
+ if (mOpalDriver.DeviceList == Dev) {
+ mOpalDriver.DeviceList = NULL;
+ return;
+ }
+
+ TmpDev = mOpalDriver.DeviceList;
+ while (TmpDev->Next != NULL) {
+ if (TmpDev->Next == Dev) {
+ TmpDev->Next = Dev->Next;
+ break;
+ }
+ }
+}
+
+/**
+ Get current device count.
+
+ @retval return the current created device count.
+
+**/
+UINT8
+GetDeviceCount (
+ VOID
+ )
+{
+ UINT8 Count;
+ OPAL_DRIVER_DEVICE *TmpDev;
+
+ Count = 0;
+ TmpDev = mOpalDriver.DeviceList;
+
+ while (TmpDev != NULL) {
+ Count++;
+ TmpDev = TmpDev->Next;
+ }
+
+ return Count;
+}
+
+/**
+ Get password input from the popup windows, and unlock the device.
+
+ @param[in] Dev The device which need to be unlock.
+ @param[out] PressEsc Whether user escape function through Press ESC.
+
+ @retval Password string if success. NULL if failed.
+
+**/
+CHAR8 *
+OpalDriverPopUpHddPassword (
+ IN OPAL_DRIVER_DEVICE *Dev,
+ OUT BOOLEAN *PressEsc
+ )
+{
+ EFI_INPUT_KEY InputKey;
+ UINTN InputLength;
+ CHAR16 Mask[MAX_PASSWORD_SIZE + 1];
+ CHAR16 Unicode[MAX_PASSWORD_SIZE + 1];
+ CHAR8 *Ascii;
+ CHAR16 *PopUpString;
+ UINTN StrLength;
+
+ ZeroMem(Unicode, sizeof(Unicode));
+ ZeroMem(Mask, sizeof(Mask));
+
+ StrLength = StrLen(Dev->Name16);
+ PopUpString = (CHAR16*) AllocateZeroPool ((8 + StrLength) * 2);
+ *PressEsc = FALSE;
+
+ if (Dev->Name16 == NULL) {
+ UnicodeSPrint(PopUpString, StrLen(L"Unlock Disk") + 1, L"Unlock Disk");
+ } else {
+ UnicodeSPrint(PopUpString, StrLen(L"Unlock ") + StrLength + 1, L"Unlock %s", Dev->Name16);
+ }
+
+ gST->ConOut->ClearScreen(gST->ConOut);
+
+ InputLength = 0;
+ while (TRUE) {
+ Mask[InputLength] = L'_';
+ CreatePopUp(
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &InputKey,
+ PopUpString,
+ L"---------------------",
+ Mask,
+ NULL
+ );
+
+ //
+ // Check key.
+ //
+ if (InputKey.ScanCode == SCAN_NULL) {
+ //
+ // password finished
+ //
+ if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // Add the null terminator.
+ //
+ Unicode[InputLength] = 0;
+ InputLength++;
+ break;
+ } else if ((InputKey.UnicodeChar == CHAR_NULL) ||
+ (InputKey.UnicodeChar == CHAR_TAB) ||
+ (InputKey.UnicodeChar == CHAR_LINEFEED)
+ ) {
+ continue;
+ } else {
+ //
+ // delete last key entered
+ //
+ if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
+ if (InputLength > 0) {
+ Unicode[InputLength] = 0;
+ Mask[InputLength] = 0;
+ InputLength--;
+ }
+ } else {
+ //
+ // add Next key entry
+ //
+ Unicode[InputLength] = InputKey.UnicodeChar;
+ Mask[InputLength] = L'*';
+ InputLength++;
+ if (InputLength == MAX_PASSWORD_SIZE) {
+ //
+ // Add the null terminator.
+ //
+ Unicode[InputLength] = 0;
+ Mask[InputLength] = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // exit on ESC
+ //
+ if (InputKey.ScanCode == SCAN_ESC) {
+ *PressEsc = TRUE;
+ break;
+ }
+ }
+
+ gST->ConOut->ClearScreen(gST->ConOut);
+
+ if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
+ return NULL;
+ }
+
+ Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);
+ if (Ascii == NULL) {
+ return NULL;
+ }
+
+ UnicodeStrToAsciiStr(Unicode, Ascii);
+
+ return Ascii;
+}
+
+/**
+ Check if disk is locked, show popup window and ask for password if it is
+
+ @param[in] Dev The device which need to be unlock.
+
+**/
+VOID
+OpalDriverRequestPassword (
+ OPAL_DRIVER_DEVICE *Dev
+ )
+{
+ UINT8 Count;
+ BOOLEAN IsEnabled;
+ CHAR8 *Password;
+ UINT32 PasswordLen;
+ TCG_RESULT Ret;
+ EFI_INPUT_KEY Key;
+ OPAL_SESSION Session;
+ BOOLEAN PressEsc;
+
+ if (Dev == NULL) {
+ return;
+ }
+
+ Count = 0;
+
+ IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
+ if (IsEnabled) {
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = Dev->OpalDisk.Sscp;
+ Session.MediaId = Dev->OpalDisk.MediaId;
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
+
+ while (Count < MAX_PASSWORD_TRY_COUNT) {
+ Password = OpalDriverPopUpHddPassword (Dev, &PressEsc);
+ if (PressEsc) {
+ //
+ // User not input password and press ESC, keep device in lock status and continue boot.
+ //
+ do {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Confirm: Not unlock device and continue boot?.",
+ L"Press ENTER to confirm, Press Esc to input password",
+ NULL
+ );
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ gST->ConOut->ClearScreen(gST->ConOut);
+ //
+ // Keep lock and continue boot.
+ //
+ return;
+ } else {
+ //
+ // Let user input password again.
+ //
+ continue;
+ }
+ }
+
+ if (Password == NULL) {
+ Count ++;
+ continue;
+ }
+ PasswordLen = (UINT32) AsciiStrLen(Password);
+
+ if (OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature)) {
+ Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
+ } else {
+ Ret = OpalSupportLock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
+ if (Ret == TcgResultSuccess) {
+ Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
+ }
+ }
+
+ if (Password != NULL) {
+ ZeroMem (Password, PasswordLen);
+ FreePool (Password);
+ }
+
+ if (Ret == TcgResultSuccess) {
+ break;
+ }
+
+ Count++;
+
+ do {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Invalid password.",
+ L"Press ENTER to retry",
+ NULL
+ );
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {
+ do {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ L"Opal password retry count is expired. Keep lock and continue boot.",
+ L"Press ENTER to continue",
+ NULL
+ );
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ gST->ConOut->ClearScreen(gST->ConOut);
+ }
+ }
+}
+
+/**
+ Get devcie list info.
+
+ @retval return the device list pointer.
+**/
+OPAL_DRIVER_DEVICE*
+OpalDriverGetDeviceList(
+ VOID
+ )
+{
+ return mOpalDriver.DeviceList;
+}
+
+/**
+ ReadyToBoot callback to send BlockSid command.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private Data
+
+**/
+VOID
+EFIAPI
+ReadyToBootCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ OPAL_DRIVER_DEVICE* Itr;
+ UINT8 Count;
+ TCG_RESULT Result;
+ OPAL_EXTRA_INFO_VAR OpalExtraInfo;
+ UINTN DataSize;
+ OPAL_SESSION Session;
+
+ Count = 0;
+
+ gBS->CloseEvent (Event);
+
+ DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
+ Status = gRT->GetVariable (
+ OPAL_EXTRA_INFO_VAR_NAME,
+ &gOpalExtraInfoVariableGuid,
+ NULL,
+ &DataSize,
+ &OpalExtraInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (OpalExtraInfo.EnableBlockSid == TRUE) {
+ //
+ // Send BlockSID command to each Opal disk
+ //
+ Itr = mOpalDriver.DeviceList;
+ Count = 0;
+ while (Itr != NULL) {
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = Itr->OpalDisk.Sscp;
+ Session.MediaId = Itr->OpalDisk.MediaId;
+ Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
+
+ Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE
+ if (Result != TcgResultSuccess) {
+ DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
+ break;
+ }
+
+ Itr = Itr->Next;
+ Count++;
+ }
+ }
+}
+
+/**
+ Stop this Controller.
+
+ @param Dev The device need to be stopped.
+
+**/
+VOID
+OpalDriverStopDevice (
+ OPAL_DRIVER_DEVICE *Dev
+ )
+{
+ //
+ // free each name
+ //
+ FreePool(Dev->Name16);
+
+ //
+ // remove OPAL_DRIVER_DEVICE from the list
+ // it updates the controllerList pointer
+ //
+ RemoveDevice(Dev);
+
+ //
+ // close protocols that were opened
+ //
+ gBS->CloseProtocol(
+ Dev->Handle,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ gOpalDriverBinding.DriverBindingHandle,
+ Dev->Handle
+ );
+
+ gBS->CloseProtocol(
+ Dev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ gOpalDriverBinding.DriverBindingHandle,
+ Dev->Handle
+ );
+
+ FreePool(Dev);
+}
+
+/**
+ Get devcie name through the component name protocol.
+
+ @param[in] AllHandlesBuffer The handle buffer for current system.
+ @param[in] NumAllHandles The number of handles for the handle buffer.
+ @param[in] Dev The device which need to get name.
+ @param[in] UseComp1 Whether use component name or name2 protocol.
+
+ @retval TRUE Find the name for this device.
+ @retval FALSE Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDeviceNameByProtocol(
+ EFI_HANDLE *AllHandlesBuffer,
+ UINTN NumAllHandles,
+ OPAL_DRIVER_DEVICE *Dev,
+ BOOLEAN UseComp1
+ )
+{
+ EFI_HANDLE* ProtocolHandlesBuffer;
+ UINTN NumProtocolHandles;
+ EFI_STATUS Status;
+ EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout
+ EFI_GUID Protocol;
+ UINTN StrLength;
+ EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;
+ UINTN Index1;
+ UINTN Index2;
+ EFI_HANDLE TmpHandle;
+ CHAR16 *DevName;
+
+ if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
+ return FALSE;
+ }
+
+ Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;
+
+ //
+ // Find all EFI_HANDLES with protocol
+ //
+ Status = gBS->LocateHandleBuffer(
+ ByProtocol,
+ &Protocol,
+ NULL,
+ &NumProtocolHandles,
+ &ProtocolHandlesBuffer
+ );
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+
+ //
+ // Exit early if no supported devices
+ //
+ if (NumProtocolHandles == 0) {
+ return FALSE;
+ }
+
+ //
+ // Get printable name by iterating through all protocols
+ // using the handle as the child, and iterate through all handles for the controller
+ // exit loop early once found, if not found, then delete device
+ // storage security protocol instances already exist, add them to internal list
+ //
+ Status = EFI_DEVICE_ERROR;
+ for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
+ DevName = NULL;
+
+ if (Dev->Name16 != NULL) {
+ return TRUE;
+ }
+
+ TmpHandle = ProtocolHandlesBuffer[Index1];
+
+ Status = gBS->OpenProtocol(
+ TmpHandle,
+ &Protocol,
+ (VOID**)&Cnp1_2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
+ continue;
+ }
+
+ //
+ // Use all handles array as controller handle
+ //
+ for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
+ Status = Cnp1_2->GetControllerName(
+ Cnp1_2,
+ AllHandlesBuffer[Index2],
+ Dev->Handle,
+ LANGUAGE_ISO_639_2_ENGLISH,
+ &DevName
+ );
+ if (EFI_ERROR(Status)) {
+ Status = Cnp1_2->GetControllerName(
+ Cnp1_2,
+ AllHandlesBuffer[Index2],
+ Dev->Handle,
+ LANGUAGE_RFC_3066_ENGLISH,
+ &DevName
+ );
+ }
+ if (!EFI_ERROR(Status) && DevName != NULL) {
+ StrLength = StrLen(DevName) + 1; // Add one for NULL terminator
+ Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
+ ASSERT (Dev->Name16 != NULL);
+ StrCpyS (Dev->Name16, StrLength, DevName);
+ Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
+ UnicodeStrToAsciiStr(DevName, Dev->NameZ);
+
+ //
+ // Retrieve bridge BDF info and port number or namespace depending on type
+ //
+ TmpDevPath = NULL;
+ Status = gBS->OpenProtocol(
+ Dev->Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&TmpDevPath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
+ return TRUE;
+ }
+
+ if (Dev->Name16 != NULL) {
+ FreePool(Dev->Name16);
+ Dev->Name16 = NULL;
+ }
+ if (Dev->NameZ != NULL) {
+ FreePool(Dev->NameZ);
+ Dev->NameZ = NULL;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Get devcie name through the component name protocol.
+
+ @param[in] Dev The device which need to get name.
+
+ @retval TRUE Find the name for this device.
+ @retval FALSE Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDriverDeviceName(
+ OPAL_DRIVER_DEVICE *Dev
+ )
+{
+ EFI_HANDLE* AllHandlesBuffer;
+ UINTN NumAllHandles;
+ EFI_STATUS Status;
+
+ if (Dev == NULL) {
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));
+ return FALSE;
+ }
+
+ //
+ // Iterate through ComponentName2 handles to get name, if fails, try ComponentName
+ //
+ if (Dev->Name16 == NULL) {
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
+ //
+ // Find all EFI_HANDLES
+ //
+ Status = gBS->LocateHandleBuffer(
+ AllHandles,
+ NULL,
+ NULL,
+ &NumAllHandles,
+ &AllHandlesBuffer
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));
+ return FALSE;
+ }
+
+ //
+ // Try component Name2
+ //
+ if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));
+ if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image Handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+**/
+EFI_STATUS
+EFIAPI
+EfiDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE* SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBootEvent;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gOpalDriverBinding,
+ ImageHandle,
+ &gOpalComponentName,
+ &gOpalComponentName2
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));
+ return Status ;
+ }
+
+ //
+ // Initialize Driver object
+ //
+ ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
+ mOpalDriver.Handle = ImageHandle;
+
+ //
+ // register a ReadyToBoot event callback for sending BlockSid command
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ ReadyToBootCallback,
+ (VOID *) &ImageHandle,
+ &ReadyToBootEvent
+ );
+
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller.
+
+ This function checks to see if the controller contains an instance of the
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL
+ and returns EFI_SUCCESS if it does.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The Handle of the controller to test. This Handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath This parameter is ignored.
+
+ @retval EFI_SUCCESS The device contains required protocols
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device does not contain requires protocols
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingSupported(
+ IN EFI_DRIVER_BINDING_PROTOCOL* This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;
+ EFI_BLOCK_IO_PROTOCOL* BlkIo;
+
+ //
+ // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.
+ //
+ Status = gBS->OpenProtocol(
+ Controller,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ ( VOID ** )&SecurityCommand,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Close protocol and reopen in Start call
+ //
+ gBS->CloseProtocol(
+ Controller,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
+ // function APIs
+ //
+ Status = gBS->OpenProtocol(
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
+ return Status;
+ }
+
+ //
+ // Close protocol and reopen in Start call
+ //
+ gBS->CloseProtocol(
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables Opal Management on a supported device if available.
+
+ The start function is designed to be called after the Opal UEFI Driver has confirmed the
+ "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
+ This function will complete the other necessary checks, such as verifying the device supports
+ the correct version of Opal. Upon verification, it will add the device to the
+ Opal HII list in order to expose Opal managmeent options.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The Handle of the controller to start. This Handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the Handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child Handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS Opal management was enabled.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failed to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStart(
+ IN EFI_DRIVER_BINDING_PROTOCOL* This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ OPAL_DRIVER_DEVICE *Dev;
+ OPAL_DRIVER_DEVICE *Itr;
+ BOOLEAN Result;
+
+ Itr = mOpalDriver.DeviceList;
+ while (Itr != NULL) {
+ if (Controller == Itr->Handle) {
+ return EFI_SUCCESS;
+ }
+ Itr = Itr->Next;
+ }
+
+ //
+ // Create internal device for tracking. This allows all disks to be tracked
+ // by same HII form
+ //
+ Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
+ if (Dev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Dev->Handle = Controller;
+
+ //
+ // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks
+ //
+ Status = gBS->OpenProtocol(
+ Controller,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ (VOID **)&Dev->Sscp,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool(Dev);
+ return Status;
+ }
+
+ //
+ // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
+ // function APIs
+ //
+ Status = gBS->OpenProtocol(
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR(Status)) {
+ //
+ // Close storage security that was opened
+ //
+ gBS->CloseProtocol(
+ Controller,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ FreePool(Dev);
+ return Status;
+ }
+
+ //
+ // Save mediaId
+ //
+ Dev->MediaId = BlkIo->Media->MediaId;
+
+ gBS->CloseProtocol(
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Acquire Ascii printable name of child, if not found, then ignore device
+ //
+ Result = OpalDriverGetDriverDeviceName (Dev);
+ if (!Result) {
+ goto Done;
+ }
+
+ Status = OpalDiskInitialize (Dev);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ AddDeviceToTail(Dev);
+
+ //
+ // Install Hii if it hasn't already been installed
+ //
+ if (!gHiiInstalled) {
+ HiiInstall();
+ gHiiInstalled = TRUE;
+ }
+
+ //
+ // check if device is locked and prompt for password
+ //
+ OpalDriverRequestPassword (Dev);
+
+ return EFI_SUCCESS;
+
+Done:
+ //
+ // free device, close protocols and exit
+ //
+ gBS->CloseProtocol(
+ Controller,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ FreePool(Dev);
+
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Stop this driver on Controller.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval other This driver could not be removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStop(
+ EFI_DRIVER_BINDING_PROTOCOL* This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE* ChildHandleBuffer
+ )
+{
+ OPAL_DRIVER_DEVICE* Itr;
+
+ Itr = mOpalDriver.DeviceList;
+
+ //
+ // does Controller match any of the devices we are managing for Opal
+ //
+ while (Itr != NULL) {
+ if (Itr->Handle == Controller) {
+ OpalDriverStopDevice (Itr);
+ return EFI_SUCCESS;
+ }
+
+ Itr = Itr->Next;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Unloads UEFI Driver. Very useful for debugging and testing.
+
+ @param ImageHandle Image Handle this driver.
+
+ @retval EFI_SUCCESS This function always complete successfully.
+ @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ OPAL_DRIVER_DEVICE *Itr;
+
+ Status = EFI_SUCCESS;
+
+ if (ImageHandle != gImageHandle) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Uninstall any interface added to each device by us
+ //
+ while (mOpalDriver.DeviceList) {
+ Itr = mOpalDriver.DeviceList;
+ //
+ // Remove OPAL_DRIVER_DEVICE from the list
+ // it updates the controllerList pointer
+ //
+ OpalDriverStopDevice(Itr);
+ }
+
+ //
+ // Uninstall the HII capability
+ //
+ Status = HiiUninstall();
+
+ return Status;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
new file mode 100644
index 0000000000..213c139e01
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.h
@@ -0,0 +1,413 @@
+/** @file
+ Values defined and used by the Opal UEFI Driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_DRIVER_H_
+#define _OPAL_DRIVER_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define EFI_DRIVER_NAME_UNICODE L"1.0 UEFI Opal Driver"
+
+// UEFI 2.1
+#define LANGUAGE_RFC_3066_ENGLISH ((CHAR8*)"en")
+
+// UEFI/EFI < 2.1
+#define LANGUAGE_ISO_639_2_ENGLISH ((CHAR8*)"eng")
+
+
+#define UNLOCK_VAR_NAME (const CHAR16*)L"UNLOCK"
+#define OPAL_FILTER_DRIVER_VAR_NAME L"FILTER_DRIVER"
+
+
+#define CONCAT_(x, y) x ## y
+#define CONCAT(x, y) CONCAT_(x, y)
+
+#define UNICODE_STR(x) CONCAT( L, x )
+
+extern EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gOpalComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gOpalComponentName2;
+
+/**
+ Unloads UEFI Driver. Very useful for debugging and testing.
+
+ @param ImageHandle Image handle this driver.
+
+ @retval EFI_SUCCESS This function always complete successfully.
+ @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
+**/
+EFI_STATUS
+EFIAPI
+EfiDriverUnload(
+ EFI_HANDLE ImageHandle
+ );
+
+
+/**
+ Test to see if this driver supports Controller.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingSupported(
+ EFI_DRIVER_BINDING_PROTOCOL* This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
+ );
+
+/**
+ Enables Opal Management on a supported device if available.
+
+ The start function is designed to be called after the Opal UEFI Driver has confirmed the
+ "controller", which is a child handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
+ This function will complete the other necessary checks, such as verifying the device supports
+ the correct version of Opal. Upon verification, it will add the device to the
+ Opal HII list in order to expose Opal managmeent options.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS Opal management was enabled.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failed to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStart(
+ EFI_DRIVER_BINDING_PROTOCOL* This,
+ EFI_HANDLE Controller,
+ EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
+ );
+
+/**
+ Stop this driver on Controller.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval other This driver could not be removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverBindingStop(
+ EFI_DRIVER_BINDING_PROTOCOL* This,
+ EFI_HANDLE Controller,
+ UINTN NumberOfChildren,
+ EFI_HANDLE* ChildHandleBuffer
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetDriverName(
+ EFI_COMPONENT_NAME_PROTOCOL* This,
+ CHAR8* Language,
+ CHAR16** DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentNameGetControllerName(
+ EFI_COMPONENT_NAME_PROTOCOL* This,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ CHAR8* Language,
+ CHAR16** ControllerName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetDriverName(
+ EFI_COMPONENT_NAME2_PROTOCOL* This,
+ CHAR8* Language,
+ CHAR16** DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OpalEfiDriverComponentName2GetControllerName(
+ EFI_COMPONENT_NAME2_PROTOCOL* This,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ CHAR8* Language,
+ CHAR16** ControllerName
+ );
+
+#endif //_OPAL_DRIVER_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
new file mode 100644
index 0000000000..19ebc32623
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriverPrivate.h
@@ -0,0 +1,102 @@
+/** @file
+ Private structures and functions used within OPAL_DRIVER
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_DRIVER_PRIVATE_H_
+#define _OPAL_DRIVER_PRIVATE_H_
+#include "OpalDriver.h"
+
+#define OPAL_MSID_LENGHT 128
+
+#pragma pack(1)
+//
+// Structure that is used to represent an OPAL_DISK.
+//
+typedef struct {
+ UINT32 MsidLength; // Byte length of MSID Pin for device
+ UINT8 Msid[OPAL_MSID_LENGHT]; // MSID Pin for device
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp;
+ UINT32 MediaId; // MediaId is used by Ssc Protocol.
+ EFI_DEVICE_PATH_PROTOCOL *OpalDevicePath;
+ UINT16 OpalBaseComId; // Opal SSC 1 base com id.
+ OPAL_OWNER_SHIP Owner;
+ OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes;
+ TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature; // Locking Feature Descriptor retrieved from performing a Level 0 Discovery
+} OPAL_DISK;
+
+//
+// Device with block IO protocol
+//
+typedef struct _OPAL_DRIVER_DEVICE OPAL_DRIVER_DEVICE;
+
+struct _OPAL_DRIVER_DEVICE {
+ OPAL_DRIVER_DEVICE *Next; ///< Linked list pointer
+ EFI_HANDLE Handle; ///< Device handle
+ OPAL_DISK OpalDisk; ///< User context
+ CHAR16 *Name16; ///< Allocated/freed by UEFI Filter Driver at device creation/removal
+ CHAR8 *NameZ; ///< Allocated/freed by UEFI Filter Driver at device creation/removal
+ UINT32 MediaId; ///< Required parameter for EFI_STORAGE_SECURITY_COMMAND_PROTOCOL, from BLOCK_IO_MEDIA
+
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp; /// Device protocols consumed
+ EFI_DEVICE_PATH_PROTOCOL *OpalDevicePath;
+};
+
+//
+// Opal Driver UEFI Driver Model
+//
+typedef struct {
+ EFI_HANDLE Handle; ///< Driver image handle
+ OPAL_DRIVER_DEVICE *DeviceList; ///< Linked list of controllers owned by this Driver
+} OPAL_DRIVER;
+#pragma pack()
+
+//
+// Retrieves a OPAL_DRIVER_DEVICE based on the pointer to its StorageSecurity protocol.
+//
+#define DRIVER_DEVICE_FROM_OPALDISK(OpalDiskPointer) (OPAL_DRIVER_DEVICE*)(BASE_CR(OpalDiskPointer, OPAL_DRIVER_DEVICE, OpalDisk))
+
+/**
+ Get devcie list info.
+
+ @retval return the device list pointer.
+**/
+OPAL_DRIVER_DEVICE*
+OpalDriverGetDeviceList(
+ VOID
+ );
+
+/**
+ Get devcie name through the component name protocol.
+
+ @param[in] Dev The device which need to get name.
+
+ @retval TRUE Find the name for this device.
+ @retval FALSE Not found the name for this device.
+**/
+BOOLEAN
+OpalDriverGetDriverDeviceName(
+ OPAL_DRIVER_DEVICE *Dev
+ );
+
+/**
+ Get current device count.
+
+ @retval return the current created device count.
+
+**/
+UINT8
+GetDeviceCount (
+ VOID
+ );
+
+#endif // _OPAL_DRIVER_P_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
new file mode 100644
index 0000000000..250cb438e9
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.c
@@ -0,0 +1,1424 @@
+/** @file
+ Implementation of the HII for the Opal UEFI Driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalHii.h"
+#include "OpalDriver.h"
+#include "OpalHiiPrivate.h"
+
+//
+// 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[];
+
+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;
+
+CHAR8 gHiiOldPassword[MAX_PASSWORD_CHARACTER_LENGTH] = {0};
+UINT32 gHiiOldPasswordLength = 0;
+
+//
+// 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)
+ }
+ }
+};
+
+
+/**
+ Sets the current system state of global config variables.
+
+**/
+VOID
+HiiSetCurrentConfiguration(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ OPAL_EXTRA_INFO_VAR OpalExtraInfo;
+ UINTN DataSize;
+
+ gHiiConfiguration.NumDisks = GetDeviceCount();
+
+ DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
+ Status = gRT->GetVariable (
+ OPAL_EXTRA_INFO_VAR_NAME,
+ &gOpalExtraInfoVariableGuid,
+ NULL,
+ &DataSize,
+ &OpalExtraInfo
+ );
+ DEBUG ((DEBUG_INFO, "GetVariable for OpalExtraInfo @ HiiSetCurrentConfiguration, Status: %r\n", Status));
+ if (!EFI_ERROR (Status)) {
+ gHiiConfiguration.EnableBlockSid = OpalExtraInfo.EnableBlockSid;
+ }
+}
+
+/**
+ Check that all required protocols for HII are available.
+
+ @retval EFI_SUCCESS All required protocols are installed.
+ @retval EFI_NOT_FOUND One or more protocol are not installed.
+**/
+EFI_STATUS
+HiiCheckForRequiredProtocols (
+ VOID
+ )
+{
+ VOID* TempProtocol;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, (VOID**)&TempProtocol );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, (VOID**)&TempProtocol );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID**)&TempProtocol );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->LocateProtocol(&gEfiFormBrowser2ProtocolGuid, NULL, (VOID**)&TempProtocol );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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;
+
+ //
+ // Check that all required protocols are available for HII.
+ // If not, fail the install
+ //
+ Status = HiiCheckForRequiredProtocols();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // 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;
+ CHAR16 *NewString;
+
+ 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;
+ }
+
+ //
+ // Update Version String in main window
+ //
+ NewString = HiiGetDriverNameCB ();
+ if (HiiSetString(gHiiPackageListHandle, STRING_TOKEN(STR_MAIN_OPAL_VERSION), NewString, NULL) == 0) {
+ DEBUG ((DEBUG_INFO, "OpalHiiAddPackages: HiiSetString( ) 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;
+}
+
+/**
+ Update the disk action info.
+
+ @param ActionString
+ @param SelectedAction
+
+ @retval EFI_SUCCESS Uninstall all the resources success.
+**/
+EFI_STATUS
+HiiSelectDiskAction (
+ CHAR8 *ActionString,
+ UINT8 SelectedAction
+ )
+{
+ OPAL_DISK *OpalDisk;
+ OPAL_DISK_ACTIONS AvailActions;
+
+ OpalHiiGetBrowserData ();
+
+ HiiSetFormString(STRING_TOKEN(STR_DISK_ACTION_LBL), ActionString);
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), " ");
+
+ gHiiConfiguration.SelectedAction = SelectedAction;
+ gHiiConfiguration.AvailableFields = 0;
+
+ OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+ if (OpalDisk == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (OpalSupportGetAvailableActions (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature, OpalDisk->Owner, &AvailActions) != TcgResultSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (SelectedAction) {
+ case HII_KEY_ID_GOTO_LOCK:
+ case HII_KEY_ID_GOTO_UNLOCK:
+ case HII_KEY_ID_GOTO_SET_ADMIN_PWD:
+ case HII_KEY_ID_GOTO_SET_USER_PWD:
+ case HII_KEY_ID_GOTO_SECURE_ERASE:
+ case HII_KEY_ID_GOTO_DISABLE_USER:
+ case HII_KEY_ID_GOTO_ENABLE_FEATURE: // User is required to enter Password to enable Feature
+ gHiiConfiguration.AvailableFields |= HII_FIELD_PASSWORD;
+ break;
+
+ case HII_KEY_ID_GOTO_PSID_REVERT:
+ gHiiConfiguration.AvailableFields |= HII_FIELD_PSID;
+ break;
+
+ case HII_KEY_ID_GOTO_REVERT:
+ gHiiConfiguration.AvailableFields |= HII_FIELD_PASSWORD;
+ gHiiConfiguration.AvailableFields |= HII_FIELD_KEEP_USER_DATA;
+ if (AvailActions.RevertKeepDataForced) {
+ gHiiConfiguration.AvailableFields |= HII_FIELD_KEEP_USER_DATA_FORCED;
+ }
+ break;
+ }
+
+ 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;
+}
+
+/**
+ 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;
+
+ if (ActionRequest != NULL) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ }
+
+ //
+ // 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:
+ 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_GOTO_LOCK:
+ return HiiSelectDiskAction("Action: Lock", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_UNLOCK:
+ return HiiSelectDiskAction("Action: Unlock", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_SET_ADMIN_PWD:
+ return HiiSelectDiskAction("Action: Set Administrator Password", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_SET_USER_PWD:
+ return HiiSelectDiskAction("Action: Set User Password", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_SECURE_ERASE:
+ return HiiSelectDiskAction("Action: Secure Erase", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_PSID_REVERT:
+ return HiiSelectDiskAction("Action: Revert to Factory Defaults with PSID", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_REVERT:
+ return HiiSelectDiskAction("Action: Revert to Factory Defaults", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_DISABLE_USER:
+ return HiiSelectDiskAction("Action: Disable User", HiiKeyId);
+
+ case HII_KEY_ID_GOTO_ENABLE_FEATURE:
+ return HiiSelectDiskAction("Action: Enable Feature", HiiKeyId);
+
+ case HII_KEY_ID_ENTER_PASSWORD:
+ return HiiPasswordEntered(Value->string);
+
+ case HII_KEY_ID_BLOCKSID:
+ return HiiSetBlockSid(Value->b);
+ }
+ } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+ switch (HiiKeyId) {
+ case HII_KEY_ID_ENTER_PSID:
+ HiiPsidRevert();
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+ return EFI_SUCCESS;
+ }
+ }
+
+ 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);
+
+ ZeroMem(gHiiConfiguration.Psid, sizeof(gHiiConfiguration.Psid));
+
+ gHiiConfiguration.SelectedDiskAvailableActions = HII_ACTION_NONE;
+
+ 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;
+ gHiiConfiguration.SelectedDiskAvailableActions |= HII_ACTION_ENABLE_BLOCKSID;
+
+ 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.KeepUserData = 1;
+ }
+ }
+ }
+
+ //
+ // Pass the current configuration to the BIOS
+ //
+ OpalHiiSetBrowserData ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reverts the Opal disk to factory default.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiPsidRevert(
+ VOID
+ )
+{
+ CHAR8 Response[DEFAULT_RESPONSE_SIZE];
+ TCG_PSID Psid;
+ OPAL_DISK *OpalDisk;
+ TCG_RESULT Ret;
+ OPAL_SESSION Session;
+
+ Ret = TcgResultFailure;
+
+ OpalHiiGetBrowserData();
+
+ UnicodeStrToAsciiStr(gHiiConfiguration.Psid, (CHAR8*)Psid.Psid);
+
+ OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = OpalDisk->Sscp;
+ Session.MediaId = OpalDisk->MediaId;
+ Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ if (OpalDisk != NULL) {
+ Ret = OpalSupportPsidRevert(&Session, Psid.Psid, (UINT32)sizeof(Psid.Psid), OpalDisk->OpalDevicePath);
+ }
+
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "PSID Revert: Success" );
+ } else {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "PSID Revert: Failure" );
+ }
+
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set password for the disk.
+
+ @param OpalDisk The disk need to set the password.
+ @param Password The input password.
+ @param PassLength The input password length.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiSetPassword(
+ OPAL_DISK *OpalDisk,
+ VOID *Password,
+ UINT32 PassLength
+ )
+{
+ CHAR8 Response[DEFAULT_RESPONSE_SIZE];
+ TCG_RESULT Ret;
+ BOOLEAN ExistingPassword;
+ OPAL_SESSION Session;
+
+ ExistingPassword = FALSE;
+
+ //
+ // PassLength = 0 means check whether exist old password.
+ //
+ if (PassLength == 0) {
+ ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
+ gHiiOldPasswordLength = 0;
+
+ if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_ENABLE_FEATURE) {
+ ExistingPassword = FALSE;
+ } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_ADMIN_PWD) {
+ ExistingPassword = OpalUtilAdminPasswordExists(OpalDisk->Owner, &OpalDisk->LockingFeature);
+ } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
+ //
+ // Set user Password option shall only be shown if an Admin Password exists
+ // so a Password is always required (Admin or Existing User Password)
+ //
+ ExistingPassword = TRUE;
+ }
+
+ //
+ // Return error if there is a previous Password
+ // see UEFI 2.4 errata B, Figure 121. Password Flowchart
+ //
+ return ExistingPassword ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+ }
+
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = OpalDisk->Sscp;
+ Session.MediaId = OpalDisk->MediaId;
+ Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Failure");
+ //
+ // Password entered.
+ // No current Owner, so set new Password, must be admin Password
+ //
+ if (OpalDisk->Owner == OpalOwnershipNobody) {
+ Ret = OpalSupportEnableOpalFeature (&Session, OpalDisk->Msid, OpalDisk->MsidLength,Password, PassLength, OpalDisk->OpalDevicePath);
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Success");
+ }
+
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // 1st Password entered
+ //
+ if (OpalDisk->Owner == OpalOwnershipUnknown && gHiiOldPasswordLength == 0) {
+
+ //
+ // Unknown ownership - prompt for old Password, then new
+ // old Password is not set yet - first time through
+ // assume authority provided is admin1, overwritten if user1 authority works below
+ //
+ if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
+ //
+ // First try to login as USER1 to Locking SP to see if we're simply updating its Password
+ //
+ Ret = OpalUtilVerifyPassword (&Session, Password, PassLength, OPAL_LOCKING_SP_USER1_AUTHORITY);
+ if (Ret == TcgResultSuccess) {
+ //
+ // User1 worked so authority 1 means user 1
+ //
+ CopyMem(gHiiOldPassword, Password, PassLength);
+ gHiiOldPasswordLength = PassLength;
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Else try admin1 below
+ //
+ Ret = OpalUtilVerifyPassword (&Session, Password, PassLength, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
+ if (Ret == TcgResultSuccess) {
+ CopyMem(gHiiOldPassword, Password, PassLength);
+ gHiiOldPasswordLength = PassLength;
+
+ return EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "start session with old PW failed - return EFI_NOT_READY - mistyped old PW\n"));
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), "Authentication Failure");
+
+ ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
+ gHiiOldPasswordLength = 0;
+
+ return EFI_NOT_READY;
+ }
+ }
+
+ //
+ // New Password entered
+ //
+ if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SET_USER_PWD) {
+ Ret = OpalSupportSetPassword(
+ &Session,
+ gHiiOldPassword,
+ gHiiOldPasswordLength,
+ Password,
+ PassLength,
+ OpalDisk->OpalDevicePath,
+ FALSE
+ );
+ } else {
+ Ret = OpalSupportSetPassword(
+ &Session,
+ gHiiOldPassword,
+ gHiiOldPasswordLength,
+ Password,
+ PassLength,
+ OpalDisk->OpalDevicePath,
+ TRUE
+ );
+ }
+
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint(Response, DEFAULT_RESPONSE_SIZE, "%a", "Set Password: Success");
+ }
+
+ //
+ // Reset old Password storage
+ //
+ ZeroMem(gHiiOldPassword, sizeof(gHiiOldPassword));
+ gHiiOldPasswordLength = 0;
+
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+ return Ret == TcgResultSuccess ? EFI_SUCCESS : EFI_NOT_READY;
+}
+
+/**
+ Secure Erases Opal Disk.
+
+ @param OpalDisk The disk need to erase data.
+ @param Password The input password.
+ @param PassLength The input password length.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiSecureErase(
+ OPAL_DISK *OpalDisk,
+ const VOID *Password,
+ UINT32 PassLength
+ )
+{
+ CHAR8 Response[DEFAULT_RESPONSE_SIZE];
+ BOOLEAN PasswordFailed;
+ TCG_RESULT Ret;
+ OPAL_SESSION AdminSpSession;
+
+ if (PassLength == 0) {
+ return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
+ }
+
+ ZeroMem(&AdminSpSession, sizeof(AdminSpSession));
+ AdminSpSession.Sscp = OpalDisk->Sscp;
+ AdminSpSession.MediaId = OpalDisk->MediaId;
+ AdminSpSession.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ Ret = OpalUtilSecureErase(&AdminSpSession, Password, PassLength, &PasswordFailed);
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Secure Erase: Success" );
+ } else {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Secure Erase: Failure" );
+ }
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+
+ //
+ // If Password failed, return invalid passowrd
+ //
+ if (PasswordFailed) {
+ DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Indicates Password was valid and is not changing to UEFI
+ // Response string will indicate action error
+ //
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Disables User for Opal Disk.
+
+ @param OpalDisk The disk need to the action.
+ @param Password The input password.
+ @param PassLength The input password length.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiDisableUser(
+ OPAL_DISK *OpalDisk,
+ VOID *Password,
+ UINT32 PassLength
+ )
+{
+ CHAR8 Response[ DEFAULT_RESPONSE_SIZE ];
+ BOOLEAN PasswordFailed;
+ TCG_RESULT Ret;
+ OPAL_SESSION Session;
+
+ if (PassLength == 0) {
+ return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
+ }
+
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = OpalDisk->Sscp;
+ Session.MediaId = OpalDisk->MediaId;
+ Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ Ret = OpalSupportDisableUser(&Session, Password, PassLength, &PasswordFailed, OpalDisk->OpalDevicePath);
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Disable User: Success" );
+ } else {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Disable User: Failure" );
+ }
+ HiiSetFormString (STRING_TOKEN(STR_ACTION_STATUS), Response);
+
+ //
+ // If Password failed, return invalid passowrd
+ //
+ if (PasswordFailed) {
+ DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Indicates Password was valid and is not changing to UEFI
+ // Response string will indicate action error
+ //
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Revert Opal Disk as Admin1.
+
+ @param OpalDisk The disk need to the action.
+ @param Password The input password.
+ @param PassLength The input password length.
+ @param KeepUserData Whether need to keey user data.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiRevert(
+ OPAL_DISK *OpalDisk,
+ VOID *Password,
+ UINT32 PassLength,
+ BOOLEAN KeepUserData
+ )
+{
+ CHAR8 Response[ DEFAULT_RESPONSE_SIZE ];
+ BOOLEAN PasswordFailed;
+ TCG_RESULT Ret;
+ OPAL_SESSION Session;
+
+ if (PassLength == 0) {
+ DEBUG ((DEBUG_INFO, "Returning error to indicate there is an existing Password\n"));
+ // return error to indicate there is an existing Password
+ return EFI_DEVICE_ERROR;
+ }
+
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = OpalDisk->Sscp;
+ Session.MediaId = OpalDisk->MediaId;
+ Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ Ret = OpalSupportRevert(
+ &Session,
+ KeepUserData,
+ Password,
+ PassLength,
+ OpalDisk->Msid,
+ OpalDisk->MsidLength,
+ &PasswordFailed,
+ OpalDisk->OpalDevicePath
+ );
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Revert: Success" );
+ } else {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Revert: Failure" );
+ }
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+
+ //
+ // If Password failed, return invalid passowrd
+ //
+ if (PasswordFailed) {
+ DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Indicates Password was valid and is not changing to UEFI
+ // Response string will indicate action error
+ //
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Unlocks Opal Disk.
+
+ @param OpalDisk The disk need to the action.
+ @param Password The input password.
+ @param PassLength The input password length.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiUnlock(
+ OPAL_DISK *OpalDisk,
+ VOID *Password,
+ UINT32 PassLength
+ )
+{
+ CHAR8 Response[DEFAULT_RESPONSE_SIZE];
+ TCG_RESULT Ret;
+ OPAL_SESSION Session;
+
+ if (PassLength == 0) {
+ DEBUG ((DEBUG_INFO, "Returning error to indicate there is an existing Password\n"));
+ return EFI_DEVICE_ERROR; // return error to indicate there is an existing Password
+ }
+
+ ZeroMem(&Session, sizeof(Session));
+ Session.Sscp = OpalDisk->Sscp;
+ Session.MediaId = OpalDisk->MediaId;
+ Session.OpalBaseComId = OpalDisk->OpalBaseComId;
+
+ Ret = OpalSupportUnlock(&Session, Password, PassLength, OpalDisk->OpalDevicePath);
+ if (Ret == TcgResultSuccess) {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Unlock: Success" );
+ } else {
+ AsciiSPrint( Response, DEFAULT_RESPONSE_SIZE, "%a", "Unlock: Failure" );
+ }
+
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), Response);
+
+ if (Ret == TcgResultSuccess) {
+ DEBUG ((DEBUG_INFO, "returning error to indicate Password was correct but is not changing\n"));
+ return EFI_DEVICE_ERROR;
+ } else {
+ DEBUG ((DEBUG_INFO, "returning EFI_NOT_READY to indicate Password was not correct\n"));
+ return EFI_NOT_READY;
+ }
+}
+
+/**
+ Use the input password to do the specified action.
+
+ @param Str The input password saved in.
+
+ @retval EFI_SUCCESS Do the required action success.
+ @retval Others Other error occur.
+
+**/
+EFI_STATUS
+HiiPasswordEntered(
+ EFI_STRING_ID Str
+ )
+{
+ OPAL_DISK* OpalDisk;
+ CHAR8 Password[MAX_PASSWORD_CHARACTER_LENGTH + 1];
+ CHAR16* UniStr;
+ UINT32 PassLength;
+ EFI_STATUS Status;
+
+ OpalHiiGetBrowserData();
+
+ OpalDisk = HiiGetOpalDiskCB(gHiiConfiguration.SelectedDiskIndex);
+ if (OpalDisk == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: disk %u not found\n", gHiiConfiguration.SelectedDiskIndex));
+ return EFI_NOT_FOUND;
+ }
+
+ if (Str == 0) {
+ DEBUG ((DEBUG_INFO, "ERROR: str=NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem(Password, sizeof(Password));
+
+ UniStr = HiiGetString(gHiiPackageListHandle, Str, NULL);
+ if (UniStr == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ PassLength = (UINT32) StrLen (UniStr);
+ if (PassLength >= sizeof(Password)) {
+ HiiSetFormString(STRING_TOKEN(STR_ACTION_STATUS), "Password too long");
+ gBS->FreePool(UniStr);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ UnicodeStrToAsciiStr(UniStr, Password);
+ gBS->FreePool(UniStr);
+
+ DEBUG ((DEBUG_INFO, "Password: '%s'\n", Password));
+
+ if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_UNLOCK) {
+ Status = HiiUnlock (OpalDisk, Password, PassLength);
+ } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_SECURE_ERASE) {
+ Status = HiiSecureErase (OpalDisk, Password, PassLength);
+ } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_DISABLE_USER) {
+ Status = HiiDisableUser (OpalDisk, Password, PassLength);
+ } else if (gHiiConfiguration.SelectedAction == HII_KEY_ID_GOTO_REVERT) {
+ DEBUG ((DEBUG_INFO, "gHiiConfiguration.KeepUserData %u\n", gHiiConfiguration.KeepUserData));
+ Status = HiiRevert(OpalDisk, Password, PassLength, gHiiConfiguration.KeepUserData);
+ } else {
+ Status = HiiSetPassword(OpalDisk, Password, PassLength);
+ }
+
+ OpalHiiSetBrowserData ();
+
+ return Status;
+}
+
+/**
+ Update block sid info.
+
+ @param Enable Enable/disable BlockSid.
+
+ @retval EFI_SUCCESS Do the required action success.
+ @retval Others Other error occur.
+
+**/
+EFI_STATUS
+HiiSetBlockSid (
+ BOOLEAN Enable
+ )
+{
+ EFI_STATUS Status;
+ OPAL_EXTRA_INFO_VAR OpalExtraInfo;
+ UINTN DataSize;
+
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "HiiSetBlockSid(enable: %x)\n", Enable));
+
+ OpalExtraInfo.EnableBlockSid = Enable;
+ DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
+ Status = gRT->SetVariable (
+ OPAL_EXTRA_INFO_VAR_NAME,
+ &gOpalExtraInfoVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DataSize,
+ &OpalExtraInfo
+ );
+ DEBUG ((DEBUG_INFO, "SetVariable, Status: %r\n", Status));
+
+ 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
+ )
+{
+ DEBUG ((DEBUG_INFO, "RouteConfig( )\n"));
+ if (Configuration == NULL || Progress == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ 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;
+
+ DEBUG ((DEBUG_INFO, "ExtractConfig( )\n"));
+
+ //
+ // Check for valid parameters
+ //
+ if (Progress == NULL || Results == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Convert Buffer Data to by helper function BlockToConfig( )
+ //
+ Status = gHiiConfigRouting->BlockToConfig(
+ gHiiConfigRouting,
+ Request,
+ (UINT8*)&gHiiConfiguration,
+ sizeof(OPAL_HII_CONFIGURATION),
+ Results,
+ Progress
+ );
+
+ return (Status);
+}
+
+
+/**
+
+ Pass the current system state to the bios via the hii_G_Configuration.
+
+**/
+VOID
+OpalHiiSetBrowserData (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "OpalHiiSetBrowserData( )\n"));
+ HiiSetBrowserData(
+ &gHiiSetupVariableGuid,
+ (CHAR16*)L"OpalHiiConfig",
+ sizeof(gHiiConfiguration),
+ (UINT8*)&gHiiConfiguration,
+ NULL
+ );
+}
+
+
+/**
+
+ Populate the hii_g_Configuraton with the browser Data.
+
+**/
+VOID
+OpalHiiGetBrowserData (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "OpalHiiGetBrowserData( )\n"));
+ 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 nned 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;
+
+ DEBUG ((DEBUG_INFO, "HiiSetFormString( )\n"));
+
+ //
+ // 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
+ //
+ AsciiStrToUnicodeStr( SrcAsciiStr, UniStr );
+
+ //
+ // 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_SUCESS 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;
+
+ 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_LENGHT, &Dev->OpalDisk.MsidLength);
+ if (TcgResult != TcgResultSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return OpalDiskUpdateStatus (&Dev->OpalDisk);
+}
+
+/**
+ Update the device info.
+
+ @param OpalDisk The Opal device.
+
+ @retval EFI_SUCESS 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.
+
+**/
+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;
+ }
+
+ if (OpalDisk->MsidLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Base on the Msid info to get the ownership, so Msid info must get first.
+ //
+ OpalDisk->Owner = OpalUtilDetermineOwnership(&Session, OpalDisk->Msid, OpalDisk->MsidLength);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
new file mode 100644
index 0000000000..c03f082780
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHii.h
@@ -0,0 +1,146 @@
+/** @file
+ Public Header file of HII library used by Opal UEFI Driver.
+ Defines required callbacks of Opal HII library.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_HII_H_
+#define _OPAL_HII_H_
+
+#include
+#include
+
+#define DEFAULT_RESPONSE_SIZE 200
+
+/**
+ Get the driver image handle.
+
+ @retval the driver image handle.
+
+**/
+EFI_HANDLE
+HiiGetDriverImageHandleCB(
+ VOID
+ );
+
+/**
+ 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
+ );
+
+/**
+ Check whether enable feature or not.
+
+ @retval Return the disk number.
+
+**/
+UINT8
+HiiGetNumConfigRequiredOpalDisksCB(
+ VOID
+ );
+
+/**
+ Returns the driver name.
+
+ @retval Returns the driver name.
+
+**/
+CHAR16*
+HiiGetDriverNameCB(
+ VOID
+ );
+
+/**
+ Returns the opaque pointer to a physical disk context.
+
+ @param DiskIndex Input the disk index.
+
+ @retval The device pointer.
+
+**/
+OPAL_DISK*
+HiiGetOpalDiskCB(
+ UINT8 DiskIndex
+ );
+
+/**
+ Returns the disk name.
+
+ @param DiskIndex Input the disk index.
+
+ @retval Returns the disk name.
+
+**/
+CHAR8*
+HiiDiskGetNameCB(
+ UINT8 DiskIndex
+ );
+
+/**
+ Set a string Value in a form.
+
+ @param DestStringId The stringid which need to update.
+ @param SrcAsciiStr The string nned to update.
+
+ @retval EFI_SUCCESS Do the required action success.
+ @retval Others Other error occur.
+
+**/
+EFI_STATUS
+HiiSetFormString(
+ EFI_STRING_ID DestStringId,
+ CHAR8 *SrcAsciiStr
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Initialize the Opal disk base on the hardware info get from device.
+
+ @param Dev The Opal device.
+
+ @retval EFI_SUCESS Initialize the device success.
+ @retval EFI_DEVICE_ERROR Get info from device failed.
+
+**/
+EFI_STATUS
+OpalDiskInitialize (
+ IN OPAL_DRIVER_DEVICE *Dev
+ );
+
+#endif // _HII_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c
new file mode 100644
index 0000000000..6f2eaeb4c3
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiCallbacks.c
@@ -0,0 +1,221 @@
+/** @file
+ Callbacks required by the HII of the Opal UEFI Driver to help display
+ Opal device information and to send password to SMM handler.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "OpalHii.h"
+#include "OpalDriver.h"
+#include "OpalDriverPrivate.h"
+
+/**
+ Get Opal var name.
+ The return Value must be freed by caller if not NULL
+
+ @param OpalDisk The disk.
+ @param Prefix The prefix string.
+
+ @retval The var name string.
+
+**/
+CHAR16*
+OpalDriverGetOpalVarName(
+ OPAL_DISK *OpalDisk,
+ const CHAR16 *Prefix
+ )
+{
+ OPAL_DRIVER_DEVICE* Dev;
+ UINTN PrefixLen;
+ UINTN NameLen;
+ UINTN VarNameLen;
+ CHAR16* VarName;
+
+ Dev = DRIVER_DEVICE_FROM_OPALDISK(OpalDisk);
+ if (Dev == NULL) {
+ return NULL;
+ }
+
+ PrefixLen = StrLen(Prefix);
+
+ NameLen = 0;
+ if (Dev->Name16 != NULL) {
+ NameLen = StrLen(Dev->Name16);
+ }
+
+ VarNameLen = PrefixLen + NameLen;
+
+ VarName = (CHAR16*)AllocateZeroPool((VarNameLen + 1) * sizeof(CHAR16));
+ if (VarName == NULL) {
+ return NULL;
+ }
+
+ CopyMem(VarName, Prefix, PrefixLen * sizeof(CHAR16));
+ if (Dev->Name16 != NULL) {
+ CopyMem(VarName + PrefixLen, Dev->Name16, NameLen * sizeof(CHAR16));
+ }
+ VarName[VarNameLen] = 0;
+
+ return VarName;
+}
+
+/**
+ Get the driver image handle.
+
+ @retval the driver image handle.
+
+**/
+EFI_HANDLE
+HiiGetDriverImageHandleCB(
+ VOID
+ )
+{
+ return gImageHandle;
+}
+
+/**
+ Check whether enable feature or not.
+
+ @retval Return the disk number.
+
+**/
+UINT8
+HiiGetNumConfigRequiredOpalDisksCB(
+ VOID
+ )
+{
+ UINT8 NumDisks;
+ UINT8 NumLockedOpalDisks;
+ OPAL_DISK *OpalDisk;
+ UINT8 Index;
+
+ NumLockedOpalDisks = 0;
+
+ NumDisks = GetDeviceCount();
+
+ for (Index = 0; Index < NumDisks; Index++) {
+ OpalDisk = HiiGetOpalDiskCB(Index);
+
+ if (OpalDisk != NULL) {
+ if (!OpalFeatureEnabled (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
+ DEBUG ((DEBUG_INFO, "Ignoring disk %u because feature is disabled or health has already been inspected\n", Index));
+ } else if (OpalDeviceLocked (&OpalDisk->SupportedAttributes, &OpalDisk->LockingFeature)) {
+ NumLockedOpalDisks++;
+ }
+ }
+ }
+
+ return NumLockedOpalDisks;
+}
+
+
+
+/**
+ Returns the opaque pointer to a physical disk context.
+
+ @param DiskIndex Input the disk index.
+
+ @retval The device pointer.
+
+**/
+VOID *
+HiiGetDiskContextCB(
+ UINT8 DiskIndex
+ )
+{
+ OPAL_DRIVER_DEVICE* Dev;
+ UINT8 CurrentDisk;
+
+ Dev = OpalDriverGetDeviceList();
+ CurrentDisk = 0;
+
+ if (DiskIndex >= GetDeviceCount()) {
+ return NULL;
+ }
+
+ while (Dev != NULL) {
+ if (CurrentDisk == DiskIndex) {
+ return Dev;
+ } else {
+ Dev = Dev->Next;
+ CurrentDisk++;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Returns the opaque pointer to a physical disk context.
+
+ @param DiskIndex Input the disk index.
+
+ @retval The device pointer.
+
+**/
+OPAL_DISK*
+HiiGetOpalDiskCB(
+ UINT8 DiskIndex
+ )
+{
+ VOID *Ctx;
+ OPAL_DRIVER_DEVICE *Tmp;
+
+ Ctx = HiiGetDiskContextCB (DiskIndex);
+
+ if (Ctx == NULL) {
+ return NULL;
+ }
+
+ Tmp = (OPAL_DRIVER_DEVICE*) Ctx;
+
+ return &Tmp->OpalDisk;
+}
+
+/**
+ Returns the disk name.
+
+ @param DiskIndex Input the disk index.
+
+ @retval Returns the disk name.
+
+**/
+CHAR8*
+HiiDiskGetNameCB(
+ UINT8 DiskIndex
+ )
+{
+ OPAL_DRIVER_DEVICE* Ctx;
+
+ Ctx = (OPAL_DRIVER_DEVICE*) HiiGetDiskContextCB (DiskIndex);
+
+ if (Ctx != NULL) {
+ if (Ctx->NameZ == NULL) {
+ OpalDriverGetDriverDeviceName (Ctx);
+ }
+ return Ctx->NameZ;
+ }
+ return NULL;
+}
+
+/**
+ Returns the driver name.
+
+ @retval Returns the driver name.
+
+**/
+CHAR16*
+HiiGetDriverNameCB(
+ VOID
+ )
+{
+ return (CHAR16*)EFI_DRIVER_NAME_UNICODE;
+}
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
new file mode 100644
index 0000000000..754dbf776b
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormStrings.uni
@@ -0,0 +1,91 @@
+// /** @file
+//
+// String definitions for Setup formset.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+/=#
+///////////////////////////////// GENERIC DEFINITIONS /////////////////////////////////
+#langdef en-US "English"
+#string STR_NULL #language en-US " "
+
+///////////////////////////////// FORM SET /////////////////////////////////
+#string STR_FORM_SET_HELP #language en-US "Manage Opal disks"
+
+///////////////////////////////// MULTIPLE FORMS /////////////////////////////////
+#string STR_OPAL #language en-US "Opal"
+#string STR_MAIN_OPAL_VERSION #language en-US "Version 00.0.0.0000"
+
+///////////////////////////////// MAIN MENU FORM /////////////////////////////////
+#string STR_MAIN_PHY_DISKS_LBL #language en-US "Physical Disks:"
+#string STR_MAIN_LOCKED_DISKS_LBL #language en-US "Locked Disks:"
+
+#string STR_MAIN_GOTO_DISK_INFO_0 #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_1 #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_2 #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_3 #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_4 #language en-US " "
+#string STR_MAIN_GOTO_DISK_INFO_5 #language en-US " "
+
+#string STR_MAIN_GOTO_DISK_INFO_HELP #language en-US "Select to see Opal disk actions"
+#string STR_MAIN_GOTO_DISK_HEALTH_HELP #language en-US "Select disk to unlock"
+
+#string STR_MAIN_NO_DISKS_PRESENT_LBL #language en-US "No disks connected to system"
+
+///////////////////////////////// DISK INFO MENU FORM /////////////////////////////////
+#string STR_DISK_INFO_SELECTED_DISK_NAME #language en-US " "
+
+#string STR_DISK_INFO_LOCK #language en-US "Lock"
+#string STR_DISK_INFO_UNLOCK #language en-US "Unlock"
+#string STR_DISK_INFO_SET_ADMIN_PSWD #language en-US "Update Drive Admin Password"
+#string STR_DISK_INFO_SET_USER_PSWD #language en-US "Set Drive User Password"
+#string STR_DISK_INFO_SECURE_ERASE #language en-US "Secure Erase User Data"
+#string STR_DISK_INFO_PSID_REVERT #language en-US "PSID Revert to factory default"
+#string STR_DISK_INFO_REVERT #language en-US "Admin Revert to factory default and Disable"
+#string STR_DISK_INFO_DISABLE_USER #language en-US "Disable User"
+#string STR_DISK_INFO_ENABLE_FEATURE #language en-US "Enable Feature"
+#string STR_DISK_INFO_ENABLE_BLOCKSID #language en-US "Enable BlockSID"
+#string STR_ENABLED #language en-US "Enabled"
+#string STR_DISABLED #language en-US "Disabled"
+
+#string STR_DISK_INFO_GOTO_LOCK_HELP #language en-US "Lock the disk"
+#string STR_DISK_INFO_GOTO_UNLOCK_HELP #language en-US "Unlock the disk"
+#string STR_DISK_INFO_GOTO_SET_ADMIN_PSWD_HELP #language en-US "Set password for the administrator"
+#string STR_DISK_INFO_GOTO_SET_USER_PSWD_HELP #language en-US "Set password for User 1"
+#string STR_DISK_INFO_GOTO_SECURE_ERASE_HELP #language en-US "Securely erase the disk"
+#string STR_DISK_INFO_GOTO_PSID_REVERT_HELP #language en-US "Revert the disk to factory defaults"
+#string STR_DISK_INFO_GOTO_DISABLE_USER_HELP #language en-US "Disable User"
+#string STR_DISK_INFO_GOTO_ENABLE_FEATURE_HELP #language en-US "Enable Feature"
+#string STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP #language en-US "Enable to send BlockSID command"
+
+///////////////////////////////// DISK ACTION MENU FORM /////////////////////////////////
+#string STR_DISK_ACTION_LBL #language en-US " "
+
+#string STR_PASSWORD_PROMPT #language en-US "Enter Password"
+#string STR_PASSWORD_HELP #language en-US "Password must be between 6 and 20 characters"
+
+#string STR_REVERT_PROMPT #language en-US "Enter PSID"
+#string STR_REVERT_HELP #language en-US "PSID is a 32 character case sensitive value"
+#string STR_ACTION_STATUS #language en-US " "
+
+#string STR_PASSWORD_SUBMIT #language en-US "Submit Password Changes"
+#string STR_PASSWORD_SUBMIT_HELP #language en-US "Submits Password Changes (new and update) after passwords have been entered"
+
+#string STR_GOTO_HOME #language en-US "Main Menu"
+#string STR_GOTO_HOME_HELP #language en-US "Return to the main menu"
+
+#string STR_KEEP_USER_DATA_PROMPT #language en-US "Keep User Data"
+#string STR_KEEP_USER_DATA_HELP #language en-US "Checkmark to keep user data, otherwise data will be lost"
+
+#string STR_OK #language en-US "OK"
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h
new file mode 100644
index 0000000000..50ad4eebcf
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiFormValues.h
@@ -0,0 +1,120 @@
+/** @file
+ Defines Opal HII form ids, structures and values.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _OPAL_HII_FORM_VALUES_H_
+#define _OPAL_HII_FORM_VALUES_H_
+
+// Maximum Opal password Length
+#define MAX_PASSWORD_CHARACTER_LENGTH 0x14
+
+// PSID Length
+#define PSID_CHARACTER_LENGTH 0x20
+
+// ID's for various forms that will be used by HII
+#define FORMID_VALUE_MAIN_MENU 0x01
+#define FORMID_VALUE_DISK_INFO_FORM_MAIN 0x02
+#define FORMID_VALUE_DISK_ACTION_FORM 0x03
+
+// Structure defining the OPAL_HII_CONFIGURATION
+#pragma pack(1)
+typedef struct {
+ UINT8 NumDisks;
+ UINT8 SelectedDiskIndex;
+ UINT8 SelectedAction;
+ UINT16 SelectedDiskAvailableActions;
+ UINT16 SupportedDisks;
+ UINT8 KeepUserData;
+ UINT16 AvailableFields;
+ UINT16 Password[MAX_PASSWORD_CHARACTER_LENGTH];
+ UINT16 Psid[PSID_CHARACTER_LENGTH];
+ UINT8 EnableBlockSid;
+} OPAL_HII_CONFIGURATION;
+#pragma pack()
+
+/* Action Flags */
+#define HII_ACTION_NONE 0x0000
+#define HII_ACTION_LOCK 0x0001
+#define HII_ACTION_UNLOCK 0x0002
+#define HII_ACTION_SET_ADMIN_PWD 0x0004
+#define HII_ACTION_SET_USER_PWD 0x0008
+#define HII_ACTION_SECURE_ERASE 0x0010
+#define HII_ACTION_PSID_REVERT 0x0020
+#define HII_ACTION_DISABLE_USER 0x0040
+#define HII_ACTION_REVERT 0x0080
+#define HII_ACTION_DISABLE_FEATURE 0x0100
+#define HII_ACTION_ENABLE_FEATURE 0x0200
+#define HII_ACTION_ENABLE_BLOCKSID 0x0400
+
+/* Flags for diskActionAvailableFields */
+#define HII_FIELD_PASSWORD 0x0001
+#define HII_FIELD_PSID 0x0002
+#define HII_FIELD_KEEP_USER_DATA 0x0004
+#define HII_FIELD_KEEP_USER_DATA_FORCED 0x0008
+
+/* Number of bits allocated for each part of a unique key for an HII_ITEM
+ * all bits together must be <= 16 (EFI_QUESTION_ID is UINT16)
+ * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ * | |-----------------------| |---------------------------|
+ * FLG INDEX ID
+ */
+#define HII_KEY_ID_BITS 8
+#define HII_KEY_INDEX_BITS 7
+#define HII_KEY_FLAG_BITS 1
+
+#define HII_KEY_FLAG 0x8000 // bit 15 (zero based)
+
+/***********/
+/* Key IDs */
+/***********/
+
+#define HII_KEY_ID_GOTO_MAIN_MENU 0
+#define HII_KEY_ID_GOTO_DISK_INFO 1
+#define HII_KEY_ID_GOTO_LOCK 2
+#define HII_KEY_ID_GOTO_UNLOCK 3
+#define HII_KEY_ID_GOTO_SET_ADMIN_PWD 4
+#define HII_KEY_ID_GOTO_SET_USER_PWD 5
+#define HII_KEY_ID_GOTO_SECURE_ERASE 6
+#define HII_KEY_ID_GOTO_PSID_REVERT 7
+#define HII_KEY_ID_GOTO_REVERT 8
+#define HII_KEY_ID_GOTO_DISABLE_USER 9
+#define HII_KEY_ID_GOTO_ENABLE_FEATURE 0xA //10
+#define HII_KEY_ID_GOTO_CONFIRM_TO_MAIN_MENU 0xB //11
+#define HII_KEY_ID_ENTER_PASSWORD 0xC //12
+#define HII_KEY_ID_ENTER_PSID 0xD //13
+#define HII_KEY_ID_VAR_SUPPORTED_DISKS 0xE //14
+#define HII_KEY_ID_VAR_SELECTED_DISK_AVAILABLE_ACTIONS 0xF //15
+
+#define HII_KEY_ID_BLOCKSID 0x17 //23
+#define HII_KEY_ID_MAX 0x17 //23 // !!Update each time a new ID is added!!
+
+#define HII_KEY_WITH_INDEX(id, index) \
+ ( \
+ HII_KEY_FLAG | \
+ (id) | \
+ ((index) << HII_KEY_ID_BITS) \
+ )
+
+#define HII_KEY(id) HII_KEY_WITH_INDEX(id, 0)
+
+#define PACKAGE_LIST_GUID { 0xf0308176, 0x9058, 0x4153, { 0x93, 0x3d, 0xda, 0x2f, 0xdc, 0xc8, 0x3e, 0x44 } }
+
+/* {410483CF-F4F9-4ece-848A-1958FD31CEB7} */
+#define SETUP_FORMSET_GUID { 0x410483cf, 0xf4f9, 0x4ece, { 0x84, 0x8a, 0x19, 0x58, 0xfd, 0x31, 0xce, 0xb7 } }
+
+// {BBF1ACD2-28D8-44ea-A291-58A237FEDF1A}
+#define SETUP_VARIABLE_GUID { 0xbbf1acd2, 0x28d8, 0x44ea, { 0xa2, 0x91, 0x58, 0xa2, 0x37, 0xfe, 0xdf, 0x1a } }
+
+#endif //_HII_FORM_VALUES_H_
+
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
new file mode 100644
index 0000000000..366cd3813e
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalHiiPrivate.h
@@ -0,0 +1,266 @@
+/** @file
+ Private functions and sturctures used by the Opal UEFI Driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _OPAL_HII_PRIVATE_H_
+#define _OPAL_HII_PRIVATE_H_
+
+
+
+#include
+#include
+
+#include "OpalHii.h"
+#include "OpalHiiFormValues.h"
+
+
+#define OPAL_PASSWORD_CONFIG_GUID \
+ { \
+ 0x0d510a4f, 0xa81b, 0x473f, { 0x87, 0x07, 0xb7, 0xfd, 0xfb, 0xc0, 0x45, 0xba } \
+ }
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 Id: HII_KEY_ID_BITS;
+ UINT16 Index: HII_KEY_INDEX_BITS;
+ UINT16 Flag: HII_KEY_FLAG_BITS;
+} KEY_BITS;
+
+typedef union {
+ UINT16 Raw;
+ KEY_BITS KeyBits;
+} HII_KEY;
+
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+/**
+* Opal PSID Authority utilized for PSID revert
+*
+* The type indicates the structure of the PSID authority
+*/
+typedef struct {
+ UINT8 Psid[32];
+} TCG_PSID;
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+
+ Pass the current system state to the bios via the hii_G_Configuration.
+
+**/
+VOID
+OpalHiiSetBrowserData (
+ VOID
+ );
+
+/**
+
+ Populate the hii_g_Configuraton with the browser Data.
+
+**/
+VOID
+OpalHiiGetBrowserData (
+ VOID
+ );
+
+/**
+ Draws the disk info form.
+
+ @retval EFI_SUCCESS Draw the disk info success.
+
+**/
+EFI_STATUS
+HiiPopulateDiskInfoForm(
+ VOID
+ );
+
+/**
+ 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
+ );
+
+/**
+ Use the input password to do the specified action.
+
+ @param Str The input password saved in.
+
+ @retval EFI_SUCCESS Do the required action success.
+ @retval Others Other error occur.
+
+**/
+EFI_STATUS
+HiiPasswordEntered(
+ EFI_STRING_ID Str
+ );
+
+/**
+ Update block sid info.
+
+ @param Enable Enable/disable BlockSid.
+
+ @retval EFI_SUCCESS Do the required action success.
+ @retval Others Other error occur.
+
+**/
+EFI_STATUS
+HiiSetBlockSid (
+ BOOLEAN Enable
+ );
+
+/**
+ Reverts the Opal disk to factory default.
+
+ @retval EFI_SUCCESS Do the required action success.
+
+**/
+EFI_STATUS
+HiiPsidRevert(
+ VOID
+ );
+
+/**
+ Get disk name string id.
+
+ @param DiskIndex The input disk index info.
+
+ @retval The disk name string id.
+
+**/
+EFI_STRING_ID
+GetDiskNameStringId(
+ UINT8 DiskIndex
+ );
+
+/**
+ Update the device info.
+
+ @param OpalDisk The Opal device.
+
+ @retval EFI_SUCESS 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.
+
+**/
+EFI_STATUS
+OpalDiskUpdateStatus (
+ OPAL_DISK *OpalDisk
+ );
+
+#pragma pack()
+
+#endif // _HII_P_H_
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
new file mode 100644
index 0000000000..7da581b887
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordDxe.inf
@@ -0,0 +1,84 @@
+## @file
+# This is a OpalPasswordDxe driver.
+#
+# This module is used to Management the Opal feature
+# for Opal supported devices.
+#
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+[Defines]
+ INF_VERSION = 0x00010007
+ BASE_NAME = OpalPasswordDxe
+ FILE_GUID = E3E4048D-6C0C-43E4-AE1C-FFB579D8EF41
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = EfiDriverEntryPoint
+ UNLOAD_IMAGE = OpalEfiDriverUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ OpalDriver.h
+ OpalHii.c
+ OpalHiiCallbacks.c
+ OpalDriver.c
+ OpalDriverPrivate.h
+ OpalHii.h
+ OpalHiiPrivate.h
+ OpalHiiFormValues.h
+ OpalPasswordForm.vfr
+ OpalHiiFormStrings.uni
+ ComponentName.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiHiiServicesLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ HiiLib
+ PrintLib
+ DevicePathLib
+ OpalPasswordSupportLib
+ UefiLib
+ TcgStorageOpalLib
+
+[Protocols]
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+ gEfiStorageSecurityCommandProtocolGuid ## CONSUMES
+ gEfiComponentNameProtocolGuid ## PRODUCES
+ gEfiComponentName2ProtocolGuid ## PRODUCES
+ gEfiBlockIoProtocolGuid ## CONSUMES
+ gEfiSmmCommunicationProtocolGuid ## PRODUCES
+ gEfiPciIoProtocolGuid ## CONSUMES
+ gEfiDevicePathToTextProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+ gOpalExtraInfoVariableGuid ## PRODUCES ## GUID
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /Od /GL-
+
+[Depex]
+ gEfiSmmCommunicationProtocolGuid
diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
new file mode 100644
index 0000000000..9c35ec76ab
--- /dev/null
+++ b/SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalPasswordForm.vfr
@@ -0,0 +1,327 @@
+/** @file
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "OpalHiiFormValues.h"
+
+
+#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
+ { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
+
+formset
+ guid = SETUP_FORMSET_GUID,
+ title = STRING_TOKEN(STR_OPAL),
+ help = STRING_TOKEN(STR_FORM_SET_HELP),
+ classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
+
+ // Define a Buffer Storage (EFI_IFR_VARSTORE) that will be filled
+ // out initially through extractConfig call
+ varstore OPAL_HII_CONFIGURATION, // This is the Data structure type
+ name = OpalHiiConfig, // Define referenced name in vfr
+ guid = SETUP_VARIABLE_GUID; // GUID of this Buffer storage
+
+form formid = FORMID_VALUE_MAIN_MENU,
+ title = STRING_TOKEN(STR_OPAL);
+
+ //CONFIG_VARIABLE(HII_KEY(HII_KEY_ID_VAR_SUPPORTED_DISKS), SupportedDisks, 0x0, 0xFFFF);
+ suppressif TRUE;
+ numeric
+ name = SupportedDisks,
+ varid = OpalHiiConfig.SupportedDisks,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ flags = INTERACTIVE,
+ key = 0x800E, //32782,
+ minimum = 0x0,
+ maximum = 0xFFFF,
+ endnumeric;
+ endif;
+
+ subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_MAIN_PHY_DISKS_LBL);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ //DISK( 0 );
+ suppressif ( questionref(SupportedDisks) & ( 0x1 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_0 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8001; //32769
+ endif;
+
+ //DISK( 1 );
+ suppressif ( questionref(SupportedDisks) & ( 0x2 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_1 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8101; //33025
+ endif;
+
+ //DISK( 2 );
+ suppressif ( questionref(SupportedDisks) & ( 0x4 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_2 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8201; //33281
+ endif;
+
+ //DISK( 3 );
+ suppressif ( questionref(SupportedDisks) & ( 0x8 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_3 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8301; // 33537
+ endif;
+
+ //DISK( 4 );
+ suppressif ( questionref(SupportedDisks) & ( 0x10 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_4 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8401; // 33793
+ endif;
+
+ //DISK( 5 );
+ suppressif ( questionref(SupportedDisks) & ( 0x20 ) ) == 0;
+ goto FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ prompt = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_5 ),
+ help = STRING_TOKEN(STR_MAIN_GOTO_DISK_INFO_HELP),
+ flags = INTERACTIVE, \
+ key = 0x8501; // 34049
+ endif;
+
+ //No disks on system
+ suppressif ideqval OpalHiiConfig.NumDisks > 0;
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_MAIN_NO_DISKS_PRESENT_LBL);
+ endif;
+
+endform; // MAIN MENU FORM
+
+//
+///////////////// DISK INFO FORM /////////////////
+//
+form formid = FORMID_VALUE_DISK_INFO_FORM_MAIN,
+ title = STRING_TOKEN(STR_OPAL);
+
+ suppressif TRUE;
+ numeric
+ name = SelectedDiskAvailableActions,
+ varid = OpalHiiConfig.SelectedDiskAvailableActions,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ flags = INTERACTIVE,
+ key = 0x800F, // 32783
+ minimum = 0x0,
+ maximum = 0xFFFF,
+ endnumeric;
+ endif;
+
+ subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_LOCK ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_LOCK),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_LOCK_HELP),
+ flags = INTERACTIVE,
+ key = 0x8002; // 32770
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_UNLOCK ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_UNLOCK),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_UNLOCK_HELP),
+ flags = INTERACTIVE,
+ key = 0x8003; //32771;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_ADMIN_PWD ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_SET_ADMIN_PSWD),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_SET_ADMIN_PSWD_HELP),
+ flags = INTERACTIVE,
+ key = 0x8004; //32772;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SET_USER_PWD ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_SET_USER_PSWD),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_SET_USER_PSWD_HELP),
+ flags = INTERACTIVE,
+ key = 0x8005; //32773;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_SECURE_ERASE ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_SECURE_ERASE),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_SECURE_ERASE_HELP),
+ flags = INTERACTIVE,
+ key = 0x8006; //32774;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_REVERT ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_REVERT),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_PSID_REVERT_HELP),
+ flags = INTERACTIVE,
+ key = 0x8008; //32776;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_PSID_REVERT ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_PSID_REVERT),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_PSID_REVERT_HELP),
+ flags = INTERACTIVE,
+ key = 0x8007; //32775;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_DISABLE_USER ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_DISABLE_USER),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_DISABLE_USER_HELP),
+ flags = INTERACTIVE,
+ key = 0x8009; //32777;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_ENABLE_FEATURE ) == 0;
+ goto FORMID_VALUE_DISK_ACTION_FORM,
+ prompt = STRING_TOKEN(STR_DISK_INFO_ENABLE_FEATURE),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_ENABLE_FEATURE_HELP),
+ flags = INTERACTIVE,
+ key = 0x800A; //32778;
+ endif;
+
+ suppressif ( questionref(SelectedDiskAvailableActions) & HII_ACTION_ENABLE_BLOCKSID ) == 0;
+ oneof varid = OpalHiiConfig.EnableBlockSid,
+ questionid = 0x8017, // 32791,
+ prompt = STRING_TOKEN(STR_DISK_INFO_ENABLE_BLOCKSID),
+ help = STRING_TOKEN(STR_DISK_INFO_GOTO_ENABLE_BLOCKSID_HELP),
+ flags = INTERACTIVE,
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;
+ endoneof;
+ endif;
+
+endform; // DISK INFO FORM
+
+//
+///////////////// DISK ACTION FORM /////////////////
+//
+form formid = FORMID_VALUE_DISK_ACTION_FORM,
+ title = STRING_TOKEN(STR_OPAL);
+
+ suppressif TRUE;
+ numeric
+ name = AvailableFields,
+ varid = OpalHiiConfig.AvailableFields,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ flags = INTERACTIVE,
+ key = 0x8012, //32786,
+ minimum = 0x0,
+ maximum = 0xFFFF,
+ endnumeric;
+ endif;
+
+ subtitle text = STRING_TOKEN(STR_MAIN_OPAL_VERSION);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_DISK_INFO_SELECTED_DISK_NAME);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_DISK_ACTION_LBL);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ suppressif (questionref(AvailableFields) & HII_FIELD_KEEP_USER_DATA) == 0;
+ grayoutif (questionref(AvailableFields) & HII_FIELD_KEEP_USER_DATA_FORCED) != 0;
+ checkbox
+ name = MyCheckbox,
+ varid = OpalHiiConfig.KeepUserData,
+ prompt = STRING_TOKEN(STR_KEEP_USER_DATA_PROMPT),
+ help = STRING_TOKEN(STR_KEEP_USER_DATA_HELP),
+ key = 0x8011, //32785,
+ endcheckbox;
+
+ //EMPTY_LINE;
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_NULL);
+ endif;
+ endif;
+
+ suppressif (questionref(AvailableFields) & HII_FIELD_PASSWORD) == 0;
+ password
+ varid = OpalHiiConfig.Password,
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ flags = INTERACTIVE,
+ key = 0x800C, //32780,
+ minsize = 6,
+ maxsize = 20,
+ endpassword;
+ endif;
+
+ suppressif (questionref(AvailableFields) & HII_FIELD_PSID) == 0;
+ string
+ varid = OpalHiiConfig.Psid,
+ prompt = STRING_TOKEN(STR_REVERT_PROMPT),
+ help = STRING_TOKEN(STR_REVERT_HELP),
+ flags = INTERACTIVE,
+ key = 0x800D, //32781,
+ minsize = PSID_CHARACTER_LENGTH,
+ maxsize = PSID_CHARACTER_LENGTH,
+ endstring;
+ endif;
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ text
+ help = STRING_TOKEN(STR_NULL),
+ text = STRING_TOKEN(STR_ACTION_STATUS);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ goto FORMID_VALUE_MAIN_MENU,
+ prompt = STRING_TOKEN(STR_GOTO_HOME),
+ help = STRING_TOKEN(STR_GOTO_HOME_HELP),
+ flags = INTERACTIVE,
+ key = 0x8000; //32768;
+
+endform; // DISK ACTION FORM
+
+endformset;