Skip to content

Commit

Permalink
Initial NVMe work, identify works
Browse files Browse the repository at this point in the history
  • Loading branch information
r0m30 committed Jul 6, 2017
1 parent 4aeebe6 commit 2a5a745
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 0 deletions.
2 changes: 2 additions & 0 deletions windows/CLI/CLI.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<ClInclude Include="..\..\Common\pbkdf2\tassert.h" />
<ClInclude Include="..\DtaDevOS.h" />
<ClInclude Include="..\DtaDiskATA.h" />
<ClInclude Include="..\DtaDiskNVMe.h" />
<ClInclude Include="..\DtaDiskUSB.h" />
<ClInclude Include="..\os.h" />
</ItemGroup>
Expand All @@ -73,6 +74,7 @@
<ClCompile Include="..\..\Common\sedutil.cpp" />
<ClCompile Include="..\DtaDevOS.cpp" />
<ClCompile Include="..\DtaDiskATA.cpp" />
<ClCompile Include="..\DtaDiskNVMe.cpp" />
<ClCompile Include="..\DtaDiskUSB.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
Expand Down
6 changes: 6 additions & 0 deletions windows/CLI/CLI.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@
<ClInclude Include="..\..\Common\pbkdf2\tassert.h">
<Filter>Header Files\pbkdf2</Filter>
</ClInclude>
<ClInclude Include="..\DtaDiskNVMe.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\Common\sedutil.cpp">
Expand Down Expand Up @@ -182,5 +185,8 @@
<ClCompile Include="..\..\Common\pbkdf2\sha1.c">
<Filter>Source Files\pbkdf2</Filter>
</ClCompile>
<ClCompile Include="..\DtaDiskNVMe.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
5 changes: 5 additions & 0 deletions windows/DtaDevOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ along with sedutil. If not, see <http://www.gnu.org/licenses/>.
#include "DtaDevGeneric.h"
#include "DtaDiskATA.h"
#include "DtaDiskUSB.h"
#include "DtaDiskNVMe.h"

using namespace std;
DtaDevOS::DtaDevOS() {};
Expand Down Expand Up @@ -85,12 +86,16 @@ void DtaDevOS::init(const char * devref)
}
// OVERLAPPED structure
switch (descriptor.BusType) {
case BusTypeAta:
case BusTypeSata:
disk = new DtaDiskATA();
break;
case BusTypeUsb:
disk = new DtaDiskUSB();
break;
case BusTypeNvme:
disk = new DtaDiskNVMe();
break;
default:
return;
}
Expand Down
191 changes: 191 additions & 0 deletions windows/DtaDiskNVMe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/* C:B**************************************************************************
This software is Copyright 2014-2016 Bright Plaza Inc. <[email protected]>
This file is part of sedutil.
sedutil is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sedutil is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with sedutil. If not, see <http://www.gnu.org/licenses/>.
* C:E********************************************************************** */
#pragma once
#include "os.h"
#include <stdio.h>
#include <iostream>
#pragma warning(push)
#pragma warning(disable : 4091)
#include <Ntddscsi.h>
#pragma warning(pop)
#include <winioctl.h>
#include <vector>
#include "DtaDiskNVMe.h"
#include "DtaEndianFixup.h"
#include "DtaStructures.h"
#include "DtaHexDump.h"

using namespace std;

// Missing stuff pulled from MSDN
//

// STORAGE PROPERTY ID is defined but these #define values are missing
#define StorageAdapterProtocolSpecificProperty (STORAGE_PROPERTY_ID) 49

