From: "Dong, Eric" <eric.dong@intel.com>
To: "Wu, Hao A" <hao.a.wu@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Zhang, Chao B" <chao.b.zhang@intel.com>,
"Yao, Jiewen" <jiewen.yao@intel.com>,
"Ni, Ray" <ray.ni@intel.com>
Subject: Re: [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI
Date: Mon, 18 Feb 2019 06:20:32 +0000 [thread overview]
Message-ID: <ED077930C258884BBCB450DB737E662259DB1153@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <20190215062338.19412-14-hao.a.wu@intel.com>
Hi Hao,
Only one minor change that below zero action is not needed.
> + ZeroMem (S3InitDevices, S3InitDevicesLength);
With above changes, Reviewed-by: Eric Dong <eric.dong@intel.com>
Thanks,
Eric
> -----Original Message-----
> From: Wu, Hao A
> Sent: Friday, February 15, 2019 2:24 PM
> To: edk2-devel@lists.01.org
> Cc: Wu, Hao A <hao.a.wu@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Ni, Ray
> <ray.ni@intel.com>; Dong, Eric <eric.dong@intel.com>
> Subject: [PATCH v5 13/13] 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>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Hao Wu <hao.a.wu@intel.com>
> ---
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf | 6 +-
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf | 12 +-
> SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h | 412 -----
> SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h | 4 +-
> SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h | 327 ----
> SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h | 815 ---------
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h | 45 +-
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h | 106 +-
> SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c | 1282 --------------
> SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c | 416 ++---
> SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c | 1823 ------------
> --------
> SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c | 757 ++------
> 12 files changed, 361 insertions(+), 5644 deletions(-)
>
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> index 11e58b95cd..2e343a4707 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf
> @@ -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
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> index 482b7c25af..5abfc69e80 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf
> @@ -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
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> deleted file mode 100644
> index 2076b0411b..0000000000
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.h
> +++ /dev/null
> @@ -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
> -
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> index 2bca770620..1baa483e72 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h
> @@ -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>
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> deleted file mode 100644
> index bd2bd5239d..0000000000
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.h
> +++ /dev/null
> @@ -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
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> deleted file mode 100644
> index 03376b9e6c..0000000000
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeReg.h
> +++ /dev/null
> @@ -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
> -
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> index e10146e466..f9fdb64137 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordCommon.h
> @@ -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;
> -
> -#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;
> + 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_LOCKBOX_GUID { 0x56a77f0d, 0x6f05, 0x4d47,
> { 0xb9, 0x11, 0x4f, 0xd, 0xec, 0x5c, 0x58, 0x61 } }
>
> #endif // _OPAL_PASSWORD_COMMON_H_
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> index 31aab37f5d..c86598f21c 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.h
> @@ -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,63 @@ 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 maximum number of Storage Security Command PPI instance
> supported
> +// by the driver
> //
> -#define ATA_TIMEOUT 30000000
> +#define OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI 32
>
> //
> -// The payload Length of HDD related ATA commands
> +// The generic command timeout value (unit in us) for Storage Security
> Command
> +// PPI ReceiveData/SendData services
> //
> -#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
> - );
> +//
> +// Private data structure for Opal PEI driver
> +//
> +#define OPAL_PEI_DRIVER_SIGNATURE SIGNATURE_32 ('o', 'd', 'r', 'i')
>
> -/**
> - Frees memory that was allocated with AllocateBuffer().
> +typedef struct {
> + UINTN Signature;
> + EFI_PEI_NOTIFY_DESCRIPTOR SscPpiNotifyList;
>
> - @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().
> + UINTN SscPpiInstanceNum;
> + UINTN
> SscPpiInstances[OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI];
> +} OPAL_PEI_DRIVER_PRIVATE_DATA;
>
> -**/
> -VOID
> -IoMmuFreeBuffer (
> - IN UINTN Pages,
> - IN VOID *HostAddress,
> - IN VOID *Mapping
> - );
> +#define OPAL_PEI_PRIVATE_DATA_FROM_THIS_NOTIFY(a) \
> + CR (a, OPAL_PEI_DRIVER_PRIVATE_DATA, SscPpiNotifyList,
> OPAL_PEI_DRIVER_SIGNATURE)
>
> #endif // _OPAL_PASSWORD_PEI_H_
>
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> deleted file mode 100644
> index 0c4edd5346..0000000000
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
> +++ /dev/null
> @@ -1,1282 +0,0 @@
> -/** @file
> - This driver is used for Opal Password Feature support at AHCI mode.
> -
> -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.
> -
> -**/
> -
> -
> -#include "OpalPasswordPei.h"
> -
> -/**
> - Start command for give slot on specific port.
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param CommandSlot The number of CommandSlot.
> - @param Timeout The timeout Value of start.
> -
> - @retval EFI_DEVICE_ERROR The command start unsuccessfully.
> - @retval EFI_TIMEOUT The operation is time out.
> - @retval EFI_SUCCESS The command start successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciStartCommand (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT8 CommandSlot,
> - IN UINT64 Timeout
> - );
> -
> -/**
> - Stop command running for giving port
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param Timeout The timeout Value of stop.
> -
> - @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
> - @retval EFI_TIMEOUT The operation is time out.
> - @retval EFI_SUCCESS The command stop successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciStopCommand (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT64 Timeout
> - );
> -
> -/**
> - Read AHCI Operation register.
> -
> - @param AhciBar AHCI bar address.
> - @param Offset The operation register offset.
> -
> - @return The register content read.
> -
> -**/
> -UINT32
> -EFIAPI
> -AhciReadReg (
> - IN UINT32 AhciBar,
> - IN UINT32 Offset
> - )
> -{
> - UINT32 Data;
> -
> - Data = 0;
> -
> - Data = MmioRead32 (AhciBar + Offset);
> -
> - return Data;
> -}
> -
> -/**
> - Write AHCI Operation register.
> -
> - @param AhciBar AHCI bar address.
> - @param Offset The operation register offset.
> - @param Data The Data used to write down.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciWriteReg (
> - IN UINT32 AhciBar,
> - IN UINT32 Offset,
> - IN UINT32 Data
> - )
> -{
> - MmioWrite32 (AhciBar + Offset, Data);
> -
> - return ;
> -}
> -
> -/**
> - Do AND operation with the Value of AHCI Operation register.
> -
> - @param AhciBar AHCI bar address.
> - @param Offset The operation register offset.
> - @param AndData The Data used to do AND operation.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciAndReg (
> - IN UINT32 AhciBar,
> - IN UINT32 Offset,
> - IN UINT32 AndData
> - )
> -{
> - UINT32 Data;
> -
> - Data = AhciReadReg (AhciBar, Offset);
> -
> - Data &= AndData;
> -
> - AhciWriteReg (AhciBar, Offset, Data);
> -}
> -
> -/**
> - Do OR operation with the Value of AHCI Operation register.
> -
> - @param AhciBar AHCI bar address.
> - @param Offset The operation register offset.
> - @param OrData The Data used to do OR operation.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciOrReg (
> - IN UINT32 AhciBar,
> - IN UINT32 Offset,
> - IN UINT32 OrData
> - )
> -{
> - UINT32 Data;
> -
> - Data = AhciReadReg (AhciBar, Offset);
> -
> - Data |= OrData;
> -
> - AhciWriteReg (AhciBar, Offset, Data);
> -}
> -
> -/**
> - Wait for memory set to the test Value.
> -
> - @param AhciBar AHCI bar address.
> - @param Offset The memory offset to test.
> - @param MaskValue The mask Value of memory.
> - @param TestValue The test Value of memory.
> - @param Timeout The time out Value for wait memory set.
> -
> - @retval EFI_DEVICE_ERROR The memory is not set.
> - @retval EFI_TIMEOUT The memory setting is time out.
> - @retval EFI_SUCCESS The memory is correct set.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciWaitMmioSet (
> - IN UINT32 AhciBar,
> - IN UINT32 Offset,
> - IN UINT32 MaskValue,
> - IN UINT32 TestValue,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Value;
> - UINT32 Delay;
> -
> - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> -
> - do {
> - Value = AhciReadReg (AhciBar, Offset) & MaskValue;
> -
> - if (Value == TestValue) {
> - return EFI_SUCCESS;
> - }
> -
> - //
> - // Stall for 100 microseconds.
> - //
> - MicroSecondDelay (100);
> -
> - Delay--;
> -
> - } while (Delay > 0);
> -
> - return EFI_TIMEOUT;
> -}
> -/**
> - Wait for the Value of the specified system memory set to the test Value.
> -
> - @param Address The system memory address to test.
> - @param MaskValue The mask Value of memory.
> - @param TestValue The test Value of memory.
> - @param Timeout The time out Value for wait memory set, uses 100ns
> as a unit.
> -
> - @retval EFI_TIMEOUT The system memory setting is time out.
> - @retval EFI_SUCCESS The system memory is correct set.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciWaitMemSet (
> - IN EFI_PHYSICAL_ADDRESS Address,
> - IN UINT32 MaskValue,
> - IN UINT32 TestValue,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Value;
> - UINT32 Delay;
> -
> - Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> -
> - do {
> - //
> - // Access sytem memory to see if the Value is the tested one.
> - //
> - // The system memory pointed by Address will be updated by the
> - // SATA Host Controller, "volatile" is introduced to prevent
> - // compiler from optimizing the access to the memory address
> - // to only read once.
> - //
> - Value = *(volatile UINT32 *) (UINTN) Address;
> - Value &= MaskValue;
> -
> - if (Value == TestValue) {
> - return EFI_SUCCESS;
> - }
> -
> - //
> - // Stall for 100 microseconds.
> - //
> - MicroSecondDelay (100);
> -
> - Delay--;
> -
> - } while (Delay > 0);
> -
> - return EFI_TIMEOUT;
> -}
> -
> -/**
> - Check the memory status to the test Value.
> -
> - @param[in] Address The memory address to test.
> - @param[in] MaskValue The mask Value of memory.
> - @param[in] TestValue The test Value of memory.
> - @param[in, out] RetryTimes The retry times Value for waitting memory
> set. If 0, then just try once.
> -
> - @retval EFI_NOTREADY The memory is not set.
> - @retval EFI_TIMEOUT The memory setting retry times out.
> - @retval EFI_SUCCESS The memory is correct set.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciCheckMemSet (
> - IN UINTN Address,
> - IN UINT32 MaskValue,
> - IN UINT32 TestValue,
> - IN OUT UINTN *RetryTimes OPTIONAL
> - )
> -{
> - UINT32 Value;
> -
> - if (RetryTimes != NULL) {
> - (*RetryTimes)--;
> - }
> -
> - Value = *(volatile UINT32 *) Address;
> - Value &= MaskValue;
> -
> - if (Value == TestValue) {
> - return EFI_SUCCESS;
> - }
> -
> - if ((RetryTimes != NULL) && (*RetryTimes == 0)) {
> - return EFI_TIMEOUT;
> - } else {
> - return EFI_NOT_READY;
> - }
> -}
> -
> -/**
> - Clear the port interrupt and error status. It will also clear
> - HBA interrupt status.
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciClearPortStatus (
> - IN UINT32 AhciBar,
> - IN UINT8 Port
> - )
> -{
> - UINT32 Offset;
> -
> - //
> - // Clear any error status
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> - AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> -
> - //
> - // Clear any port interrupt status
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IS;
> - AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
> -
> - //
> - // Clear any HBA interrupt status
> - //
> - AhciWriteReg (AhciBar, EFI_AHCI_IS_OFFSET, AhciReadReg (AhciBar,
> EFI_AHCI_IS_OFFSET));
> -}
> -
> -/**
> - Enable the FIS running for giving port.
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param Timeout The timeout Value of enabling FIS.
> -
> - @retval EFI_DEVICE_ERROR The FIS enable setting fails.
> - @retval EFI_TIMEOUT The FIS enable setting is time out.
> - @retval EFI_SUCCESS The FIS enable successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciEnableFisReceive (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Offset;
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_FRE);
> -
> - return AhciWaitMmioSet (
> - AhciBar,
> - Offset,
> - EFI_AHCI_PORT_CMD_FR,
> - EFI_AHCI_PORT_CMD_FR,
> - Timeout
> - );
> -}
> -
> -/**
> - Disable the FIS running for giving port.
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param Timeout The timeout Value of disabling FIS.
> -
> - @retval EFI_DEVICE_ERROR The FIS disable setting fails.
> - @retval EFI_TIMEOUT The FIS disable setting is time out.
> - @retval EFI_UNSUPPORTED The port is in running state.
> - @retval EFI_SUCCESS The FIS disable successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciDisableFisReceive (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Offset;
> - UINT32 Data;
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - Data = AhciReadReg (AhciBar, Offset);
> -
> - //
> - // Before disabling Fis receive, the DMA engine of the port should NOT be
> in running status.
> - //
> - if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
> - return EFI_UNSUPPORTED;
> - }
> -
> - //
> - // Check if the Fis receive DMA engine for the port is running.
> - //
> - if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
> - return EFI_SUCCESS;
> - }
> -
> - AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
> -
> - return AhciWaitMmioSet (
> - AhciBar,
> - Offset,
> - EFI_AHCI_PORT_CMD_FR,
> - 0,
> - Timeout
> - );
> -}
> -
> -/**
> - Build the command list, command table and prepare the fis receiver.
> -
> - @param AhciContext The pointer to the AHCI_CONTEXT.
> - @param Port The number of port.
> - @param PortMultiplier The timeout Value of stop.
> - @param CommandFis The control fis will be used for the transfer.
> - @param CommandList The command list will be used for the transfer.
> - @param AtapiCommand The atapi command will be used for the
> transfer.
> - @param AtapiCommandLength The Length of the atapi command.
> - @param CommandSlotNumber The command slot will be used for the
> transfer.
> - @param DataPhysicalAddr The pointer to the Data Buffer pci bus
> master address.
> - @param DataLength The Data count to be transferred.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciBuildCommand (
> - IN AHCI_CONTEXT *AhciContext,
> - IN UINT8 Port,
> - IN UINT8 PortMultiplier,
> - IN EFI_AHCI_COMMAND_FIS *CommandFis,
> - IN EFI_AHCI_COMMAND_LIST *CommandList,
> - IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
> - IN UINT8 AtapiCommandLength,
> - IN UINT8 CommandSlotNumber,
> - IN OUT VOID *DataPhysicalAddr,
> - IN UINT64 DataLength
> - )
> -{
> - EFI_AHCI_REGISTERS *AhciRegisters;
> - UINT32 AhciBar;
> - UINT64 BaseAddr;
> - UINT64 PrdtNumber;
> - UINTN RemainedData;
> - UINTN MemAddr;
> - DATA_64 Data64;
> - UINT32 Offset;
> -
> - AhciRegisters = &AhciContext->AhciRegisters;
> - AhciBar = AhciContext->AhciBar;
> -
> - //
> - // Filling the PRDT
> - //
> - PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT
> - 1, EFI_AHCI_MAX_DATA_PER_PRDT);
> -
> - //
> - // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB
> Data block.
> - // It also limits that the maximum amount of the PRDT entry in the
> command table
> - // is 65535.
> - //
> - ASSERT (PrdtNumber <= 1);
> -
> - Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);
> -
> - BaseAddr = Data64.Uint64;
> -
> - ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
> -
> - ZeroMem (AhciRegisters->AhciCommandTable, sizeof
> (EFI_AHCI_COMMAND_TABLE));
> -
> - CommandFis->AhciCFisPmNum = PortMultiplier;
> -
> - CopyMem (&AhciRegisters->AhciCommandTable->CommandFis,
> CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - if (AtapiCommand != NULL) {
> - CopyMem (
> - &AhciRegisters->AhciCommandTable->AtapiCmd,
> - AtapiCommand,
> - AtapiCommandLength
> - );
> -
> - CommandList->AhciCmdA = 1;
> - CommandList->AhciCmdP = 1;
> -
> - AhciOrReg (AhciBar, Offset, (EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> - } else {
> - AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE |
> EFI_AHCI_PORT_CMD_ATAPI));
> - }
> -
> - RemainedData = (UINTN) DataLength;
> - MemAddr = (UINTN) DataPhysicalAddr;
> - CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
> -
> - AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc =
> (UINT32)RemainedData - 1;
> -
> - Data64.Uint64 = (UINT64)MemAddr;
> - AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba =
> Data64.Uint32.Lower32;
> - AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau =
> Data64.Uint32.Upper32;
> -
> - //
> - // Set the last PRDT to Interrupt On Complete
> - //
> - AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;
> -
> - CopyMem (
> - (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN)
> CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
> - CommandList,
> - sizeof (EFI_AHCI_COMMAND_LIST)
> - );
> -
> - Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;
> - AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba =
> Data64.Uint32.Lower32;
> - AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau =
> Data64.Uint32.Upper32;
> - AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp =
> PortMultiplier;
> -
> -}
> -
> -/**
> - Buid a command FIS.
> -
> - @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS Data
> structure.
> - @param AtaCommandBlock A pointer to the AhciBuildCommandFis Data
> structure.
> -
> -**/
> -VOID
> -EFIAPI
> -AhciBuildCommandFis (
> - IN OUT EFI_AHCI_COMMAND_FIS *CmdFis,
> - IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
> - )
> -{
> - ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
> -
> - CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
> - //
> - // Indicator it's a command
> - //
> - CmdFis->AhciCFisCmdInd = 0x1;
> - CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
> -
> - CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
> - CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
> -
> - CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
> - CmdFis->AhciCFisSecNumExp = AtaCommandBlock-
> >AtaSectorNumberExp;
> -
> - CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
> - CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
> -
> - CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
> - CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
> -
> - CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
> - CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
> -
> - CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock-
> >AtaDeviceHead | 0xE0);
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - EFI_AHCI_REGISTERS *AhciRegisters;
> - UINT32 AhciBar;
> - UINT32 FisBaseAddr;
> - UINT32 Offset;
> - UINT32 Delay;
> - EFI_AHCI_COMMAND_FIS CFis;
> - EFI_AHCI_COMMAND_LIST CmdList;
> - UINT32 PortTfd;
> - UINT32 PrdCount;
> - UINT32 OldRfisLo;
> - UINT32 OldRfisHi;
> - UINT32 OldCmdListLo;
> - UINT32 OldCmdListHi;
> -
> - AhciRegisters = &AhciContext->AhciRegisters;
> - AhciBar = AhciContext->AhciBar;
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> - OldRfisLo = AhciReadReg (AhciBar, Offset);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> - OldRfisHi = AhciReadReg (AhciBar, Offset);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> - AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> - AhciWriteReg (AhciBar, Offset, 0);
> -
> - //
> - // Single task envrionment, we only use one command table for all port
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> - OldCmdListLo = AhciReadReg (AhciBar, Offset);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> - OldCmdListHi = AhciReadReg (AhciBar, Offset);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> - AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters-
> >AhciCmdList);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> - AhciWriteReg (AhciBar, Offset, 0);
> -
> - //
> - // Package read needed
> - //
> - AhciBuildCommandFis (&CFis, AtaCommandBlock);
> -
> - ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
> -
> - CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
> - CmdList.AhciCmdW = Read ? 0 : 1;
> -
> - AhciBuildCommand (
> - AhciContext,
> - Port,
> - PortMultiplier,
> - &CFis,
> - &CmdList,
> - AtapiCommand,
> - AtapiCommandLength,
> - 0,
> - MemoryAddr,
> - DataCount
> - );
> -
> - Status = AhciStartCommand (
> - AhciBar,
> - Port,
> - 0,
> - Timeout
> - );
> - if (EFI_ERROR (Status)) {
> - goto Exit;
> - }
> -
> - //
> - // Checking the status and wait the driver sending Data
> - //
> - FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;
> - if (Read && (AtapiCommand == 0)) {
> - //
> - // Wait device sends the PIO setup fis before Data transfer
> - //
> - Status = EFI_TIMEOUT;
> - Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);
> - do {
> - Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
> -
> - Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_PIO_SETUP, 0);
> - if (!EFI_ERROR (Status)) {
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> - PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> - //
> - // PxTFD will be updated if there is a D2H or SetupFIS received.
> - // For PIO IN transfer, D2H means a device error. Therefore we only
> need to check the TFD after receiving a SetupFIS.
> - //
> - if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> - Status = EFI_DEVICE_ERROR;
> - break;
> - }
> -
> - PrdCount = *(volatile UINT32 *) (&(AhciRegisters-
> >AhciCmdList[0].AhciCmdPrdbc));
> - if (PrdCount == DataCount) {
> - break;
> - }
> - }
> -
> - Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> - Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK,
> EFI_AHCI_FIS_REGISTER_D2H, 0);
> - if (!EFI_ERROR (Status)) {
> - Status = EFI_DEVICE_ERROR;
> - break;
> - }
> -
> - //
> - // Stall for 100 microseconds.
> - //
> - MicroSecondDelay(100);
> -
> - Delay--;
> - } while (Delay > 0);
> - } else {
> - //
> - // Wait for D2H Fis is received
> - //
> - Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
> - Status = AhciWaitMemSet (
> - Offset,
> - EFI_AHCI_FIS_TYPE_MASK,
> - EFI_AHCI_FIS_REGISTER_D2H,
> - Timeout
> - );
> -
> - if (EFI_ERROR (Status)) {
> - goto Exit;
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> - PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
> - if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
> - Status = EFI_DEVICE_ERROR;
> - }
> - }
> -
> -Exit:
> - AhciStopCommand (
> - AhciBar,
> - Port,
> - Timeout
> - );
> -
> - AhciDisableFisReceive (
> - AhciBar,
> - Port,
> - Timeout
> - );
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> - AhciWriteReg (AhciBar, Offset, OldRfisLo);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FBU;
> - AhciWriteReg (AhciBar, Offset, OldRfisHi);
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> - AhciWriteReg (AhciBar, Offset, OldCmdListLo);
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLBU;
> - AhciWriteReg (AhciBar, Offset, OldCmdListHi);
> -
> - return Status;
> -}
> -
> -/**
> - Stop command running for giving port
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param Timeout The timeout Value of stop.
> -
> - @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
> - @retval EFI_TIMEOUT The operation is time out.
> - @retval EFI_SUCCESS The command stop successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciStopCommand (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Offset;
> - UINT32 Data;
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - Data = AhciReadReg (AhciBar, Offset);
> -
> - if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {
> - return EFI_SUCCESS;
> - }
> -
> - if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
> - AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
> - }
> -
> - return AhciWaitMmioSet (
> - AhciBar,
> - Offset,
> - EFI_AHCI_PORT_CMD_CR,
> - 0,
> - Timeout
> - );
> -}
> -
> -/**
> - Start command for give slot on specific port.
> -
> - @param AhciBar AHCI bar address.
> - @param Port The number of port.
> - @param CommandSlot The number of CommandSlot.
> - @param Timeout The timeout Value of start.
> -
> - @retval EFI_DEVICE_ERROR The command start unsuccessfully.
> - @retval EFI_TIMEOUT The operation is time out.
> - @retval EFI_SUCCESS The command start successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciStartCommand (
> - IN UINT32 AhciBar,
> - IN UINT8 Port,
> - IN UINT8 CommandSlot,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 CmdSlotBit;
> - EFI_STATUS Status;
> - UINT32 PortStatus;
> - UINT32 StartCmd;
> - UINT32 PortTfd;
> - UINT32 Offset;
> - UINT32 Capability;
> -
> - //
> - // Collect AHCI controller information
> - //
> - Capability = AhciReadReg(AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> -
> - CmdSlotBit = (UINT32) (1 << CommandSlot);
> -
> - AhciClearPortStatus (
> - AhciBar,
> - Port
> - );
> -
> - Status = AhciEnableFisReceive (
> - AhciBar,
> - Port,
> - Timeout
> - );
> -
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - PortStatus = AhciReadReg (AhciBar, Offset);
> -
> - StartCmd = 0;
> - if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
> - StartCmd = AhciReadReg (AhciBar, Offset);
> - StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
> - StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> - PortTfd = AhciReadReg (AhciBar, Offset);
> -
> - if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0)
> {
> - if ((Capability & BIT24) != 0) {
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_COL);
> -
> - AhciWaitMmioSet (
> - AhciBar,
> - Offset,
> - EFI_AHCI_PORT_CMD_COL,
> - 0,
> - Timeout
> - );
> - }
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
> -
> - //
> - // Setting the command
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SACT;
> - AhciAndReg (AhciBar, Offset, 0);
> - AhciOrReg (AhciBar, Offset, CmdSlotBit);
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CI;
> - AhciAndReg (AhciBar, Offset, 0);
> - AhciOrReg (AhciBar, Offset, CmdSlotBit);
> - return EFI_SUCCESS;
> -}
> -
> -
> -/**
> - Do AHCI HBA reset.
> -
> - @param[in] AhciBar AHCI bar address.
> - @param[in] Timeout The timeout Value of reset.
> -
> - @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware
> reset.
> - @retval EFI_TIMEOUT The reset operation is time out.
> - @retval EFI_SUCCESS AHCI controller is reset successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -AhciReset (
> - IN UINT32 AhciBar,
> - IN UINT64 Timeout
> - )
> -{
> - UINT32 Delay;
> - UINT32 Value;
> - UINT32 Capability;
> -
> - //
> - // Collect AHCI controller information
> - //
> - Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> -
> - //
> - // Enable AE before accessing any AHCI registers if Supports AHCI Mode
> Only is not set
> - //
> - if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> - AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> - }
> -
> - AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
> -
> - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
> -
> - do {
> - Value = AhciReadReg(AhciBar, EFI_AHCI_GHC_OFFSET);
> - if ((Value & EFI_AHCI_GHC_RESET) == 0) {
> - return EFI_SUCCESS;
> - }
> -
> - //
> - // Stall for 100 microseconds.
> - //
> - MicroSecondDelay(100);
> -
> - Delay--;
> - } while (Delay > 0);
> -
> - return EFI_TIMEOUT;
> -
> -
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - EFI_AHCI_REGISTERS *AhciRegisters;
> - EFI_PHYSICAL_ADDRESS DeviceAddress;
> - VOID *Base;
> - VOID *Mapping;
> -
> - AhciRegisters = &AhciContext->AhciRegisters;
> -
> - //
> - // Allocate resources required by AHCI host controller.
> - //
> - Status = IoMmuAllocateBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - &Base,
> - &DeviceAddress,
> - &Mapping
> - );
> - if (EFI_ERROR (Status)) {
> - return EFI_OUT_OF_RESOURCES;
> - }
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> - AhciRegisters->AhciRFisMapping = Mapping;
> - AhciRegisters->AhciRFis = Base;
> - ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (sizeof (EFI_AHCI_RECEIVED_FIS)));
> -
> - Status = IoMmuAllocateBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> - &Base,
> - &DeviceAddress,
> - &Mapping
> - );
> - if (EFI_ERROR (Status)) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - AhciRegisters->AhciRFis,
> - AhciRegisters->AhciRFisMapping
> - );
> - AhciRegisters->AhciRFis = NULL;
> - return EFI_OUT_OF_RESOURCES;
> - }
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> - AhciRegisters->AhciCmdListMapping = Mapping;
> - AhciRegisters->AhciCmdList = Base;
> - ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));
> -
> - Status = IoMmuAllocateBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> - &Base,
> - &DeviceAddress,
> - &Mapping
> - );
> - if (EFI_ERROR (Status)) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> - AhciRegisters->AhciCmdList,
> - AhciRegisters->AhciCmdListMapping
> - );
> - AhciRegisters->AhciCmdList = NULL;
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - AhciRegisters->AhciRFis,
> - AhciRegisters->AhciRFisMapping
> - );
> - AhciRegisters->AhciRFis = NULL;
> - return EFI_OUT_OF_RESOURCES;
> - }
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> - AhciRegisters->AhciCommandTableMapping = Mapping;
> - AhciRegisters->AhciCommandTable = Base;
> - ZeroMem (AhciRegisters->AhciCommandTable, EFI_PAGE_SIZE *
> EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));
> -
> - //
> - // Allocate resources for data transfer.
> - //
> - Status = IoMmuAllocateBuffer (
> - EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> - &Base,
> - &DeviceAddress,
> - &Mapping
> - );
> - if (EFI_ERROR (Status)) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - AhciRegisters->AhciCommandTable,
> - AhciRegisters->AhciCommandTableMapping
> - );
> - AhciRegisters->AhciCommandTable = NULL;
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> - AhciRegisters->AhciCmdList,
> - AhciRegisters->AhciCmdListMapping
> - );
> - AhciRegisters->AhciCmdList = NULL;
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - AhciRegisters->AhciRFis,
> - AhciRegisters->AhciRFisMapping
> - );
> - AhciRegisters->AhciRFis = NULL;
> - return EFI_OUT_OF_RESOURCES;
> - }
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> - AhciContext->BufferMapping = Mapping;
> - AhciContext->Buffer = Base;
> - ZeroMem (AhciContext->Buffer, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (HDD_PAYLOAD));
> -
> - DEBUG ((
> - DEBUG_INFO,
> - "%a() AhciContext 0x%x 0x%x 0x%x 0x%x\n",
> - __FUNCTION__,
> - AhciContext->Buffer,
> - AhciRegisters->AhciRFis,
> - AhciRegisters->AhciCmdList,
> - AhciRegisters->AhciCommandTable
> - ));
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_AHCI_REGISTERS *AhciRegisters;
> -
> - AhciRegisters = &AhciContext->AhciRegisters;
> -
> - if (AhciContext->Buffer != NULL) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (HDD_PAYLOAD),
> - AhciContext->Buffer,
> - AhciContext->BufferMapping
> - );
> - AhciContext->Buffer = NULL;
> - }
> -
> - if (AhciRegisters->AhciCommandTable != NULL) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),
> - AhciRegisters->AhciCommandTable,
> - AhciRegisters->AhciCommandTableMapping
> - );
> - AhciRegisters->AhciCommandTable = NULL;
> - }
> -
> - if (AhciRegisters->AhciCmdList != NULL) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),
> - AhciRegisters->AhciCmdList,
> - AhciRegisters->AhciCmdListMapping
> - );
> - AhciRegisters->AhciCmdList = NULL;
> - }
> -
> - if (AhciRegisters->AhciRFis != NULL) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),
> - AhciRegisters->AhciRFis,
> - AhciRegisters->AhciRFisMapping
> - );
> - AhciRegisters->AhciRFis = NULL;
> - }
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - EFI_AHCI_REGISTERS *AhciRegisters;
> - UINT32 AhciBar;
> - UINT32 Capability;
> - UINT32 Offset;
> - UINT32 Data;
> - UINT32 PhyDetectDelay;
> -
> - AhciRegisters = &AhciContext->AhciRegisters;
> - AhciBar = AhciContext->AhciBar;
> -
> - Status = AhciReset (AhciBar, ATA_TIMEOUT);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - //
> - // Collect AHCI controller information
> - //
> - Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);
> -
> - //
> - // Enable AE before accessing any AHCI registers if Supports AHCI Mode
> Only is not set
> - //
> - if ((Capability & EFI_AHCI_CAP_SAM) == 0) {
> - AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_FB;
> - AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);
> -
> - //
> - // Single task envrionment, we only use one command table for all port
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CLB;
> - AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters-
> >AhciCmdList);
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_CMD;
> - Data = AhciReadReg (AhciBar, Offset);
> - if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_POD);
> - }
> -
> - if ((Capability & BIT27) != 0) {
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_SUD);
> - }
> -
> - //
> - // Disable aggressive power management.
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SCTL;
> - AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
> - //
> - // Disable the reporting of the corresponding interrupt to system software.
> - //
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_IE;
> - AhciAndReg (AhciBar, Offset, 0);
> -
> - Status = AhciEnableFisReceive (
> - AhciBar,
> - Port,
> - 5000000
> - );
> - ASSERT_EFI_ERROR (Status);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - //
> - // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY
> and PxTFD.DRQ
> - // and PxTFD.ERR to be zero. The maximum wait time is 16s which is
> defined at ATA spec.
> - //
> - PhyDetectDelay = 16 * 1000;
> - do {
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SERR;
> - if (AhciReadReg(AhciBar, Offset) != 0) {
> - AhciWriteReg (AhciBar, Offset, AhciReadReg(AhciBar, Offset));
> - }
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_TFD;
> -
> - Data = AhciReadReg (AhciBar, Offset) & EFI_AHCI_PORT_TFD_MASK;
> - if (Data == 0) {
> - break;
> - }
> -
> - MicroSecondDelay (1000);
> - PhyDetectDelay--;
> - } while (PhyDetectDelay > 0);
> -
> - if (PhyDetectDelay == 0) {
> - return EFI_NOT_FOUND;
> - }
> -
> - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH +
> EFI_AHCI_PORT_SIG;
> - Status = AhciWaitMmioSet (
> - AhciBar,
> - Offset,
> - 0x0000FFFF,
> - 0x00000101,
> - 160000000
> - );
> -
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - return Status;
> -}
> -
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> index b5317d82b8..40fd892bc1 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
> @@ -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 (DevInfo != NULL) {
> - SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;
> - DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
> - DevInfoAta->Port = SataDevPath->HBAPortNumber;
> - DevInfoAta->PortMultiplierPort = SataDevPath-
> >PortMultiplierPortNumber;
> - }
> - 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 ((TmpDevPath->Type == MESSAGING_DEVICE_PATH) &&
> + (TmpDevPath->SubType == MSG_SATA_DP || TmpDevPath->SubType
> == MSG_NVME_NAMESPACE_DP)) {
> if (DevInfo != NULL) {
> - NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;
> - DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
> - DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;
> + DevInfo->DevicePathLength = (UINT32) GetDevicePathSize
> (DevicePath);
> + CopyMem (DevInfo->DevicePath, DevicePath, DevInfo-
> >DevicePathLength);
> }
> - 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,159 @@ ExtractDeviceInfoFromDevicePath (
> }
>
> ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
> - return DeviceType;
> -}
> -
> -/**
> - Save boot script for ATA OPAL device.
> -
> - @param[in] DevInfo Pointer to ATA Opal device information.
> -
> - **/
> -VOID
> -OpalDeviceAtaSaveBootScript (
> - IN OPAL_DEVICE_ATA *DevInfo
> - )
> -{
> - 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;
> -
> - Data = 0;
> -
> - Bus = DevInfo->Device.Bus;
> - Device = DevInfo->Device.Device;
> - Function = DevInfo->Device.Function;
> -
> - 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;
> - }
> -
> - Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function,
> Offset);
> - Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
> - ASSERT_EFI_ERROR (Status);
> - }
> + return;
> }
>
> /**
> - Build ATA OPAL device info and save them to LockBox.
> -
> - @param[in] BarAddr Bar address allocated.
> + Build OPAL device info and save them to LockBox.
>
> **/
> VOID
> -BuildOpalDeviceInfoAta (
> - IN UINT32 BarAddr
> +BuildOpalDeviceInfo (
> + VOID
> )
> {
> - EFI_STATUS Status;
> - UINT8 DeviceType;
> - OPAL_DEVICE_ATA *DevInfoAta;
> - OPAL_DEVICE_ATA *TempDevInfoAta;
> - UINTN DevInfoLengthAta;
> - UINT16 DevInfoLength;
> - OPAL_DRIVER_DEVICE *TmpDev;
> + 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;
>
> //
> - // Build ATA OPAL device info and save them to LockBox.
> + // Build OPAL device info and save them to LockBox.
> //
> - DevInfoLengthAta = 0;
> + TotalDevInfoLength = 0;
> TmpDev = mOpalDriver.DeviceList;
> while (TmpDev != NULL) {
> - DeviceType = ExtractDeviceInfoFromDevicePath (
> - TmpDev->OpalDisk.OpalDevicePath,
> - &DevInfoLength,
> - NULL
> - );
> - if (DeviceType == OPAL_DEVICE_TYPE_ATA) {
> - DevInfoLengthAta += DevInfoLength;
> - }
> -
> + ExtractDeviceInfoFromDevicePath (
> + TmpDev->OpalDisk.OpalDevicePath,
> + &DevInfoLength,
> + NULL
> + );
> + TotalDevInfoLength += DevInfoLength;
> TmpDev = TmpDev->Next;
> }
>
> - if (DevInfoLengthAta == 0) {
> + if (TotalDevInfoLength == 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
> + S3InitDevicesLength = sizeof (DummyData);
> + Status = RestoreLockBox (
> + &gS3StorageDeviceInitListGuid,
> + &DummyData,
> + &S3InitDevicesLength
> );
> - 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;
> + 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;
> }
>
> - TmpDev = TmpDev->Next;
> - }
> -
> - if (DevInfoLengthNvme == 0) {
> + Status = RestoreLockBox (
> + &gS3StorageDeviceInitListGuid,
> + S3InitDevices,
> + &S3InitDevicesLength
> + );
> + ASSERT_EFI_ERROR (Status);
> + S3InitDevicesExist = TRUE;
> + } else {
> return;
> }
>
> - DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);
> - ASSERT (DevInfoNvme != NULL);
> - if (DevInfoNvme == NULL) {
> + DevInfo = AllocateZeroPool (TotalDevInfoLength);
> + ASSERT (DevInfo != NULL);
> + if (DevInfo == NULL) {
> return;
> }
>
> - TempDevInfoNvme = DevInfoNvme;
> - TmpDev = mOpalDriver.DeviceList;
> + TempDevInfo = DevInfo;
> + 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);
> + 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) {
> + ZeroMem (S3InitDevicesBak, GetDevicePathSize (S3InitDevicesBak));
> + FreePool (S3InitDevicesBak);
> + }
> + ASSERT (S3InitDevices != NULL);
> + if (S3InitDevices == NULL) {
> + return;
> }
>
> + TempDevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN)
> TempDevInfo + DevInfoLength);
> TmpDev = TmpDev->Next;
> }
>
> Status = SaveLockBox (
> - &mOpalDeviceNvmeGuid,
> - DevInfoNvme,
> - DevInfoLengthNvme
> + &mOpalDeviceLockBoxGuid,
> + DevInfo,
> + TotalDevInfoLength
> );
> ASSERT_EFI_ERROR (Status);
>
> Status = SetLockBoxAttributes (
> - &mOpalDeviceNvmeGuid,
> + &mOpalDeviceLockBoxGuid,
> LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
> );
> ASSERT_EFI_ERROR (Status);
>
> - ZeroMem (DevInfoNvme, DevInfoLengthNvme);
> - FreePool (DevInfoNvme);
> + 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, TotalDevInfoLength);
> + FreePool (DevInfo);
> + ZeroMem (S3InitDevices, S3InitDevicesLength);
> + FreePool (S3InitDevices);
> }
>
> /**
> @@ -596,9 +448,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 +472,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.
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> deleted file mode 100644
> index 01c316d597..0000000000
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalNvmeMode.c
> +++ /dev/null
> @@ -1,1823 +0,0 @@
> -/** @file
> - Provide functions to initialize NVME controller and perform NVME
> commands
> -
> -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.
> -
> -**/
> -
> -#include "OpalPasswordPei.h"
> -
> -
> -#define ALIGN(v, a) (UINTN)((((v) - 1) | ((a) - 1)) + 1)
> -
> -///
> -/// NVME Host controller registers operation
> -///
> -#define NVME_GET_CAP(Nvme, Cap) NvmeMmioRead (Cap, Nvme-
> >Nbar + NVME_CAP_OFFSET, sizeof (NVME_CAP))
> -#define NVME_GET_CC(Nvme, Cc) NvmeMmioRead (Cc, Nvme-
> >Nbar + NVME_CC_OFFSET, sizeof (NVME_CC))
> -#define NVME_SET_CC(Nvme, Cc) NvmeMmioWrite (Nvme->Nbar +
> NVME_CC_OFFSET, Cc, sizeof (NVME_CC))
> -#define NVME_GET_CSTS(Nvme, Csts) NvmeMmioRead (Csts, Nvme-
> >Nbar + NVME_CSTS_OFFSET, sizeof (NVME_CSTS))
> -#define NVME_GET_AQA(Nvme, Aqa) NvmeMmioRead (Aqa, Nvme-
> >Nbar + NVME_AQA_OFFSET, sizeof (NVME_AQA))
> -#define NVME_SET_AQA(Nvme, Aqa) NvmeMmioWrite (Nvme-
> >Nbar + NVME_AQA_OFFSET, Aqa, sizeof (NVME_AQA))
> -#define NVME_GET_ASQ(Nvme, Asq) NvmeMmioRead (Asq, Nvme-
> >Nbar + NVME_ASQ_OFFSET, sizeof (NVME_ASQ))
> -#define NVME_SET_ASQ(Nvme, Asq) NvmeMmioWrite (Nvme->Nbar
> + NVME_ASQ_OFFSET, Asq, sizeof (NVME_ASQ))
> -#define NVME_GET_ACQ(Nvme, Acq) NvmeMmioRead (Acq, Nvme-
> >Nbar + NVME_ACQ_OFFSET, sizeof (NVME_ACQ))
> -#define NVME_SET_ACQ(Nvme, Acq) NvmeMmioWrite (Nvme->Nbar
> + NVME_ACQ_OFFSET, Acq, sizeof (NVME_ACQ))
> -#define NVME_GET_VER(Nvme, Ver) NvmeMmioRead (Ver, Nvme-
> >Nbar + NVME_VER_OFFSET, sizeof (NVME_VER))
> -#define NVME_SET_SQTDBL(Nvme, Qid, Sqtdbl) NvmeMmioWrite (Nvme-
> >Nbar + NVME_SQTDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Sqtdbl, sizeof
> (NVME_SQTDBL))
> -#define NVME_SET_CQHDBL(Nvme, Qid, Cqhdbl) NvmeMmioWrite (Nvme-
> >Nbar + NVME_CQHDBL_OFFSET(Qid, Nvme->Cap.Dstrd), Cqhdbl, sizeof
> (NVME_CQHDBL))
> -
> -///
> -/// Base memory address
> -///
> -enum {
> - BASEMEM_CONTROLLER_DATA,
> - BASEMEM_IDENTIFY_DATA,
> - BASEMEM_ASQ,
> - BASEMEM_ACQ,
> - BASEMEM_SQ,
> - BASEMEM_CQ,
> - BASEMEM_PRP,
> - BASEMEM_SECURITY,
> - MAX_BASEMEM_COUNT
> -};
> -
> -///
> -/// All of base memories are 4K(0x1000) alignment
> -///
> -#define NVME_MEM_BASE(Nvme) ((UINTN)(Nvme->BaseMem))
> -#define NVME_CONTROL_DATA_BASE(Nvme) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_CONTROLLER_DATA)) * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> -#define NVME_NAMESPACE_DATA_BASE(Nvme) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_IDENTIFY_DATA)) * EFI_PAGE_SIZE),
> EFI_PAGE_SIZE))
> -#define NVME_ASQ_BASE(Nvme) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ASQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> -#define NVME_ACQ_BASE(Nvme) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_ACQ))
> * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> -#define NVME_SQ_BASE(Nvme, index) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_SQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1))) * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> -#define NVME_CQ_BASE(Nvme, index) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_CQ) +
> ((index)*(NVME_MAX_IO_QUEUES-1))) * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> -#define NVME_PRP_BASE(Nvme, index) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages (BASEMEM_PRP)
> + ((index)*NVME_PRP_SIZE)) * EFI_PAGE_SIZE), EFI_PAGE_SIZE))
> -#define NVME_SEC_BASE(Nvme) (ALIGN
> (NVME_MEM_BASE(Nvme) + ((NvmeGetBaseMemPages
> (BASEMEM_SECURITY)) * EFI_PAGE_SIZE), EFI_PAGE_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
> -NvmeMmioRead (
> - IN OUT VOID *MemBuffer,
> - IN UINTN MmioAddr,
> - IN UINTN Size
> - )
> -{
> - UINTN Offset;
> - UINT8 Data;
> - UINT8 *Ptr;
> -
> - // priority has adjusted
> - switch (Size) {
> - case 4:
> - *((UINT32 *)MemBuffer) = MmioRead32 (MmioAddr);
> - break;
> -
> - case 8:
> - *((UINT64 *)MemBuffer) = MmioRead64 (MmioAddr);
> - break;
> -
> - case 2:
> - *((UINT16 *)MemBuffer) = MmioRead16 (MmioAddr);
> - break;
> -
> - case 1:
> - *((UINT8 *)MemBuffer) = MmioRead8 (MmioAddr);
> - break;
> -
> - default:
> - Ptr = (UINT8 *)MemBuffer;
> - for (Offset = 0; Offset < Size; Offset += 1) {
> - Data = MmioRead8 (MmioAddr + Offset);
> - Ptr[Offset] = Data;
> - }
> - break;
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - UINTN Offset;
> - UINT8 Data;
> - UINT8 *Ptr;
> -
> - // priority has adjusted
> - switch (Size) {
> - case 4:
> - MmioWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> - break;
> -
> - case 8:
> - MmioWrite64 (MmioAddr, *((UINT64 *)MemBuffer));
> - break;
> -
> - case 2:
> - MmioWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> - break;
> -
> - case 1:
> - MmioWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> - break;
> -
> - default:
> - Ptr = (UINT8 *)MemBuffer;
> - for (Offset = 0; Offset < Size; Offset += 1) {
> - Data = Ptr[Offset];
> - MmioWrite8 (MmioAddr + Offset, Data);
> - }
> - break;
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - UINTN Offset;
> - UINT8 Data;
> - UINT8 *Ptr;
> -
> - // priority has adjusted
> - switch (Size) {
> - case 4:
> - *((UINT32 *)MemBuffer) = PciRead32 (MmioAddr);
> - break;
> -
> - case 2:
> - *((UINT16 *)MemBuffer) = PciRead16 (MmioAddr);
> - break;
> -
> - case 1:
> - *((UINT8 *)MemBuffer) = PciRead8 (MmioAddr);
> - break;
> -
> - default:
> - Ptr = (UINT8 *)MemBuffer;
> - for (Offset = 0; Offset < Size; Offset += 1) {
> - Data = PciRead8 (MmioAddr + Offset);
> - Ptr[Offset] = Data;
> - }
> - break;
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - UINTN Offset;
> - UINT8 Data;
> - UINT8 *Ptr;
> -
> - // priority has adjusted
> - switch (Size) {
> - case 4:
> - PciWrite32 (MmioAddr, *((UINT32 *)MemBuffer));
> - break;
> -
> - case 2:
> - PciWrite16 (MmioAddr, *((UINT16 *)MemBuffer));
> - break;
> -
> - case 1:
> - PciWrite8 (MmioAddr, *((UINT8 *)MemBuffer));
> - break;
> -
> - default:
> - Ptr = (UINT8 *)MemBuffer;
> - for (Offset = 0; Offset < Size; Offset += 1) {
> - Data = Ptr[Offset];
> - PciWrite8 (MmioAddr + Offset, Data);
> - }
> - break;
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - Get total pages for specific NVME based memory.
> -
> - @param[in] BaseMemIndex - The Index of BaseMem (0-based).
> -
> - @retval - The page count for specific BaseMem Index
> -
> -**/
> -UINT32
> -NvmeGetBaseMemPages (
> - IN UINTN BaseMemIndex
> - )
> -{
> - UINT32 Pages;
> - UINTN Index;
> - UINT32 PageSizeList[8];
> -
> - PageSizeList[0] = 1; /* Controller Data */
> - PageSizeList[1] = 1; /* Identify Data */
> - PageSizeList[2] = 1; /* ASQ */
> - PageSizeList[3] = 1; /* ACQ */
> - PageSizeList[4] = 1; /* SQs */
> - PageSizeList[5] = 1; /* CQs */
> - PageSizeList[6] = NVME_PRP_SIZE * NVME_CSQ_DEPTH; /* PRPs */
> - PageSizeList[7] = 1; /* Security Commands */
> -
> - if (BaseMemIndex > MAX_BASEMEM_COUNT) {
> - ASSERT (FALSE);
> - return 0;
> - }
> -
> - Pages = 0;
> - for (Index = 0; Index < BaseMemIndex; Index++) {
> - Pages += PageSizeList[Index];
> - }
> -
> - return Pages;
> -}
> -
> -/**
> - Wait for NVME controller status to be ready or not.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> - @param[in] WaitReady - Flag for waitting status ready or not
> -
> - @return EFI_SUCCESS - Successfully to wait specific status.
> - @return others - Fail to wait for specific controller status.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeWaitController (
> - IN NVME_CONTEXT *Nvme,
> - IN BOOLEAN WaitReady
> - )
> -{
> - NVME_CSTS Csts;
> - EFI_STATUS Status;
> - UINT32 Index;
> - UINT8 Timeout;
> -
> - //
> - // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set
> after
> - // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 *
> Cap.To.
> - //
> - if (Nvme->Cap.To == 0) {
> - Timeout = 1;
> - } else {
> - Timeout = Nvme->Cap.To;
> - }
> -
> - Status = EFI_SUCCESS;
> - for(Index = (Timeout * 500); Index != 0; --Index) {
> - MicroSecondDelay (1000);
> -
> - //
> - // Check if the controller is initialized
> - //
> - Status = NVME_GET_CSTS (Nvme, &Csts);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
> - return Status;
> - }
> -
> - if ((BOOLEAN) Csts.Rdy == WaitReady) {
> - break;
> - }
> - }
> -
> - if (Index == 0) {
> - Status = EFI_TIMEOUT;
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Disable the Nvm Express controller.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully disable the controller.
> - @return others - Fail to disable the controller.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeDisableController (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVME_CC Cc;
> - NVME_CSTS Csts;
> - EFI_STATUS Status;
> -
> - Status = NVME_GET_CSTS (Nvme, &Csts);
> -
> - ///
> - /// Read Controller Configuration Register.
> - ///
> - Status = NVME_GET_CC (Nvme, &Cc);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> - goto Done;
> - }
> -
> - if (Cc.En == 1) {
> - Cc.En = 0;
> - ///
> - /// Disable the controller.
> - ///
> - Status = NVME_SET_CC (Nvme, &Cc);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> - goto Done;
> - }
> - }
> -
> - Status = NvmeWaitController (Nvme, FALSE);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> - goto Done;
> - }
> -
> - return EFI_SUCCESS;
> -
> -Done:
> - DEBUG ((DEBUG_INFO, "NvmeDisableController fail, Status: %r\n", Status));
> - return Status;
> -}
> -
> -/**
> - Enable the Nvm Express controller.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully enable the controller.
> - @return EFI_DEVICE_ERROR - Fail to enable the controller.
> - @return EFI_TIMEOUT - Fail to enable the controller in given time
> slot.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeEnableController (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVME_CC Cc;
> - EFI_STATUS Status;
> -
> - //
> - // Enable the controller
> - //
> - ZeroMem (&Cc, sizeof (NVME_CC));
> - Cc.En = 1;
> - Cc.Iosqes = 6;
> - Cc.Iocqes = 4;
> - Status = NVME_SET_CC (Nvme, &Cc);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> - goto Done;
> - }
> -
> - Status = NvmeWaitController (Nvme, TRUE);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeWaitController fail, Status = %r\n",
> Status));
> - goto Done;
> - }
> -
> - return EFI_SUCCESS;
> -
> -Done:
> - DEBUG ((DEBUG_INFO, "NvmeEnableController fail, Status: %r\n", Status));
> - return Status;
> -}
> -
> -/**
> - Shutdown the Nvm Express controller.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully shutdown the controller.
> - @return EFI_DEVICE_ERROR - Fail to shutdown the controller.
> - @return EFI_TIMEOUT - Fail to shutdown the controller in given
> time slot.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeShutdownController (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVME_CC Cc;
> - NVME_CSTS Csts;
> - EFI_STATUS Status;
> - UINT32 Index;
> - UINTN Timeout;
> -
> - Status = NVME_GET_CC (Nvme, &Cc);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_GET_CC fail, Status = %r\n", Status));
> - return Status;
> - }
> -
> - Cc.Shn = 1; // Normal shutdown
> -
> - Status = NVME_SET_CC (Nvme, &Cc);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_SET_CC fail, Status = %r\n", Status));
> - return Status;
> - }
> -
> - Timeout = NVME_GENERIC_TIMEOUT/1000; // ms
> - for(Index = (UINT32)(Timeout); Index != 0; --Index) {
> - MicroSecondDelay (1000);
> -
> - Status = NVME_GET_CSTS (Nvme, &Csts);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_GET_CSTS fail, Status = %r\n", Status));
> - return Status;
> - }
> -
> - if (Csts.Shst == 2) { // Shutdown processing complete
> - break;
> - }
> - }
> -
> - if (Index == 0) {
> - Status = EFI_TIMEOUT;
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Check the execution status from a given completion queue entry.
> -
> - @param[in] Cq - A pointer to the NVME_CQ item.
> -
> -**/
> -EFI_STATUS
> -NvmeCheckCqStatus (
> - IN NVME_CQ *Cq
> - )
> -{
> - if (Cq->Sct == 0x0 && Cq->Sc == 0x0) {
> - return EFI_SUCCESS;
> - }
> -
> - DEBUG ((DEBUG_INFO, "Dump NVMe Completion Entry Status from
> [0x%x]:\n", (UINTN)Cq));
> - DEBUG ((DEBUG_INFO, " SQ Identifier : [0x%x], Phase Tag : [%d], Cmd
> Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
> - DEBUG ((DEBUG_INFO, " NVMe Cmd Execution Result - "));
> -
> - switch (Cq->Sct) {
> - case 0x0:
> - switch (Cq->Sc) {
> - case 0x0:
> - DEBUG ((DEBUG_INFO, "Successful Completion\n"));
> - return EFI_SUCCESS;
> - case 0x1:
> - DEBUG ((DEBUG_INFO, "Invalid Command Opcode\n"));
> - break;
> - case 0x2:
> - DEBUG ((DEBUG_INFO, "Invalid Field in Command\n"));
> - break;
> - case 0x3:
> - DEBUG ((DEBUG_INFO, "Command ID Conflict\n"));
> - break;
> - case 0x4:
> - DEBUG ((DEBUG_INFO, "Data Transfer Error\n"));
> - break;
> - case 0x5:
> - DEBUG ((DEBUG_INFO, "Commands Aborted due to Power Loss
> Notification\n"));
> - break;
> - case 0x6:
> - DEBUG ((DEBUG_INFO, "Internal Device Error\n"));
> - break;
> - case 0x7:
> - DEBUG ((DEBUG_INFO, "Command Abort Requested\n"));
> - break;
> - case 0x8:
> - DEBUG ((DEBUG_INFO, "Command Aborted due to SQ Deletion\n"));
> - break;
> - case 0x9:
> - DEBUG ((DEBUG_INFO, "Command Aborted due to Failed Fused
> Command\n"));
> - break;
> - case 0xA:
> - DEBUG ((DEBUG_INFO, "Command Aborted due to Missing Fused
> Command\n"));
> - break;
> - case 0xB:
> - DEBUG ((DEBUG_INFO, "Invalid Namespace or Format\n"));
> - break;
> - case 0xC:
> - DEBUG ((DEBUG_INFO, "Command Sequence Error\n"));
> - break;
> - case 0xD:
> - DEBUG ((DEBUG_INFO, "Invalid SGL Last Segment Descriptor\n"));
> - break;
> - case 0xE:
> - DEBUG ((DEBUG_INFO, "Invalid Number of SGL Descriptors\n"));
> - break;
> - case 0xF:
> - DEBUG ((DEBUG_INFO, "Data SGL Length Invalid\n"));
> - break;
> - case 0x10:
> - DEBUG ((DEBUG_INFO, "Metadata SGL Length Invalid\n"));
> - break;
> - case 0x11:
> - DEBUG ((DEBUG_INFO, "SGL Descriptor Type Invalid\n"));
> - break;
> - case 0x80:
> - DEBUG ((DEBUG_INFO, "LBA Out of Range\n"));
> - break;
> - case 0x81:
> - DEBUG ((DEBUG_INFO, "Capacity Exceeded\n"));
> - break;
> - case 0x82:
> - DEBUG ((DEBUG_INFO, "Namespace Not Ready\n"));
> - break;
> - case 0x83:
> - DEBUG ((DEBUG_INFO, "Reservation Conflict\n"));
> - break;
> - }
> - break;
> -
> - case 0x1:
> - switch (Cq->Sc) {
> - case 0x0:
> - DEBUG ((DEBUG_INFO, "Completion Queue Invalid\n"));
> - break;
> - case 0x1:
> - DEBUG ((DEBUG_INFO, "Invalid Queue Identifier\n"));
> - break;
> - case 0x2:
> - DEBUG ((DEBUG_INFO, "Maximum Queue Size Exceeded\n"));
> - break;
> - case 0x3:
> - DEBUG ((DEBUG_INFO, "Abort Command Limit Exceeded\n"));
> - break;
> - case 0x5:
> - DEBUG ((DEBUG_INFO, "Asynchronous Event Request Limit
> Exceeded\n"));
> - break;
> - case 0x6:
> - DEBUG ((DEBUG_INFO, "Invalid Firmware Slot\n"));
> - break;
> - case 0x7:
> - DEBUG ((DEBUG_INFO, "Invalid Firmware Image\n"));
> - break;
> - case 0x8:
> - DEBUG ((DEBUG_INFO, "Invalid Interrupt Vector\n"));
> - break;
> - case 0x9:
> - DEBUG ((DEBUG_INFO, "Invalid Log Page\n"));
> - break;
> - case 0xA:
> - DEBUG ((DEBUG_INFO, "Invalid Format\n"));
> - break;
> - case 0xB:
> - DEBUG ((DEBUG_INFO, "Firmware Application Requires Conventional
> Reset\n"));
> - break;
> - case 0xC:
> - DEBUG ((DEBUG_INFO, "Invalid Queue Deletion\n"));
> - break;
> - case 0xD:
> - DEBUG ((DEBUG_INFO, "Feature Identifier Not Saveable\n"));
> - break;
> - case 0xE:
> - DEBUG ((DEBUG_INFO, "Feature Not Changeable\n"));
> - break;
> - case 0xF:
> - DEBUG ((DEBUG_INFO, "Feature Not Namespace Specific\n"));
> - break;
> - case 0x10:
> - DEBUG ((DEBUG_INFO, "Firmware Application Requires NVM
> Subsystem Reset\n"));
> - break;
> - case 0x80:
> - DEBUG ((DEBUG_INFO, "Conflicting Attributes\n"));
> - break;
> - case 0x81:
> - DEBUG ((DEBUG_INFO, "Invalid Protection Information\n"));
> - break;
> - case 0x82:
> - DEBUG ((DEBUG_INFO, "Attempted Write to Read Only Range\n"));
> - break;
> - }
> - break;
> -
> - case 0x2:
> - switch (Cq->Sc) {
> - case 0x80:
> - DEBUG ((DEBUG_INFO, "Write Fault\n"));
> - break;
> - case 0x81:
> - DEBUG ((DEBUG_INFO, "Unrecovered Read Error\n"));
> - break;
> - case 0x82:
> - DEBUG ((DEBUG_INFO, "End-to-end Guard Check Error\n"));
> - break;
> - case 0x83:
> - DEBUG ((DEBUG_INFO, "End-to-end Application Tag Check Error\n"));
> - break;
> - case 0x84:
> - DEBUG ((DEBUG_INFO, "End-to-end Reference Tag Check Error\n"));
> - break;
> - case 0x85:
> - DEBUG ((DEBUG_INFO, "Compare Failure\n"));
> - break;
> - case 0x86:
> - DEBUG ((DEBUG_INFO, "Access Denied\n"));
> - break;
> - }
> - break;
> -
> - default:
> - DEBUG ((DEBUG_INFO, "Unknown error\n"));
> - break;
> - }
> -
> - return EFI_DEVICE_ERROR;
> -}
> -
> -/**
> - Create PRP lists for Data transfer which is larger than 2 memory pages.
> - Note here we calcuate the number of required PRP lists and allocate them
> at one time.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> - @param[in] SqId - The SQ index for this PRP
> - @param[in] PhysicalAddr - The physical base address of Data Buffer.
> - @param[in] Pages - The number of pages to be transfered.
> - @param[out] PrpListHost - The host base address of PRP lists.
> - @param[in,out] PrpListNo - The number of PRP List.
> -
> - @retval The pointer Value to the first PRP List of the PRP lists.
> -
> -**/
> -STATIC
> -UINT64
> -NvmeCreatePrpList (
> - IN NVME_CONTEXT *Nvme,
> - IN UINT16 SqId,
> - IN EFI_PHYSICAL_ADDRESS PhysicalAddr,
> - IN UINTN Pages,
> - OUT VOID **PrpListHost,
> - IN OUT UINTN *PrpListNo
> - )
> -{
> - UINTN PrpEntryNo;
> - UINT64 PrpListBase;
> - UINTN PrpListIndex;
> - UINTN PrpEntryIndex;
> - UINT64 Remainder;
> - EFI_PHYSICAL_ADDRESS PrpListPhyAddr;
> - UINTN Bytes;
> - UINT8 *PrpEntry;
> - EFI_PHYSICAL_ADDRESS NewPhyAddr;
> -
> - ///
> - /// The number of Prp Entry in a memory page.
> - ///
> - PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
> -
> - ///
> - /// Calculate total PrpList number.
> - ///
> - *PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages,
> (UINT64)PrpEntryNo, &Remainder);
> - if (Remainder != 0) {
> - *PrpListNo += 1;
> - }
> -
> - if (*PrpListNo > NVME_PRP_SIZE) {
> - DEBUG ((DEBUG_INFO, "NvmeCreatePrpList (PhysicalAddr: %lx,
> Pages: %x) PrpEntryNo: %x\n",
> - PhysicalAddr, Pages, PrpEntryNo));
> - DEBUG ((DEBUG_INFO, "*PrpListNo: %x, Remainder: %lx", *PrpListNo,
> Remainder));
> - ASSERT (FALSE);
> - }
> - *PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Nvme, SqId);
> -
> - Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
> - PrpListPhyAddr = (UINT64)(UINTN)(*PrpListHost);
> -
> - ///
> - /// Fill all PRP lists except of last one.
> - ///
> - ZeroMem (*PrpListHost, Bytes);
> - for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
> - PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> -
> - for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
> - PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> - if (PrpEntryIndex != PrpEntryNo - 1) {
> - ///
> - /// Fill all PRP entries except of last one.
> - ///
> - CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof
> (UINT64));
> - PhysicalAddr += EFI_PAGE_SIZE;
> - } else {
> - ///
> - /// Fill last PRP entries with next PRP List pointer.
> - ///
> - NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE);
> - CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof
> (UINT64));
> - }
> - }
> - }
> -
> - ///
> - /// Fill last PRP list.
> - ///
> - PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
> - for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder :
> PrpEntryNo); ++PrpEntryIndex) {
> - PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex *
> sizeof(UINT64));
> - CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64));
> -
> - PhysicalAddr += EFI_PAGE_SIZE;
> - }
> -
> - return PrpListPhyAddr;
> -}
> -
> -/**
> - 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
> - )
> -{
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - NVME_SQ *Sq;
> - NVME_CQ *Cq;
> - UINT8 Qid;
> - UINT32 Bytes;
> - UINT32 Offset;
> - EFI_PHYSICAL_ADDRESS PhyAddr;
> - VOID *PrpListHost;
> - UINTN PrpListNo;
> - UINT32 Timer;
> - UINTN SqSize;
> - UINTN CqSize;
> -
> - ///
> - /// check the Data fields in Packet parameter.
> - ///
> - if ((Nvme == NULL) || (Packet == NULL)) {
> - DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> Nvme(%x)/Packet(%x)\n",
> - (UINTN)Nvme, (UINTN)Packet));
> - return EFI_INVALID_PARAMETER;
> - }
> -
> - if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
> - DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> NvmeCmd(%x)/NvmeResponse(%x)\n",
> - (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeResponse));
> - return EFI_INVALID_PARAMETER;
> - }
> -
> - if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId !=
> NVME_IO_QUEUE) {
> - DEBUG ((DEBUG_ERROR, "NvmePassThru, invalid parameter:
> QueueId(%x)\n",
> - Packet->QueueId));
> - return EFI_INVALID_PARAMETER;
> - }
> -
> - PrpListHost = NULL;
> - PrpListNo = 0;
> - Status = EFI_SUCCESS;
> -
> - Qid = Packet->QueueId;
> - Sq = Nvme->SqBuffer[Qid] + Nvme->SqTdbl[Qid].Sqt;
> - Cq = Nvme->CqBuffer[Qid] + Nvme->CqHdbl[Qid].Cqh;
> - if (Qid == NVME_ADMIN_QUEUE) {
> - SqSize = NVME_ASQ_SIZE + 1;
> - CqSize = NVME_ACQ_SIZE + 1;
> - } else {
> - SqSize = NVME_CSQ_DEPTH;
> - CqSize = NVME_CCQ_DEPTH;
> - }
> -
> - if (Packet->NvmeCmd->Nsid != NamespaceId) {
> - DEBUG ((DEBUG_ERROR, "NvmePassThru: Nsid mismatch (%x, %x)\n",
> - Packet->NvmeCmd->Nsid, NamespaceId));
> - return EFI_INVALID_PARAMETER;
> - }
> -
> - ZeroMem (Sq, sizeof (NVME_SQ));
> - Sq->Opc = Packet->NvmeCmd->Cdw0.Opcode;
> - Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
> - Sq->Cid = Packet->NvmeCmd->Cdw0.Cid;
> - Sq->Nsid = Packet->NvmeCmd->Nsid;
> -
> - ///
> - /// Currently we only support PRP for Data transfer, SGL is NOT supported.
> - ///
> - ASSERT (Sq->Psdt == 0);
> - if (Sq->Psdt != 0) {
> - DEBUG ((DEBUG_ERROR, "NvmePassThru: doesn't support SGL
> mechanism\n"));
> - return EFI_UNSUPPORTED;
> - }
> -
> - Sq->Prp[0] = Packet->TransferBuffer;
> - Sq->Prp[1] = 0;
> -
> - if(Packet->MetadataBuffer != (UINT64)(UINTN)NULL) {
> - Sq->Mptr = Packet->MetadataBuffer;
> - }
> -
> - ///
> - /// If the Buffer Size spans more than two memory pages (page Size as
> defined in CC.Mps),
> - /// then build a PRP list in the second PRP submission queue entry.
> - ///
> - Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
> - Bytes = Packet->TransferLength;
> -
> - if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
> - ///
> - /// Create PrpList for remaining Data Buffer.
> - ///
> - PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> - Sq->Prp[1] = NvmeCreatePrpList (Nvme, Nvme->SqTdbl[Qid].Sqt,
> PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo);
> - if (Sq->Prp[1] == 0) {
> - Status = EFI_OUT_OF_RESOURCES;
> - DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList fail, Status: %r\n", Status));
> - goto EXIT;
> - }
> -
> - } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
> - Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
> - }
> -
> - if(Packet->NvmeCmd->Flags & CDW10_VALID) {
> - Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
> - }
> - if(Packet->NvmeCmd->Flags & CDW11_VALID) {
> - Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
> - }
> - if(Packet->NvmeCmd->Flags & CDW12_VALID) {
> - Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
> - }
> - if(Packet->NvmeCmd->Flags & CDW13_VALID) {
> - Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
> - }
> - if(Packet->NvmeCmd->Flags & CDW14_VALID) {
> - Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
> - }
> - if(Packet->NvmeCmd->Flags & CDW15_VALID) {
> - Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
> - }
> -
> - ///
> - /// Ring the submission queue doorbell.
> - ///
> - Nvme->SqTdbl[Qid].Sqt++;
> - if(Nvme->SqTdbl[Qid].Sqt == SqSize) {
> - Nvme->SqTdbl[Qid].Sqt = 0;
> - }
> - Status = NVME_SET_SQTDBL (Nvme, Qid, &Nvme->SqTdbl[Qid]);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_SET_SQTDBL fail, Status: %r\n", Status));
> - goto EXIT;
> - }
> -
> - ///
> - /// Wait for completion queue to get filled in.
> - ///
> - Status = EFI_TIMEOUT;
> - Timer = 0;
> - while (Timer < NVME_CMD_TIMEOUT) {
> - //DEBUG ((DEBUG_VERBOSE, "Timer: %x, Cq:\n", Timer));
> - //DumpMem (Cq, sizeof (NVME_CQ));
> - if (Cq->Pt != Nvme->Pt[Qid]) {
> - Status = EFI_SUCCESS;
> - break;
> - }
> -
> - MicroSecondDelay (NVME_CMD_WAIT);
> - Timer += NVME_CMD_WAIT;
> - }
> -
> - Nvme->CqHdbl[Qid].Cqh++;
> - if (Nvme->CqHdbl[Qid].Cqh == CqSize) {
> - Nvme->CqHdbl[Qid].Cqh = 0;
> - Nvme->Pt[Qid] ^= 1;
> - }
> -
> - ///
> - /// Copy the Respose Queue entry for this command to the callers
> response Buffer
> - ///
> - CopyMem (Packet->NvmeResponse, Cq,
> sizeof(NVM_EXPRESS_RESPONSE));
> -
> - if (!EFI_ERROR(Status)) { // We still need to check CQ status if no timeout
> error occured
> - Status = NvmeCheckCqStatus (Cq);
> - }
> - NVME_SET_CQHDBL (Nvme, Qid, &Nvme->CqHdbl[Qid]);
> -
> -EXIT:
> - return Status;
> -}
> -
> -/**
> - Get identify controller Data.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> - @param[in] Buffer - The Buffer used to store the identify controller
> Data.
> -
> - @return EFI_SUCCESS - Successfully get the identify controller Data.
> - @return others - Fail to get the identify controller Data.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeIdentifyController (
> - IN NVME_CONTEXT *Nvme,
> - IN VOID *Buffer
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - //
> - // According to Nvm Express 1.1 spec Figure 38, When not used, the field
> shall be cleared to 0h.
> - // For the Identify command, the Namespace Identifier is only used for the
> Namespace Data structure.
> - //
> - Command.Nsid = 0;
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> - CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_CONTROLLER_DATA);
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> - //
> - // Set bit 0 (Cns bit) to 1 to identify a controller
> - //
> - Command.Cdw10 = 1;
> - Command.Flags = CDW10_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Get specified identify namespace Data.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> - @param[in] NamespaceId - The specified namespace identifier.
> - @param[in] Buffer - The Buffer used to store the identify
> namespace Data.
> -
> - @return EFI_SUCCESS - Successfully get the identify namespace
> Data.
> - @return others - Fail to get the identify namespace Data.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeIdentifyNamespace (
> - IN NVME_CONTEXT *Nvme,
> - IN UINT32 NamespaceId,
> - IN VOID *Buffer
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - Command.Nsid = NamespaceId;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Buffer;
> - CommandPacket.TransferLength = sizeof
> (NVME_ADMIN_NAMESPACE_DATA);
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> - //
> - // Set bit 0 (Cns bit) to 1 to identify a namespace
> - //
> - CommandPacket.NvmeCmd->Cdw10 = 0;
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NamespaceId,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Get Block Size for specific namespace of NVME.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return - Block Size in bytes
> -
> -**/
> -STATIC
> -UINT32
> -NvmeGetBlockSize (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - UINT32 BlockSize;
> - UINT32 Lbads;
> - UINT32 Flbas;
> - UINT32 LbaFmtIdx;
> -
> - Flbas = Nvme->NamespaceData->Flbas;
> - LbaFmtIdx = Flbas & 3;
> - Lbads = Nvme->NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
> -
> - BlockSize = (UINT32)1 << Lbads;
> - return BlockSize;
> -}
> -
> -/**
> - Get last LBA for specific namespace of NVME.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return - Last LBA address
> -
> -**/
> -STATIC
> -EFI_LBA
> -NvmeGetLastLba (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - EFI_LBA LastBlock;
> - LastBlock = Nvme->NamespaceData->Nsze - 1;
> - return LastBlock;
> -}
> -
> -/**
> - Create io completion queue.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully create io completion queue.
> - @return others - Fail to create io completion queue.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeCreateIoCompletionQueue (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> - NVME_ADMIN_CRIOCQ CrIoCq;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> - ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme-
> >CqBuffer[NVME_IO_QUEUE];
> - CommandPacket.TransferLength = EFI_PAGE_SIZE;
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> -
> - CrIoCq.Qid = NVME_IO_QUEUE;
> - CrIoCq.Qsize = NVME_CCQ_SIZE;
> - CrIoCq.Pc = 1;
> - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof
> (NVME_ADMIN_CRIOCQ));
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Create io submission queue.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully create io submission queue.
> - @return others - Fail to create io submission queue.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeCreateIoSubmissionQueue (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> - NVME_ADMIN_CRIOSQ CrIoSq;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> - ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme-
> >SqBuffer[NVME_IO_QUEUE];
> - CommandPacket.TransferLength = EFI_PAGE_SIZE;
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> -
> - CrIoSq.Qid = NVME_IO_QUEUE;
> - CrIoSq.Qsize = NVME_CSQ_SIZE;
> - CrIoSq.Pc = 1;
> - CrIoSq.Cqid = NVME_IO_QUEUE;
> - CrIoSq.Qprio = 0;
> - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof
> (NVME_ADMIN_CRIOSQ));
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - 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
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> - NVME_ADMIN_SECSEND SecSend;
> - OACS *Oacs;
> - UINT8 Opcode;
> - VOID* *SecBuff;
> -
> - Oacs = (OACS *)&Nvme->ControllerData->Oacs;
> -
> - //
> - // Verify security bit for Security Send/Receive commands
> - //
> - if (Oacs->Security == 0) {
> - DEBUG ((DEBUG_ERROR, "Security command doesn't support.\n"));
> - return EFI_NOT_READY;
> - }
> -
> - SecBuff = (VOID *)(UINTN) NVME_SEC_BASE (Nvme);
> -
> - //
> - // Actions for sending security command
> - //
> - if (SendCommand) {
> - CopyMem (SecBuff, TransferBuffer, TransferLength);
> - }
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> - ZeroMem (&SecSend, sizeof(NVME_ADMIN_SECSEND));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Opcode = (UINT8)(SendCommand ? NVME_ADMIN_SECURITY_SEND_OPC :
> NVME_ADMIN_SECURITY_RECV_OPC);
> - Command.Cdw0.Opcode = Opcode;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)SecBuff;
> - CommandPacket.TransferLength = (UINT32)TransferLength;
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> -
> - SecSend.Spsp = SpSpecific;
> - SecSend.Secp = SecurityProtocol;
> - SecSend.Tl = (UINT32)TransferLength;
> -
> - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SecSend, sizeof
> (NVME_ADMIN_SECSEND));
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - //
> - // Actions for receiving security command
> - //
> - if (!SendCommand) {
> - CopyMem (TransferBuffer, SecBuff, TransferLength);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Destroy io completion queue.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully destroy io completion queue.
> - @return others - Fail to destroy io completion queue.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeDestroyIoCompletionQueue (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> - NVME_ADMIN_DEIOCQ DelIoCq;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> - ZeroMem (&DelIoCq, sizeof(NVME_ADMIN_DEIOCQ));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_DELIOCQ_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme-
> >CqBuffer[NVME_IO_QUEUE];
> - CommandPacket.TransferLength = EFI_PAGE_SIZE;
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> -
> - DelIoCq.Qid = NVME_IO_QUEUE;
> - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoCq, sizeof
> (NVME_ADMIN_DEIOCQ));
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - Destroy io submission queue.
> -
> - @param[in] Nvme - The pointer to the NVME_CONTEXT Data
> structure.
> -
> - @return EFI_SUCCESS - Successfully destroy io submission queue.
> - @return others - Fail to destroy io submission queue.
> -
> -**/
> -STATIC
> -EFI_STATUS
> -NvmeDestroyIoSubmissionQueue (
> - IN NVME_CONTEXT *Nvme
> - )
> -{
> - NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
> - NVM_EXPRESS_COMMAND Command;
> - NVM_EXPRESS_RESPONSE Response;
> - EFI_STATUS Status;
> - NVME_ADMIN_DEIOSQ DelIoSq;
> -
> - ZeroMem (&CommandPacket,
> sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
> - ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
> - ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
> - ZeroMem (&DelIoSq, sizeof(NVME_ADMIN_DEIOSQ));
> -
> - CommandPacket.NvmeCmd = &Command;
> - CommandPacket.NvmeResponse = &Response;
> -
> - Command.Cdw0.Opcode = NVME_ADMIN_DELIOSQ_OPC;
> - Command.Cdw0.Cid = Nvme->Cid[NVME_ADMIN_QUEUE]++;
> - CommandPacket.TransferBuffer = (UINT64)(UINTN)Nvme-
> >SqBuffer[NVME_IO_QUEUE];
> - CommandPacket.TransferLength = EFI_PAGE_SIZE;
> - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
> - CommandPacket.QueueId = NVME_ADMIN_QUEUE;
> -
> - DelIoSq.Qid = NVME_IO_QUEUE;
> - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &DelIoSq, sizeof
> (NVME_ADMIN_DEIOSQ));
> - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
> -
> - Status = NvmePassThru (
> - Nvme,
> - NVME_CONTROLLER_ID,
> - 0,
> - &CommandPacket
> - );
> - if (!EFI_ERROR (Status)) {
> - Status = NvmeWaitAllComplete (Nvme, CommandPacket.QueueId);
> - }
> -
> - return Status;
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - EFI_PHYSICAL_ADDRESS DeviceAddress;
> - VOID *Base;
> - VOID *Mapping;
> -
> - //
> - // Allocate resources for DMA.
> - //
> - Status = IoMmuAllocateBuffer (
> - EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> - &Base,
> - &DeviceAddress,
> - &Mapping
> - );
> - if (EFI_ERROR (Status)) {
> - return EFI_OUT_OF_RESOURCES;
> - }
> - ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
> - Nvme->BaseMemMapping = Mapping;
> - Nvme->BaseMem = Base;
> - ZeroMem (Nvme->BaseMem, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES
> (NVME_MEM_MAX_SIZE));
> -
> - DEBUG ((
> - DEBUG_INFO,
> - "%a() NvmeContext 0x%x\n",
> - __FUNCTION__,
> - Nvme->BaseMem
> - ));
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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
> - )
> -{
> - if (Nvme->BaseMem != NULL) {
> - IoMmuFreeBuffer (
> - EFI_SIZE_TO_PAGES (NVME_MEM_MAX_SIZE),
> - Nvme->BaseMem,
> - Nvme->BaseMemMapping
> - );
> - Nvme->BaseMem = NULL;
> - }
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> - NVME_AQA Aqa;
> - NVME_ASQ Asq;
> - NVME_ACQ Acq;
> - NVME_VER Ver;
> -
> - UINT32 MlBAR;
> - UINT32 MuBAR;
> -
> - ///
> - /// Update PCIE BAR0/1 for NVME device
> - ///
> - MlBAR = Nvme->Nbar;
> - MuBAR = 0;
> - PciWrite32 (Nvme->PciBase + 0x10, MlBAR); // MLBAR (BAR0)
> - PciWrite32 (Nvme->PciBase + 0x14, MuBAR); // MUBAR (BAR1)
> -
> - ///
> - /// Enable PCIE decode
> - ///
> - PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x6);
> -
> - // Version
> - NVME_GET_VER (Nvme, &Ver);
> - if (!(Ver.Mjr == 0x0001) && (Ver.Mnr == 0x0000)) {
> - DEBUG ((DEBUG_INFO, "\n!!!\n!!! NVME Version mismatch for the
> implementation !!!\n!!!\n"));
> - }
> -
> - ///
> - /// Read the Controller Capabilities register and verify that the NVM
> command set is supported
> - ///
> - Status = NVME_GET_CAP (Nvme, &Nvme->Cap);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((DEBUG_ERROR, "NVME_GET_CAP fail, Status: %r\n", Status));
> - goto Done;
> - }
> -
> - if (Nvme->Cap.Css != 0x01) {
> - DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: the controller doesn't
> support NVMe command set\n"));
> - Status = EFI_UNSUPPORTED;
> - goto Done;
> - }
> -
> - ///
> - /// Currently the driver only supports 4k page Size.
> - ///
> - if ((Nvme->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) {
> - DEBUG ((DEBUG_ERROR, "NvmeControllerInit fail: only supports 4k page
> Size\n"));
> - ASSERT (FALSE);
> - Status = EFI_UNSUPPORTED;
> - goto Done;
> - }
> -
> - Nvme->Cid[0] = 0;
> - Nvme->Cid[1] = 0;
> -
> - Nvme->Pt[0] = 0;
> - Nvme->Pt[1] = 0;
> -
> - ZeroMem ((VOID *)(UINTN)(&(Nvme->SqTdbl[0])), sizeof (NVME_SQTDBL)
> * NVME_MAX_IO_QUEUES);
> - ZeroMem ((VOID *)(UINTN)(&(Nvme->CqHdbl[0])), sizeof
> (NVME_CQHDBL) * NVME_MAX_IO_QUEUES);
> -
> - ZeroMem (Nvme->BaseMem, NVME_MEM_MAX_SIZE);
> -
> - Status = NvmeDisableController (Nvme);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeDisableController fail, Status: %r\n",
> Status));
> - goto Done;
> - }
> -
> - ///
> - /// set number of entries admin submission & completion queues.
> - ///
> - Aqa.Asqs = NVME_ASQ_SIZE;
> - Aqa.Rsvd1 = 0;
> - Aqa.Acqs = NVME_ACQ_SIZE;
> - Aqa.Rsvd2 = 0;
> -
> - ///
> - /// Address of admin submission queue.
> - ///
> - Asq = (UINT64)(UINTN)(NVME_ASQ_BASE (Nvme) & ~0xFFF);
> -
> - ///
> - /// Address of admin completion queue.
> - ///
> - Acq = (UINT64)(UINTN)(NVME_ACQ_BASE (Nvme) & ~0xFFF);
> -
> - ///
> - /// Address of I/O submission & completion queue.
> - ///
> - Nvme->SqBuffer[0] = (NVME_SQ *)(UINTN)NVME_ASQ_BASE (Nvme); //
> NVME_ADMIN_QUEUE
> - Nvme->CqBuffer[0] = (NVME_CQ *)(UINTN)NVME_ACQ_BASE (Nvme);
> // NVME_ADMIN_QUEUE
> - Nvme->SqBuffer[1] = (NVME_SQ *)(UINTN)NVME_SQ_BASE (Nvme, 0); //
> NVME_IO_QUEUE
> - Nvme->CqBuffer[1] = (NVME_CQ *)(UINTN)NVME_CQ_BASE (Nvme, 0);
> // NVME_IO_QUEUE
> -
> - DEBUG ((DEBUG_INFO, "Admin Submission Queue Size (Aqa.Asqs) =
> [%08X]\n", Aqa.Asqs));
> - DEBUG ((DEBUG_INFO, "Admin Completion Queue Size (Aqa.Acqs) =
> [%08X]\n", Aqa.Acqs));
> - DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) =
> [%08X]\n", Nvme->SqBuffer[0]));
> - DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) =
> [%08X]\n", Nvme->CqBuffer[0]));
> - DEBUG ((DEBUG_INFO, "I/O Submission Queue (SqBuffer[1]) =
> [%08X]\n", Nvme->SqBuffer[1]));
> - DEBUG ((DEBUG_INFO, "I/O Completion Queue (CqBuffer[1]) =
> [%08X]\n", Nvme->CqBuffer[1]));
> -
> - ///
> - /// Program admin queue attributes.
> - ///
> - Status = NVME_SET_AQA (Nvme, &Aqa);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Program admin submission queue address.
> - ///
> - Status = NVME_SET_ASQ (Nvme, &Asq);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Program admin completion queue address.
> - ///
> - Status = NVME_SET_ACQ (Nvme, &Acq);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - Status = NvmeEnableController (Nvme);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Create one I/O completion queue.
> - ///
> - Status = NvmeCreateIoCompletionQueue (Nvme);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Create one I/O Submission queue.
> - ///
> - Status = NvmeCreateIoSubmissionQueue (Nvme);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Get current Identify Controller Data
> - ///
> - Nvme->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)(UINTN)
> NVME_CONTROL_DATA_BASE (Nvme);
> - Status = NvmeIdentifyController (Nvme, Nvme->ControllerData);
> - if (EFI_ERROR(Status)) {
> - goto Done;
> - }
> -
> - ///
> - /// Dump NvmExpress Identify Controller Data
> - ///
> - Nvme->ControllerData->Sn[19] = 0;
> - Nvme->ControllerData->Mn[39] = 0;
> - //NvmeDumpIdentifyController (Nvme->ControllerData);
> -
> - ///
> - /// Get current Identify Namespace Data
> - ///
> - Nvme->NamespaceData = (NVME_ADMIN_NAMESPACE_DATA
> *)NVME_NAMESPACE_DATA_BASE (Nvme);
> - Status = NvmeIdentifyNamespace (Nvme, Nvme->Nsid, Nvme-
> >NamespaceData);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeIdentifyNamespace fail, Status = %r\n",
> Status));
> - goto Done;
> - }
> -
> - ///
> - /// Dump NvmExpress Identify Namespace Data
> - ///
> - if (Nvme->NamespaceData->Ncap == 0) {
> - DEBUG ((DEBUG_ERROR, "Invalid Namespace, Ncap: %lx\n", Nvme-
> >NamespaceData->Ncap));
> - Status = EFI_DEVICE_ERROR;
> - goto Done;
> - }
> -
> - Nvme->BlockSize = NvmeGetBlockSize (Nvme);
> - Nvme->LastBlock = NvmeGetLastLba (Nvme);
> -
> - Nvme->State = NvmeStatusInit;
> -
> - return EFI_SUCCESS;
> -
> -Done:
> - return Status;
> -}
> -
> -/**
> - 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
> - )
> -{
> - EFI_STATUS Status;
> -
> - Status = EFI_SUCCESS;
> - if (Nvme->State == NvmeStatusInit || Nvme->State == NvmeStatusMax) {
> - ///
> - /// Destroy I/O Submission queue.
> - ///
> - Status = NvmeDestroyIoSubmissionQueue (Nvme);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeDestroyIoSubmissionQueue fail, Status
> = %r\n", Status));
> - return Status;
> - }
> -
> - ///
> - /// Destroy I/O completion queue.
> - ///
> - Status = NvmeDestroyIoCompletionQueue (Nvme);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeDestroyIoCompletionQueue fail, Status
> = %r\n", Status));
> - return Status;
> - }
> -
> - Status = NvmeShutdownController (Nvme);
> - if (EFI_ERROR(Status)) {
> - DEBUG ((DEBUG_ERROR, "NvmeShutdownController fail, Status: %r\n",
> Status));
> - }
> - }
> -
> - ///
> - /// Disable PCIE decode
> - ///
> - PciWrite8 (Nvme->PciBase + NVME_PCIE_PCICMD, 0x0);
> - PciWrite32 (Nvme->PciBase + 0x10, 0); // MLBAR (BAR0)
> - PciWrite32 (Nvme->PciBase + 0x14, 0); // MUBAR (BAR1)
> -
> - Nvme->State = NvmeStatusUnknown;
> - return Status;
> -}
> diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> index edb47ca8bc..4d78a6a4ed 100644
> --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
> @@ -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,249 +14,34 @@ 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;
> -
> -#define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)
> -#define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)
> +EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
>
> /**
> - Get IOMMU PPI.
> + Tell whether the input EDKII_PEI_STORAGE_SECURITY_CMD_PPI instance
> has already
> + been handled by the Opal PEI driver.
>
> - @return Pointer to IOMMU PPI.
> + @param[in] Private Pointer to the Opal PEI driver private data.
> + @param[in] SscInstance Pointer to the
> EDKII_PEI_STORAGE_SECURITY_CMD_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.
> + @retval TRUE The PPI instance has already been handled.
> + @retval FALSE The PPI instance has not been handled before.
>
> **/
> -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
> +BOOLEAN
> +IsSscInstanceHandled (
> + IN OPAL_PEI_DRIVER_PRIVATE_DATA *Private,
> + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *SscInstance
> )
> {
> - 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 );
> - }
> + UINTN Index;
>
> - 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 );
> + for (Index = 0; Index < Private->SscPpiInstanceNum; Index++) {
> + if ((UINTN)SscInstance == Private->SscPpiInstances[Index]) {
> + return TRUE;
> }
> - } 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;
> + return FALSE;
> }
>
> /**
> @@ -351,14 +136,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 +228,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,272 +342,178 @@ UnlockOpalPassword (
> }
>
> /**
> - Unlock ATA OPAL password for S3.
> + Unlock the OPAL NVM Express and ATA devices for S3.
> +
> + @param[in] Private Pointer to the Opal PEI driver private data.
>
> **/
> VOID
> -UnlockOpalPasswordAta (
> - VOID
> +UnlockOpalPasswordDevices (
> + IN OPAL_PEI_DRIVER_PRIVATE_DATA *Private
> )
> {
> - 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_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
> + UINTN SscPpiInstance;
> + EDKII_PEI_STORAGE_SECURITY_CMD_PPI *SscPpi;
> + 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;
> -
> - 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;
> - OpalDev.Sscp.ReceiveData = SecurityReceiveData;
> - OpalDev.Sscp.SendData = SecuritySendData;
> - OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
> - OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
> - OpalDev.Context = &AhciContext;
> -
> - UnlockOpalPassword (&OpalDev);
> - }
> - 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));
> - }
> -
> - 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.
> + // Go through the Storage Security Command PPI instances within system.
> //
> - 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);
> + for (SscPpiInstance = 0;
> + SscPpiInstance < OPAL_PEI_MAX_STORAGE_SECURITY_CMD_PPI;
> + SscPpiInstance++) {
> + Status = PeiServicesLocatePpi (
> + &gEdkiiPeiStorageSecurityCommandPpiGuid,
> + SscPpiInstance,
> + &TempPpiDescriptor,
> + (VOID **) &SscPpi
> + );
> + if (EFI_ERROR (Status)) {
> + break;
> }
> - }
> - 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__));
> + //
> + // Check whether this PPI instance has been handled previously.
> + //
> + if (IsSscInstanceHandled (Private, SscPpi)) {
> + DEBUG ((
> + DEBUG_INFO, "%a: Ssc PPI instance (0x%p) already handled.\n",
> + __FUNCTION__, (UINTN)SscPpi
> + ));
> + continue;
> } 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);
> + DEBUG ((
> + DEBUG_INFO, "%a: New Ssc PPI instance (0x%p) found.\n",
> + __FUNCTION__, (UINTN)SscPpi
> + ));
> + Private->SscPpiInstances[Private->SscPpiInstanceNum] = (UINTN)SscPpi;
> + Private->SscPpiInstanceNum++;
> }
>
> - ASSERT (RpBase != 0);
> - PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0);
> - RpBase = SaveRestoreRootportConfSpace (
> - DevInfoNvme,
> - FALSE, // restore
> - StorePcieConfDataList
> - );
> - PciWrite8 (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
> - }
> + //
> + // Go through all the devices managed by this PPI instance.
> + //
> + Status = SscPpi->GetNumberofDevices (SscPpi, &SscDeviceNum);
> + if (EFI_ERROR (Status)) {
> + continue;
> + }
> + 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;
> + }
>
> - ZeroMem (DevInfo, DevInfoLengthNvme);
> - if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
> - FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
> + //
> + // 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.Device = DevInfo;
> + OpalDev.Context = NULL;
> + OpalDev.SscPpi = SscPpi;
> + OpalDev.DeviceIndex = SscDeviceIndex;
> + UnlockOpalPassword (&OpalDev);
> + break;
> + }
> + }
> + }
> }
>
> - DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
> -}
> -
> -/**
> - Unlock OPAL password for S3.
> + ZeroMem (DevInfoBuffer, DevInfoLength);
> + FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));
>
> -**/
> -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;
> + OPAL_PEI_DRIVER_PRIVATE_DATA *Private;
>
> - Status = PeiServicesGetBootMode (&BootMode);
> - ASSERT_EFI_ERROR (Status);
> - if (BootMode != BOOT_ON_S3_RESUME) {
> - return EFI_UNSUPPORTED;
> - }
> + DEBUG ((DEBUG_INFO, "%a entered at S3 resume!\n", __FUNCTION__));
>
> - DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
> + Private = OPAL_PEI_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDesc);
> + UnlockOpalPasswordDevices (Private);
>
> - 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_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> - &gEfiEndOfPeiSignalPpiGuid,
> - OpalPasswordEndOfPeiNotify
> +OPAL_PEI_DRIVER_PRIVATE_DATA mOpalPeiDriverPrivateTemplate = {
> + OPAL_PEI_DRIVER_SIGNATURE, // Signature
> + { // SscPpiNotifyList
> + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> + &gEdkiiPeiStorageSecurityCommandPpiGuid,
> + OpalPasswordStorageSecurityPpiNotify
> + },
> + 0, // SscPpiInstanceNum
> + {0} // SscPpiInstances
> };
>
> /**
> @@ -935,10 +532,32 @@ OpalPasswordPeiInit (
> IN CONST EFI_PEI_SERVICES **PeiServices
> )
> {
> - EFI_STATUS Status;
> + EFI_STATUS Status;
> + EFI_BOOT_MODE BootMode;
> + OPAL_PEI_DRIVER_PRIVATE_DATA *Private;
>
> - 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__));
> +
> + Private = (OPAL_PEI_DRIVER_PRIVATE_DATA *)
> + AllocateCopyPool (
> + sizeof (OPAL_PEI_DRIVER_PRIVATE_DATA),
> + &mOpalPeiDriverPrivateTemplate
> + );
> + if (Private == NULL) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "%a: Failed to allocate memory for
> OPAL_PEI_DRIVER_PRIVATE_DATA.\n",
> + __FUNCTION__
> + ));
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = PeiServicesNotifyPpi (&Private->SscPpiNotifyList);
> ASSERT_EFI_ERROR (Status);
> return Status;
> }
> -
> --
> 2.12.0.windows.1
next prev parent reply other threads:[~2019-02-18 6:20 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-15 6:23 [PATCH v5 00/13] Split the S3 PEI phase HW init codes from Opal driver Hao Wu
2019-02-15 6:23 ` [PATCH v5 01/13] MdeModulePkg: Add definitions for ATA AHCI host controller PPI Hao Wu
2019-02-18 1:44 ` Dong, Eric
2019-02-15 6:23 ` [PATCH v5 02/13] MdeModulePkg: Add definitions for EDKII PEI ATA PassThru PPI Hao Wu
2019-02-18 1:44 ` Dong, Eric
2019-02-15 6:23 ` [PATCH v5 03/13] MdeModulePkg: Add definitions for Storage Security Command PPI Hao Wu
2019-02-18 1:45 ` Dong, Eric
2019-02-15 6:23 ` [PATCH v5 04/13] MdeModulePkg: Add GUID for LockBox to save storage dev to init in S3 Hao Wu
2019-02-18 1:45 ` Dong, Eric
2019-02-15 6:23 ` [PATCH v5 05/13] MdeModulePkg/NvmExpressPei: Avoid updating the module-level variable Hao Wu
2019-02-15 6:23 ` [PATCH v5 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Hao Wu
2019-02-18 2:58 ` Dong, Eric
2019-02-18 6:06 ` Wu, Hao A
2019-02-18 6:29 ` Dong, Eric
2019-02-20 8:33 ` Ni, Ray
2019-02-15 6:23 ` [PATCH v5 07/13] MdeModulePkg/NvmExpressPei: Consume S3StorageDeviceInitList LockBox Hao Wu
2019-02-18 3:01 ` Dong, Eric
2019-02-20 9:41 ` Ni, Ray
2019-02-15 6:23 ` [PATCH v5 08/13] MdeModulePkg/AhciPei: Add AHCI mode ATA device support in PEI Hao Wu
2019-02-20 9:51 ` Ni, Ray
2019-02-15 6:23 ` [PATCH v5 09/13] MdeModulePkg/SmmLockBoxLib: Use 'DEBUG_' prefix instead of 'EFI_D_' Hao Wu
2019-02-15 6:23 ` [PATCH v5 10/13] MdeModulePkg/SmmLockBox(PEI): Remove an ASSERT in RestoreLockBox() Hao Wu
2019-02-15 6:23 ` [PATCH v5 11/13] MdeModulePkg/SmmLockBoxLib: Support LockBox enlarge in UpdateLockBox() Hao Wu
2019-02-15 6:23 ` [PATCH v5 12/13] OvmfPkg/LockBoxLib: Update the comments for API UpdateLockBox() Hao Wu
2019-02-15 6:23 ` [PATCH v5 13/13] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI Hao Wu
2019-02-18 6:20 ` Dong, Eric [this message]
2019-02-19 2:50 ` Wu, Hao A
2019-02-20 13:08 ` Ni, Ray
2019-02-15 13:23 ` [PATCH v5 00/13] Split the S3 PEI phase HW init codes from Opal driver Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ED077930C258884BBCB450DB737E662259DB1153@shsmsx102.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox