REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1959 Replaces usage of the linked list iteration macros defined in HddPasswordDxe.h with the common definition in BaseLib.h. Cc: Chao Zhang <chao.b.zhang@intel.com> Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Sean Brogan <sean.brogan@microsoft.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Bret Barkelew <bret.barkelew@microsoft.com>
		
			
				
	
	
		
			2825 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2825 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  HDD password driver which is used to support HDD security feature.
 | 
						|
 | 
						|
  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) Microsoft Corporation.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "HddPasswordDxe.h"
 | 
						|
 | 
						|
EFI_GUID   mHddPasswordVendorGuid          = HDD_PASSWORD_CONFIG_GUID;
 | 
						|
CHAR16     mHddPasswordVendorStorageName[] = L"HDD_PASSWORD_CONFIG";
 | 
						|
LIST_ENTRY mHddPasswordConfigFormList;
 | 
						|
UINT32     mNumberOfHddDevices = 0;
 | 
						|
 | 
						|
EFI_GUID mHddPasswordDeviceInfoGuid = HDD_PASSWORD_DEVICE_INFO_GUID;
 | 
						|
BOOLEAN                         mHddPasswordEndOfDxe = FALSE;
 | 
						|
HDD_PASSWORD_REQUEST_VARIABLE   *mHddPasswordRequestVariable = NULL;
 | 
						|
UINTN                           mHddPasswordRequestVariableSize = 0;
 | 
						|
 | 
						|
