SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1409

For the current implementation of OpalPassword drivers, it has a feature
to support devices being automatically unlocked in the S3 resume. For this
feature, two types of devices are supported:

* ATA hard disks working under AHCI mode
* NVM Express devices

The support of this feature requires the above 2 types of device to be
initialized at the PEI phase during S3 resume, which is done by the
co-work of the OpalPasswordDxe driver and the OpalPasswordPei driver.

More specifically, the OpalPasswordDxe will handle:

* Pre-allocate MMIO resource and save it in a driver internal LockBox for
  OpalPasswordPei to retrieve;
* Save the PCI configuration space of ATA controllers into boot script.

Meanwhile, the OpalPasswordPei will handle:

* Rely on the boot script for the PCI configuration space program of ATA
  controllers;
* Restore the driver internal LockBox to get the MMIO resource;
* Complete the PCI configuration space program for ATA and NVME
  controllers;
* Initialize ATA and NVME controllers and devices.

This commit will remove these hardware initialization related codes from
the OpalPassword drivers. The hardware initialization will be covered by
PEI storage device drivers (e.g. NvmExpressPei & AhciPei in the
MdeModulePkg).

After such codes removal, the OpalPasswordDxe will only handle:

* Construct/update the S3StorageDeviceInitList LockBox with the managing
  ATA and NVME devices.

And the OpalPasswordPei will only handle:

* Locate Storage Security Command PPI instances to perform the device
  automatic unlock during the S3 resume.

Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
Hao Wu 2018-08-27 16:52:13 +08:00
parent b6de92f74e
commit a3efbc29c4
12 changed files with 301 additions and 5692 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,412 +0,0 @@
/** @file
Header file for AHCI mode of ATA host controller.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __OPAL_PASSWORD_AHCI_MODE_H__
#define __OPAL_PASSWORD_AHCI_MODE_H__
//
// OPAL LIBRARY CALLBACKS
//
#define ATA_COMMAND_TRUSTED_RECEIVE 0x5C
#define ATA_COMMAND_TRUSTED_SEND 0x5E
//
// ATA TRUSTED commands express transfer Length in 512 byte multiple
//
#define ATA_TRUSTED_TRANSFER_LENGTH_MULTIPLE 512
#define ATA_DEVICE_LBA 0x40 ///< Set for commands with LBA (rather than CHS) addresses
#define EFI_AHCI_BAR_INDEX 0x05
#define EFI_AHCI_CAPABILITY_OFFSET 0x0000
#define EFI_AHCI_CAP_SAM BIT18
#define EFI_AHCI_GHC_OFFSET 0x0004
#define EFI_AHCI_GHC_RESET BIT0
#define EFI_AHCI_GHC_IE BIT1
#define EFI_AHCI_GHC_ENABLE BIT31
#define EFI_AHCI_IS_OFFSET 0x0008
#define EFI_AHCI_PI_OFFSET 0x000C
typedef struct {
UINT32 Lower32;
UINT32 Upper32;
} DATA_32;
typedef union {
DATA_32 Uint32;
UINT64 Uint64;
} DATA_64;
//
// Each PRDT entry can point to a memory block up to 4M byte
//
#define EFI_AHCI_MAX_DATA_PER_PRDT 0x400000
#define EFI_AHCI_FIS_REGISTER_H2D 0x27 //Register FIS - Host to Device
#define EFI_AHCI_FIS_REGISTER_H2D_LENGTH 20
#define EFI_AHCI_FIS_REGISTER_D2H 0x34 //Register FIS - Device to Host
#define EFI_AHCI_FIS_REGISTER_D2H_LENGTH 20
#define EFI_AHCI_FIS_DMA_ACTIVATE 0x39 //DMA Activate FIS - Device to Host
#define EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH 4
#define EFI_AHCI_FIS_DMA_SETUP 0x41 //DMA Setup FIS - Bi-directional
#define EFI_AHCI_FIS_DMA_SETUP_LENGTH 28
#define EFI_AHCI_FIS_DATA 0x46 //Data FIS - Bi-directional
#define EFI_AHCI_FIS_BIST 0x58 //BIST Activate FIS - Bi-directional
#define EFI_AHCI_FIS_BIST_LENGTH 12
#define EFI_AHCI_FIS_PIO_SETUP 0x5F //PIO Setup FIS - Device to Host
#define EFI_AHCI_FIS_PIO_SETUP_LENGTH 20
#define EFI_AHCI_FIS_SET_DEVICE 0xA1 //Set Device Bits FIS - Device to Host
#define EFI_AHCI_FIS_SET_DEVICE_LENGTH 8
#define EFI_AHCI_D2H_FIS_OFFSET 0x40
#define EFI_AHCI_DMA_FIS_OFFSET 0x00
#define EFI_AHCI_PIO_FIS_OFFSET 0x20
#define EFI_AHCI_SDB_FIS_OFFSET 0x58
#define EFI_AHCI_FIS_TYPE_MASK 0xFF
#define EFI_AHCI_U_FIS_OFFSET 0x60
//
// Port register
//
#define EFI_AHCI_PORT_START 0x0100
#define EFI_AHCI_PORT_REG_WIDTH 0x0080
#define EFI_AHCI_PORT_CLB 0x0000
#define EFI_AHCI_PORT_CLBU 0x0004
#define EFI_AHCI_PORT_FB 0x0008
#define EFI_AHCI_PORT_FBU 0x000C
#define EFI_AHCI_PORT_IS 0x0010
#define EFI_AHCI_PORT_IS_DHRS BIT0
#define EFI_AHCI_PORT_IS_PSS BIT1
#define EFI_AHCI_PORT_IS_SSS BIT2
#define EFI_AHCI_PORT_IS_SDBS BIT3
#define EFI_AHCI_PORT_IS_UFS BIT4
#define EFI_AHCI_PORT_IS_DPS BIT5
#define EFI_AHCI_PORT_IS_PCS BIT6
#define EFI_AHCI_PORT_IS_DIS BIT7
#define EFI_AHCI_PORT_IS_PRCS BIT22
#define EFI_AHCI_PORT_IS_IPMS BIT23
#define EFI_AHCI_PORT_IS_OFS BIT24
#define EFI_AHCI_PORT_IS_INFS BIT26
#define EFI_AHCI_PORT_IS_IFS BIT27
#define EFI_AHCI_PORT_IS_HBDS BIT28
#define EFI_AHCI_PORT_IS_HBFS BIT29
#define EFI_AHCI_PORT_IS_TFES BIT30
#define EFI_AHCI_PORT_IS_CPDS BIT31
#define EFI_AHCI_PORT_IS_CLEAR 0xFFFFFFFF
#define EFI_AHCI_PORT_IS_FIS_CLEAR 0x0000000F
#define EFI_AHCI_PORT_IE 0x0014
#define EFI_AHCI_PORT_CMD 0x0018
#define EFI_AHCI_PORT_CMD_ST_MASK 0xFFFFFFFE
#define EFI_AHCI_PORT_CMD_ST BIT0
#define EFI_AHCI_PORT_CMD_SUD BIT1
#define EFI_AHCI_PORT_CMD_POD BIT2
#define EFI_AHCI_PORT_CMD_COL BIT3
#define EFI_AHCI_PORT_CMD_CR BIT15
#define EFI_AHCI_PORT_CMD_FRE BIT4
#define EFI_AHCI_PORT_CMD_FR BIT14
#define EFI_AHCI_PORT_CMD_MASK ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL)
#define EFI_AHCI_PORT_CMD_PMA BIT17
#define EFI_AHCI_PORT_CMD_HPCP BIT18
#define EFI_AHCI_PORT_CMD_MPSP BIT19
#define EFI_AHCI_PORT_CMD_CPD BIT20
#define EFI_AHCI_PORT_CMD_ESP BIT21
#define EFI_AHCI_PORT_CMD_ATAPI BIT24
#define EFI_AHCI_PORT_CMD_DLAE BIT25
#define EFI_AHCI_PORT_CMD_ALPE BIT26
#define EFI_AHCI_PORT_CMD_ASP BIT27
#define EFI_AHCI_PORT_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31)
#define EFI_AHCI_PORT_CMD_ACTIVE (1 << 28 )
#define EFI_AHCI_PORT_TFD 0x0020
#define EFI_AHCI_PORT_TFD_MASK (BIT7 | BIT3 | BIT0)
#define EFI_AHCI_PORT_TFD_BSY BIT7
#define EFI_AHCI_PORT_TFD_DRQ BIT3
#define EFI_AHCI_PORT_TFD_ERR BIT0
#define EFI_AHCI_PORT_TFD_ERR_MASK 0x00FF00
#define EFI_AHCI_PORT_SIG 0x0024
#define EFI_AHCI_PORT_SSTS 0x0028
#define EFI_AHCI_PORT_SSTS_DET_MASK 0x000F
#define EFI_AHCI_PORT_SSTS_DET 0x0001
#define EFI_AHCI_PORT_SSTS_DET_PCE 0x0003
#define EFI_AHCI_PORT_SSTS_SPD_MASK 0x00F0
#define EFI_AHCI_PORT_SCTL 0x002C
#define EFI_AHCI_PORT_SCTL_DET_MASK 0x000F
#define EFI_AHCI_PORT_SCTL_MASK (~EFI_AHCI_PORT_SCTL_DET_MASK)
#define EFI_AHCI_PORT_SCTL_DET_INIT 0x0001
#define EFI_AHCI_PORT_SCTL_DET_PHYCOMM 0x0003
#define EFI_AHCI_PORT_SCTL_SPD_MASK 0x00F0
#define EFI_AHCI_PORT_SCTL_IPM_MASK 0x0F00
#define EFI_AHCI_PORT_SCTL_IPM_INIT 0x0300
#define EFI_AHCI_PORT_SCTL_IPM_PSD 0x0100
#define EFI_AHCI_PORT_SCTL_IPM_SSD 0x0200
#define EFI_AHCI_PORT_SERR 0x0030
#define EFI_AHCI_PORT_SERR_RDIE BIT0
#define EFI_AHCI_PORT_SERR_RCE BIT1
#define EFI_AHCI_PORT_SERR_TDIE BIT8
#define EFI_AHCI_PORT_SERR_PCDIE BIT9
#define EFI_AHCI_PORT_SERR_PE BIT10
#define EFI_AHCI_PORT_SERR_IE BIT11
#define EFI_AHCI_PORT_SERR_PRC BIT16
#define EFI_AHCI_PORT_SERR_PIE BIT17
#define EFI_AHCI_PORT_SERR_CW BIT18
#define EFI_AHCI_PORT_SERR_BDE BIT19
#define EFI_AHCI_PORT_SERR_DE BIT20
#define EFI_AHCI_PORT_SERR_CRCE BIT21
#define EFI_AHCI_PORT_SERR_HE BIT22
#define EFI_AHCI_PORT_SERR_LSE BIT23
#define EFI_AHCI_PORT_SERR_TSTE BIT24
#define EFI_AHCI_PORT_SERR_UFT BIT25
#define EFI_AHCI_PORT_SERR_EX BIT26
#define EFI_AHCI_PORT_ERR_CLEAR 0xFFFFFFFF
#define EFI_AHCI_PORT_SACT 0x0034
#define EFI_AHCI_PORT_CI 0x0038
#define EFI_AHCI_PORT_SNTF 0x003C
#pragma pack(1)
//
// Command List structure includes total 32 entries.
// The entry Data structure is listed at the following.
//
typedef struct {
UINT32 AhciCmdCfl:5; //Command FIS Length
UINT32 AhciCmdA:1; //ATAPI
UINT32 AhciCmdW:1; //Write
UINT32 AhciCmdP:1; //Prefetchable
UINT32 AhciCmdR:1; //Reset
UINT32 AhciCmdB:1; //BIST
UINT32 AhciCmdC:1; //Clear Busy upon R_OK
UINT32 AhciCmdRsvd:1;
UINT32 AhciCmdPmp:4; //Port Multiplier Port
UINT32 AhciCmdPrdtl:16; //Physical Region Descriptor Table Length
UINT32 AhciCmdPrdbc; //Physical Region Descriptor Byte Count
UINT32 AhciCmdCtba; //Command Table Descriptor Base Address
UINT32 AhciCmdCtbau; //Command Table Descriptor Base Address Upper 32-BITs
UINT32 AhciCmdRsvd1[4];
} EFI_AHCI_COMMAND_LIST;
//
// This is a software constructed FIS.
// For Data transfer operations, this is the H2D Register FIS format as
// specified in the Serial ATA Revision 2.6 specification.
//
typedef struct {
UINT8 AhciCFisType;
UINT8 AhciCFisPmNum:4;
UINT8 AhciCFisRsvd:1;
UINT8 AhciCFisRsvd1:1;
UINT8 AhciCFisRsvd2:1;
UINT8 AhciCFisCmdInd:1;
UINT8 AhciCFisCmd;
UINT8 AhciCFisFeature;
UINT8 AhciCFisSecNum;
UINT8 AhciCFisClyLow;
UINT8 AhciCFisClyHigh;
UINT8 AhciCFisDevHead;
UINT8 AhciCFisSecNumExp;
UINT8 AhciCFisClyLowExp;
UINT8 AhciCFisClyHighExp;
UINT8 AhciCFisFeatureExp;
UINT8 AhciCFisSecCount;
UINT8 AhciCFisSecCountExp;
UINT8 AhciCFisRsvd3;
UINT8 AhciCFisControl;
UINT8 AhciCFisRsvd4[4];
UINT8 AhciCFisRsvd5[44];
} EFI_AHCI_COMMAND_FIS;
//
// ACMD: ATAPI command (12 or 16 bytes)
//
typedef struct {
UINT8 AtapiCmd[0x10];
} EFI_AHCI_ATAPI_COMMAND;
//
// Physical Region Descriptor Table includes up to 65535 entries
// The entry Data structure is listed at the following.
// the actual entry number comes from the PRDTL field in the command
// list entry for this command slot.
//
typedef struct {
UINT32 AhciPrdtDba; //Data Base Address
UINT32 AhciPrdtDbau; //Data Base Address Upper 32-BITs
UINT32 AhciPrdtRsvd;
UINT32 AhciPrdtDbc:22; //Data Byte Count
UINT32 AhciPrdtRsvd1:9;
UINT32 AhciPrdtIoc:1; //Interrupt on Completion
} EFI_AHCI_COMMAND_PRDT;
//
// Command table Data strucute which is pointed to by the entry in the command list
//
typedef struct {
EFI_AHCI_COMMAND_FIS CommandFis; // A software constructed FIS.
EFI_AHCI_ATAPI_COMMAND AtapiCmd; // 12 or 16 bytes ATAPI cmd.
UINT8 Reserved[0x30];
EFI_AHCI_COMMAND_PRDT PrdtTable; // The scatter/gather list for Data transfer
} EFI_AHCI_COMMAND_TABLE;
//
// Received FIS structure
//
typedef struct {
UINT8 AhciDmaSetupFis[0x1C]; // Dma Setup Fis: offset 0x00
UINT8 AhciDmaSetupFisRsvd[0x04];
UINT8 AhciPioSetupFis[0x14]; // Pio Setup Fis: offset 0x20
UINT8 AhciPioSetupFisRsvd[0x0C];
UINT8 AhciD2HRegisterFis[0x14]; // D2H Register Fis: offset 0x40
UINT8 AhciD2HRegisterFisRsvd[0x04];
UINT64 AhciSetDeviceBitsFis; // Set Device Bits Fix: offset 0x58
UINT8 AhciUnknownFis[0x40]; // Unkonwn Fis: offset 0x60
UINT8 AhciUnknownFisRsvd[0x60];
} EFI_AHCI_RECEIVED_FIS;
#pragma pack()
typedef struct {
EFI_AHCI_RECEIVED_FIS *AhciRFis;
VOID *AhciRFisMapping;
EFI_AHCI_COMMAND_LIST *AhciCmdList;
VOID *AhciCmdListMapping;
EFI_AHCI_COMMAND_TABLE *AhciCommandTable;
VOID *AhciCommandTableMapping;
} EFI_AHCI_REGISTERS;
typedef struct {
VOID *Buffer;
VOID *BufferMapping;
EFI_AHCI_REGISTERS AhciRegisters;
UINT32 AhciBar;
} AHCI_CONTEXT;
/**
Allocate transfer-related data struct which is used at AHCI mode.
@param[in, out] AhciContext The pointer to the AHCI_CONTEXT.
@retval EFI_OUT_OF_RESOURCE No enough resource.
@retval EFI_SUCCESS Successful to allocate resource.
**/
EFI_STATUS
EFIAPI
AhciAllocateResource (
IN OUT AHCI_CONTEXT *AhciContext
);
/**
Free allocated transfer-related data struct which is used at AHCI mode.
@param[in, out] AhciContext The pointer to the AHCI_CONTEXT.
**/
VOID
EFIAPI
AhciFreeResource (
IN OUT AHCI_CONTEXT *AhciContext
);
/**
Initialize ATA host controller at AHCI mode.
The function is designed to initialize ATA host controller.
@param[in] AhciContext The pointer to the AHCI_CONTEXT.
@param[in] Port The port number to do initialization.
**/
EFI_STATUS
EFIAPI
AhciModeInitialize (
IN AHCI_CONTEXT *AhciContext,
IN UINT8 Port
);
typedef struct _EFI_ATA_COMMAND_BLOCK {
UINT8 Reserved1[2];
UINT8 AtaCommand;
UINT8 AtaFeatures;
UINT8 AtaSectorNumber;
UINT8 AtaCylinderLow;
UINT8 AtaCylinderHigh;
UINT8 AtaDeviceHead;
UINT8 AtaSectorNumberExp;
UINT8 AtaCylinderLowExp;
UINT8 AtaCylinderHighExp;
UINT8 AtaFeaturesExp;
UINT8 AtaSectorCount;
UINT8 AtaSectorCountExp;
UINT8 Reserved2[6];
} EFI_ATA_COMMAND_BLOCK;
typedef struct _EFI_ATA_STATUS_BLOCK {
UINT8 Reserved1[2];
UINT8 AtaStatus;
UINT8 AtaError;
UINT8 AtaSectorNumber;
UINT8 AtaCylinderLow;
UINT8 AtaCylinderHigh;
UINT8 AtaDeviceHead;
UINT8 AtaSectorNumberExp;
UINT8 AtaCylinderLowExp;
UINT8 AtaCylinderHighExp;
UINT8 Reserved2;
UINT8 AtaSectorCount;
UINT8 AtaSectorCountExp;
UINT8 Reserved3[6];
} EFI_ATA_STATUS_BLOCK;
/**
Start a PIO Data transfer on specific port.
@param AhciContext The pointer to the AHCI_CONTEXT.
@param Port The number of port.
@param PortMultiplier The timeout Value of stop.
@param AtapiCommand The atapi command will be used for the transfer.
@param AtapiCommandLength The Length of the atapi command.
@param Read The transfer direction.
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK Data.
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK Data.
@param MemoryAddr The pointer to the Data Buffer.
@param DataCount The Data count to be transferred.
@param Timeout The timeout Value of non Data transfer.
@retval EFI_DEVICE_ERROR The PIO Data transfer abort with error occurs.
@retval EFI_TIMEOUT The operation is time out.
@retval EFI_UNSUPPORTED The device is not ready for transfer.
@retval EFI_SUCCESS The PIO Data transfer executes successfully.
**/
EFI_STATUS
EFIAPI
AhciPioTransfer (
IN AHCI_CONTEXT *AhciContext,
IN UINT8 Port,
IN UINT8 PortMultiplier,
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
IN UINT8 AtapiCommandLength,
IN BOOLEAN Read,
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
IN OUT VOID *MemoryAddr,
IN UINT32 DataCount,
IN UINT64 Timeout
);
#endif

View File

@ -21,40 +21,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "OpalDriver.h"
#include "OpalHii.h"
EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
BOOLEAN mOpalEndOfDxe = FALSE;
OPAL_REQUEST_VARIABLE *mOpalRequestVariable = NULL;
UINTN mOpalRequestVariableSize = 0;
CHAR16 mPopUpString[100];
typedef struct {
UINT32 Address;
S3_BOOT_SCRIPT_LIB_WIDTH Width;
} OPAL_HC_PCI_REGISTER_SAVE;
//
// To unlock the Intel SATA controller at S3 Resume, restored the following registers.
//
const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
{0x9, S3BootScriptWidthUint8},
{0x10, S3BootScriptWidthUint32},
{0x14, S3BootScriptWidthUint32},
{0x18, S3BootScriptWidthUint32},
{0x1C, S3BootScriptWidthUint32},
{0x20, S3BootScriptWidthUint32},
{0x24, S3BootScriptWidthUint32},
{0x3c, S3BootScriptWidthUint8},
{0x3d, S3BootScriptWidthUint8},
{0x40, S3BootScriptWidthUint16},
{0x42, S3BootScriptWidthUint16},
{0x92, S3BootScriptWidthUint16},
{0x94, S3BootScriptWidthUint32},
{0x9C, S3BootScriptWidthUint32},
{0x4, S3BootScriptWidthUint16},
};
OPAL_DRIVER mOpalDriver;
//
@ -233,14 +206,12 @@ OpalSupportUpdatePassword (
@param[out] DevInfoLength Device information length needed.
@param[out] DevInfo Device information extracted.
@return Device type.
**/
UINT8
VOID
ExtractDeviceInfoFromDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT UINT16 *DevInfoLength,
OUT OPAL_DEVICE_COMMON *DevInfo OPTIONAL
OUT UINT32 *DevInfoLength,
OUT OPAL_DEVICE_LOCKBOX_DATA *DevInfo OPTIONAL
)
{
EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;
@ -249,10 +220,6 @@ ExtractDeviceInfoFromDevicePath (
UINT8 DeviceType;
UINT8 BusNum;
OPAL_PCI_DEVICE *PciDevice;
OPAL_DEVICE_ATA *DevInfoAta;
OPAL_DEVICE_NVME *DevInfoNvme;
SATA_DEVICE_PATH *SataDevPath;
NVME_NAMESPACE_DEVICE_PATH *NvmeDevPath;
ASSERT (DevicePath != NULL);
ASSERT (DevInfoLength != NULL);
@ -266,30 +233,15 @@ ExtractDeviceInfoFromDevicePath (
// Get device type.
//
while (!IsDevicePathEnd (TmpDevPath)) {
if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {
//
// SATA
//
if ((TmpDevPath->Type == MESSAGING_DEVICE_PATH) &&
(TmpDevPath->SubType == MSG_SATA_DP || TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP)) {
if (DevInfo != NULL) {
SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;
DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
DevInfoAta->Port = SataDevPath->HBAPortNumber;
DevInfoAta->PortMultiplierPort = SataDevPath->PortMultiplierPortNumber;
DevInfo->DevicePathLength = (UINT32) GetDevicePathSize (DevicePath);
CopyMem (DevInfo->DevicePath, DevicePath, DevInfo->DevicePathLength);
}
DeviceType = OPAL_DEVICE_TYPE_ATA;
*DevInfoLength = sizeof (OPAL_DEVICE_ATA);
break;
} else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
//
// NVMe
//
if (DevInfo != NULL) {
NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
}
DeviceType = OPAL_DEVICE_TYPE_NVME;
*DevInfoLength = sizeof (OPAL_DEVICE_NVME);
DeviceType = (TmpDevPath->SubType == MSG_SATA_DP) ? OPAL_DEVICE_TYPE_ATA : OPAL_DEVICE_TYPE_NVME;
*DevInfoLength = sizeof (OPAL_DEVICE_LOCKBOX_DATA) + (UINT32) GetDevicePathSize (DevicePath);
break;
}
TmpDevPath = NextDevicePathNode (TmpDevPath);
@ -304,8 +256,8 @@ ExtractDeviceInfoFromDevicePath (
while (!IsDevicePathEnd (TmpDevPath2)) {
if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {
PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
(TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {
if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH) &&
(TmpDevPath2->SubType == MSG_SATA_DP || TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)) {
if (DevInfo != NULL) {
PciDevice = &DevInfo->Device;
PciDevice->Segment = 0;
@ -314,14 +266,6 @@ ExtractDeviceInfoFromDevicePath (
PciDevice->Function = PciDevPath->Function;
}
} else {
if (DevInfo != NULL) {
PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo + *DevInfoLength);
PciDevice->Segment = 0;
PciDevice->Bus = BusNum;
PciDevice->Device = PciDevPath->Device;
PciDevice->Function = PciDevPath->Function;
}
*DevInfoLength += sizeof (OPAL_PCI_DEVICE);
if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {
BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
}
@ -333,251 +277,157 @@ ExtractDeviceInfoFromDevicePath (
}
ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
return DeviceType;
return;
}
/**
Save boot script for ATA OPAL device.
@param[in] DevInfo Pointer to ATA Opal device information.
Build OPAL device info and save them to LockBox.
**/
VOID
OpalDeviceAtaSaveBootScript (
IN OPAL_DEVICE_ATA *DevInfo
BuildOpalDeviceInfo (
VOID
)
{
UINTN Bus;
UINTN Device;
UINTN Function;
UINTN Index;
EFI_STATUS Status;
UINTN Offset;
UINT64 Address;
S3_BOOT_SCRIPT_LIB_WIDTH Width;
UINT32 Data;
OPAL_HC_PCI_REGISTER_SAVE *HcRegisterSaveListPtr;
UINTN Count;
EFI_STATUS Status;
OPAL_DEVICE_LOCKBOX_DATA *DevInfo;
OPAL_DEVICE_LOCKBOX_DATA *TempDevInfo;
UINTN TotalDevInfoLength;
UINT32 DevInfoLength;
OPAL_DRIVER_DEVICE *TmpDev;
UINT8 DummyData;
BOOLEAN S3InitDevicesExist;
UINTN S3InitDevicesLength;
EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;
EFI_DEVICE_PATH_PROTOCOL *S3InitDevicesBak;
Data = 0;
//
// Build OPAL device info and save them to LockBox.
//
TotalDevInfoLength = 0;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
NULL
);
TotalDevInfoLength += DevInfoLength;
TmpDev = TmpDev->Next;
}
Bus = DevInfo->Device.Bus;
Device = DevInfo->Device.Device;
Function = DevInfo->Device.Function;
if (TotalDevInfoLength == 0) {
return;
}
HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;
Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);
for (Index = 0; Index < Count; Index++) {
Offset = HcRegisterSaveListPtr[Index].Address;
Width = HcRegisterSaveListPtr[Index].Width;
switch (Width) {
case S3BootScriptWidthUint8:
Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
break;
case S3BootScriptWidthUint16:
Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
break;
case S3BootScriptWidthUint32:
Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
break;
default:
ASSERT (FALSE);
break;
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);
if (S3InitDevices == NULL) {
return;
}
Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);
Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
Status = RestoreLockBox (
&gS3StorageDeviceInitListGuid,
S3InitDevices,
&S3InitDevicesLength
);
ASSERT_EFI_ERROR (Status);
S3InitDevicesExist = TRUE;
} else {
return;
}
DevInfo = AllocateZeroPool (TotalDevInfoLength);
ASSERT (DevInfo != NULL);
if (DevInfo == NULL) {
return;
}
TempDevInfo = DevInfo;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
TempDevInfo
);
TempDevInfo->Length = DevInfoLength;
TempDevInfo->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
CopyMem (
TempDevInfo->Password,
TmpDev->OpalDisk.Password,
TmpDev->OpalDisk.PasswordLength
);
TempDevInfo->PasswordLength = TmpDev->OpalDisk.PasswordLength;
S3InitDevicesBak = S3InitDevices;
S3InitDevices = AppendDevicePathInstance (
S3InitDevicesBak,
TmpDev->OpalDisk.OpalDevicePath
);
if (S3InitDevicesBak != NULL) {
FreePool (S3InitDevicesBak);
}
ASSERT (S3InitDevices != NULL);
if (S3InitDevices == NULL) {
return;
}
TempDevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) TempDevInfo + DevInfoLength);
TmpDev = TmpDev->Next;
}
Status = SaveLockBox (
&mOpalDeviceLockBoxGuid,
DevInfo,
TotalDevInfoLength
);
ASSERT_EFI_ERROR (Status);
Status = SetLockBoxAttributes (
&mOpalDeviceLockBoxGuid,
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);
}
}
/**
Build ATA OPAL device info and save them to LockBox.
@param[in] BarAddr Bar address allocated.
**/
VOID
BuildOpalDeviceInfoAta (
IN UINT32 BarAddr
)
{
EFI_STATUS Status;
UINT8 DeviceType;
OPAL_DEVICE_ATA *DevInfoAta;
OPAL_DEVICE_ATA *TempDevInfoAta;
UINTN DevInfoLengthAta;
UINT16 DevInfoLength;
OPAL_DRIVER_DEVICE *TmpDev;
//
// Build ATA OPAL device info and save them to LockBox.
//
DevInfoLengthAta = 0;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
DeviceType = ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
NULL
);
if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
DevInfoLengthAta += DevInfoLength;
}
TmpDev = TmpDev->Next;
}
if (DevInfoLengthAta == 0) {
return;
}
DevInfoAta = AllocateZeroPool (DevInfoLengthAta);
ASSERT (DevInfoAta != NULL);
if (DevInfoAta == NULL) {
return;
}
TempDevInfoAta = DevInfoAta;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
DeviceType = ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
NULL
);
if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
(OPAL_DEVICE_COMMON *) TempDevInfoAta
);
TempDevInfoAta->Length = DevInfoLength;
TempDevInfoAta->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
TempDevInfoAta->BarAddr = BarAddr;
CopyMem (
TempDevInfoAta->Password,
TmpDev->OpalDisk.Password,
TmpDev->OpalDisk.PasswordLength
);
TempDevInfoAta->PasswordLength = TmpDev->OpalDisk.PasswordLength;
OpalDeviceAtaSaveBootScript (TempDevInfoAta);
TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta + DevInfoLength);
}
TmpDev = TmpDev->Next;
}
Status = SaveLockBox (
&mOpalDeviceAtaGuid,
DevInfoAta,
DevInfoLengthAta
);
ASSERT_EFI_ERROR (Status);
Status = SetLockBoxAttributes (
&mOpalDeviceAtaGuid,
LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
);
ASSERT_EFI_ERROR (Status);
ZeroMem (DevInfoAta, DevInfoLengthAta);
FreePool (DevInfoAta);
}
/**
Build NVMe OPAL device info and save them to LockBox.
@param[in] BarAddr Bar address allocated.
**/
VOID
BuildOpalDeviceInfoNvme (
IN UINT32 BarAddr
)
{
EFI_STATUS Status;
UINT8 DeviceType;
OPAL_DEVICE_NVME *DevInfoNvme;
OPAL_DEVICE_NVME *TempDevInfoNvme;
UINTN DevInfoLengthNvme;
UINT16 DevInfoLength;
OPAL_DRIVER_DEVICE *TmpDev;
//
// Build NVMe OPAL device info and save them to LockBox.
//
DevInfoLengthNvme = 0;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
DeviceType = ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
NULL
);
if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
DevInfoLengthNvme += DevInfoLength;
}
TmpDev = TmpDev->Next;
}
if (DevInfoLengthNvme == 0) {
return;
}
DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
ASSERT (DevInfoNvme != NULL);
if (DevInfoNvme == NULL) {
return;
}
TempDevInfoNvme = DevInfoNvme;
TmpDev = mOpalDriver.DeviceList;
while (TmpDev != NULL) {
DeviceType = ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
NULL
);
if (DeviceType == OPAL_DEVICE_TYPE_NVME) {
ExtractDeviceInfoFromDevicePath (
TmpDev->OpalDisk.OpalDevicePath,
&DevInfoLength,
(OPAL_DEVICE_COMMON *) TempDevInfoNvme
);
TempDevInfoNvme->Length = DevInfoLength;
TempDevInfoNvme->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
TempDevInfoNvme->BarAddr = BarAddr;
CopyMem (
TempDevInfoNvme->Password,
TmpDev->OpalDisk.Password,
TmpDev->OpalDisk.PasswordLength
);
TempDevInfoNvme->PasswordLength = TmpDev->OpalDisk.PasswordLength;
TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) TempDevInfoNvme + DevInfoLength);
}
TmpDev = TmpDev->Next;
}
Status = SaveLockBox (
&mOpalDeviceNvmeGuid,
DevInfoNvme,
DevInfoLengthNvme
);
ASSERT_EFI_ERROR (Status);
Status = SetLockBoxAttributes (
&mOpalDeviceNvmeGuid,
LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
);
ASSERT_EFI_ERROR (Status);
ZeroMem (DevInfoNvme, DevInfoLengthNvme);
FreePool (DevInfoNvme);
ZeroMem (DevInfo, TotalDevInfoLength);
FreePool (DevInfo);
FreePool (S3InitDevices);
}
/**
@ -596,9 +446,6 @@ OpalEndOfDxeEventNotify (
VOID *Context
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Address;
UINT64 Length;
OPAL_DRIVER_DEVICE *TmpDev;
DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
@ -623,24 +470,7 @@ OpalEndOfDxeEventNotify (
return;
}
//
// Assume 64K size and alignment are enough.
//
Length = 0x10000;
Address = 0xFFFFFFFF;
Status = gDS->AllocateMemorySpace (
EfiGcdAllocateMaxAddressSearchBottomUp,
EfiGcdMemoryTypeMemoryMappedIo,
16, // 2^16: 64K Alignment
Length,
&Address,
gImageHandle,
NULL
);
ASSERT_EFI_ERROR (Status);
BuildOpalDeviceInfoAta ((UINT32) Address);
BuildOpalDeviceInfoNvme ((UINT32) Address);
BuildOpalDeviceInfo ();
//
// Zero passsword.

View File

@ -1,7 +1,7 @@
/** @file
Values defined and used by the Opal UEFI Driver.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/StorageSecurityCommand.h>
#include <Guid/EventGroup.h>
#include <Guid/S3StorageDeviceInitList.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
@ -42,7 +43,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/HiiLib.h>
#include <Library/UefiHiiServicesLib.h>
#include <Library/PciLib.h>
#include <Library/S3BootScriptLib.h>
#include <Library/LockBoxLib.h>
#include <Library/TcgStorageOpalLib.h>
#include <Library/Tcg2PhysicalPresenceLib.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,327 +0,0 @@
/** @file
Header file for NVMe function definitions
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __OPAL_PASSWORD_NVME_MODE_H__
#define __OPAL_PASSWORD_NVME_MODE_H__
#include "OpalNvmeReg.h"
#define NVME_MAX_SECTORS 0x10000
//
// QueueId
//
#define NVME_ADMIN_QUEUE 0x00
#define NVME_IO_QUEUE 0x01
typedef struct {
UINT8 Opcode;
UINT8 FusedOperation;
#define NORMAL_CMD 0x00
#define FUSED_FIRST_CMD 0x01
#define FUSED_SECOND_CMD 0x02
UINT16 Cid;
} NVME_CDW0;
typedef struct {
NVME_CDW0 Cdw0;
UINT8 Flags;
#define CDW10_VALID 0x01
#define CDW11_VALID 0x02
#define CDW12_VALID 0x04
#define CDW13_VALID 0x08
#define CDW14_VALID 0x10
#define CDW15_VALID 0x20
UINT32 Nsid;
UINT32 Cdw10;
UINT32 Cdw11;
UINT32 Cdw12;
UINT32 Cdw13;
UINT32 Cdw14;
UINT32 Cdw15;
} NVM_EXPRESS_COMMAND;
typedef struct {
UINT32 Cdw0;
UINT32 Cdw1;
UINT32 Cdw2;
UINT32 Cdw3;
} NVM_EXPRESS_RESPONSE;
typedef struct {
UINT64 CommandTimeout;
UINT64 TransferBuffer;
UINT32 TransferLength;
UINT64 MetadataBuffer;
UINT32 MetadataLength;
UINT8 QueueId;
NVM_EXPRESS_COMMAND *NvmeCmd;
NVM_EXPRESS_RESPONSE *NvmeResponse;
} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
#pragma pack(1)
// Internal fields
typedef enum {
NvmeStatusUnknown,
NvmeStatusInit,
NvmeStatusInuse,
NvmeStatusMax,
} NVME_STATUS;
typedef struct {
UINT32 Nbar;
VOID *BaseMem;
VOID *BaseMemMapping;
BOOLEAN PollCancellation;
UINT16 NvmeInitWaitTime;
NVME_STATUS State;
UINT8 BusID;
UINT8 DeviceID;
UINT8 FuncID;
UINTN PciBase;
UINT32 Nsid;
UINT64 Nsuuid;
UINT32 BlockSize;
EFI_LBA LastBlock;
//
// Pointers to 4kB aligned submission & completion queues.
//
NVME_SQ *SqBuffer[NVME_MAX_IO_QUEUES];
NVME_CQ *CqBuffer[NVME_MAX_IO_QUEUES];
UINT16 Cid[NVME_MAX_IO_QUEUES];
//
// Submission and completion queue indices.
//
NVME_SQTDBL SqTdbl[NVME_MAX_IO_QUEUES];
NVME_CQHDBL CqHdbl[NVME_MAX_IO_QUEUES];
UINT8 Pt[NVME_MAX_IO_QUEUES];
UINTN SqeCount[NVME_MAX_IO_QUEUES];
//
// Nvme controller capabilities
//
NVME_CAP Cap;
//
// pointer to identify controller Data
//
NVME_ADMIN_CONTROLLER_DATA *ControllerData;
NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
} NVME_CONTEXT;
#pragma pack()
/**
Transfer MMIO Data to memory.
@param[in,out] MemBuffer - Destination: Memory address
@param[in] MmioAddr - Source: MMIO address
@param[in] Size - Size for read
@retval EFI_SUCCESS - MMIO read sucessfully
**/
EFI_STATUS
NvmeMmioRead (
IN OUT VOID *MemBuffer,
IN UINTN MmioAddr,
IN UINTN Size
);
/**
Transfer memory Data to MMIO.
@param[in,out] MmioAddr - Destination: MMIO address
@param[in] MemBuffer - Source: Memory address
@param[in] Size - Size for write
@retval EFI_SUCCESS - MMIO write sucessfully
**/
EFI_STATUS
NvmeMmioWrite (
IN OUT UINTN MmioAddr,
IN VOID *MemBuffer,
IN UINTN Size
);
/**
Transfer memory data to MMIO.
@param[in,out] MmioAddr - Destination: MMIO address
@param[in] MemBuffer - Source: Memory address
@param[in] Size - Size for write
@retval EFI_SUCCESS - MMIO write sucessfully
**/
EFI_STATUS
OpalPciWrite (
IN OUT UINTN MmioAddr,
IN VOID *MemBuffer,
IN UINTN Size
);
/**
Transfer MMIO data to memory.
@param[in,out] MemBuffer - Destination: Memory address
@param[in] MmioAddr - Source: MMIO address
@param[in] Size - Size for read
@retval EFI_SUCCESS - MMIO read sucessfully
**/
EFI_STATUS
OpalPciRead (
IN OUT VOID *MemBuffer,
IN UINTN MmioAddr,
IN UINTN Size
);
/**
Allocate transfer-related Data struct which is used at Nvme.
@param[in, out] Nvme The pointer to the NVME_CONTEXT Data structure.
@retval EFI_OUT_OF_RESOURCE No enough resource.
@retval EFI_SUCCESS Successful to allocate resource.
**/
EFI_STATUS
EFIAPI
NvmeAllocateResource (
IN OUT NVME_CONTEXT *Nvme
);
/**
Free allocated transfer-related Data struct which is used at NVMe.
@param[in, out] Nvme The pointer to the NVME_CONTEXT Data structure.
**/
VOID
EFIAPI
NvmeFreeResource (
IN OUT NVME_CONTEXT *Nvme
);
/**
Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
I/O functionality is optional.
@param[in] Nvme - The pointer to the NVME_CONTEXT Data structure.
@param[in] NamespaceId - Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
ID specifies that the command packet should be sent to all valid namespaces.
@param[in] NamespaceUuid - Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace
UUID specifies that the command packet should be sent to all valid namespaces.
@param[in,out] Packet - A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
by NamespaceId.
@retval EFI_SUCCESS - The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
to, or from DataBuffer.
@retval EFI_NOT_READY - The NVM Express Command Packet could not be sent because the controller is not ready. The caller
may retry again later.
@retval EFI_DEVICE_ERROR - A device error occurred while attempting to send the NVM Express Command Packet.
@retval EFI_INVALID_PARAMETER - Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
Express Command Packet was not sent, so no additional status information is available.
@retval EFI_UNSUPPORTED - The command described by the NVM Express Command Packet is not supported by the host adapter.
The NVM Express Command Packet was not sent, so no additional status information is available.
@retval EFI_TIMEOUT - A timeout occurred while waiting for the NVM Express Command Packet to execute.
**/
EFI_STATUS
NvmePassThru (
IN NVME_CONTEXT *Nvme,
IN UINT32 NamespaceId,
IN UINT64 NamespaceUuid,
IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet
);
/**
Waits until all NVME commands completed.
@param[in] Nvme - The pointer to the NVME_CONTEXT Data structure.
@param[in] Qid - Queue index
@retval EFI_SUCCESS - All NVME commands have completed
@retval EFI_TIMEOUT - Timeout occured
@retval EFI_NOT_READY - Not all NVME commands have completed
@retval others - Error occurred on device side.
**/
EFI_STATUS
NvmeWaitAllComplete (
IN NVME_CONTEXT *Nvme,
IN UINT8 Qid
);
/**
Initialize the Nvm Express controller.
@param[in] Nvme - The pointer to the NVME_CONTEXT Data structure.
@retval EFI_SUCCESS - The NVM Express Controller is initialized successfully.
@retval Others - A device error occurred while initializing the controller.
**/
EFI_STATUS
NvmeControllerInit (
IN NVME_CONTEXT *Nvme
);
/**
Un-initialize the Nvm Express controller.
@param[in] Nvme - The pointer to the NVME_CONTEXT Data structure.
@retval EFI_SUCCESS - The NVM Express Controller is un-initialized successfully.
@retval Others - A device error occurred while un-initializing the controller.
**/
EFI_STATUS
NvmeControllerExit (
IN NVME_CONTEXT *Nvme
);
/**
Security send and receive commands.
@param[in] Nvme - The pointer to the NVME_CONTEXT Data structure.
@param[in] SendCommand - The flag to indicate the command type, TRUE for Send command and FALSE for receive command
@param[in] SecurityProtocol - Security Protocol
@param[in] SpSpecific - Security Protocol Specific
@param[in] TransferLength - Transfer Length of Buffer (in bytes) - always a multiple of 512
@param[in,out] TransferBuffer - Address of Data to transfer
@return EFI_SUCCESS - Successfully create io submission queue.
@return others - Fail to send/receive commands.
**/
EFI_STATUS
NvmeSecuritySendReceive (
IN NVME_CONTEXT *Nvme,
IN BOOLEAN SendCommand,
IN UINT8 SecurityProtocol,
IN UINT16 SpSpecific,
IN UINTN TransferLength,
IN OUT VOID *TransferBuffer
);
#endif

View File

@ -1,815 +0,0 @@
/** @file
Header file for Registers and Structure definitions
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __OPAL_PASSWORD_NVME_REG_H__
#define __OPAL_PASSWORD_NVME_REG_H__
//
// PCI Header for PCIe root port configuration
//
#define NVME_PCIE_PCICMD 0x04
#define NVME_PCIE_BNUM 0x18
#define NVME_PCIE_SEC_BNUM 0x19
#define NVME_PCIE_IOBL 0x1C
#define NVME_PCIE_MBL 0x20
#define NVME_PCIE_PMBL 0x24
#define NVME_PCIE_PMBU32 0x28
#define NVME_PCIE_PMLU32 0x2C
#define NVME_PCIE_INTR 0x3C
//
// NVMe related definitions
//
#define PCI_CLASS_MASS_STORAGE_NVM 0x08 // mass storage sub-class non-volatile memory.
#define PCI_IF_NVMHCI 0x02 // mass storage programming interface NVMHCI.
#define NVME_ASQ_SIZE 1 // Number of admin submission queue entries, which is 0-based
#define NVME_ACQ_SIZE 1 // Number of admin completion queue entries, which is 0-based
#define NVME_CSQ_SIZE 63 // Number of I/O submission queue entries, which is 0-based
#define NVME_CCQ_SIZE 63 // Number of I/O completion queue entries, which is 0-based
#define NVME_MAX_IO_QUEUES 2 // Number of I/O queues supported by the driver, 1 for AQ, 1 for CQ
#define NVME_CSQ_DEPTH (NVME_CSQ_SIZE+1)
#define NVME_CCQ_DEPTH (NVME_CCQ_SIZE+1)
#define NVME_PRP_SIZE (4) // Pages of PRP list
#define NVME_CONTROLLER_ID 0
//
// Time out Value for Nvme transaction execution
//
#define NVME_GENERIC_TIMEOUT 5000000 ///< us
#define NVME_CMD_WAIT 100 ///< us
#define NVME_CMD_TIMEOUT 20000000 ///< us
#define NVME_MEM_MAX_SIZE \
(( \
1 /* Controller Data */ + \
1 /* Identify Data */ + \
1 /* ASQ */ + \
1 /* ACQ */ + \
1 /* SQs */ + \
1 /* CQs */ + \
NVME_PRP_SIZE * NVME_CSQ_DEPTH /* PRPs */ + \
1 /* SECURITY */ \
) * EFI_PAGE_SIZE)
//
// controller register offsets
//
#define NVME_CAP_OFFSET 0x0000 // Controller Capabilities
#define NVME_VER_OFFSET 0x0008 // Version
#define NVME_INTMS_OFFSET 0x000c // Interrupt Mask Set
#define NVME_INTMC_OFFSET 0x0010 // Interrupt Mask Clear
#define NVME_CC_OFFSET 0x0014 // Controller Configuration
#define NVME_CSTS_OFFSET 0x001c // Controller Status
#define NVME_AQA_OFFSET 0x0024 // Admin Queue Attributes
#define NVME_ASQ_OFFSET 0x0028 // Admin Submission Queue Base Address
#define NVME_ACQ_OFFSET 0x0030 // Admin Completion Queue Base Address
#define NVME_SQ0_OFFSET 0x1000 // Submission Queue 0 (admin) Tail Doorbell
#define NVME_CQ0_OFFSET 0x1004 // Completion Queue 0 (admin) Head Doorbell
//
// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
// Get the doorbell stride bit shift Value from the controller capabilities.
//
#define NVME_SQTDBL_OFFSET(QID, DSTRD) 0x1000 + ((2 * (QID)) * (4 << (DSTRD))) // Submission Queue y (NVM) Tail Doorbell
#define NVME_CQHDBL_OFFSET(QID, DSTRD) 0x1000 + (((2 * (QID)) + 1) * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
#pragma pack(1)
//
// 3.1.1 Offset 00h: CAP - Controller Capabilities
//
typedef struct {
UINT16 Mqes; // Maximum Queue Entries Supported
UINT8 Cqr:1; // Contiguous Queues Required
UINT8 Ams:2; // Arbitration Mechanism Supported
UINT8 Rsvd1:5;
UINT8 To; // Timeout
UINT16 Dstrd:4;
UINT16 Rsvd2:1;
UINT16 Css:4; // Command Sets Supported
UINT16 Rsvd3:7;
UINT8 Mpsmin:4;
UINT8 Mpsmax:4;
UINT8 Rsvd4;
} NVME_CAP;
//
// 3.1.2 Offset 08h: VS - Version
//
typedef struct {
UINT16 Mnr; // Minor version number
UINT16 Mjr; // Major version number
} NVME_VER;
//
// 3.1.5 Offset 14h: CC - Controller Configuration
//
typedef struct {
UINT16 En:1; // Enable
UINT16 Rsvd1:3;
UINT16 Css:3; // Command Set Selected
UINT16 Mps:4; // Memory Page Size
UINT16 Ams:3; // Arbitration Mechanism Selected
UINT16 Shn:2; // Shutdown Notification
UINT8 Iosqes:4; // I/O Submission Queue Entry Size
UINT8 Iocqes:4; // I/O Completion Queue Entry Size
UINT8 Rsvd2;
} NVME_CC;
//
// 3.1.6 Offset 1Ch: CSTS - Controller Status
//
typedef struct {
UINT32 Rdy:1; // Ready
UINT32 Cfs:1; // Controller Fatal Status
UINT32 Shst:2; // Shutdown Status
UINT32 Nssro:1; // NVM Subsystem Reset Occurred
UINT32 Rsvd1:27;
} NVME_CSTS;
//
// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
//
typedef struct {
UINT16 Asqs:12; // Submission Queue Size
UINT16 Rsvd1:4;
UINT16 Acqs:12; // Completion Queue Size
UINT16 Rsvd2:4;
} NVME_AQA;
//
// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
//
#define NVME_ASQ UINT64
//
// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
//
#define NVME_ACQ UINT64
//
// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission Queue y Tail Doorbell
//
typedef struct {
UINT16 Sqt;
UINT16 Rsvd1;
} NVME_SQTDBL;
//
// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL - Completion Queue y Head Doorbell
//
typedef struct {
UINT16 Cqh;
UINT16 Rsvd1;
} NVME_CQHDBL;
//
// NVM command set structures
//
// Read Command
//
typedef struct {
//
// CDW 10, 11
//
UINT64 Slba; /* Starting Sector Address */
//
// CDW 12
//
UINT16 Nlb; /* Number of Sectors */
UINT16 Rsvd1:10;
UINT16 Prinfo:4; /* Protection Info Check */
UINT16 Fua:1; /* Force Unit Access */
UINT16 Lr:1; /* Limited Retry */
//
// CDW 13
//
UINT32 Af:4; /* Access Frequency */
UINT32 Al:2; /* Access Latency */
UINT32 Sr:1; /* Sequential Request */
UINT32 In:1; /* Incompressible */
UINT32 Rsvd2:24;
//
// CDW 14
//
UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */
//
// CDW 15
//
UINT16 Elbat; /* Expected Logical Block Application Tag */
UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */
} NVME_READ;
//
// Write Command
//
typedef struct {
//
// CDW 10, 11
//
UINT64 Slba; /* Starting Sector Address */
//
// CDW 12
//
UINT16 Nlb; /* Number of Sectors */
UINT16 Rsvd1:10;
UINT16 Prinfo:4; /* Protection Info Check */
UINT16 Fua:1; /* Force Unit Access */
UINT16 Lr:1; /* Limited Retry */
//
// CDW 13
//
UINT32 Af:4; /* Access Frequency */
UINT32 Al:2; /* Access Latency */
UINT32 Sr:1; /* Sequential Request */
UINT32 In:1; /* Incompressible */
UINT32 Rsvd2:24;
//
// CDW 14
//
UINT32 Ilbrt; /* Initial Logical Block Reference Tag */
//
// CDW 15
//
UINT16 Lbat; /* Logical Block Application Tag */
UINT16 Lbatm; /* Logical Block Application Tag Mask */
} NVME_WRITE;
//
// Flush
//
typedef struct {
//
// CDW 10
//
UINT32 Flush; /* Flush */
} NVME_FLUSH;
//
// Write Uncorrectable command
//
typedef struct {
//
// CDW 10, 11
//
UINT64 Slba; /* Starting LBA */
//
// CDW 12
//
UINT32 Nlb:16; /* Number of Logical Blocks */
UINT32 Rsvd1:16;
} NVME_WRITE_UNCORRECTABLE;
//
// Write Zeroes command
//
typedef struct {
//
// CDW 10, 11
//
UINT64 Slba; /* Starting LBA */
//
// CDW 12
//
UINT16 Nlb; /* Number of Logical Blocks */
UINT16 Rsvd1:10;
UINT16 Prinfo:4; /* Protection Info Check */
UINT16 Fua:1; /* Force Unit Access */
UINT16 Lr:1; /* Limited Retry */
//
// CDW 13
//
UINT32 Rsvd2;
//
// CDW 14
//
UINT32 Ilbrt; /* Initial Logical Block Reference Tag */
//
// CDW 15
//
UINT16 Lbat; /* Logical Block Application Tag */
UINT16 Lbatm; /* Logical Block Application Tag Mask */
} NVME_WRITE_ZEROES;
//
// Compare command
//
typedef struct {
//
// CDW 10, 11
//
UINT64 Slba; /* Starting LBA */
//
// CDW 12
//
UINT16 Nlb; /* Number of Logical Blocks */
UINT16 Rsvd1:10;
UINT16 Prinfo:4; /* Protection Info Check */
UINT16 Fua:1; /* Force Unit Access */
UINT16 Lr:1; /* Limited Retry */
//
// CDW 13
//
UINT32 Rsvd2;
//
// CDW 14
//
UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */
//
// CDW 15
//
UINT16 Elbat; /* Expected Logical Block Application Tag */
UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */
} NVME_COMPARE;
typedef union {
NVME_READ Read;
NVME_WRITE Write;
NVME_FLUSH Flush;
NVME_WRITE_UNCORRECTABLE WriteUncorrectable;
NVME_WRITE_ZEROES WriteZeros;
NVME_COMPARE Compare;
} NVME_CMD;
typedef struct {
UINT16 Mp; /* Maximum Power */
UINT8 Rsvd1; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 Mps:1; /* Max Power Scale */
UINT8 Nops:1; /* Non-Operational State */
UINT8 Rsvd2:6; /* Reserved as of Nvm Express 1.1 Spec */
UINT32 Enlat; /* Entry Latency */
UINT32 Exlat; /* Exit Latency */
UINT8 Rrt:5; /* Relative Read Throughput */
UINT8 Rsvd3:3; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 Rrl:5; /* Relative Read Leatency */
UINT8 Rsvd4:3; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 Rwt:5; /* Relative Write Throughput */
UINT8 Rsvd5:3; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 Rwl:5; /* Relative Write Leatency */
UINT8 Rsvd6:3; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 Rsvd7[16]; /* Reserved as of Nvm Express 1.1 Spec */
} NVME_PSDESCRIPTOR;
//
// Identify Controller Data
//
typedef struct {
//
// Controller Capabilities and Features 0-255
//
UINT16 Vid; /* PCI Vendor ID */
UINT16 Ssvid; /* PCI sub-system vendor ID */
UINT8 Sn[20]; /* Produce serial number */
UINT8 Mn[40]; /* Proeduct model number */
UINT8 Fr[8]; /* Firmware Revision */
UINT8 Rab; /* Recommended Arbitration Burst */
UINT8 Ieee_oiu[3]; /* Organization Unique Identifier */
UINT8 Cmic; /* Multi-interface Capabilities */
UINT8 Mdts; /* Maximum Data Transfer Size */
UINT8 Cntlid[2]; /* Controller ID */
UINT8 Rsvd1[176]; /* Reserved as of Nvm Express 1.1 Spec */
//
// Admin Command Set Attributes
//
UINT16 Oacs; /* Optional Admin Command Support */
UINT8 Acl; /* Abort Command Limit */
UINT8 Aerl; /* Async Event Request Limit */
UINT8 Frmw; /* Firmware updates */
UINT8 Lpa; /* Log Page Attributes */
UINT8 Elpe; /* Error Log Page Entries */
UINT8 Npss; /* Number of Power States Support */
UINT8 Avscc; /* Admin Vendor Specific Command Configuration */
UINT8 Apsta; /* Autonomous Power State Transition Attributes */
UINT8 Rsvd2[246]; /* Reserved as of Nvm Express 1.1 Spec */
//
// NVM Command Set Attributes
//
UINT8 Sqes; /* Submission Queue Entry Size */
UINT8 Cqes; /* Completion Queue Entry Size */
UINT16 Rsvd3; /* Reserved as of Nvm Express 1.1 Spec */
UINT32 Nn; /* Number of Namespaces */
UINT16 Oncs; /* Optional NVM Command Support */
UINT16 Fuses; /* Fused Operation Support */
UINT8 Fna; /* Format NVM Attributes */
UINT8 Vwc; /* Volatile Write Cache */
UINT16 Awun; /* Atomic Write Unit Normal */
UINT16 Awupf; /* Atomic Write Unit Power Fail */
UINT8 Nvscc; /* NVM Vendor Specific Command Configuration */
UINT8 Rsvd4; /* Reserved as of Nvm Express 1.1 Spec */
UINT16 Acwu; /* Atomic Compare & Write Unit */
UINT16 Rsvd5; /* Reserved as of Nvm Express 1.1 Spec */
UINT32 Sgls; /* SGL Support */
UINT8 Rsvd6[164]; /* Reserved as of Nvm Express 1.1 Spec */
//
// I/O Command set Attributes
//
UINT8 Rsvd7[1344]; /* Reserved as of Nvm Express 1.1 Spec */
//
// Power State Descriptors
//
NVME_PSDESCRIPTOR PsDescriptor[32];
UINT8 VendorData[1024]; /* Vendor specific Data */
} NVME_ADMIN_CONTROLLER_DATA;
typedef struct {
UINT16 Security : 1; /* supports security send/receive commands */
UINT16 Format : 1; /* supports format nvm command */
UINT16 Firmware : 1; /* supports firmware activate/download commands */
UINT16 Oacs_rsvd : 13;
} OACS; // optional admin command support: NVME_ADMIN_CONTROLLER_DATA.Oacs
typedef struct {
UINT16 Ms; /* Metadata Size */
UINT8 Lbads; /* LBA Data Size */
UINT8 Rp:2; /* Relative Performance */
#define LBAF_RP_BEST 00b
#define LBAF_RP_BETTER 01b
#define LBAF_RP_GOOD 10b
#define LBAF_RP_DEGRADED 11b
UINT8 Rsvd1:6; /* Reserved as of Nvm Express 1.1 Spec */
} NVME_LBAFORMAT;
//
// Identify Namespace Data
//
typedef struct {
//
// NVM Command Set Specific
//
UINT64 Nsze; /* Namespace Size (total number of blocks in formatted namespace) */
UINT64 Ncap; /* Namespace Capacity (max number of logical blocks) */
UINT64 Nuse; /* Namespace Utilization */
UINT8 Nsfeat; /* Namespace Features */
UINT8 Nlbaf; /* Number of LBA Formats */
UINT8 Flbas; /* Formatted LBA Size */
UINT8 Mc; /* Metadata Capabilities */
UINT8 Dpc; /* End-to-end Data Protection capabilities */
UINT8 Dps; /* End-to-end Data Protection Type Settings */
UINT8 Nmic; /* Namespace Multi-path I/O and Namespace Sharing Capabilities */
UINT8 Rescap; /* Reservation Capabilities */
UINT8 Rsvd1[88]; /* Reserved as of Nvm Express 1.1 Spec */
UINT64 Eui64; /* IEEE Extended Unique Identifier */
//
// LBA Format
//
NVME_LBAFORMAT LbaFormat[16];
UINT8 Rsvd2[192]; /* Reserved as of Nvm Express 1.1 Spec */
UINT8 VendorData[3712]; /* Vendor specific Data */
} NVME_ADMIN_NAMESPACE_DATA;
//
// NvmExpress Admin Identify Cmd
//
typedef struct {
//
// CDW 10
//
UINT32 Cns:2;
UINT32 Rsvd1:30;
} NVME_ADMIN_IDENTIFY;
//
// NvmExpress Admin Create I/O Completion Queue
//
typedef struct {
//
// CDW 10
//
UINT32 Qid:16; /* Queue Identifier */
UINT32 Qsize:16; /* Queue Size */
//
// CDW 11
//
UINT32 Pc:1; /* Physically Contiguous */
UINT32 Ien:1; /* Interrupts Enabled */
UINT32 Rsvd1:14; /* reserved as of Nvm Express 1.1 Spec */
UINT32 Iv:16; /* Interrupt Vector */
} NVME_ADMIN_CRIOCQ;
//
// NvmExpress Admin Create I/O Submission Queue
//
typedef struct {
//
// CDW 10
//
UINT32 Qid:16; /* Queue Identifier */
UINT32 Qsize:16; /* Queue Size */
//
// CDW 11
//
UINT32 Pc:1; /* Physically Contiguous */
UINT32 Qprio:2; /* Queue Priority */
UINT32 Rsvd1:13; /* Reserved as of Nvm Express 1.1 Spec */
UINT32 Cqid:16; /* Completion Queue ID */
} NVME_ADMIN_CRIOSQ;
//
// NvmExpress Admin Delete I/O Completion Queue
//
typedef struct {
//
// CDW 10
//
UINT16 Qid;
UINT16 Rsvd1;
} NVME_ADMIN_DEIOCQ;
//
// NvmExpress Admin Delete I/O Submission Queue
//
typedef struct {
//
// CDW 10
//
UINT16 Qid;
UINT16 Rsvd1;
} NVME_ADMIN_DEIOSQ;
//
// NvmExpress Admin Security Send
//
typedef struct {
//
// CDW 10
//
UINT32 Resv:8; /* Reserve */
UINT32 Spsp:16; /* SP Specific */
UINT32 Secp:8; /* Security Protocol */
//
// CDW 11
//
UINT32 Tl; /* Transfer Length */
} NVME_ADMIN_SECSEND;
//
// NvmExpress Admin Abort Command
//
typedef struct {
//
// CDW 10
//
UINT32 Sqid:16; /* Submission Queue identifier */
UINT32 Cid:16; /* Command Identifier */
} NVME_ADMIN_ABORT;
//
// NvmExpress Admin Firmware Activate Command
//
typedef struct {
//
// CDW 10
//
UINT32 Fs:3; /* Submission Queue identifier */
UINT32 Aa:2; /* Command Identifier */
UINT32 Rsvd1:27;
} NVME_ADMIN_FIRMWARE_ACTIVATE;
//
// NvmExpress Admin Firmware Image Download Command
//
typedef struct {
//
// CDW 10
//
UINT32 Numd; /* Number of Dwords */
//
// CDW 11
//
UINT32 Ofst; /* Offset */
} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
//
// NvmExpress Admin Get Features Command
//
typedef struct {
//
// CDW 10
//
UINT32 Fid:8; /* Feature Identifier */
UINT32 Sel:3; /* Select */
UINT32 Rsvd1:21;
} NVME_ADMIN_GET_FEATURES;
//
// NvmExpress Admin Get Log Page Command
//
typedef struct {
//
// CDW 10
//
UINT32 Lid:8; /* Log Page Identifier */
#define LID_ERROR_INFO
#define LID_SMART_INFO
#define LID_FW_SLOT_INFO
UINT32 Rsvd1:8;
UINT32 Numd:12; /* Number of Dwords */
UINT32 Rsvd2:4; /* Reserved as of Nvm Express 1.1 Spec */
} NVME_ADMIN_GET_LOG_PAGE;
//
// NvmExpress Admin Set Features Command
//
typedef struct {
//
// CDW 10
//
UINT32 Fid:8; /* Feature Identifier */
UINT32 Rsvd1:23;
UINT32 Sv:1; /* Save */
} NVME_ADMIN_SET_FEATURES;
//
// NvmExpress Admin Format NVM Command
//
typedef struct {
//
// CDW 10
//
UINT32 Lbaf:4; /* LBA Format */
UINT32 Ms:1; /* Metadata Settings */
UINT32 Pi:3; /* Protection Information */
UINT32 Pil:1; /* Protection Information Location */
UINT32 Ses:3; /* Secure Erase Settings */
UINT32 Rsvd1:20;
} NVME_ADMIN_FORMAT_NVM;
//
// NvmExpress Admin Security Receive Command
//
typedef struct {
//
// CDW 10
//
UINT32 Rsvd1:8;
UINT32 Spsp:16; /* SP Specific */
UINT32 Secp:8; /* Security Protocol */
//
// CDW 11
//
UINT32 Al; /* Allocation Length */
} NVME_ADMIN_SECURITY_RECEIVE;
//
// NvmExpress Admin Security Send Command
//
typedef struct {
//
// CDW 10
//
UINT32 Rsvd1:8;
UINT32 Spsp:16; /* SP Specific */
UINT32 Secp:8; /* Security Protocol */
//
// CDW 11
//
UINT32 Tl; /* Transfer Length */
} NVME_ADMIN_SECURITY_SEND;
typedef union {
NVME_ADMIN_IDENTIFY Identify;
NVME_ADMIN_CRIOCQ CrIoCq;
NVME_ADMIN_CRIOSQ CrIoSq;
NVME_ADMIN_DEIOCQ DeIoCq;
NVME_ADMIN_DEIOSQ DeIoSq;
NVME_ADMIN_ABORT Abort;
NVME_ADMIN_FIRMWARE_ACTIVATE Activate;
NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD FirmwareImageDownload;
NVME_ADMIN_GET_FEATURES GetFeatures;
NVME_ADMIN_GET_LOG_PAGE GetLogPage;
NVME_ADMIN_SET_FEATURES SetFeatures;
NVME_ADMIN_FORMAT_NVM FormatNvm;
NVME_ADMIN_SECURITY_RECEIVE SecurityReceive;
NVME_ADMIN_SECURITY_SEND SecuritySend;
} NVME_ADMIN_CMD;
typedef struct {
UINT32 Cdw10;
UINT32 Cdw11;
UINT32 Cdw12;
UINT32 Cdw13;
UINT32 Cdw14;
UINT32 Cdw15;
} NVME_RAW;
typedef union {
NVME_ADMIN_CMD Admin; // Union of Admin commands
NVME_CMD Nvm; // Union of Nvm commands
NVME_RAW Raw;
} NVME_PAYLOAD;
//
// Submission Queue
//
typedef struct {
//
// CDW 0, Common to all comnmands
//
UINT8 Opc; // Opcode
UINT8 Fuse:2; // Fused Operation
UINT8 Rsvd1:5;
UINT8 Psdt:1; // PRP or SGL for Data Transfer
UINT16 Cid; // Command Identifier
//
// CDW 1
//
UINT32 Nsid; // Namespace Identifier
//
// CDW 2,3
//
UINT64 Rsvd2;
//
// CDW 4,5
//
UINT64 Mptr; // Metadata Pointer
//
// CDW 6-9
//
UINT64 Prp[2]; // First and second PRP entries
NVME_PAYLOAD Payload;
} NVME_SQ;
//
// Completion Queue
//
typedef struct {
//
// CDW 0
//
UINT32 Dword0;
//
// CDW 1
//
UINT32 Rsvd1;
//
// CDW 2
//
UINT16 Sqhd; // Submission Queue Head Pointer
UINT16 Sqid; // Submission Queue Identifier
//
// CDW 3
//
UINT16 Cid; // Command Identifier
UINT16 Pt:1; // Phase Tag
UINT16 Sc:8; // Status Code
UINT16 Sct:3; // Status Code Type
UINT16 Rsvd2:2;
UINT16 Mo:1; // More
UINT16 Dnr:1; // Retry
} NVME_CQ;
//
// Nvm Express Admin cmd opcodes
//
#define NVME_ADMIN_DELIOSQ_OPC 0
#define NVME_ADMIN_CRIOSQ_OPC 1
#define NVME_ADMIN_DELIOCQ_OPC 4
#define NVME_ADMIN_CRIOCQ_OPC 5
#define NVME_ADMIN_IDENTIFY_OPC 6
#define NVME_ADMIN_SECURITY_SEND_OPC 0x81
#define NVME_ADMIN_SECURITY_RECV_OPC 0x82
#define NVME_IO_FLUSH_OPC 0
#define NVME_IO_WRITE_OPC 1
#define NVME_IO_READ_OPC 2
//
// Offset from the beginning of private Data queue Buffer
//
#define NVME_ASQ_BUF_OFFSET EFI_PAGE_SIZE
#pragma pack()
#endif

View File

@ -1,7 +1,7 @@
/** @file
Opal Password common header file.
Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -30,38 +30,15 @@ typedef struct {
} OPAL_PCI_DEVICE;
typedef struct {
UINT16 Length;
OPAL_PCI_DEVICE Device;
UINT8 PasswordLength;
UINT8 Password[OPAL_MAX_PASSWORD_SIZE];
UINT16 OpalBaseComId;
UINT32 BarAddr;
} OPAL_DEVICE_COMMON;
UINT32 Length;
OPAL_PCI_DEVICE Device;
UINT8 PasswordLength;
UINT8 Password[OPAL_MAX_PASSWORD_SIZE];
UINT16 OpalBaseComId;
UINT32 DevicePathLength;
EFI_DEVICE_PATH_PROTOCOL DevicePath[];
} OPAL_DEVICE_LOCKBOX_DATA;
#define OPAL_DEVICE_ATA_GUID { 0xcb934fe1, 0xb8cd, 0x46b1, { 0xa0, 0x58, 0xdd, 0xcb, 0x7, 0xb7, 0xb4, 0x17 } }
typedef struct {
UINT16 Length;
OPAL_PCI_DEVICE Device;
UINT8 PasswordLength;
UINT8 Password[OPAL_MAX_PASSWORD_SIZE];
UINT16 OpalBaseComId;
UINT32 BarAddr;
UINT16 Port;
UINT16 PortMultiplierPort;
} OPAL_DEVICE_ATA;
#define OPAL_DEVICE_NVME_GUID { 0xde116925, 0xaf7f, 0x42d9, { 0x83, 0xc0, 0x7e, 0xd6, 0x26, 0x59, 0x0, 0xfb } }
typedef struct {
UINT16 Length;
OPAL_PCI_DEVICE Device;
UINT8 PasswordLength;
UINT8 Password[OPAL_MAX_PASSWORD_SIZE];
UINT16 OpalBaseComId;
UINT32 BarAddr;
UINT32 NvmeNamespaceId;
OPAL_PCI_DEVICE PciBridgeNode[0];
} OPAL_DEVICE_NVME;
#define OPAL_DEVICE_LOCKBOX_GUID { 0x56a77f0d, 0x6f05, 0x4d47, { 0xb9, 0x11, 0x4f, 0xd, 0xec, 0x5c, 0x58, 0x61 } }
#endif // _OPAL_PASSWORD_COMMON_H_

View File

@ -4,7 +4,7 @@
# This module is used to Management the Opal feature
# for Opal supported devices.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@ -62,7 +62,6 @@
TcgStorageOpalLib
Tcg2PhysicalPresenceLib
PciLib
S3BootScriptLib
LockBoxLib
[Protocols]
@ -73,7 +72,8 @@
gEfiBlockIoProtocolGuid ## CONSUMES
[Guids]
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gS3StorageDeviceInitListGuid ## SOMETIMES_PRODUCES ## UNDEFINED
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdSkipOpalDxeUnlock ## CONSUMES

View File

@ -1,7 +1,7 @@
/** @file
Opal Password PEI driver which is used to unlock Opal Password for S3.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -14,250 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "OpalPasswordPei.h"
EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
#define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)
#define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)
/**
Get IOMMU PPI.
@return Pointer to IOMMU PPI.
**/
EDKII_IOMMU_PPI *
GetIoMmu (
VOID
)
{
EFI_STATUS Status;
EDKII_IOMMU_PPI *IoMmu;
IoMmu = NULL;
Status = PeiServicesLocatePpi (
&gEdkiiIoMmuPpiGuid,
0,
NULL,
(VOID **) &IoMmu
);
if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
return IoMmu;
}
return NULL;
}
/**
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
OperationBusMasterCommonBuffer64 mapping.
@param Pages The number of pages to allocate.
@param HostAddress A pointer to store the base system memory address of the
allocated range.
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
access the hosts HostAddress.
@param Mapping A resulting value to pass to Unmap().
@retval EFI_SUCCESS The requested memory pages were allocated.
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
**/
EFI_STATUS
IoMmuAllocateBuffer (
IN UINTN Pages,
OUT VOID **HostAddress,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
{
EFI_STATUS Status;
UINTN NumberOfBytes;
EFI_PHYSICAL_ADDRESS HostPhyAddress;
EDKII_IOMMU_PPI *IoMmu;
*HostAddress = NULL;
*DeviceAddress = 0;
*Mapping = NULL;
IoMmu = GetIoMmu ();
if (IoMmu != NULL) {
Status = IoMmu->AllocateBuffer (
IoMmu,
EfiBootServicesData,
Pages,
HostAddress,
0
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
Status = IoMmu->Map (
IoMmu,
EdkiiIoMmuOperationBusMasterCommonBuffer,
*HostAddress,
&NumberOfBytes,
DeviceAddress,
Mapping
);
if (EFI_ERROR (Status)) {
IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
*HostAddress = NULL;
return EFI_OUT_OF_RESOURCES;
}
Status = IoMmu->SetAttribute (
IoMmu,
*Mapping,
EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
);
if (EFI_ERROR (Status)) {
IoMmu->Unmap (IoMmu, *Mapping);
IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
*Mapping = NULL;
*HostAddress = NULL;
return Status;
}
} else {
Status = PeiServicesAllocatePages (
EfiBootServicesData,
Pages,
&HostPhyAddress
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
*HostAddress = (VOID *) (UINTN) HostPhyAddress;
*DeviceAddress = HostPhyAddress;
*Mapping = NULL;
}
return Status;
}
/**
Frees memory that was allocated with AllocateBuffer().
@param Pages The number of pages to free.
@param HostAddress The base system memory address of the allocated range.
@param Mapping The mapping value returned from Map().
**/
VOID
IoMmuFreeBuffer (
IN UINTN Pages,
IN VOID *HostAddress,
IN VOID *Mapping
)
{
EDKII_IOMMU_PPI *IoMmu;
IoMmu = GetIoMmu ();
if (IoMmu != NULL) {
IoMmu->SetAttribute (IoMmu, Mapping, 0);
IoMmu->Unmap (IoMmu, Mapping);
IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
} else {
PeiServicesFreePages (
(EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
Pages
);
}
}
/**
Provide IO action support.
@param[in] PeiDev The opal device need to perform trusted IO.
@param[in] IoType OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
@param[in] SecurityProtocol Security Protocol
@param[in] SpSpecific Security Protocol Specific
@param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
@param[in] Buffer Address of Data to transfer
@retval EFI_SUCCESS Perform the IO action success.
@retval Others Perform the IO action failed.
**/
EFI_STATUS
PerformTrustedIo (
OPAL_PEI_DEVICE *PeiDev,
OPAL_IO_TYPE IoType,
UINT8 SecurityProtocol,
UINT16 SpSpecific,
UINTN TransferLength,
VOID *Buffer
)
{
EFI_STATUS Status;
UINTN BufferSizeBlocks;
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
OPAL_DEVICE_ATA *DevInfoAta;
AHCI_CONTEXT *AhciContext;
NVME_CONTEXT *NvmeContext;
Status = EFI_DEVICE_ERROR;
if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {
DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;
AhciContext = (AHCI_CONTEXT *) PeiDev->Context;
BufferSizeBlocks = TransferLength / 512;
ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
AtaCommandBlock.AtaFeatures = SecurityProtocol;
AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );
ASSERT( TransferLength <= HDD_PAYLOAD );
if (IoType == OpalSend) {
CopyMem( AhciContext->Buffer, Buffer, TransferLength );
}
Status = AhciPioTransfer(
AhciContext,
(UINT8) DevInfoAta->Port,
(UINT8) DevInfoAta->PortMultiplierPort,
NULL,
0,
( IoType == OpalSend ) ? FALSE : TRUE, // i/o direction
&AtaCommandBlock,
NULL,
AhciContext->Buffer,
(UINT32)TransferLength,
ATA_TIMEOUT
);
if (IoType == OpalRecv) {
CopyMem( Buffer, AhciContext->Buffer, TransferLength );
}
} else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
NvmeContext = (NVME_CONTEXT *) PeiDev->Context;
Status = NvmeSecuritySendReceive (
NvmeContext,
IoType == OpalSend,
SecurityProtocol,
SwapBytes16(SpSpecific),
TransferLength,
Buffer
);
} else {
DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", PeiDev->DeviceType));
}
return Status;
}
/**
Send a security protocol command to a device that receives data and/or the result
@ -351,14 +109,16 @@ SecurityReceiveData (
return EFI_DEVICE_ERROR;
}
return PerformTrustedIo (
PeiDev,
OpalRecv,
SecurityProtocolId,
SecurityProtocolSpecificData,
PayloadBufferSize,
PayloadBuffer
);
return PeiDev->SscPpi->ReceiveData (
PeiDev->SscPpi,
PeiDev->DeviceIndex,
SSC_PPI_GENERIC_TIMEOUT,
SecurityProtocolId,
SecurityProtocolSpecificData,
PayloadBufferSize,
PayloadBuffer,
PayloadTransferSize
);
}
/**
@ -441,111 +201,15 @@ SecuritySendData (
return EFI_DEVICE_ERROR;
}
return PerformTrustedIo (
PeiDev,
OpalSend,
SecurityProtocolId,
SecurityProtocolSpecificData,
PayloadBufferSize,
PayloadBuffer
);
}
/**
Save/Restore RootPort configuration space.
@param[in] DevInfoNvme Pointer to NVMe device info.
@param[in] SaveAction TRUE: Save, FALSE: Restore
@param[in,out] PcieConfBufferList Configuration space data buffer for save/restore
@return PCIE base address of this RootPort
**/
UINTN
SaveRestoreRootportConfSpace (
IN OPAL_DEVICE_NVME *DevInfoNvme,
IN BOOLEAN SaveAction,
IN OUT UINT8 **PcieConfBufferList
)
{
UINTN RpBase;
UINTN Length;
OPAL_PCI_DEVICE *DevNode;
UINT8 *StorePcieConfData;
UINTN Index;
Length = 0;
Index = 0;
RpBase = 0;
while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {
DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode + Length);
RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device, DevNode->Function, 0x0);
if (PcieConfBufferList != NULL) {
if (SaveAction) {
StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);
ASSERT (StorePcieConfData != NULL);
OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);
PcieConfBufferList[Index] = StorePcieConfData;
} else {
// Skip PCIe Command & Status registers
StorePcieConfData = PcieConfBufferList[Index];
OpalPciWrite (RpBase, StorePcieConfData, 4);
OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
FreePool (StorePcieConfData);
}
}
Length += sizeof (OPAL_PCI_DEVICE);
Index ++;
}
return RpBase;
}
/**
Configure RootPort for downstream PCIe NAND devices.
@param[in] RpBase - PCIe configuration space address of this RootPort
@param[in] BusNumber - Bus number
@param[in] MemoryBase - Memory base address
@param[in] MemoryLength - Memory size
**/
VOID
ConfigureRootPortForPcieNand (
IN UINTN RpBase,
IN UINTN BusNumber,
IN UINT32 MemoryBase,
IN UINT32 MemoryLength
)
{
UINT32 MemoryLimit;
DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
BusNumber, MemoryBase, MemoryLength));
if (MemoryLength == 0) {
MemoryLimit = MemoryBase;
} else {
MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
}
///
/// Configue PCIE configuration space for RootPort
///
PciWrite8 (RpBase + NVME_PCIE_BNUM + 1, (UINT8) BusNumber); // Secondary Bus Number registers
PciWrite8 (RpBase + NVME_PCIE_BNUM + 2, (UINT8) BusNumber); // Subordinate Bus Number registers
PciWrite8 (RpBase + NVME_PCIE_IOBL, 0xFF); // I/O Base registers
PciWrite8 (RpBase + NVME_PCIE_IOBL + 1, 0x00); // I/O Limit registers
PciWrite16 (RpBase + NVME_PCIE_MBL, (UINT16) RShiftU64 ((UINTN)MemoryBase, 16)); // Memory Base register
PciWrite16 (RpBase + NVME_PCIE_MBL + 2, (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register
PciWrite16 (RpBase + NVME_PCIE_PMBL, 0xFFFF); // Prefetchable Memory Base registers
PciWrite16 (RpBase + NVME_PCIE_PMBL + 2, 0x0000); // Prefetchable Memory Limit registers
PciWrite32 (RpBase + NVME_PCIE_PMBU32, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers
PciWrite32 (RpBase + NVME_PCIE_PMLU32, 0x00000000); // Prefetchable Memory Upper Limit registers
return PeiDev->SscPpi->SendData (
PeiDev->SscPpi,
PeiDev->DeviceIndex,
SSC_PPI_GENERIC_TIMEOUT,
SecurityProtocolId,
SecurityProtocolSpecificData,
PayloadBufferSize,
PayloadBuffer
);
}
/**
@ -651,274 +315,137 @@ UnlockOpalPassword (
}
/**
Unlock ATA OPAL password for S3.
Unlock the OPAL NVM Express and ATA devices for S3.
@param[in] SscPpi Pointer to the EDKII_PEI_STORAGE_SECURITY_CMD_PPI instance.
**/
VOID
UnlockOpalPasswordAta (
VOID
UnlockOpalPasswordDevices (
IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *SscPpi
)
{
EFI_STATUS Status;
UINT8 *DevInfo;
OPAL_DEVICE_ATA TempDevInfoAta;
OPAL_DEVICE_ATA *DevInfoAta;
UINTN DevInfoLengthAta;
UINT8 Bus;
UINT8 Device;
UINT8 Function;
OPAL_PEI_DEVICE OpalDev;
UINT8 BaseClassCode;
UINT8 SubClassCode;
UINT8 SataCmdSt;
AHCI_CONTEXT AhciContext;
UINT32 AhciBar;
DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
EFI_STATUS Status;
UINT8 *DevInfoBuffer;
UINT8 DummyData;
OPAL_DEVICE_LOCKBOX_DATA *DevInfo;
UINTN DevInfoLength;
EFI_DEVICE_PATH_PROTOCOL *SscDevicePath;
UINTN SscDevicePathLength;
UINTN SscDeviceNum;
UINTN SscDeviceIndex;
OPAL_PEI_DEVICE OpalDev;
//
// Get ATA OPAL device info from LockBox.
// Get OPAL devices info from LockBox.
//
DevInfo = (UINT8 *) &TempDevInfoAta;
DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
DevInfoBuffer = &DummyData;
DevInfoLength = sizeof (DummyData);
Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer, &DevInfoLength);
if (Status == EFI_BUFFER_TOO_SMALL) {
DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
if (DevInfo != NULL) {
Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
DevInfoBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLength));
if (DevInfoBuffer != NULL) {
Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer, &DevInfoLength);
}
}
if (EFI_ERROR (Status) || (DevInfo == NULL)) {
if (DevInfoBuffer == NULL || DevInfoBuffer == &DummyData) {
return;
} else if (EFI_ERROR (Status)) {
FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));
return;
}
for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
(UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);
DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta + DevInfoAta->Length)) {
Bus = DevInfoAta->Device.Bus;
Device = DevInfoAta->Device.Device;
Function = DevInfoAta->Device.Function;
//
// Go through all the devices managed by the SSC PPI instance.
//
Status = SscPpi->GetNumberofDevices (SscPpi, &SscDeviceNum);
if (EFI_ERROR (Status)) {
goto Exit;
}
for (SscDeviceIndex = 1; SscDeviceIndex <= SscDeviceNum; SscDeviceIndex++) {
Status = SscPpi->GetDevicePath (
SscPpi,
SscDeviceIndex,
&SscDevicePathLength,
&SscDevicePath
);
if (SscDevicePathLength <= sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
//
// Device path validity check.
//
continue;
}
SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET));
PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), 0x6);
BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
SubClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) && (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {
DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not supported\n", __FUNCTION__));
} else {
AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), DevInfoAta->BarAddr);
ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));
AhciContext.AhciBar = DevInfoAta->BarAddr;
AhciAllocateResource (&AhciContext);
Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error, Status: %r\n", __FUNCTION__, Status));
} else {
OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
//
// Search the device in the restored LockBox.
//
for (DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) DevInfoBuffer;
(UINTN) DevInfo < ((UINTN) DevInfoBuffer + DevInfoLength);
DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) DevInfo + DevInfo->Length)) {
//
// Find the matching device.
//
if ((DevInfo->DevicePathLength >= SscDevicePathLength) &&
(CompareMem (
DevInfo->DevicePath,
SscDevicePath,
SscDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) == 0)) {
OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
OpalDev.Sscp.ReceiveData = SecurityReceiveData;
OpalDev.Sscp.SendData = SecuritySendData;
OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
OpalDev.Context = &AhciContext;
OpalDev.Sscp.SendData = SecuritySendData;
OpalDev.Device = DevInfo;
OpalDev.Context = NULL;
OpalDev.SscPpi = SscPpi;
OpalDev.DeviceIndex = SscDeviceIndex;
UnlockOpalPassword (&OpalDev);
break;
}
AhciFreeResource (&AhciContext);
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);
}
PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), SataCmdSt);
}
ZeroMem (DevInfo, DevInfoLengthAta);
if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {
FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));
}
Exit:
ZeroMem (DevInfoBuffer, DevInfoLength);
FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));
DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
}
/**
Unlock NVMe OPAL password for S3.
**/
VOID
UnlockOpalPasswordNvme (
VOID
)
{
EFI_STATUS Status;
UINT8 *DevInfo;
OPAL_DEVICE_NVME TempDevInfoNvme;
OPAL_DEVICE_NVME *DevInfoNvme;
UINTN DevInfoLengthNvme;
UINT8 Bus;
UINT8 Device;
UINT8 Function;
OPAL_PEI_DEVICE OpalDev;
UINT8 BaseClassCode;
UINT8 SubClassCode;
UINT8 ProgInt;
UINT8 NvmeCmdSt;
UINT8 *StorePcieConfDataList[16];
UINTN RpBase;
UINTN MemoryBase;
UINTN MemoryLength;
NVME_CONTEXT NvmeContext;
DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
//
// Get NVMe OPAL device info from LockBox.
//
DevInfo = (UINT8 *) &TempDevInfoNvme;
DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);
Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
if (Status == EFI_BUFFER_TOO_SMALL) {
DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
if (DevInfo != NULL) {
Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
}
}
if (EFI_ERROR (Status) || (DevInfo == NULL)) {
return;
}
for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
(UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);
DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme + DevInfoNvme->Length)) {
Bus = DevInfoNvme->Device.Bus;
Device = DevInfoNvme->Device.Device;
Function = DevInfoNvme->Device.Function;
RpBase = 0;
NvmeCmdSt = 0;
///
/// Save original RootPort configuration space to heap
///
RpBase = SaveRestoreRootportConfSpace (
DevInfoNvme,
TRUE, // save
StorePcieConfDataList
);
MemoryBase = DevInfoNvme->BarAddr;
MemoryLength = 0;
ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase, (UINT32) MemoryLength);
///
/// Enable PCIE decode for RootPort
///
NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6);
BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
SubClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
ProgInt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x09));
if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
(SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||
(ProgInt != PCI_IF_NVMHCI)) {
DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not supported\n", __FUNCTION__));
} else {
ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));
NvmeContext.Nbar = DevInfoNvme->BarAddr;
NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);
NvmeContext.NvmeInitWaitTime = 0;
NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;
NvmeAllocateResource (&NvmeContext);
Status = NvmeControllerInit (&NvmeContext);
OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
OpalDev.Sscp.ReceiveData = SecurityReceiveData;
OpalDev.Sscp.SendData = SecuritySendData;
OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;
OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;
OpalDev.Context = &NvmeContext;
UnlockOpalPassword (&OpalDev);
Status = NvmeControllerExit (&NvmeContext);
NvmeFreeResource (&NvmeContext);
}
ASSERT (RpBase != 0);
PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0);
RpBase = SaveRestoreRootportConfSpace (
DevInfoNvme,
FALSE, // restore
StorePcieConfDataList
);
PciWrite8 (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
}
ZeroMem (DevInfo, DevInfoLengthNvme);
if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
}
DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
}
/**
Unlock OPAL password for S3.
**/
VOID
OpalPasswordS3 (
VOID
)
{
UnlockOpalPasswordAta ();
UnlockOpalPasswordNvme ();
}
/**
Entry point of the notification callback function itself within the PEIM.
One notified function at the installation of EDKII_PEI_STORAGE_SECURITY_CMD_PPI.
It is to unlock OPAL password for S3.
@param PeiServices Indirect reference to the PEI Services Table.
@param NotifyDescriptor Address of the notification descriptor data structure.
@param Ppi Address of the PPI that was installed.
@param[in] PeiServices Indirect reference to the PEI Services Table.
@param[in] NotifyDescriptor Address of the notification descriptor data structure.
@param[in] Ppi Address of the PPI that was installed.
@return Status of the notification.
The status code returned from this function is ignored.
**/
EFI_STATUS
EFIAPI
OpalPasswordEndOfPeiNotify(
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
OpalPasswordStorageSecurityPpiNotify (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
DEBUG ((DEBUG_INFO, "%a entered at S3 resume!\n", __FUNCTION__));
Status = PeiServicesGetBootMode (&BootMode);
ASSERT_EFI_ERROR (Status);
if (BootMode != BOOT_ON_S3_RESUME) {
return EFI_UNSUPPORTED;
}
UnlockOpalPasswordDevices ((EDKII_PEI_STORAGE_SECURITY_CMD_PPI *) Ppi);
DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
OpalPasswordS3 ();
DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
DEBUG ((DEBUG_INFO, "%a exit at S3 resume!\n", __FUNCTION__));
return EFI_SUCCESS;
}
EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {
EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordStorageSecurityPpiNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSignalPpiGuid,
OpalPasswordEndOfPeiNotify
&gEdkiiPeiStorageSecurityCommandPpiGuid,
OpalPasswordStorageSecurityPpiNotify
};
/**
Main entry for this module.
@ -935,10 +462,17 @@ OpalPasswordPeiInit (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
Status = PeiServicesGetBootMode (&BootMode);
if ((EFI_ERROR (Status)) || (BootMode != BOOT_ON_S3_RESUME)) {
return EFI_UNSUPPORTED;
}
DEBUG ((DEBUG_INFO, "%a: Enters in S3 path.\n", __FUNCTION__));
Status = PeiServicesNotifyPpi (&mOpalPasswordStorageSecurityPpiNotifyDesc);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -1,7 +1,7 @@
/** @file
Opal Password PEI driver which is used to unlock Opal Password for S3.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -16,8 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define _OPAL_PASSWORD_PEI_H_
#include <PiPei.h>
#include <IndustryStandard/Atapi.h>
#include <IndustryStandard/Pci.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
@ -27,107 +25,42 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/MemoryAllocationLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/HobLib.h>
#include <Library/TimerLib.h>
#include <Library/LockBoxLib.h>
#include <Library/TcgStorageOpalLib.h>
#include <Library/Tcg2PhysicalPresenceLib.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Protocol/StorageSecurityCommand.h>
#include <Ppi/IoMmu.h>
#include <Ppi/StorageSecurityCommand.h>
#include "OpalPasswordCommon.h"
#include "OpalAhciMode.h"
#include "OpalNvmeMode.h"
//
// Time out Value for ATA pass through protocol
// The generic command timeout value (unit in us) for Storage Security Command
// PPI ReceiveData/SendData services
//
#define ATA_TIMEOUT 30000000
//
// The payload Length of HDD related ATA commands
//
#define HDD_PAYLOAD 512
//
// According to ATA spec, the max Length of hdd password is 32 bytes
//
#define OPAL_PASSWORD_MAX_LENGTH 32
#define SSC_PPI_GENERIC_TIMEOUT 30000000
#pragma pack(1)
/**
* Opal I/O Type utilized by the Trusted IO callback
*
* The type indicates if the I/O is a send or receive
*/
typedef enum {
//
// I/O is a TCG Trusted Send command
//
OpalSend,
//
// I/O is a TCG Trusted Receive command
//
OpalRecv
} OPAL_IO_TYPE;
#define OPAL_PEI_DEVICE_SIGNATURE SIGNATURE_32 ('o', 'p', 'd', 's')
#define OPAL_PEI_DEVICE_SIGNATURE SIGNATURE_32 ('o', 'p', 'd', 's')
typedef struct {
UINTN Signature;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL Sscp;
UINT8 DeviceType;
OPAL_DEVICE_COMMON *Device;
VOID *Context;
UINTN Signature;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL Sscp;
OPAL_DEVICE_LOCKBOX_DATA *Device;
VOID *Context;
EDKII_PEI_STORAGE_SECURITY_CMD_PPI *SscPpi;
UINTN DeviceIndex;
} OPAL_PEI_DEVICE;
#define OPAL_PEI_DEVICE_FROM_THIS(a) CR (a, OPAL_PEI_DEVICE, Sscp, OPAL_PEI_DEVICE_SIGNATURE)
#define OPAL_PEI_DEVICE_FROM_THIS(a) \
CR (a, OPAL_PEI_DEVICE, Sscp, OPAL_PEI_DEVICE_SIGNATURE)
#pragma pack()
/**
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
OperationBusMasterCommonBuffer64 mapping.
@param Pages The number of pages to allocate.
@param HostAddress A pointer to store the base system memory address of the
allocated range.
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
access the hosts HostAddress.
@param Mapping A resulting value to pass to Unmap().
@retval EFI_SUCCESS The requested memory pages were allocated.
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
**/
EFI_STATUS
IoMmuAllocateBuffer (
IN UINTN Pages,
OUT VOID **HostAddress,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
);
/**
Frees memory that was allocated with AllocateBuffer().
@param Pages The number of pages to free.
@param HostAddress The base system memory address of the allocated range.
@param Mapping The mapping value returned from Map().
**/
VOID
IoMmuFreeBuffer (
IN UINTN Pages,
IN VOID *HostAddress,
IN VOID *Mapping
);
#endif // _OPAL_PASSWORD_PEI_H_

View File

@ -1,7 +1,7 @@
## @file
# This is a Opal Password PEI driver.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@ -29,11 +29,6 @@
OpalPasswordPei.c
OpalPasswordPei.h
OpalPasswordCommon.h
OpalAhciMode.c
OpalAhciMode.h
OpalNvmeMode.c
OpalNvmeMode.h
OpalNvmeReg.h
[Packages]
MdePkg/MdePkg.dec
@ -49,14 +44,13 @@
BaseLib
BaseMemoryLib
MemoryAllocationLib
TimerLib
LockBoxLib
TcgStorageOpalLib
Tcg2PhysicalPresenceLib
PeiServicesTablePointerLib
[Ppis]
gEdkiiIoMmuPpiGuid ## SOMETIMES_CONSUMES
gEfiEndOfPeiSignalPpiGuid ## NOTIFY
gEdkiiPeiStorageSecurityCommandPpiGuid ## NOTIFY
[Depex]
gEfiPeiMasterBootModePpiGuid