#define NVME_MAX_LOG_SIZE 4096 // value from random internet search
typedef enum _STORAGE_PROTOCOL_TYPE {
ProtocolTypeUnknown = 0x00,
ProtocolTypeScsi,
ProtocolTypeAta,
ProtocolTypeNvme,
ProtocolTypeSd,
ProtocolTypeProprietary = 0x7E,
ProtocolTypeMaxReserved = 0x7F
} STORAGE_PROTOCOL_TYPE, *PSTORAGE_PROTOCOL_TYPE;
typedef struct _STORAGE_PROTOCOL_SPECIFIC_DATA {
STORAGE_PROTOCOL_TYPE ProtocolType;
DWORD DataType;
DWORD ProtocolDataRequestValue;
DWORD ProtocolDataRequestSubValue;
DWORD ProtocolDataOffset;
DWORD ProtocolDataLength;
DWORD FixedProtocolReturnData;
DWORD Reserved[3];
} STORAGE_PROTOCOL_SPECIFIC_DATA, *PSTORAGE_PROTOCOL_SPECIFIC_DATA;

typedef enum _STORAGE_PROTOCOL_NVME_DATA_TYPE {
NVMeDataTypeUnknown = 0,
NVMeDataTypeIdentify,
NVMeDataTypeLogPage,
NVMeDataTypeFeature
} STORAGE_PROTOCOL_NVME_DATA_TYPE, *PSTORAGE_PROTOCOL_NVME_DATA_TYPE;
typedef struct _STORAGE_PROTOCOL_DATA_DESCRIPTOR {
DWORD Version;
DWORD Size;
STORAGE_PROTOCOL_SPECIFIC_DATA ProtocolSpecificData;
} STORAGE_PROTOCOL_DATA_DESCRIPTOR, *PSTORAGE_PROTOCOL_DATA_DESCRIPTOR;

// End of missing stuff



DtaDiskNVMe::DtaDiskNVMe() {};
void DtaDiskNVMe::init(const char * devref)
{
LOG(D1) << "Creating DtaDiskNVMe::DtaDiskNVMe() " << devref;

hDev = CreateFile(devref,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hDev)
return;
else
isOpen = TRUE;
}

uint8_t DtaDiskNVMe::sendCmd(ATACOMMAND cmd, uint8_t protocol, uint16_t comID,
void * buffer, uint16_t bufferlen)
{
UNREFERENCED_PARAMETER(cmd);
UNREFERENCED_PARAMETER(protocol);
UNREFERENCED_PARAMETER(comID);
UNREFERENCED_PARAMETER(buffer);
UNREFERENCED_PARAMETER(bufferlen);
LOG(D1) << "Entering DtaDiskNVMe::sendCmd";
LOG(D1) << "DtaDiskNVMe::sendCmd Not yet implemented ";
return DTAERROR_COMMAND_ERROR;
}

/** adds the IDENTIFY information to the disk_info structure */

void DtaDiskNVMe::identify(OPAL_DiskInfo& disk_info)
{
LOG(D1) << "Entering DtaDiskNVMe::identify()";
PVOID buffer = NULL;
UINT8 *results = NULL;
ULONG bufferLength = 0;
DWORD dwReturned = 0;
BOOL iorc = 0;

PSTORAGE_PROPERTY_QUERY query = NULL;
PSTORAGE_PROTOCOL_SPECIFIC_DATA protocolData = NULL;
PSTORAGE_PROTOCOL_DATA_DESCRIPTOR protocolDataDescr = NULL;
// This buffer allocation is needed because the STORAGE_PROPERTY_QUERY has additional data
// that the nvme driver doesn't use ???????????????????
/* ****************************************************************************************
!!DANGER WILL ROBINSON!! !!DANGER WILL ROBINSON!! !!DANGER WILL ROBINSON!!
This buffer definition causes the STORAGE_PROTOCOL_SPECIFIC_DATA to OVERLAY the
STORAGE_PROPERTY_QUERY.AdditionalParameters field
* **************************************************************************************** */
bufferLength = FIELD_OFFSET(STORAGE_PROPERTY_QUERY, AdditionalParameters)
+ sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) + NVME_MAX_LOG_SIZE;
buffer = malloc(bufferLength);
/* */
if (buffer == NULL) {
LOG(E) << "DeviceNVMeQueryProtocolDataTest: allocate buffer failed, exit.\n";
return;
}

//
// Initialize query data structure to get Identify Data.
//
ZeroMemory(buffer, bufferLength);

query = (PSTORAGE_PROPERTY_QUERY)buffer;
/* ****************************************************************************************
!!DANGER WILL ROBINSON!! !!DANGER WILL ROBINSON!! !!DANGER WILL ROBINSON!!
This buffer definition causes the STORAGE_PROTOCOL_SPECIFIC_DATA to OVERLAY the
STORAGE_PROPERTY_QUERY.AdditionalParameters field
* **************************************************************************************** */
protocolDataDescr = (PSTORAGE_PROTOCOL_DATA_DESCRIPTOR)buffer;
protocolData = (PSTORAGE_PROTOCOL_SPECIFIC_DATA)query->AdditionalParameters;
/* */
query->PropertyId = StorageAdapterProtocolSpecificProperty;
query->QueryType = PropertyStandardQuery;

protocolData->ProtocolType = ProtocolTypeNvme;
protocolData->DataType = NVMeDataTypeIdentify;
// protocolData->ProtocolDataRequestValue = NVME_IDENTIFY_CNS_CONTROLLER;
protocolData->ProtocolDataRequestSubValue = 0;
protocolData->ProtocolDataOffset = sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA);
protocolData->ProtocolDataLength = NVME_MAX_LOG_SIZE;

iorc = DeviceIoControl(hDev, IOCTL_STORAGE_QUERY_PROPERTY,
buffer, bufferLength, buffer, bufferLength, &dwReturned, NULL);

//
//
//
disk_info.devType = DEVICE_TYPE_NVME;
results = (UINT8 *)buffer + FIELD_OFFSET(STORAGE_PROPERTY_QUERY, AdditionalParameters)
+ sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA);
results += 4;
memcpy(disk_info.serialNum, results, sizeof(disk_info.serialNum));
results += sizeof(disk_info.serialNum);
memcpy(disk_info.modelNum, results, sizeof(disk_info.modelNum));
results += sizeof(disk_info.modelNum);
memcpy(disk_info.firmwareRev, results, sizeof(disk_info.firmwareRev));


return;
}

/** Close the filehandle so this object can be delete. */
DtaDiskNVMe::~DtaDiskNVMe()
{
LOG(D1) << "Destroying DtaDiskNVMe";
CloseHandle(hDev);

}
52 changes: 52 additions & 0 deletions windows/DtaDiskNVMe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* C:B**************************************************************************
This software is Copyright 2014-2016 Bright Plaza Inc. <[email protected]>
This file is part of sedutil.
sedutil is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sedutil is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with sedutil. If not, see <http://www.gnu.org/licenses/>.
* C:E********************************************************************** */
#pragma once
#include "os.h"
#include "DtaDiskType.h"
/** Device specific implementation of disk access functions. */

class DtaDiskNVMe : public DtaDiskType {
public:
DtaDiskNVMe();
~DtaDiskNVMe();
/** device specific initialization.
* This function should perform the necessary authority and environment checking
* to allow proper functioning of the program, open the device, perform an
* identify, add the fields from the identify response to the disk info structure
* and if the device is an ATA device perform a call to Discovery0() to complete
* the disk_info structure
* @param devref character representation of the device is standard OS lexicon
*/
void init(const char * devref);
/** OS specific method to send an ATA command to the device
* @param cmd command to be sent to the device
* @param protocol security protocol to be used in the command
* @param comID communications ID to be used
* @param buffer input/output buffer
* @param bufferlen length of the input/output buffer
*/
uint8_t sendCmd(ATACOMMAND cmd, uint8_t protocol, uint16_t comID,
void * buffer, uint16_t bufferlen);
/** OS specific routine to send an ATA identify to the device */
void identify(OPAL_DiskInfo& disk_info);
private:
HANDLE hDev; /**< Windows device handle */
uint8_t isOpen = FALSE;
};

0 comments on commit 2a5a745

Please sign in to comment.