HII_VENDOR_DEVICE_PATH          mHddPasswordHiiVendorDevicePath = {
 | 
						|
  {
 | 
						|
    {
 | 
						|
      HARDWARE_DEVICE_PATH,
 | 
						|
      HW_VENDOR_DP,
 | 
						|
      {
 | 
						|
        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
 | 
						|
        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | 
						|
      }
 | 
						|
    },
 | 
						|
    HDD_PASSWORD_CONFIG_GUID
 | 
						|
  },
 | 
						|
  {
 | 
						|
    END_DEVICE_PATH_TYPE,
 | 
						|
    END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | 
						|
    {
 | 
						|
      (UINT8) (END_DEVICE_PATH_LENGTH),
 | 
						|
      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the password is full zero.
 | 
						|
 | 
						|
  @param[in]   Password       Points to the data buffer
 | 
						|
 | 
						|
  @retval      TRUE           This password string is full zero.
 | 
						|
  @retval      FALSE          This password string is not full zero.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
PasswordIsFullZero (
 | 
						|
  IN CHAR8                    *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < HDD_PASSWORD_MAX_LENGTH; Index++) {
 | 
						|
    if (Password[Index] != 0) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Save device info.
 | 
						|
 | 
						|
  @param[in]       ConfigFormEntry       Points to HDD_PASSWORD_CONFIG_FORM_ENTRY buffer
 | 
						|
  @param[in,out]   TempDevInfo           Points to HDD_PASSWORD_DEVICE_INFO buffer
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveDeviceInfo (
 | 
						|
  IN     HDD_PASSWORD_CONFIG_FORM_ENTRY    *ConfigFormEntry,
 | 
						|
  IN OUT HDD_PASSWORD_DEVICE_INFO          *TempDevInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  TempDevInfo->Device.Bus                = (UINT8) ConfigFormEntry->Bus;
 | 
						|
  TempDevInfo->Device.Device             = (UINT8) ConfigFormEntry->Device;
 | 
						|
  TempDevInfo->Device.Function           = (UINT8) ConfigFormEntry->Function;
 | 
						|
  TempDevInfo->Device.Port               = ConfigFormEntry->Port;
 | 
						|
  TempDevInfo->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
 | 
						|
  CopyMem (TempDevInfo->Password, ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
  TempDevInfo->DevicePathLength          = (UINT32) GetDevicePathSize (ConfigFormEntry->DevicePath);
 | 
						|
  CopyMem (TempDevInfo->DevicePath, ConfigFormEntry->DevicePath, TempDevInfo->DevicePathLength);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Build HDD password device info and save them to LockBox.
 | 
						|
 | 
						|
 **/
 | 
						|
VOID
 | 
						|
BuildHddPasswordDeviceInfo (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  LIST_ENTRY                        *Entry;
 | 
						|
  HDD_PASSWORD_CONFIG_FORM_ENTRY    *ConfigFormEntry;
 | 
						|
  HDD_PASSWORD_DEVICE_INFO          *DevInfo;
 | 
						|
  HDD_PASSWORD_DEVICE_INFO          *TempDevInfo;
 | 
						|
  UINTN                             DevInfoLength;
 | 
						|
  UINT8                             DummyData;
 | 
						|
  BOOLEAN                           S3InitDevicesExist;
 | 
						|
  UINTN                             S3InitDevicesLength;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL          *S3InitDevices;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL          *S3InitDevicesBak;
 | 
						|
 | 
						|
  //
 | 
						|
  // Build HDD password device info and save them to LockBox.
 | 
						|
  //
 | 
						|
  DevInfoLength = 0;
 | 
						|
  BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
    ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
 | 
						|
    //
 | 
						|
    // 1. Handle device which already set password.
 | 
						|
    // 2. When request to send freeze command, driver also needs to handle device
 | 
						|
    //    which support security feature.
 | 
						|
    //
 | 
						|
    if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||
 | 
						|
        ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&
 | 
						|
         (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {
 | 
						|
      DevInfoLength += sizeof (HDD_PASSWORD_DEVICE_INFO) +
 | 
						|
                       GetDevicePathSize (ConfigFormEntry->DevicePath);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (DevInfoLength == 0) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  S3InitDevicesLength = sizeof (DummyData);
 | 
						|
  Status = RestoreLockBox (
 | 
						|
             &gS3StorageDeviceInitListGuid,
 | 
						|
             &DummyData,
 | 
						|
             &S3InitDevicesLength
 | 
						|
             );
 | 
						|
  ASSERT ((Status == EFI_NOT_FOUND) || (Status == EFI_BUFFER_TOO_SMALL));
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    S3InitDevices      = NULL;
 | 
						|
    S3InitDevicesExist = FALSE;
 | 
						|
  } else if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
    S3InitDevices = AllocatePool (S3InitDevicesLength);
 | 
						|
    ASSERT (S3InitDevices != NULL);
 | 
						|
 | 
						|
    Status = RestoreLockBox (
 | 
						|
               &gS3StorageDeviceInitListGuid,
 | 
						|
               S3InitDevices,
 | 
						|
               &S3InitDevicesLength
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    S3InitDevicesExist = TRUE;
 | 
						|
  } else {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  DevInfo = AllocateZeroPool (DevInfoLength);
 | 
						|
  ASSERT (DevInfo != NULL);
 | 
						|
 | 
						|
  TempDevInfo = DevInfo;
 | 
						|
  BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
    ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
 | 
						|
    if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||
 | 
						|
        ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&
 | 
						|
         (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {
 | 
						|
      SaveDeviceInfo (ConfigFormEntry, TempDevInfo);
 | 
						|
 | 
						|
      S3InitDevicesBak = S3InitDevices;
 | 
						|
      S3InitDevices    = AppendDevicePathInstance (
 | 
						|
                           S3InitDevicesBak,
 | 
						|
                           ConfigFormEntry->DevicePath
 | 
						|
                           );
 | 
						|
      if (S3InitDevicesBak != NULL) {
 | 
						|
        FreePool (S3InitDevicesBak);
 | 
						|
      }
 | 
						|
      ASSERT (S3InitDevices != NULL);
 | 
						|
 | 
						|
      TempDevInfo = (HDD_PASSWORD_DEVICE_INFO *) ((UINTN)TempDevInfo +
 | 
						|
                                                  sizeof (HDD_PASSWORD_DEVICE_INFO) +
 | 
						|
                                                  TempDevInfo->DevicePathLength);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = SaveLockBox (
 | 
						|
             &mHddPasswordDeviceInfoGuid,
 | 
						|
             DevInfo,
 | 
						|
             DevInfoLength
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = SetLockBoxAttributes (
 | 
						|
             &mHddPasswordDeviceInfoGuid,
 | 
						|
             LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  S3InitDevicesLength = GetDevicePathSize (S3InitDevices);
 | 
						|
  if (S3InitDevicesExist) {
 | 
						|
    Status = UpdateLockBox (
 | 
						|
               &gS3StorageDeviceInitListGuid,
 | 
						|
               0,
 | 
						|
               S3InitDevices,
 | 
						|
               S3InitDevicesLength
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  } else {
 | 
						|
    Status = SaveLockBox (
 | 
						|
               &gS3StorageDeviceInitListGuid,
 | 
						|
               S3InitDevices,
 | 
						|
               S3InitDevicesLength
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = SetLockBoxAttributes (
 | 
						|
               &gS3StorageDeviceInitListGuid,
 | 
						|
               LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (DevInfo, DevInfoLength);
 | 
						|
  FreePool (DevInfo);
 | 
						|
  FreePool (S3InitDevices);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send freeze lock cmd through Ata Pass Thru Protocol.
 | 
						|
 | 
						|
  @param[in] AtaPassThru         The pointer to the ATA_PASS_THRU protocol.
 | 
						|
  @param[in] Port                The port number of the ATA device to send the command.
 | 
						|
  @param[in] PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
 | 
						|
                                 If there is no port multiplier, then specify 0xFFFF.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successful to send freeze lock cmd.
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter passed-in is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough memory to send freeze lock cmd.
 | 
						|
  @retval EFI_DEVICE_ERROR       Can not send freeze lock cmd.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FreezeLockDevice (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_ATA_COMMAND_BLOCK             Acb;
 | 
						|
  EFI_ATA_STATUS_BLOCK              *Asb;
 | 
						|
  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;
 | 
						|
 | 
						|
  if (AtaPassThru == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
 | 
						|
  // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
 | 
						|
  // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
 | 
						|
  // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
 | 
						|
  // may not be aligned when allocated on stack for some compilers. Hence, we
 | 
						|
  // use the API AllocateAlignedPages to ensure this structure is properly
 | 
						|
  // aligned.
 | 
						|
  //
 | 
						|
  Asb = AllocateAlignedPages (
 | 
						|
          EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),
 | 
						|
          AtaPassThru->Mode->IoAlign
 | 
						|
          );
 | 
						|
  if (Asb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA command block.
 | 
						|
  //
 | 
						|
  ZeroMem (&Acb, sizeof (Acb));
 | 
						|
  ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));
 | 
						|
  Acb.AtaCommand    = ATA_SECURITY_FREEZE_LOCK_CMD;
 | 
						|
  Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA pass through packet.
 | 
						|
  //
 | 
						|
  ZeroMem (&Packet, sizeof (Packet));
 | 
						|
  Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;
 | 
						|
  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER;
 | 
						|
  Packet.Asb      = Asb;
 | 
						|
  Packet.Acb      = &Acb;
 | 
						|
  Packet.Timeout  = ATA_TIMEOUT;
 | 
						|
 | 
						|
  Status = AtaPassThru->PassThru (
 | 
						|
                          AtaPassThru,
 | 
						|
                          Port,
 | 
						|
                          PortMultiplierPort,
 | 
						|
                          &Packet,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
  if (!EFI_ERROR (Status) &&
 | 
						|
      ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&
 | 
						|
      ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get attached harddisk identify data through Ata Pass Thru Protocol.
 | 
						|
 | 
						|
  @param[in] AtaPassThru         The pointer to the ATA_PASS_THRU protocol.
 | 
						|
  @param[in] Port                The port number of the ATA device to send the command.
 | 
						|
  @param[in] PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
 | 
						|
                                 If there is no port multiplier, then specify 0xFFFF.
 | 
						|
  @param[in] IdentifyData        The buffer to store identify data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successful to get identify data.
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter passed-in is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough memory to get identify data.
 | 
						|
  @retval EFI_DEVICE_ERROR       Can not get identify data.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetHddDeviceIdentifyData (
 | 
						|
  IN  EFI_ATA_PASS_THRU_PROTOCOL    *AtaPassThru,
 | 
						|
  IN  UINT16                        Port,
 | 
						|
  IN  UINT16                        PortMultiplierPort,
 | 
						|
  IN  ATA_IDENTIFY_DATA             *IdentifyData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_ATA_COMMAND_BLOCK             Acb;
 | 
						|
  EFI_ATA_STATUS_BLOCK              *Asb;
 | 
						|
  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;
 | 
						|
 | 
						|
  if ((AtaPassThru == NULL) || (IdentifyData == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
 | 
						|
  // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
 | 
						|
  // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
 | 
						|
  // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
 | 
						|
  // may not be aligned when allocated on stack for some compilers. Hence, we
 | 
						|
  // use the API AllocateAlignedPages to ensure this structure is properly
 | 
						|
  // aligned.
 | 
						|
  //
 | 
						|
  Asb = AllocateAlignedPages (
 | 
						|
          EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),
 | 
						|
          AtaPassThru->Mode->IoAlign
 | 
						|
          );
 | 
						|
  if (Asb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA command block.
 | 
						|
  //
 | 
						|
  ZeroMem (&Acb, sizeof (Acb));
 | 
						|
  ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));
 | 
						|
  Acb.AtaCommand    = ATA_CMD_IDENTIFY_DRIVE;
 | 
						|
  Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4)));
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA pass through packet.
 | 
						|
  //
 | 
						|
  ZeroMem (&Packet, sizeof (Packet));
 | 
						|
  Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;
 | 
						|
  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
 | 
						|
  Packet.Asb      = Asb;
 | 
						|
  Packet.Acb      = &Acb;
 | 
						|
  Packet.InDataBuffer     = IdentifyData;
 | 
						|
  Packet.InTransferLength = sizeof (ATA_IDENTIFY_DATA);
 | 
						|
  Packet.Timeout          = ATA_TIMEOUT;
 | 
						|
 | 
						|
  Status = AtaPassThru->PassThru (
 | 
						|
                          AtaPassThru,
 | 
						|
                          Port,
 | 
						|
                          PortMultiplierPort,
 | 
						|
                          &Packet,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
 | 
						|
  FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Parse security status according to identify data.
 | 
						|
 | 
						|
  @param[in] IdentifyData        The buffer to store identify data.
 | 
						|
  @param[in, out] IfrData        IFR data to hold security status.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GetHddPasswordSecurityStatus (
 | 
						|
  IN     ATA_IDENTIFY_DATA    *IdentifyData,
 | 
						|
  IN OUT HDD_PASSWORD_CONFIG  *IfrData
 | 
						|
  )
 | 
						|
{
 | 
						|
  IfrData->SecurityStatus.Supported = (IdentifyData->command_set_supported_82 & BIT1) ? 1 : 0;
 | 
						|
  IfrData->SecurityStatus.Enabled   = (IdentifyData->security_status & BIT1) ? 1 : 0;
 | 
						|
  IfrData->SecurityStatus.Locked    = (IdentifyData->security_status & BIT2) ? 1 : 0;
 | 
						|
  IfrData->SecurityStatus.Frozen    = (IdentifyData->security_status & BIT3) ? 1 : 0;
 | 
						|
  IfrData->SecurityStatus.UserPasswordStatus   = IfrData->SecurityStatus.Enabled;
 | 
						|
  IfrData->SecurityStatus.MasterPasswordStatus = IfrData->SecurityStatus.Supported;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Supported            = %x\n", IfrData->SecurityStatus.Supported));
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Enabled              = %x\n", IfrData->SecurityStatus.Enabled));
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Locked               = %x\n", IfrData->SecurityStatus.Locked));
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Frozen               = %x\n", IfrData->SecurityStatus.Frozen));
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.UserPasswordStatus   = %x\n", IfrData->SecurityStatus.UserPasswordStatus));
 | 
						|
  DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.MasterPasswordStatus = %x\n", IfrData->SecurityStatus.MasterPasswordStatus));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
 | 
						|
 | 
						|
  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
 | 
						|
 | 
						|
  @param  Event        Event whose notification function is being invoked.
 | 
						|
  @param  Context      Pointer to the notification function's context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
HddPasswordEndOfDxeEventNotify (
 | 
						|
  EFI_EVENT                               Event,
 | 
						|
  VOID                                    *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                        *Entry;
 | 
						|
  HDD_PASSWORD_CONFIG_FORM_ENTRY    *ConfigFormEntry;
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  ATA_IDENTIFY_DATA                 IdentifyData;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  mHddPasswordEndOfDxe = TRUE;
 | 
						|
 | 
						|
  if (mHddPasswordRequestVariable != NULL) {
 | 
						|
    //
 | 
						|
    // Free the HDD password request variable buffer here
 | 
						|
    // as the HDD password requests should have been processed.
 | 
						|
    //
 | 
						|
    FreePool (mHddPasswordRequestVariable);
 | 
						|
    mHddPasswordRequestVariable = NULL;
 | 
						|
    mHddPasswordRequestVariableSize = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If no any device, return directly.
 | 
						|
  //
 | 
						|
  if (IsListEmpty (&mHddPasswordConfigFormList)) {
 | 
						|
    gBS->CloseEvent (Event);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  BuildHddPasswordDeviceInfo ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Zero passsword and freeze lock device.
 | 
						|
  //
 | 
						|
  BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
    ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
 | 
						|
    ZeroMem (ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check whether need send freeze lock command.
 | 
						|
    // Below device will be froze:
 | 
						|
    // 1. Device not enable password.
 | 
						|
    // 2. Device enable password and unlocked.
 | 
						|
    //
 | 
						|
    if ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&
 | 
						|
        (ConfigFormEntry->IfrData.SecurityStatus.Locked == 0) &&
 | 
						|
        (ConfigFormEntry->IfrData.SecurityStatus.Frozen == 0)) {
 | 
						|
      Status = FreezeLockDevice (ConfigFormEntry->AtaPassThru, ConfigFormEntry->Port, ConfigFormEntry->PortMultiplierPort);
 | 
						|
      DEBUG ((DEBUG_INFO, "FreezeLockDevice return %r!\n", Status));
 | 
						|
      Status = GetHddDeviceIdentifyData (
 | 
						|
                 ConfigFormEntry->AtaPassThru,
 | 
						|
                 ConfigFormEntry->Port,
 | 
						|
                 ConfigFormEntry->PortMultiplierPort,
 | 
						|
                 &IdentifyData
 | 
						|
                 );
 | 
						|
      GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
 | 
						|
  gBS->CloseEvent (Event);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate Salt value.
 | 
						|
 | 
						|
  @param[in, out]   SaltValue           Points to the salt buffer, 32 bytes
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GenSalt (
 | 
						|
  IN OUT UINT8  *SaltValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  RandomSeed (NULL, 0);
 | 
						|
  RandomBytes (SaltValue, PASSWORD_SALT_SIZE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Hash the data to get credential.
 | 
						|
 | 
						|
  @param[in]   Buffer         Points to the data buffer
 | 
						|
  @param[in]   BufferSize     Buffer size
 | 
						|
  @param[in]   SaltValue      Points to the salt buffer, 32 bytes
 | 
						|
  @param[out]  Credential     Points to the hashed result
 | 
						|
 | 
						|
  @retval      TRUE           Hash the data successfully.
 | 
						|
  @retval      FALSE          Failed to hash the data.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
GenerateCredential (
 | 
						|
  IN      UINT8               *Buffer,
 | 
						|
  IN      UINTN               BufferSize,
 | 
						|
  IN      UINT8               *SaltValue,
 | 
						|
     OUT  UINT8               *Credential
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN                     Status;
 | 
						|
  UINTN                       HashSize;
 | 
						|
  VOID                        *Hash;
 | 
						|
  VOID                        *HashData;
 | 
						|
 | 
						|
  Hash      = NULL;
 | 
						|
  HashData  = NULL;
 | 
						|
  Status    = FALSE;
 | 
						|
 | 
						|
  HashSize = Sha256GetContextSize ();
 | 
						|
  Hash     = AllocateZeroPool (HashSize);
 | 
						|
  ASSERT (Hash != NULL);
 | 
						|
  if (Hash == NULL) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Sha256Init (Hash);
 | 
						|
  if (!Status) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  HashData = AllocateZeroPool (PASSWORD_SALT_SIZE + BufferSize);
 | 
						|
  ASSERT (HashData != NULL);
 | 
						|
  if (HashData == NULL) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (HashData, SaltValue, PASSWORD_SALT_SIZE);
 | 
						|
  CopyMem ((UINT8 *) HashData + PASSWORD_SALT_SIZE, Buffer, BufferSize);
 | 
						|
 | 
						|
  Status = Sha256Update (Hash, HashData, PASSWORD_SALT_SIZE + BufferSize);
 | 
						|
  if (!Status) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Sha256Final (Hash, Credential);
 | 
						|
 | 
						|
Done:
 | 
						|
  if (Hash != NULL) {
 | 
						|
    FreePool (Hash);
 | 
						|
  }
 | 
						|
  if (HashData != NULL) {
 | 
						|
    ZeroMem (HashData, PASSWORD_SALT_SIZE + BufferSize);
 | 
						|
    FreePool (HashData);
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Save HDD password variable that will be used to validate HDD password
 | 
						|
  when the device is at frozen state.
 | 
						|
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
  @param[in] Password               The hdd password of attached ATA device.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveHddPasswordVariable (
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,
 | 
						|
  IN CHAR8                          *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_VARIABLE             *TempVariable;
 | 
						|
  UINTN                             TempVariableSize;
 | 
						|
  HDD_PASSWORD_VARIABLE             *NextNode;
 | 
						|
  HDD_PASSWORD_VARIABLE             *Variable;
 | 
						|
  UINTN                             VariableSize;
 | 
						|
  HDD_PASSWORD_VARIABLE             *NewVariable;
 | 
						|
  UINTN                             NewVariableSize;
 | 
						|
  BOOLEAN                           Delete;
 | 
						|
  BOOLEAN                           HashOk;
 | 
						|
  UINT8                             HashData[SHA256_DIGEST_SIZE];
 | 
						|
  UINT8                             SaltData[PASSWORD_SALT_SIZE];
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  Delete = FALSE;
 | 
						|
  if (!PasswordIsFullZero (Password)) {
 | 
						|
    //
 | 
						|
    // It is Set/Update HDD Password.
 | 
						|
    //
 | 
						|
    ZeroMem (HashData, sizeof (HashData));
 | 
						|
    ZeroMem (SaltData, sizeof (SaltData));
 | 
						|
    GenSalt (SaltData);
 | 
						|
    HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, SaltData, HashData);
 | 
						|
    if (!HashOk) {
 | 
						|
      DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // It is Disable HDD Password.
 | 
						|
    // Go to delete the variable node for the HDD password device.
 | 
						|
    //
 | 
						|
    Delete = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  Variable = NULL;
 | 
						|
  VariableSize = 0;
 | 
						|
  NewVariable = NULL;
 | 
						|
  NewVariableSize = 0;
 | 
						|
 | 
						|
  Status = GetVariable2 (
 | 
						|
             HDD_PASSWORD_VARIABLE_NAME,
 | 
						|
             &mHddPasswordVendorGuid,
 | 
						|
             (VOID **) &Variable,
 | 
						|
             &VariableSize
 | 
						|
             );
 | 
						|
  if (Delete) {
 | 
						|
    if (!EFI_ERROR (Status) && (Variable != NULL)) {
 | 
						|
      TempVariable = Variable;
 | 
						|
      TempVariableSize = VariableSize;
 | 
						|
      while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {
 | 
						|
        if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
            (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
            (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
            (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
            (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
          //
 | 
						|
          // Found the node for the HDD password device.
 | 
						|
          // Delete the node.
 | 
						|
          //
 | 
						|
          NextNode = TempVariable + 1;
 | 
						|
          CopyMem (TempVariable, NextNode, (UINTN) Variable + VariableSize - (UINTN) NextNode);
 | 
						|
          NewVariable = Variable;
 | 
						|
          NewVariableSize = VariableSize - sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
        TempVariable += 1;
 | 
						|
      }
 | 
						|
      if (NewVariable == NULL) {
 | 
						|
        DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (!EFI_ERROR (Status) && (Variable != NULL)) {
 | 
						|
      TempVariable = Variable;
 | 
						|
      TempVariableSize = VariableSize;
 | 
						|
      while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {
 | 
						|
        if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
            (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
            (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
            (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
            (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
          //
 | 
						|
          // Found the node for the HDD password device.
 | 
						|
          // Update the node.
 | 
						|
          //
 | 
						|
          CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));
 | 
						|
          CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));
 | 
						|
          NewVariable = Variable;
 | 
						|
          NewVariableSize = VariableSize;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
        TempVariable += 1;
 | 
						|
      }
 | 
						|
      if (NewVariable == NULL) {
 | 
						|
        //
 | 
						|
        // The node for the HDD password device is not found.
 | 
						|
        // Create node for the HDD password device.
 | 
						|
        //
 | 
						|
        NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
        NewVariable = AllocateZeroPool (NewVariableSize);
 | 
						|
        ASSERT (NewVariable != NULL);
 | 
						|
        CopyMem (NewVariable, Variable, VariableSize);
 | 
						|
        TempVariable = (HDD_PASSWORD_VARIABLE *) ((UINTN) NewVariable + VariableSize);
 | 
						|
        TempVariable->Device.Bus                = (UINT8) ConfigFormEntry->Bus;
 | 
						|
        TempVariable->Device.Device             = (UINT8) ConfigFormEntry->Device;
 | 
						|
        TempVariable->Device.Function           = (UINT8) ConfigFormEntry->Function;
 | 
						|
        TempVariable->Device.Port               = ConfigFormEntry->Port;
 | 
						|
        TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
 | 
						|
        CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));
 | 
						|
        CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      NewVariableSize = sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
      NewVariable = AllocateZeroPool (NewVariableSize);
 | 
						|
      ASSERT (NewVariable != NULL);
 | 
						|
      NewVariable->Device.Bus                = (UINT8) ConfigFormEntry->Bus;
 | 
						|
      NewVariable->Device.Device             = (UINT8) ConfigFormEntry->Device;
 | 
						|
      NewVariable->Device.Function           = (UINT8) ConfigFormEntry->Function;
 | 
						|
      NewVariable->Device.Port               = ConfigFormEntry->Port;
 | 
						|
      NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
 | 
						|
      CopyMem (NewVariable->PasswordHash, HashData, sizeof (HashData));
 | 
						|
      CopyMem (NewVariable->PasswordSalt, SaltData, sizeof (SaltData));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (NewVariable != NULL) {
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    HDD_PASSWORD_VARIABLE_NAME,
 | 
						|
                    &mHddPasswordVendorGuid,
 | 
						|
                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                    NewVariableSize,
 | 
						|
                    NewVariable
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_INFO, "HddPassword variable set failed (%r)\n", Status));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (NewVariable != Variable) {
 | 
						|
    FreePool (NewVariable);
 | 
						|
  }
 | 
						|
  if (Variable != NULL) {
 | 
						|
    FreePool (Variable);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get saved HDD password variable that will be used to validate HDD password
 | 
						|
  when the device is at frozen state.
 | 
						|
 | 
						|
  @param[in]  ConfigFormEntry       The HDD Password configuration form entry.
 | 
						|
  @param[out] HddPasswordVariable   The variable node for the HDD password device.
 | 
						|
 | 
						|
  @retval TRUE      The variable node for the HDD password device is found and returned.
 | 
						|
  @retval FALSE     The variable node for the HDD password device is not found.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
GetSavedHddPasswordVariable (
 | 
						|
  IN  HDD_PASSWORD_CONFIG_FORM_ENTRY    *ConfigFormEntry,
 | 
						|
  OUT HDD_PASSWORD_VARIABLE             *HddPasswordVariable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_VARIABLE             *TempVariable;
 | 
						|
  HDD_PASSWORD_VARIABLE             *Variable;
 | 
						|
  UINTN                             VariableSize;
 | 
						|
  BOOLEAN                           Found;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  Variable = NULL;
 | 
						|
  VariableSize = 0;
 | 
						|
 | 
						|
  Status = GetVariable2 (
 | 
						|
             HDD_PASSWORD_VARIABLE_NAME,
 | 
						|
             &mHddPasswordVendorGuid,
 | 
						|
             (VOID **) &Variable,
 | 
						|
             &VariableSize
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status) || (Variable == NULL)) {
 | 
						|
    DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Found = FALSE;
 | 
						|
  TempVariable = Variable;
 | 
						|
  while (VariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {
 | 
						|
    if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
        (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
        (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
        (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
        (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
      //
 | 
						|
      // Found the node for the HDD password device.
 | 
						|
      // Get the node.
 | 
						|
      //
 | 
						|
      CopyMem (HddPasswordVariable, TempVariable, sizeof (HDD_PASSWORD_VARIABLE));
 | 
						|
      Found = TRUE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    VariableSize -= sizeof (HDD_PASSWORD_VARIABLE);
 | 
						|
    TempVariable += 1;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Variable);
 | 
						|
 | 
						|
  if (!Found) {
 | 
						|
    DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
 | 
						|
  return Found;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Use saved HDD password variable to validate HDD password
 | 
						|
  when the device is at frozen state.
 | 
						|
 | 
						|
  @param[in] ConfigFormEntry    The HDD Password configuration form entry.
 | 
						|
  @param[in] Password           The hdd password of attached ATA device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Pass to validate the HDD password.
 | 
						|
  @retval EFI_NOT_FOUND         The variable node for the HDD password device is not found.
 | 
						|
  @retval EFI_DEVICE_ERROR      Failed to generate credential for the HDD password.
 | 
						|
  @retval EFI_INVALID_PARAMETER Failed to validate the HDD password.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ValidateHddPassword (
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,
 | 
						|
  IN CHAR8                          *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_VARIABLE             HddPasswordVariable;
 | 
						|
  BOOLEAN                           HashOk;
 | 
						|
  UINT8                             HashData[SHA256_DIGEST_SIZE];
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  if (!GetSavedHddPasswordVariable (ConfigFormEntry, &HddPasswordVariable)) {
 | 
						|
    DEBUG ((DEBUG_INFO, "GetSavedHddPasswordVariable failed\n"));
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (HashData, sizeof (HashData));
 | 
						|
  HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, HddPasswordVariable.PasswordSalt, HashData);
 | 
						|
  if (!HashOk) {
 | 
						|
    DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareMem (HddPasswordVariable.PasswordHash, HashData, sizeof (HashData)) != 0) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  } else {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit (%r)\n", __FUNCTION__, Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send unlock hdd password cmd through Ata Pass Thru Protocol.
 | 
						|
 | 
						|
  @param[in] AtaPassThru         The pointer to the ATA_PASS_THRU protocol.
 | 
						|
  @param[in] Port                The port number of the ATA device to send the command.
 | 
						|
  @param[in] PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
 | 
						|
                                 If there is no port multiplier, then specify 0xFFFF.
 | 
						|
  @param[in] Identifier          The identifier to set user or master password.
 | 
						|
  @param[in] Password            The hdd password of attached ATA device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successful to send unlock hdd password cmd.
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter passed-in is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough memory to send unlock hdd password cmd.
 | 
						|
  @retval EFI_DEVICE_ERROR       Can not send unlock hdd password cmd.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UnlockHddPassword (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN CHAR8                          Identifier,
 | 
						|
  IN CHAR8                          *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_ATA_COMMAND_BLOCK             Acb;
 | 
						|
  EFI_ATA_STATUS_BLOCK              *Asb;
 | 
						|
  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;
 | 
						|
  UINT8                             Buffer[HDD_PAYLOAD];
 | 
						|
 | 
						|
  if ((AtaPassThru == NULL) || (Password == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
 | 
						|
  // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
 | 
						|
  // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
 | 
						|
  // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
 | 
						|
  // may not be aligned when allocated on stack for some compilers. Hence, we
 | 
						|
  // use the API AllocateAlignedPages to ensure this structure is properly
 | 
						|
  // aligned.
 | 
						|
  //
 | 
						|
  Asb = AllocateAlignedPages (
 | 
						|
          EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),
 | 
						|
          AtaPassThru->Mode->IoAlign
 | 
						|
          );
 | 
						|
  if (Asb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA command block.
 | 
						|
  //
 | 
						|
  ZeroMem (&Acb, sizeof (Acb));
 | 
						|
  ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));
 | 
						|
  Acb.AtaCommand    = ATA_SECURITY_UNLOCK_CMD;
 | 
						|
  Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA pass through packet.
 | 
						|
  //
 | 
						|
  ZeroMem (&Packet, sizeof (Packet));
 | 
						|
  Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;
 | 
						|
  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_BYTES;
 | 
						|
  Packet.Asb      = Asb;
 | 
						|
  Packet.Acb      = &Acb;
 | 
						|
 | 
						|
  ((CHAR16 *) Buffer)[0] = Identifier & BIT0;
 | 
						|
  CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
  Packet.OutDataBuffer     = Buffer;
 | 
						|
  Packet.OutTransferLength = sizeof (Buffer);
 | 
						|
  Packet.Timeout           = ATA_TIMEOUT;
 | 
						|
 | 
						|
  Status = AtaPassThru->PassThru (
 | 
						|
                          AtaPassThru,
 | 
						|
                          Port,
 | 
						|
                          PortMultiplierPort,
 | 
						|
                          &Packet,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
  if (!EFI_ERROR (Status) &&
 | 
						|
      ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&
 | 
						|
      ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));
 | 
						|
 | 
						|
  ZeroMem (Buffer, sizeof (Buffer));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send disable hdd password cmd through Ata Pass Thru Protocol.
 | 
						|
 | 
						|
  @param[in] AtaPassThru         The pointer to the ATA_PASS_THRU protocol.
 | 
						|
  @param[in] Port                The port number of the ATA device to send the command.
 | 
						|
  @param[in] PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
 | 
						|
                                 If there is no port multiplier, then specify 0xFFFF.
 | 
						|
  @param[in] Identifier          The identifier to set user or master password.
 | 
						|
  @param[in] Password            The hdd password of attached ATA device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successful to disable hdd password cmd.
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter passed-in is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough memory to disable hdd password cmd.
 | 
						|
  @retval EFI_DEVICE_ERROR       Can not disable hdd password cmd.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DisableHddPassword (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN CHAR8                          Identifier,
 | 
						|
  IN CHAR8                          *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_ATA_COMMAND_BLOCK             Acb;
 | 
						|
  EFI_ATA_STATUS_BLOCK              *Asb;
 | 
						|
  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;
 | 
						|
  UINT8                             Buffer[HDD_PAYLOAD];
 | 
						|
 | 
						|
  if ((AtaPassThru == NULL) || (Password == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
 | 
						|
  // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
 | 
						|
  // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
 | 
						|
  // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
 | 
						|
  // may not be aligned when allocated on stack for some compilers. Hence, we
 | 
						|
  // use the API AllocateAlignedPages to ensure this structure is properly
 | 
						|
  // aligned.
 | 
						|
  //
 | 
						|
  Asb = AllocateAlignedPages (
 | 
						|
          EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),
 | 
						|
          AtaPassThru->Mode->IoAlign
 | 
						|
          );
 | 
						|
  if (Asb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA command block.
 | 
						|
  //
 | 
						|
  ZeroMem (&Acb, sizeof (Acb));
 | 
						|
  ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));
 | 
						|
  Acb.AtaCommand    = ATA_SECURITY_DIS_PASSWORD_CMD;
 | 
						|
  Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA pass through packet.
 | 
						|
  //
 | 
						|
  ZeroMem (&Packet, sizeof (Packet));
 | 
						|
  Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;
 | 
						|
  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_BYTES;
 | 
						|
  Packet.Asb      = Asb;
 | 
						|
  Packet.Acb      = &Acb;
 | 
						|
 | 
						|
  ((CHAR16 *) Buffer)[0] = Identifier & BIT0;
 | 
						|
  CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
  Packet.OutDataBuffer     = Buffer;
 | 
						|
  Packet.OutTransferLength = sizeof (Buffer);
 | 
						|
  Packet.Timeout           = ATA_TIMEOUT;
 | 
						|
 | 
						|
  Status = AtaPassThru->PassThru (
 | 
						|
                          AtaPassThru,
 | 
						|
                          Port,
 | 
						|
                          PortMultiplierPort,
 | 
						|
                          &Packet,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
  if (!EFI_ERROR (Status) &&
 | 
						|
      ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&
 | 
						|
      ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));
 | 
						|
 | 
						|
  ZeroMem (Buffer, sizeof (Buffer));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send set hdd password cmd through Ata Pass Thru Protocol.
 | 
						|
 | 
						|
  @param[in] AtaPassThru                The pointer to the ATA_PASS_THRU protocol.
 | 
						|
  @param[in] Port                       The port number of the ATA device to send the command.
 | 
						|
  @param[in] PortMultiplierPort         The port multiplier port number of the ATA device to send the command.
 | 
						|
                                        If there is no port multiplier, then specify 0xFFFF.
 | 
						|
  @param[in] Identifier                 The identifier to set user or master password.
 | 
						|
  @param[in] SecurityLevel              The security level to be set to device.
 | 
						|
  @param[in] MasterPasswordIdentifier   The master password identifier to be set to device.
 | 
						|
  @param[in] Password                   The hdd password of attached ATA device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Successful to set hdd password cmd.
 | 
						|
  @retval EFI_INVALID_PARAMETER  The parameter passed-in is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough memory to set hdd password cmd.
 | 
						|
  @retval EFI_DEVICE_ERROR       Can not set hdd password cmd.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SetHddPassword (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN CHAR8                          Identifier,
 | 
						|
  IN CHAR8                          SecurityLevel,
 | 
						|
  IN CHAR16                         MasterPasswordIdentifier,
 | 
						|
  IN CHAR8                          *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_ATA_COMMAND_BLOCK             Acb;
 | 
						|
  EFI_ATA_STATUS_BLOCK              *Asb;
 | 
						|
  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;
 | 
						|
  UINT8                             Buffer[HDD_PAYLOAD];
 | 
						|
 | 
						|
  if ((AtaPassThru == NULL) || (Password == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
 | 
						|
  // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
 | 
						|
  // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
 | 
						|
  // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
 | 
						|
  // may not be aligned when allocated on stack for some compilers. Hence, we
 | 
						|
  // use the API AllocateAlignedPages to ensure this structure is properly
 | 
						|
  // aligned.
 | 
						|
  //
 | 
						|
  Asb = AllocateAlignedPages (
 | 
						|
          EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),
 | 
						|
          AtaPassThru->Mode->IoAlign
 | 
						|
          );
 | 
						|
  if (Asb == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA command block.
 | 
						|
  //
 | 
						|
  ZeroMem (&Acb, sizeof (Acb));
 | 
						|
  ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));
 | 
						|
  Acb.AtaCommand    = ATA_SECURITY_SET_PASSWORD_CMD;
 | 
						|
  Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for ATA pass through packet.
 | 
						|
  //
 | 
						|
  ZeroMem (&Packet, sizeof (Packet));
 | 
						|
  Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;
 | 
						|
  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_BYTES;
 | 
						|
  Packet.Asb      = Asb;
 | 
						|
  Packet.Acb      = &Acb;
 | 
						|
 | 
						|
  ((CHAR16 *) Buffer)[0] = (Identifier | (UINT16)(SecurityLevel << 8)) & (BIT0 | BIT8);
 | 
						|
  CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
  if ((Identifier & BIT0) != 0) {
 | 
						|
    ((CHAR16 *) Buffer)[17] = MasterPasswordIdentifier;
 | 
						|
  }
 | 
						|
 | 
						|
  Packet.OutDataBuffer     = Buffer;
 | 
						|
  Packet.OutTransferLength = sizeof (Buffer);
 | 
						|
  Packet.Timeout           = ATA_TIMEOUT;
 | 
						|
 | 
						|
  Status = AtaPassThru->PassThru (
 | 
						|
                          AtaPassThru,
 | 
						|
                          Port,
 | 
						|
                          PortMultiplierPort,
 | 
						|
                          &Packet,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
  if (!EFI_ERROR (Status) &&
 | 
						|
      ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&
 | 
						|
      ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));
 | 
						|
 | 
						|
  ZeroMem (Buffer, sizeof (Buffer));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get attached harddisk model number from identify data buffer.
 | 
						|
 | 
						|
  @param[in] IdentifyData    Pointer to identify data buffer.
 | 
						|
  @param[in, out] String     The buffer to store harddisk model number.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GetHddDeviceModelNumber (
 | 
						|
  IN ATA_IDENTIFY_DATA             *IdentifyData,
 | 
						|
  IN OUT CHAR16                    *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN             Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Swap the byte order in the original module name.
 | 
						|
  // From Ata spec, the maximum length is 40 bytes.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < 40; Index += 2) {
 | 
						|
    String[Index]      = IdentifyData->ModelName[Index + 1];
 | 
						|
    String[Index + 1]  = IdentifyData->ModelName[Index];
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Chap it off after 20 characters
 | 
						|
  //
 | 
						|
  String[20] = L'\0';
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get password input from the popup windows.
 | 
						|
 | 
						|
  @param[in]      PopUpString1  Pop up string 1.
 | 
						|
  @param[in]      PopUpString2  Pop up string 2.
 | 
						|
  @param[in, out] Password      The buffer to hold the input password.
 | 
						|
 | 
						|
  @retval EFI_ABORTED           It is given up by pressing 'ESC' key.
 | 
						|
  @retval EFI_SUCCESS           Get password input successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PopupHddPasswordInputWindows (
 | 
						|
  IN CHAR16         *PopUpString1,
 | 
						|
  IN CHAR16         *PopUpString2,
 | 
						|
  IN OUT CHAR8      *Password
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_INPUT_KEY Key;
 | 
						|
  UINTN         Length;
 | 
						|
  CHAR16        Mask[HDD_PASSWORD_MAX_LENGTH + 1];
 | 
						|
  CHAR16        Unicode[HDD_PASSWORD_MAX_LENGTH + 1];
 | 
						|
  CHAR8         Ascii[HDD_PASSWORD_MAX_LENGTH + 1];
 | 
						|
 | 
						|
  ZeroMem (Unicode, sizeof (Unicode));
 | 
						|
  ZeroMem (Ascii, sizeof (Ascii));
 | 
						|
  ZeroMem (Mask, sizeof (Mask));
 | 
						|
 | 
						|
  gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
 | 
						|
  Length = 0;
 | 
						|
  while (TRUE) {
 | 
						|
    Mask[Length] = L'_';
 | 
						|
    if (PopUpString2 == NULL) {
 | 
						|
      CreatePopUp (
 | 
						|
        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
        &Key,
 | 
						|
        PopUpString1,
 | 
						|
        L"---------------------",
 | 
						|
        Mask,
 | 
						|
        NULL
 | 
						|
      );
 | 
						|
    } else {
 | 
						|
      CreatePopUp (
 | 
						|
        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
        &Key,
 | 
						|
        PopUpString1,
 | 
						|
        PopUpString2,
 | 
						|
        L"---------------------",
 | 
						|
        Mask,
 | 
						|
        NULL
 | 
						|
      );
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check key.
 | 
						|
    //
 | 
						|
    if (Key.ScanCode == SCAN_NULL) {
 | 
						|
      if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
 | 
						|
        //
 | 
						|
        // Add the null terminator.
 | 
						|
        //
 | 
						|
        Unicode[Length] = 0;
 | 
						|
        break;
 | 
						|
      } else if ((Key.UnicodeChar == CHAR_NULL) ||
 | 
						|
                 (Key.UnicodeChar == CHAR_TAB) ||
 | 
						|
                 (Key.UnicodeChar == CHAR_LINEFEED)
 | 
						|
                 ) {
 | 
						|
        continue;
 | 
						|
      } else {
 | 
						|
        if (Key.UnicodeChar == CHAR_BACKSPACE) {
 | 
						|
          if (Length > 0) {
 | 
						|
            Unicode[Length] = 0;
 | 
						|
            Mask[Length] = 0;
 | 
						|
            Length--;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          Unicode[Length] = Key.UnicodeChar;
 | 
						|
          Mask[Length] = L'*';
 | 
						|
          Length++;
 | 
						|
          if (Length == HDD_PASSWORD_MAX_LENGTH) {
 | 
						|
            //
 | 
						|
            // Add the null terminator.
 | 
						|
            //
 | 
						|
            Unicode[Length] = 0;
 | 
						|
            Mask[Length] = 0;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Key.ScanCode == SCAN_ESC) {
 | 
						|
      ZeroMem (Unicode, sizeof (Unicode));
 | 
						|
      ZeroMem (Ascii, sizeof (Ascii));
 | 
						|
      gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeStrToAsciiStrS (Unicode, Ascii, sizeof (Ascii));
 | 
						|
  CopyMem (Password, Ascii, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
  ZeroMem (Unicode, sizeof (Unicode));
 | 
						|
  ZeroMem (Ascii, sizeof (Ascii));
 | 
						|
 | 
						|
  gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if disk is locked, show popup window and ask for password if it is.
 | 
						|
 | 
						|
  @param[in] AtaPassThru            Pointer to ATA_PASSTHRU instance.
 | 
						|
  @param[in] Port                   The port number of attached ATA device.
 | 
						|
  @param[in] PortMultiplierPort     The port number of port multiplier of attached ATA device.
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
HddPasswordRequestPassword (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  CHAR16                            PopUpString[100];
 | 
						|
  ATA_IDENTIFY_DATA                 IdentifyData;
 | 
						|
  EFI_INPUT_KEY                     Key;
 | 
						|
  UINT16                            RetryCount;
 | 
						|
  CHAR8                             Password[HDD_PASSWORD_MAX_LENGTH];
 | 
						|
 | 
						|
  RetryCount = 0;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
 | 
						|
 | 
						|
  UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Unlock: %s", ConfigFormEntry->HddString);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the device security status.
 | 
						|
  //
 | 
						|
  if ((ConfigFormEntry->IfrData.SecurityStatus.Supported) &&
 | 
						|
      (ConfigFormEntry->IfrData.SecurityStatus.Enabled)) {
 | 
						|
 | 
						|
     //
 | 
						|
     // Add PcdSkipHddPasswordPrompt to determin whether to skip password prompt.
 | 
						|
     // Due to board design, device may not power off during system warm boot, which result in
 | 
						|
     // security status remain unlocked status, hence we add device security status check here.
 | 
						|
     //
 | 
						|
     // If device is in the locked status, device keeps locked and system continues booting.
 | 
						|
     // If device is in the unlocked status, system is forced shutdown for security concern.
 | 
						|
     //
 | 
						|
     if (PcdGetBool (PcdSkipHddPasswordPrompt)) {
 | 
						|
       if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
 | 
						|
         return;
 | 
						|
       } else {
 | 
						|
         gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
 | 
						|
       }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd
 | 
						|
    // no matter it's really in locked or unlocked state.
 | 
						|
    // This way forces user to enter password every time to provide best safety.
 | 
						|
    //
 | 
						|
    while (TRUE) {
 | 
						|
      Status = PopupHddPasswordInputWindows (PopUpString, NULL, Password);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // The HDD is in locked state, unlock it by user input.
 | 
						|
        //
 | 
						|
        if (!PasswordIsFullZero (Password)) {
 | 
						|
          if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
 | 
						|
            Status = UnlockHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, Password);
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Use saved HDD password variable to validate HDD password
 | 
						|
            // when the device is at frozen state.
 | 
						|
            //
 | 
						|
            Status = ValidateHddPassword (ConfigFormEntry, Password);
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          Status = EFI_INVALID_PARAMETER;
 | 
						|
        }
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
          if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
 | 
						|
            SaveHddPasswordVariable (ConfigFormEntry, Password);
 | 
						|
          }
 | 
						|
          ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
          Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
 | 
						|
          ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
          //
 | 
						|
          // Check the device security status again.
 | 
						|
          //
 | 
						|
          GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          RetryCount ++;
 | 
						|
          if (RetryCount < MAX_HDD_PASSWORD_RETRY_COUNT) {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Invalid password.",
 | 
						|
                L"Press ENTER to retry",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            continue;
 | 
						|
          } else {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Hdd password retry count is expired. Please shutdown the machine.",
 | 
						|
                L"Press ENTER to shutdown",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else if (Status == EFI_ABORTED) {
 | 
						|
        if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
 | 
						|
          //
 | 
						|
          // Current device in the lock status and
 | 
						|
          // User not input password and press ESC,
 | 
						|
          // keep device in lock status and continue boot.
 | 
						|
          //
 | 
						|
          do {
 | 
						|
            CreatePopUp (
 | 
						|
              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
              &Key,
 | 
						|
              L"Press ENTER to skip the request and continue boot,",
 | 
						|
              L"Press ESC to input password again",
 | 
						|
              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;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Current device in the unlock status and
 | 
						|
          // User not input password and press ESC,
 | 
						|
          // Shutdown the device.
 | 
						|
          //
 | 
						|
          do {
 | 
						|
            CreatePopUp (
 | 
						|
              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
              &Key,
 | 
						|
              L"Press ENTER to shutdown, Press ESC to input password again",
 | 
						|
              NULL
 | 
						|
              );
 | 
						|
          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
 | 
						|
 | 
						|
          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
 | 
						|
            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Let user input password again.
 | 
						|
            //
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process Set User Pwd HDD password request.
 | 
						|
 | 
						|
  @param[in] AtaPassThru            Pointer to ATA_PASSTHRU instance.
 | 
						|
  @param[in] Port                   The port number of attached ATA device.
 | 
						|
  @param[in] PortMultiplierPort     The port number of port multiplier of attached ATA device.
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ProcessHddPasswordRequestSetUserPwd (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  CHAR16                            PopUpString[100];
 | 
						|
  ATA_IDENTIFY_DATA                 IdentifyData;
 | 
						|
  EFI_INPUT_KEY                     Key;
 | 
						|
  UINT16                            RetryCount;
 | 
						|
  CHAR8                             Password[HDD_PASSWORD_MAX_LENGTH];
 | 
						|
  CHAR8                             PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];
 | 
						|
 | 
						|
  RetryCount = 0;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
 | 
						|
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
 | 
						|
    DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
 | 
						|
    DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set User Pwd: %s", ConfigFormEntry->HddString);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the device security status.
 | 
						|
  //
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {
 | 
						|
    while (TRUE) {
 | 
						|
      Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {
 | 
						|
            if (!PasswordIsFullZero (Password)) {
 | 
						|
              Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, 1, 0, Password);
 | 
						|
            } else {
 | 
						|
              if (ConfigFormEntry->IfrData.SecurityStatus.Enabled) {
 | 
						|
                Status = DisableHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, ConfigFormEntry->Password);
 | 
						|
              } else {
 | 
						|
                Status = EFI_INVALID_PARAMETER;
 | 
						|
              }
 | 
						|
            }
 | 
						|
            if (!EFI_ERROR (Status)) {
 | 
						|
              CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
              SaveHddPasswordVariable (ConfigFormEntry, Password);
 | 
						|
              ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
              ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
              Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
 | 
						|
              ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
              //
 | 
						|
              // Check the device security status again.
 | 
						|
              //
 | 
						|
              GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
 | 
						|
              return;
 | 
						|
            } else {
 | 
						|
              do {
 | 
						|
                CreatePopUp (
 | 
						|
                  EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                  &Key,
 | 
						|
                  L"Set/Disable User Pwd failed or invalid password.",
 | 
						|
                  L"Press ENTER to retry",
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
              } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            }
 | 
						|
          } else {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Passwords are not the same.",
 | 
						|
                L"Press ENTER to retry",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            Status = EFI_INVALID_PARAMETER;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
        ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          RetryCount ++;
 | 
						|
          if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Hdd password retry count is expired.",
 | 
						|
                L"Press ENTER to skip the request and continue boot",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else if (Status == EFI_ABORTED) {
 | 
						|
        do {
 | 
						|
          CreatePopUp (
 | 
						|
            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
            &Key,
 | 
						|
            L"Press ENTER to skip the request and continue boot,",
 | 
						|
            L"Press ESC to input password again",
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
 | 
						|
 | 
						|
        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
 | 
						|
          gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
          return;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Let user input password again.
 | 
						|
          //
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process Set Master Pwd HDD password request.
 | 
						|
 | 
						|
  @param[in] AtaPassThru            Pointer to ATA_PASSTHRU instance.
 | 
						|
  @param[in] Port                   The port number of attached ATA device.
 | 
						|
  @param[in] PortMultiplierPort     The port number of port multiplier of attached ATA device.
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ProcessHddPasswordRequestSetMasterPwd (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  CHAR16                            PopUpString[100];
 | 
						|
  EFI_INPUT_KEY                     Key;
 | 
						|
  UINT16                            RetryCount;
 | 
						|
  CHAR8                             Password[HDD_PASSWORD_MAX_LENGTH];
 | 
						|
  CHAR8                             PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];
 | 
						|
 | 
						|
  RetryCount = 0;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
 | 
						|
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
 | 
						|
    DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
 | 
						|
    DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set Master Pwd: %s", ConfigFormEntry->HddString);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the device security status.
 | 
						|
  //
 | 
						|
  if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {
 | 
						|
    while (TRUE) {
 | 
						|
      Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {
 | 
						|
            if (!PasswordIsFullZero (Password)) {
 | 
						|
              Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 1, 1, 1, Password);
 | 
						|
            } else {
 | 
						|
              Status = EFI_INVALID_PARAMETER;
 | 
						|
            }
 | 
						|
            if (!EFI_ERROR (Status)) {
 | 
						|
              ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
              ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
              return;
 | 
						|
            } else {
 | 
						|
              do {
 | 
						|
                CreatePopUp (
 | 
						|
                  EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                  &Key,
 | 
						|
                  L"Set Master Pwd failed or invalid password.",
 | 
						|
                  L"Press ENTER to retry",
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
              } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            }
 | 
						|
          } else {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Passwords are not the same.",
 | 
						|
                L"Press ENTER to retry",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            Status = EFI_INVALID_PARAMETER;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
        ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          RetryCount ++;
 | 
						|
          if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {
 | 
						|
            do {
 | 
						|
              CreatePopUp (
 | 
						|
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
                &Key,
 | 
						|
                L"Hdd password retry count is expired.",
 | 
						|
                L"Press ENTER to skip the request and continue boot",
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
            } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
            gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else if (Status == EFI_ABORTED) {
 | 
						|
        do {
 | 
						|
          CreatePopUp (
 | 
						|
            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | 
						|
            &Key,
 | 
						|
            L"Press ENTER to skip the request and continue boot,",
 | 
						|
            L"Press ESC to input password again",
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
        } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
 | 
						|
 | 
						|
        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
 | 
						|
          gST->ConOut->ClearScreen(gST->ConOut);
 | 
						|
          return;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Let user input password again.
 | 
						|
          //
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process HDD password request.
 | 
						|
 | 
						|
  @param[in] AtaPassThru            Pointer to ATA_PASSTHRU instance.
 | 
						|
  @param[in] Port                   The port number of attached ATA device.
 | 
						|
  @param[in] PortMultiplierPort     The port number of port multiplier of attached ATA device.
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ProcessHddPasswordRequest (
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL     *AtaPassThru,
 | 
						|
  IN UINT16                         Port,
 | 
						|
  IN UINT16                         PortMultiplierPort,
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *TempVariable;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *Variable;
 | 
						|
  UINTN                             VariableSize;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  if (mHddPasswordRequestVariable == NULL) {
 | 
						|
    Status = GetVariable2 (
 | 
						|
               HDD_PASSWORD_REQUEST_VARIABLE_NAME,
 | 
						|
               &mHddPasswordVendorGuid,
 | 
						|
               (VOID **) &Variable,
 | 
						|
               &VariableSize
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status) || (Variable == NULL)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    mHddPasswordRequestVariable = Variable;
 | 
						|
    mHddPasswordRequestVariableSize = VariableSize;
 | 
						|
 | 
						|
    //
 | 
						|
    // Delete the HDD password request variable.
 | 
						|
    //
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    HDD_PASSWORD_REQUEST_VARIABLE_NAME,
 | 
						|
                    &mHddPasswordVendorGuid,
 | 
						|
                    0,
 | 
						|
                    0,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  } else {
 | 
						|
    Variable = mHddPasswordRequestVariable;
 | 
						|
    VariableSize = mHddPasswordRequestVariableSize;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Process the HDD password requests.
 | 
						|
  //
 | 
						|
  TempVariable = Variable;
 | 
						|
  while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
 | 
						|
    if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
        (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
        (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
        (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
        (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
      //
 | 
						|
      // Found the node for the HDD password device.
 | 
						|
      //
 | 
						|
      if (TempVariable->Request.UserPassword != 0) {
 | 
						|
        ProcessHddPasswordRequestSetUserPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
 | 
						|
      }
 | 
						|
      if (TempVariable->Request.MasterPassword != 0) {
 | 
						|
        ProcessHddPasswordRequestSetMasterPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
 | 
						|
    TempVariable += 1;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get saved HDD password request.
 | 
						|
 | 
						|
  @param[in, out] ConfigFormEntry       The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GetSavedHddPasswordRequest (
 | 
						|
  IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *TempVariable;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *Variable;
 | 
						|
  UINTN                             VariableSize;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  Variable = NULL;
 | 
						|
  VariableSize = 0;
 | 
						|
 | 
						|
  Status = GetVariable2 (
 | 
						|
             HDD_PASSWORD_REQUEST_VARIABLE_NAME,
 | 
						|
             &mHddPasswordVendorGuid,
 | 
						|
             (VOID **) &Variable,
 | 
						|
             &VariableSize
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status) || (Variable == NULL)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  TempVariable = Variable;
 | 
						|
  while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
 | 
						|
    if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
        (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
        (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
        (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
        (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
      //
 | 
						|
      // Found the node for the HDD password device.
 | 
						|
      // Get the HDD password request.
 | 
						|
      //
 | 
						|
      CopyMem (&ConfigFormEntry->IfrData.Request, &TempVariable->Request, sizeof (HDD_PASSWORD_REQUEST));
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "HddPasswordRequest got: 0x%x\n",
 | 
						|
        ConfigFormEntry->IfrData.Request
 | 
						|
        ));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
 | 
						|
    TempVariable += 1;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Variable);
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Save HDD password request.
 | 
						|
 | 
						|
  @param[in] ConfigFormEntry        The HDD Password configuration form entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SaveHddPasswordRequest (
 | 
						|
  IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *TempVariable;
 | 
						|
  UINTN                             TempVariableSize;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *Variable;
 | 
						|
  UINTN                             VariableSize;
 | 
						|
  HDD_PASSWORD_REQUEST_VARIABLE     *NewVariable;
 | 
						|
  UINTN                             NewVariableSize;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
 | 
						|
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_INFO,
 | 
						|
    "HddPasswordRequest to save: 0x%x\n",
 | 
						|
    ConfigFormEntry->IfrData.Request
 | 
						|
    ));
 | 
						|
 | 
						|
  Variable = NULL;
 | 
						|
  VariableSize = 0;
 | 
						|
  NewVariable = NULL;
 | 
						|
  NewVariableSize = 0;
 | 
						|
 | 
						|
  Status = GetVariable2 (
 | 
						|
             HDD_PASSWORD_REQUEST_VARIABLE_NAME,
 | 
						|
             &mHddPasswordVendorGuid,
 | 
						|
             (VOID **) &Variable,
 | 
						|
             &VariableSize
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status) && (Variable != NULL)) {
 | 
						|
    TempVariable = Variable;
 | 
						|
    TempVariableSize = VariableSize;
 | 
						|
    while (TempVariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
 | 
						|
      if ((TempVariable->Device.Bus                == ConfigFormEntry->Bus) &&
 | 
						|
          (TempVariable->Device.Device             == ConfigFormEntry->Device) &&
 | 
						|
          (TempVariable->Device.Function           == ConfigFormEntry->Function) &&
 | 
						|
          (TempVariable->Device.Port               == ConfigFormEntry->Port) &&
 | 
						|
          (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
 | 
						|
        //
 | 
						|
        // Found the node for the HDD password device.
 | 
						|
        // Update the HDD password request.
 | 
						|
        //
 | 
						|
        CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
 | 
						|
        NewVariable = Variable;
 | 
						|
        NewVariableSize = VariableSize;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      TempVariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
 | 
						|
      TempVariable += 1;
 | 
						|
    }
 | 
						|
    if (NewVariable == NULL) {
 | 
						|
      //
 | 
						|
      // The node for the HDD password device is not found.
 | 
						|
      // Create node for the HDD password device.
 | 
						|
      //
 | 
						|
      NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
 | 
						|
      NewVariable = AllocateZeroPool (NewVariableSize);
 | 
						|
      ASSERT (NewVariable != NULL);
 | 
						|
      CopyMem (NewVariable, Variable, VariableSize);
 | 
						|
      TempVariable = (HDD_PASSWORD_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize);
 | 
						|
      TempVariable->Device.Bus                = (UINT8) ConfigFormEntry->Bus;
 | 
						|
      TempVariable->Device.Device             = (UINT8) ConfigFormEntry->Device;
 | 
						|
      TempVariable->Device.Function           = (UINT8) ConfigFormEntry->Function;
 | 
						|
      TempVariable->Device.Port               = ConfigFormEntry->Port;
 | 
						|
      TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
 | 
						|
      CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    NewVariableSize = sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
 | 
						|
    NewVariable = AllocateZeroPool (NewVariableSize);
 | 
						|
    ASSERT (NewVariable != NULL);
 | 
						|
    NewVariable->Device.Bus                = (UINT8) ConfigFormEntry->Bus;
 | 
						|
    NewVariable->Device.Device             = (UINT8) ConfigFormEntry->Device;
 | 
						|
    NewVariable->Device.Function           = (UINT8) ConfigFormEntry->Function;
 | 
						|
    NewVariable->Device.Port               = ConfigFormEntry->Port;
 | 
						|
    NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
 | 
						|
    CopyMem (&NewVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
 | 
						|
  }
 | 
						|
  Status = gRT->SetVariable (
 | 
						|
                  HDD_PASSWORD_REQUEST_VARIABLE_NAME,
 | 
						|
                  &mHddPasswordVendorGuid,
 | 
						|
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                  NewVariableSize,
 | 
						|
                  NewVariable
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_INFO, "HddPasswordRequest variable set failed (%r)\n", Status));
 | 
						|
  }
 | 
						|
  if (NewVariable != Variable) {
 | 
						|
    FreePool (NewVariable);
 | 
						|
  }
 | 
						|
  if (Variable != NULL) {
 | 
						|
    FreePool (Variable);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the HDD Password configuration form entry by the index of the goto opcode activated.
 | 
						|
 | 
						|
  @param[in]  Index The 0-based index of the goto opcode activated.
 | 
						|
 | 
						|
  @return The HDD Password configuration form entry found.
 | 
						|
**/
 | 
						|
HDD_PASSWORD_CONFIG_FORM_ENTRY *
 | 
						|
HddPasswordGetConfigFormEntryByIndex (
 | 
						|
  IN UINT32 Index
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                     *Entry;
 | 
						|
  UINT32                         CurrentIndex;
 | 
						|
  HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;
 | 
						|
 | 
						|
  CurrentIndex    = 0;
 | 
						|
  ConfigFormEntry = NULL;
 | 
						|
 | 
						|
  BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
    if (CurrentIndex == Index) {
 | 
						|
      ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentIndex++;
 | 
						|
  }
 | 
						|
 | 
						|
  return ConfigFormEntry;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function allows the caller to request the current
 | 
						|
  configuration for one or more named elements. The resulting
 | 
						|
  string is in <ConfigAltResp> format. Any and all alternative
 | 
						|
  configuration strings shall also be appended to the end of the
 | 
						|
  current configuration string. If they are, they must appear
 | 
						|
  after the current configuration. They must contain the same
 | 
						|
  routing (GUID, NAME, PATH) as the current configuration string.
 | 
						|
  They must have an additional description indicating the type of
 | 
						|
  alternative configuration the string represents,
 | 
						|
  "ALTCFG=<StringToken>". That <StringToken> (when
 | 
						|
  converted from Hex UNICODE to binary) is a reference to a
 | 
						|
  string in the associated string pack.
 | 
						|
 | 
						|
  @param[in] This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in] Request    A null-terminated Unicode string in
 | 
						|
                        <ConfigRequest> format. Note that this
 | 
						|
                        includes the routing information as well as
 | 
						|
                        the configurable name / value pairs. It is
 | 
						|
                        invalid for this string to be in
 | 
						|
                        <MultiConfigRequest> format.
 | 
						|
  @param[out] 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[out] Results   A null-terminated Unicode string in
 | 
						|
                        <ConfigAltResp> format which has all values
 | 
						|
                        filled in for the names in the Request string.
 | 
						|
                        String to be allocated by the called function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Results string is filled with the
 | 
						|
                                  values corresponding to all requested
 | 
						|
                                  names.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
 | 
						|
                                  parts of the results that must be
 | 
						|
                                  stored awaiting possible future
 | 
						|
                                  protocols.
 | 
						|
  @retval EFI_INVALID_PARAMETER   For example, passing in a NULL
 | 
						|
                                  for the Request parameter
 | 
						|
                                  would result in this type of
 | 
						|
                                  error. In this case, the
 | 
						|
                                  Progress parameter would be
 | 
						|
                                  set to NULL.
 | 
						|
  @retval EFI_NOT_FOUND           Routing data doesn't match any
 | 
						|
                                  known driver. Progress set to the
 | 
						|
                                  first character in the routing header.
 | 
						|
                                  Note: There is no requirement that the
 | 
						|
                                  driver validate the routing data. It
 | 
						|
                                  must skip the <ConfigHdr> in order to
 | 
						|
                                  process the names.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
 | 
						|
                                  to most recent & before the
 | 
						|
                                  error or the beginning of the
 | 
						|
                                  string.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
 | 
						|
                                  to the & before the name in
 | 
						|
                                  question.Currently not implemented.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HddPasswordFormExtractConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  CONST EFI_STRING                       Request,
 | 
						|
  OUT EFI_STRING                             *Progress,
 | 
						|
  OUT EFI_STRING                             *Results
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  UINTN                            BufferSize;
 | 
						|
  HDD_PASSWORD_CONFIG              *IfrData;
 | 
						|
  HDD_PASSWORD_DXE_PRIVATE_DATA    *Private;
 | 
						|
  EFI_STRING                       ConfigRequestHdr;
 | 
						|
  EFI_STRING                       ConfigRequest;
 | 
						|
  BOOLEAN                          AllocatedRequest;
 | 
						|
  UINTN                            Size;
 | 
						|
 | 
						|
  if (Progress == NULL || Results == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress = Request;
 | 
						|
  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  ConfigRequestHdr = NULL;
 | 
						|
  ConfigRequest    = NULL;
 | 
						|
  AllocatedRequest = FALSE;
 | 
						|
  Size             = 0;
 | 
						|
 | 
						|
  Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);
 | 
						|
  IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));
 | 
						|
  ASSERT (IfrData != NULL);
 | 
						|
  if (Private->Current != NULL) {
 | 
						|
    CopyMem (IfrData, &Private->Current->IfrData, sizeof (HDD_PASSWORD_CONFIG));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
 | 
						|
  //
 | 
						|
  BufferSize = sizeof (HDD_PASSWORD_CONFIG);
 | 
						|
  ConfigRequest = Request;
 | 
						|
  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | 
						|
    //
 | 
						|
    // Request has no request element, construct full request string.
 | 
						|
    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | 
						|
    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | 
						|
    //
 | 
						|
    ConfigRequestHdr = HiiConstructConfigHdr (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, Private->DriverHandle);
 | 
						|
    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | 
						|
    ConfigRequest = AllocateZeroPool (Size);
 | 
						|
    ASSERT (ConfigRequest != NULL);
 | 
						|
    AllocatedRequest = TRUE;
 | 
						|
    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | 
						|
    FreePool (ConfigRequestHdr);
 | 
						|
  }
 | 
						|
  Status = gHiiConfigRouting->BlockToConfig (
 | 
						|
                                gHiiConfigRouting,
 | 
						|
                                ConfigRequest,
 | 
						|
                                (UINT8 *) IfrData,
 | 
						|
                                BufferSize,
 | 
						|
                                Results,
 | 
						|
                                Progress
 | 
						|
                                );
 | 
						|
  FreePool (IfrData);
 | 
						|
  //
 | 
						|
  // Free the allocated config request string.
 | 
						|
  //
 | 
						|
  if (AllocatedRequest) {
 | 
						|
    FreePool (ConfigRequest);
 | 
						|
    ConfigRequest = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set Progress string to the original request string.
 | 
						|
  //
 | 
						|
  if (Request == NULL) {
 | 
						|
    *Progress = NULL;
 | 
						|
  } else if (StrStr (Request, L"OFFSET") == NULL) {
 | 
						|
    *Progress = Request + StrLen (Request);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function applies changes in a driver's configuration.
 | 
						|
  Input is a Configuration, which has the routing data for this
 | 
						|
  driver followed by name / value configuration pairs. The driver
 | 
						|
  must apply those pairs to its configurable storage. If the
 | 
						|
  driver's configuration is stored in a linear block of data
 | 
						|
  and the driver's name / value pairs are in <BlockConfig>
 | 
						|
  format, it may use the ConfigToBlock helper function (above) to
 | 
						|
  simplify the job. Currently not implemented.
 | 
						|
 | 
						|
  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Configuration  A null-terminated Unicode string in
 | 
						|
                             <ConfigString> format.
 | 
						|
  @param[out] Progress       A pointer to a string filled in with the
 | 
						|
                             offset of the most recent '&' before the
 | 
						|
                             first failing name / value pair (or the
 | 
						|
                             beginn ing 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 have been distributed or are
 | 
						|
                                  awaiting distribution.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
 | 
						|
                                  parts of the results that must be
 | 
						|
                                  stored awaiting possible future
 | 
						|
                                  protocols.
 | 
						|
  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
 | 
						|
                                  Results parameter would result
 | 
						|
                                  in this type of error.
 | 
						|
  @retval EFI_NOT_FOUND           Target for the specified routing data
 | 
						|
                                  was not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HddPasswordFormRouteConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  CONST EFI_STRING                       Configuration,
 | 
						|
  OUT EFI_STRING                             *Progress
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Configuration == NULL || Progress == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check routing data in <ConfigHdr>.
 | 
						|
  // Note: if only one Storage is used, then this checking could be skipped.
 | 
						|
  //
 | 
						|
  if (!HiiIsConfigHdrMatch (Configuration, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {
 | 
						|
    *Progress = Configuration;
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress = Configuration + StrLen (Configuration);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is called to provide results data to the driver.
 | 
						|
  This data consists of a unique key that is used to identify
 | 
						|
  which data is either being passed back or being asked for.
 | 
						|
 | 
						|
  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Action             Specifies the type of action taken by the browser.
 | 
						|
  @param[in]  QuestionId         A unique value which is sent to the original
 | 
						|
                                 exporting driver so that it can identify the type
 | 
						|
                                 of data to expect. The format of the data tends to
 | 
						|
                                 vary based on the opcode that enerated the callback.
 | 
						|
  @param[in]  Type               The type of value for the question.
 | 
						|
  @param[in]  Value              A pointer to the data being sent to the original
 | 
						|
                                 exporting driver.
 | 
						|
  @param[out]  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.Currently not implemented.
 | 
						|
  @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
 | 
						|
  @retval Others                 Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HddPasswordFormCallback (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  EFI_BROWSER_ACTION                     Action,
 | 
						|
  IN  EFI_QUESTION_ID                        QuestionId,
 | 
						|
  IN  UINT8                                  Type,
 | 
						|
  IN  EFI_IFR_TYPE_VALUE                     *Value,
 | 
						|
  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
 | 
						|
  )
 | 
						|
{
 | 
						|
  HDD_PASSWORD_DXE_PRIVATE_DATA   *Private;
 | 
						|
  EFI_STRING_ID                    DeviceFormTitleToken;
 | 
						|
  HDD_PASSWORD_CONFIG              *IfrData;
 | 
						|
  HDD_PASSWORD_CONFIG_FORM_ENTRY   *ConfigFormEntry;
 | 
						|
 | 
						|
  if (ActionRequest != NULL) {
 | 
						|
    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
 | 
						|
  } else {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
 | 
						|
    //
 | 
						|
    // Do nothing for other UEFI Action. Only do call back when data is changing or changed.
 | 
						|
    //
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrive data from Browser
 | 
						|
  //
 | 
						|
  IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));
 | 
						|
  ASSERT (IfrData != NULL);
 | 
						|
  if (!HiiGetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData)) {
 | 
						|
    FreePool (IfrData);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (QuestionId) {
 | 
						|
  case KEY_HDD_USER_PASSWORD:
 | 
						|
    if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | 
						|
      DEBUG ((DEBUG_INFO, "KEY_HDD_USER_PASSWORD\n"));
 | 
						|
      ConfigFormEntry = Private->Current;
 | 
						|
      ConfigFormEntry->IfrData.Request.UserPassword = Value->b;
 | 
						|
      SaveHddPasswordRequest (ConfigFormEntry);
 | 
						|
      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case KEY_HDD_MASTER_PASSWORD:
 | 
						|
    if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | 
						|
      DEBUG ((DEBUG_INFO, "KEY_HDD_MASTER_PASSWORD\n"));
 | 
						|
      ConfigFormEntry = Private->Current;
 | 
						|
      ConfigFormEntry->IfrData.Request.MasterPassword = Value->b;
 | 
						|
      SaveHddPasswordRequest (ConfigFormEntry);
 | 
						|
      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    if ((QuestionId >= KEY_HDD_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfHddDevices + KEY_HDD_DEVICE_ENTRY_BASE))) {
 | 
						|
      if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | 
						|
        //
 | 
						|
        // In case goto the device configuration form, update the device form title.
 | 
						|
        //
 | 
						|
        ConfigFormEntry = HddPasswordGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_HDD_DEVICE_ENTRY_BASE));
 | 
						|
        ASSERT (ConfigFormEntry != NULL);
 | 
						|
 | 
						|
        DeviceFormTitleToken = (EFI_STRING_ID) STR_HDD_SECURITY_HD;
 | 
						|
        HiiSetString (Private->HiiHandle, DeviceFormTitleToken, ConfigFormEntry->HddString, NULL);
 | 
						|
 | 
						|
        Private->Current = ConfigFormEntry;
 | 
						|
        CopyMem (IfrData, &ConfigFormEntry->IfrData, sizeof (HDD_PASSWORD_CONFIG));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Pass changed uncommitted data back to Form Browser
 | 
						|
  //
 | 
						|
  HiiSetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData, NULL);
 | 
						|
 | 
						|
  FreePool (IfrData);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Updates the HDD Password configuration form to add an entry for the attached
 | 
						|
  ata harddisk device specified by the Controller.
 | 
						|
 | 
						|
  @param[in] HiiHandle            The HII Handle associated with the registered package list.
 | 
						|
  @param[in] AtaPassThru          Pointer to ATA_PASSTHRU instance.
 | 
						|
  @param[in] PciIo                Pointer to PCI_IO instance.
 | 
						|
  @param[in] Controller           The controller handle of the attached ata controller.
 | 
						|
  @param[in] Bus                  The bus number of ATA controller.
 | 
						|
  @param[in] Device               The device number of ATA controller.
 | 
						|
  @param[in] Function             The function number of ATA controller.
 | 
						|
  @param[in] Port                 The port number of attached ATA device.
 | 
						|
  @param[in] PortMultiplierPort   The port number of port multiplier of attached ATA device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Hdd Password configuration form is updated.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | 
						|
  @retval Others                  Other errors as indicated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HddPasswordConfigUpdateForm (
 | 
						|
  IN EFI_HII_HANDLE              HiiHandle,
 | 
						|
  IN EFI_ATA_PASS_THRU_PROTOCOL  *AtaPassThru,
 | 
						|
  IN EFI_PCI_IO_PROTOCOL         *PciIo,
 | 
						|
  IN EFI_HANDLE                  Controller,
 | 
						|
  IN UINTN                       Bus,
 | 
						|
  IN UINTN                       Device,
 | 
						|
  IN UINTN                       Function,
 | 
						|
  IN UINT16                      Port,
 | 
						|
  IN UINT16                      PortMultiplierPort
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                       *Entry;
 | 
						|
  HDD_PASSWORD_CONFIG_FORM_ENTRY   *ConfigFormEntry;
 | 
						|
  BOOLEAN                          EntryExisted;
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  VOID                             *StartOpCodeHandle;
 | 
						|
  VOID                             *EndOpCodeHandle;
 | 
						|
  EFI_IFR_GUID_LABEL               *StartLabel;
 | 
						|
  EFI_IFR_GUID_LABEL               *EndLabel;
 | 
						|
  CHAR16                           HddString[40];
 | 
						|
  ATA_IDENTIFY_DATA                IdentifyData;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL         *AtaDeviceNode;
 | 
						|
 | 
						|
  ConfigFormEntry = NULL;
 | 
						|
  EntryExisted    = FALSE;
 | 
						|
 | 
						|
  BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
    ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
 | 
						|
    if ((ConfigFormEntry->Bus == Bus) &&
 | 
						|
        (ConfigFormEntry->Device == Device) &&
 | 
						|
        (ConfigFormEntry->Function == Function) &&
 | 
						|
        (ConfigFormEntry->Port == Port) &&
 | 
						|
        (ConfigFormEntry->PortMultiplierPort == PortMultiplierPort)) {
 | 
						|
      EntryExisted = TRUE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EntryExisted) {
 | 
						|
    //
 | 
						|
    // Add a new form.
 | 
						|
    //
 | 
						|
    ConfigFormEntry = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY));
 | 
						|
    if (ConfigFormEntry == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    InitializeListHead (&ConfigFormEntry->Link);
 | 
						|
    ConfigFormEntry->Controller         = Controller;
 | 
						|
    ConfigFormEntry->Bus                = Bus;
 | 
						|
    ConfigFormEntry->Device             = Device;
 | 
						|
    ConfigFormEntry->Function           = Function;
 | 
						|
    ConfigFormEntry->Port               = Port;
 | 
						|
    ConfigFormEntry->PortMultiplierPort = PortMultiplierPort;
 | 
						|
    ConfigFormEntry->AtaPassThru        = AtaPassThru;
 | 
						|
 | 
						|
    DEBUG ((DEBUG_INFO, "HddPasswordDxe: Create new form for device[%d][%d] at Bus 0x%x Dev 0x%x Func 0x%x\n", Port, PortMultiplierPort, Bus, Device, Function));
 | 
						|
 | 
						|
    //
 | 
						|
    // Construct the device path for the HDD password device
 | 
						|
    //
 | 
						|
    Status = AtaPassThru->BuildDevicePath (
 | 
						|
                            AtaPassThru,
 | 
						|
                            Port,
 | 
						|
                            PortMultiplierPort,
 | 
						|
                            &AtaDeviceNode
 | 
						|
                            );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    ConfigFormEntry->DevicePath = AppendDevicePathNode (DevicePathFromHandle (Controller), AtaDeviceNode);
 | 
						|
    FreePool (AtaDeviceNode);
 | 
						|
    if (ConfigFormEntry->DevicePath == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get attached harddisk model number
 | 
						|
    //
 | 
						|
    Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    GetHddDeviceModelNumber (&IdentifyData, HddString);
 | 
						|
    //
 | 
						|
    // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.
 | 
						|
    //
 | 
						|
    UnicodeSPrint (ConfigFormEntry->HddString, sizeof (ConfigFormEntry->HddString), L"HDD %d:%s", mNumberOfHddDevices, HddString);
 | 
						|
    ConfigFormEntry->TitleToken     = HiiSetString (HiiHandle, 0, ConfigFormEntry->HddString, NULL);
 | 
						|
    ConfigFormEntry->TitleHelpToken = HiiSetString (HiiHandle, 0, L"Request to set HDD Password", NULL);
 | 
						|
 | 
						|
    GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
 | 
						|
 | 
						|
    InsertTailList (&mHddPasswordConfigFormList, &ConfigFormEntry->Link);
 | 
						|
 | 
						|
    //
 | 
						|
    // Init OpCode Handle
 | 
						|
    //
 | 
						|
    StartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | 
						|
    ASSERT (StartOpCodeHandle != NULL);
 | 
						|
 | 
						|
    EndOpCodeHandle = HiiAllocateOpCodeHandle ();
 | 
						|
    ASSERT (EndOpCodeHandle != NULL);
 | 
						|
 | 
						|
    //
 | 
						|
    // Create Hii Extend Label OpCode as the start opcode
 | 
						|
    //
 | 
						|
    StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | 
						|
    StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | 
						|
    StartLabel->Number       = HDD_DEVICE_ENTRY_LABEL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Create Hii Extend Label OpCode as the end opcode
 | 
						|
    //
 | 
						|
    EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
 | 
						|
    EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | 
						|
    EndLabel->Number       = HDD_DEVICE_LABEL_END;
 | 
						|
 | 
						|
    mNumberOfHddDevices = 0;
 | 
						|
    BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
 | 
						|
      ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
 | 
						|
 | 
						|
      HiiCreateGotoOpCode (
 | 
						|
        StartOpCodeHandle,                                // Container for dynamic created opcodes
 | 
						|
        FORMID_HDD_DEVICE_FORM,                           // Target Form ID
 | 
						|
        ConfigFormEntry->TitleToken,                      // Prompt text
 | 
						|
        ConfigFormEntry->TitleHelpToken,                  // Help text
 | 
						|
        EFI_IFR_FLAG_CALLBACK,                            // Question flag
 | 
						|
        (UINT16) (KEY_HDD_DEVICE_ENTRY_BASE + mNumberOfHddDevices)   // Question ID
 | 
						|
        );
 | 
						|
 | 
						|
      mNumberOfHddDevices++;
 | 
						|
    }
 | 
						|
 | 
						|
    HiiUpdateForm (
 | 
						|
      HiiHandle,
 | 
						|
      &mHddPasswordVendorGuid,
 | 
						|
      FORMID_HDD_MAIN_FORM,
 | 
						|
      StartOpCodeHandle,
 | 
						|
      EndOpCodeHandle
 | 
						|
      );
 | 
						|
 | 
						|
    HiiFreeOpCodeHandle (StartOpCodeHandle);
 | 
						|
    HiiFreeOpCodeHandle (EndOpCodeHandle);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check if device is locked and prompt for password.
 | 
						|
    //
 | 
						|
    HddPasswordRequestPassword (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
 | 
						|
 | 
						|
    //
 | 
						|
    // Process HDD password request from last boot.
 | 
						|
    //
 | 
						|
    ProcessHddPasswordRequest (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Ata Pass Thru Protocol notification event handler.
 | 
						|
 | 
						|
  Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.
 | 
						|
  It also registers a form for user configuration on Hdd password configuration.
 | 
						|
 | 
						|
  @param[in] Event    Event whose notification function is being invoked.
 | 
						|
  @param[in] Context  Pointer to the notification function's context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
HddPasswordNotificationEvent (
 | 
						|
  IN  EFI_EVENT       Event,
 | 
						|
  IN  VOID            *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  HDD_PASSWORD_DXE_PRIVATE_DATA     *Private;
 | 
						|
  EFI_ATA_PASS_THRU_PROTOCOL        *AtaPassThru;
 | 
						|
  UINT16                            Port;
 | 
						|
  UINT16                            PortMultiplierPort;
 | 
						|
  EFI_HANDLE                        Controller;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  UINTN                             HandleCount;
 | 
						|
  UINTN                             Index;
 | 
						|
  EFI_PCI_IO_PROTOCOL               *PciIo;
 | 
						|
  UINTN                             SegNum;
 | 
						|
  UINTN                             BusNum;
 | 
						|
  UINTN                             DevNum;
 | 
						|
  UINTN                             FuncNum;
 | 
						|
 | 
						|
  if (mHddPasswordEndOfDxe) {
 | 
						|
    gBS->CloseEvent (Event);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = (HDD_PASSWORD_DXE_PRIVATE_DATA *)Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate all handles of AtaPassThru protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiAtaPassThruProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check attached hard disk status to see if it's locked
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HandleCount; Index += 1) {
 | 
						|
    Controller = HandleBuffer[Index];
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiAtaPassThruProtocolGuid,
 | 
						|
                    (VOID **) &AtaPassThru
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Ignore those logical ATA_PASS_THRU instance.
 | 
						|
    //
 | 
						|
    if ((AtaPassThru->Mode->Attributes & EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = PciIo->GetLocation (
 | 
						|
                      PciIo,
 | 
						|
                      &SegNum,
 | 
						|
                      &BusNum,
 | 
						|
                      &DevNum,
 | 
						|
                      &FuncNum
 | 
						|
                      );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Assume and only support Segment == 0.
 | 
						|
    //
 | 
						|
    ASSERT (SegNum == 0);
 | 
						|
 | 
						|
    //
 | 
						|
    // traverse all attached harddisk devices to update form and unlock it
 | 
						|
    //
 | 
						|
    Port = 0xFFFF;
 | 
						|
 | 
						|
    while (TRUE) {
 | 
						|
      Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // We cannot find more legal port then we are done.
 | 
						|
        //
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      PortMultiplierPort = 0xFFFF;
 | 
						|
      while (TRUE) {
 | 
						|
        Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          //
 | 
						|
          // We cannot find more legal port multiplier port number for ATA device
 | 
						|
          // on the port, then we are done.
 | 
						|
          //
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Find out the attached harddisk devices.
 | 
						|
        // Try to add a HDD Password configuration page for the attached devices.
 | 
						|
        //
 | 
						|
        gBS->RestoreTPL (TPL_APPLICATION);
 | 
						|
        Status = HddPasswordConfigUpdateForm (Private->HiiHandle, AtaPassThru, PciIo, Controller, BusNum, DevNum, FuncNum, Port, PortMultiplierPort);
 | 
						|
        gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize the HDD Password configuration form.
 | 
						|
 | 
						|
  @param[out] Instance             Pointer to private instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The HDD Password configuration form is initialized.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES     Failed to allocate memory.
 | 
						|
  @retval Others                   Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
HddPasswordConfigFormInit (
 | 
						|
  OUT HDD_PASSWORD_DXE_PRIVATE_DATA    **Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  HDD_PASSWORD_DXE_PRIVATE_DATA    *Private;
 | 
						|
 | 
						|
  InitializeListHead (&mHddPasswordConfigFormList);
 | 
						|
 | 
						|
  Private = AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA));
 | 
						|
  if (Private == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Signature   = HDD_PASSWORD_DXE_PRIVATE_SIGNATURE;
 | 
						|
 | 
						|
  Private->ConfigAccess.ExtractConfig = HddPasswordFormExtractConfig;
 | 
						|
  Private->ConfigAccess.RouteConfig   = HddPasswordFormRouteConfig;
 | 
						|
  Private->ConfigAccess.Callback      = HddPasswordFormCallback;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install Device Path Protocol and Config Access protocol to driver handle
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Private->DriverHandle,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  &mHddPasswordHiiVendorDevicePath,
 | 
						|
                  &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
                  &Private->ConfigAccess,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool(Private);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Publish our HII data
 | 
						|
  //
 | 
						|
  Private->HiiHandle = HiiAddPackages (
 | 
						|
                         &mHddPasswordVendorGuid,
 | 
						|
                         Private->DriverHandle,
 | 
						|
                         HddPasswordDxeStrings,
 | 
						|
                         HddPasswordBin,
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  if (Private->HiiHandle == NULL) {
 | 
						|
    FreePool(Private);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *Instance = Private;
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Main entry for this driver.
 | 
						|
 | 
						|
  @param ImageHandle     Image handle this driver.
 | 
						|
  @param SystemTable     Pointer to SystemTable.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS     This function always complete successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HddPasswordDxeInit (
 | 
						|
  IN EFI_HANDLE                   ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE             *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  HDD_PASSWORD_DXE_PRIVATE_DATA  *Private;
 | 
						|
  VOID                           *Registration;
 | 
						|
  EFI_EVENT                      EndOfDxeEvent;
 | 
						|
  EDKII_VARIABLE_LOCK_PROTOCOL   *VariableLock;
 | 
						|
 | 
						|
  Private = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the configuration form of HDD Password.
 | 
						|
  //
 | 
						|
  Status = HddPasswordConfigFormInit (&Private);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Register HddPasswordNotificationEvent() notify function.
 | 
						|
  //
 | 
						|
  EfiCreateProtocolNotifyEvent (
 | 
						|
    &gEfiAtaPassThruProtocolGuid,
 | 
						|
    TPL_CALLBACK,
 | 
						|
    HddPasswordNotificationEvent,
 | 
						|
    (VOID *)Private,
 | 
						|
    &Registration
 | 
						|
    );
 | 
						|
 | 
						|
  Status = gBS->CreateEventEx (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  HddPasswordEndOfDxeEventNotify,
 | 
						|
                  NULL,
 | 
						|
                  &gEfiEndOfDxeEventGroupGuid,
 | 
						|
                  &EndOfDxeEvent
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Make HDD_PASSWORD_VARIABLE_NAME variable read-only.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = VariableLock->RequestToLock (
 | 
						|
                             VariableLock,
 | 
						|
                             HDD_PASSWORD_VARIABLE_NAME,
 | 
						|
                             &mHddPasswordVendorGuid
 | 
						|
                             );
 | 
						|
    DEBUG ((DEBUG_INFO, "%a(): Lock %s variable (%r)\n", __FUNCTION__, HDD_PASSWORD_VARIABLE_NAME, Status));
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |