From 7d8038e3b6eca3d4e9380d6e607ef780fffd5872 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 18 Dec 2017 17:51:52 +0000 Subject: [PATCH] Added ATA report to DiscImageChef.Device.Report. --- DiscImageChef.Device.Report/CMakeLists.txt | 2 +- DiscImageChef.Device.Report/ata.c | 247 ++++++++ DiscImageChef.Device.Report/ata.h | 19 + DiscImageChef.Device.Report/ata_report.c | 641 +++++++++++++++++++++ DiscImageChef.Device.Report/ata_report.h | 9 + DiscImageChef.Device.Report/atapi_report.c | 8 +- DiscImageChef.Device.Report/main.c | 4 + DiscImageChef.Device.Report/scsi_report.c | 7 +- 8 files changed, 929 insertions(+), 8 deletions(-) create mode 100644 DiscImageChef.Device.Report/ata_report.c create mode 100644 DiscImageChef.Device.Report/ata_report.h diff --git a/DiscImageChef.Device.Report/CMakeLists.txt b/DiscImageChef.Device.Report/CMakeLists.txt index 9794ec71..646dbcbd 100644 --- a/DiscImageChef.Device.Report/CMakeLists.txt +++ b/DiscImageChef.Device.Report/CMakeLists.txt @@ -7,5 +7,5 @@ find_package(LibXml2) include_directories(${LIBXML2_INCLUDE_DIR}) -add_executable(DiscImageChef_Device_Report main.c scsi.c scsi.h main.h ata.h ata.c atapi.c atapi.h atapi_report.c atapi_report.h identify_decode.c identify_decode.h scsi_report.c scsi_report.h inquiry_decode.c inquiry_decode.h scsi_mode.h scsi_mode.c mmc_report.c mmc_report.h cdrom_mode.h ssc_report.c ssc_report.h) +add_executable(DiscImageChef_Device_Report main.c scsi.c scsi.h main.h ata.h ata.c atapi.c atapi.h atapi_report.c atapi_report.h identify_decode.c identify_decode.h scsi_report.c scsi_report.h inquiry_decode.c inquiry_decode.h scsi_mode.h scsi_mode.c mmc_report.c mmc_report.h cdrom_mode.h ssc_report.c ssc_report.h ata_report.c ata_report.h) target_link_libraries(DiscImageChef_Device_Report ${LIBXML2_LIBRARIES}) \ No newline at end of file diff --git a/DiscImageChef.Device.Report/ata.c b/DiscImageChef.Device.Report/ata.c index 383d9446..a79e8123 100644 --- a/DiscImageChef.Device.Report/ata.c +++ b/DiscImageChef.Device.Report/ata.c @@ -233,5 +233,252 @@ int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegiste int error = SendAtaCommandChs(fd, registers, errorRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_NONE, *buffer, 512, 0); + return error; +} + +int Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 256; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersCHS registers; + memset(®isters, 0, sizeof(AtaRegistersCHS)); + + if(retry) + registers.command = ATA_READ_RETRY; + else + registers.command = ATA_READ_SECTORS; + registers.sectorCount = count; + registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (uint8_t)(head & 0x0F); + registers.sector = sector; + + int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + + return error; +} + +int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint32_t blockSize) +{ + *buffer = malloc(blockSize); + memset(*buffer, 0, blockSize); + AtaRegistersCHS registers; + memset(®isters, 0, sizeof(AtaRegistersCHS)); + + if(retry) + registers.command = ATA_READ_LONG_RETRY; + else + registers.command = ATA_READ_LONG; + registers.sectorCount = 1; + registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (uint8_t)(head & 0x0F); + registers.sector = sector; + + int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT, *buffer, blockSize, 1); + + return error; +} + +int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector) +{ + unsigned char *buffer = malloc(0); + memset(*buffer, 0, 0); + AtaRegistersCHS registers; + memset(®isters, 0, sizeof(AtaRegistersCHS)); + + registers.command = ATA_SEEK; + registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (uint8_t)(head & 0x0F); + registers.sector = sector; + + int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0, 0); + + return error; +} + +int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 256; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersCHS registers; + memset(®isters, 0, sizeof(AtaRegistersCHS)); + + if(retry) + registers.command = ATA_READ_DMA_RETRY; + else + registers.command = ATA_READ_DMA; + registers.sectorCount = count; + registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (uint8_t)(head & 0x0F); + registers.sector = sector; + + int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + + return error; +} + +int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint8_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 256; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersLBA28 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA28)); + + if(retry) + registers.command = ATA_READ_DMA_RETRY; + else + registers.command = ATA_READ_DMA; + registers.sectorCount = count; + registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100); + registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + + return error; +} + +int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint8_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 256; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersLBA28 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA28)); + + if(retry) + registers.command = ATA_READ_RETRY; + else + registers.command = ATA_READ_SECTORS; + registers.sectorCount = count; + registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100); + registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + + return error; +} + +int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint32_t blockSize) +{ + *buffer = malloc(blockSize); + memset(*buffer, 0, blockSize); + AtaRegistersLBA28 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA28)); + + if(retry) + registers.command = ATA_READ_LONG_RETRY; + else + registers.command = ATA_READ_LONG; + registers.sectorCount = 1; + registers.sectorCount = 1; + registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100); + registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT, *buffer, blockSize, 1); + + return error; +} + +int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba) +{ + unsigned char *buffer = malloc(0); + memset(*buffer, 0, 0); + AtaRegistersLBA28 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA28)); + + registers.command = ATA_SEEK; + registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100); + registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0, 0); + + return error; +} + +int ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 65536; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersLBA48 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA48)); + + registers.command = ATA_READ_DMA_EXT; + registers.sectorCount = count; + registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000); + registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000); + registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + + return error; +} + +int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count) +{ + int buffer_len; + if(count == 0) + buffer_len = 512 * 65536; + else + buffer_len = 512 * count; + + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + AtaRegistersLBA48 registers; + memset(®isters, 0, sizeof(AtaRegistersLBA48)); + + registers.command = ATA_READ_EXT; + registers.sectorCount = count; + registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000); + registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000); + registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1); + registers.deviceHead += 0x40; + + int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT, *buffer, buffer_len, 1); + return error; } \ No newline at end of file diff --git a/DiscImageChef.Device.Report/ata.h b/DiscImageChef.Device.Report/ata.h index c95e2800..8f808c1e 100644 --- a/DiscImageChef.Device.Report/ata.h +++ b/DiscImageChef.Device.Report/ata.h @@ -103,6 +103,15 @@ typedef enum { typedef enum { + ATA_READ_RETRY = 0x20, + ATA_READ_SECTORS = 0x21, + ATA_READ_LONG_RETRY = 0x22, + ATA_READ_LONG = 0x23, + ATA_READ_EXT = 0x24, + ATA_READ_DMA_EXT = 0x25, + ATA_SEEK = 0x70, + ATA_READ_DMA_RETRY = 0xC8, + ATA_READ_DMA = 0xC9, ATA_IDENTIFY_PACKET_DEVICE = 0xA1, ATA_IDENTIFY_DEVICE = 0xEC } AtaCommands; @@ -847,4 +856,14 @@ int SendAtaCommandChs(int fd, AtaRegistersCHS registers, AtaErrorRegistersCHS ** int SendAtaCommandLba28(int fd, AtaRegistersLBA28 registers, AtaErrorRegistersLBA28 **errorRegisters, int protocol, int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks); int SendAtaCommandLba48(int fd, AtaRegistersLBA48 registers, AtaErrorRegistersLBA48 **errorRegisters, int protocol, int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks); int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters); +int Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t count); +int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint32_t blockSize); +int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector); +int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head, uint8_t sector, uint8_t count); +int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint8_t count); +int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint8_t count); +int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba, uint32_t blockSize); +int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba); +int ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count); +int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count); #endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_H diff --git a/DiscImageChef.Device.Report/ata_report.c b/DiscImageChef.Device.Report/ata_report.c new file mode 100644 index 00000000..78cabf3c --- /dev/null +++ b/DiscImageChef.Device.Report/ata_report.c @@ -0,0 +1,641 @@ +// +// Created by claunia on 18/12/17. +// + +#include +#include +#include "ata_report.h" +#include "ata.h" +#include "identify_decode.h" + +void AtaReport(int fd, xmlTextWriterPtr xmlWriter) +{ + unsigned char *ata_ident = NULL; + unsigned char *buffer = NULL; + AtaErrorRegistersCHS *ata_error_chs; + AtaErrorRegistersLBA28 *ata_error_lba; + AtaErrorRegistersLBA48 *ata_error_lba48; + int error; + int removable = FALSE; + char user_response = ' '; + + printf("Querying ATA IDENTIFY...\n"); + error = Identify(fd, &ata_ident, &ata_error_chs); + + if(error) + { + fprintf(stderr, "Error {0} requesting IDENTIFY DEVICE", error); + return; + } + + IdentifyDevice *identify = malloc(512); + memcpy(identify, ata_ident, 512); + + xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATA_REPORT_ELEMENT); + + if(le16toh(identify->GeneralConfiguration) == 0x848A) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CompactFlash", "%s", "TRUE"); + removable = FALSE; + } + else if(identify->GeneralConfiguration & 0x0080) + { + do + { + printf("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): "); + scanf("%c", &user_response); + printf("\n"); + } while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n'); + + removable = (user_response == 'Y' || user_response == 'y'); + } + + if(removable) + { + printf("Please remove any media from the device and press any key when it is out.\n"); + scanf("%c"); + printf("Querying ATA IDENTIFY...\n"); + error = Identify(fd, &ata_ident, &ata_error_chs); + free(identify); + identify = malloc(512); + memcpy(identify, ata_ident, 512); + } + + if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8)); + if(identify->APIOSupported) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "APIOSupported", DecodeTransferMode(le16toh(identify->APIOSupported))); + if(identify->BufferType) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferType", "%u", le16toh(identify->BufferType)); + if(identify->BufferSize) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferSize", "%u", le16toh(identify->BufferSize)); + if(identify->Capabilities) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities", DecodeCapabilities(le16toh(identify->Capabilities))); + if(identify->Capabilities2) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities2", DecodeCapabilities2(le16toh(identify->Capabilities2))); + if(identify->Capabilities3) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities3", DecodeCapabilities3(identify->Capabilities3)); + if(identify->CFAPowerMode) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CFAPowerMode", "%u", le16toh(identify->CFAPowerMode)); + if(identify->CommandSet) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet", DecodeCommandSet(le16toh(identify->CommandSet))); + if(identify->CommandSet2) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet2", DecodeCommandSet2(le16toh(identify->CommandSet2))); + if(identify->CommandSet3) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet3", DecodeCommandSet3(le16toh(identify->CommandSet3))); + if(identify->CommandSet4) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet4", DecodeCommandSet4(le16toh(identify->CommandSet4))); + if(identify->CommandSet5) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet5", DecodeCommandSet5(le16toh(identify->CommandSet5))); + if(identify->CurrentAAM) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAAM", "%u", identify->CurrentAAM); + if(identify->CurrentAPM) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAPM", "%u", le16toh(identify->CurrentAPM)); + if(identify->DataSetMgmt) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DataSetMgmt", DecodeDataSetMgmt(le16toh(identify->DataSetMgmt))); + if(identify->DataSetMgmtSize) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DataSetMgmtSize", "%u", le16toh(identify->DataSetMgmtSize)); + if(identify->DeviceFormFactor) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DeviceFormFactor", DecodeDeviceFormFactor(le16toh(identify->DeviceFormFactor))); + if(identify->DMAActive) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMAActive", DecodeTransferMode(le16toh(identify->DMAActive))); + if(identify->DMASupported) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMASupported", DecodeTransferMode(le16toh(identify->DMASupported))); + if(identify->DMATransferTimingMode) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DMATransferTimingMode", "%u", identify->DMATransferTimingMode); + if(identify->EnhancedSecurityEraseTime) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnhancedSecurityEraseTime", "%u", le16toh(identify->EnhancedSecurityEraseTime)); + if(identify->EnabledCommandSet) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet", DecodeCommandSet(le16toh(identify->EnabledCommandSet))); + if(identify->EnabledCommandSet2) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet2", DecodeCommandSet2(le16toh(identify->EnabledCommandSet2))); + if(identify->EnabledCommandSet3) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet3", DecodeCommandSet3(le16toh(identify->EnabledCommandSet3))); + if(identify->EnabledCommandSet4) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet4", DecodeCommandSet4(le16toh(identify->EnabledCommandSet4))); + if(identify->EnabledSATAFeatures) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledSATAFeatures", DecodeSATAFeatures(le16toh(identify->EnabledSATAFeatures))); + if(identify->ExtendedUserSectors) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ExtendedUserSectors", "%llu", le64toh(identify->ExtendedUserSectors)); + if(identify->FreeFallSensitivity) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "FreeFallSensitivity", "%u", identify->FreeFallSensitivity); + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "FirmwareRevision", AtaToCString(identify->FirmwareRevision, 8)); + if(identify->GeneralConfiguration) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "GeneralConfiguration", DecodeGeneralConfiguration(le16toh(identify->GeneralConfiguration))); + if(identify->HardwareResetResult) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HardwareResetResult", "%u", le16toh(identify->HardwareResetResult)); + if(identify->InterseekDelay) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "InterseekDelay", "%u", le16toh(identify->InterseekDelay)); + if(identify->MajorVersion) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MajorVersion", DecodeMajorVersion(le16toh(identify->MajorVersion))); + if(identify->MasterPasswordRevisionCode) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MasterPasswordRevisionCode", "%u", le16toh(identify->MasterPasswordRevisionCode)); + if(identify->MaxDownloadMicroMode3) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxDownloadMicroMode3", "%u", le16toh(identify->MaxDownloadMicroMode3)); + if(identify->MaxQueueDepth) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxQueueDepth", "%u", le16toh(identify->MaxQueueDepth)); + if(identify->MDMAActive) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMAActive", DecodeTransferMode(le16toh(identify->MDMAActive))); + if(identify->MDMASupported) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMASupported", DecodeTransferMode(le16toh(identify->MDMASupported))); + if(identify->MinDownloadMicroMode3) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinDownloadMicroMode3", "%u", le16toh(identify->MinDownloadMicroMode3)); + if(identify->MinMDMACycleTime) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinMDMACycleTime", "%u", le16toh(identify->MinMDMACycleTime)); + if(identify->MinorVersion) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinorVersion", "%u", le16toh(identify->MinorVersion)); + if(identify->MinPIOCycleTimeNoFlow) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeNoFlow", "%u", le16toh(identify->MinPIOCycleTimeNoFlow)); + if(identify->MinPIOCycleTimeFlow) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeFlow", "%u", le16toh(identify->MinPIOCycleTimeFlow)); + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Model", AtaToCString(identify->Model, 40)); + if(identify->MultipleMaxSectors) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleMaxSectors", "%u", identify->MultipleMaxSectors); + if(identify->MultipleSectorNumber) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleSectorNumber", "%u", identify->MultipleSectorNumber); + if(identify->NVCacheCaps) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheCaps", "%u", le16toh(identify->NVCacheCaps)); + if(identify->NVCacheSize) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheSize", "%u", le32toh(identify->NVCacheSize)); + if(identify->NVCacheWriteSpeed) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheWriteSpeed", "%u", le16toh(identify->NVCacheWriteSpeed)); + if(identify->NVEstimatedSpinUp) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVEstimatedSpinUp", "%u", identify->NVEstimatedSpinUp); + if(identify->PacketBusRelease) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PacketBusRelease", "%u", le16toh(identify->PacketBusRelease)); + if(identify->PIOTransferTimingMode) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PIOTransferTimingMode", "%u", identify->PIOTransferTimingMode); + if(identify->RecommendedAAM) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecommendedAAM", "%u", identify->RecommendedAAM); + if(identify->RecMDMACycleTime) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecMDMACycleTime", "%u", le16toh(identify->RecMDMACycleTime)); + if(identify->RemovableStatusSet) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RemovableStatusSet", "%u", le16toh(identify->RemovableStatusSet)); + if(identify->SATACapabilities) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities", DecodeSATACapabilities(le16toh(identify->SATACapabilities))); + if(identify->SATACapabilities2) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities2", DecodeSATACapabilities2(le16toh(identify->SATACapabilities2))); + if(identify->SATAFeatures) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATAFeatures", DecodeSATAFeatures(le16toh(identify->SATAFeatures))); + if(identify->SCTCommandTransport) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SCTCommandTransport", DecodeSCTCommandTransport(le16toh(identify->SCTCommandTransport))); + if(identify->SectorsPerCard) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SectorsPerCard", "%u", le32toh(identify->SectorsPerCard)); + if(identify->SecurityEraseTime) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecurityEraseTime", "%u", le16toh(identify->SecurityEraseTime)); + if(identify->SecurityStatus) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SecurityStatus", DecodeSecurityStatus(le16toh(identify->SecurityStatus))); + if(identify->ServiceBusyClear) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ServiceBusyClear", "%u", le16toh(identify->ServiceBusyClear)); + if(identify->SpecificConfiguration) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SpecificConfiguration", DecodeSpecificConfiguration(le16toh(identify->SpecificConfiguration))); + if(identify->StreamAccessLatency) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamAccessLatency", "%u", le16toh(identify->StreamAccessLatency)); + if(identify->StreamMinReqSize) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamMinReqSize", "%u", le16toh(identify->StreamMinReqSize)); + if(identify->StreamPerformanceGranularity) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamPerformanceGranularity", "%u", le32toh(identify->StreamPerformanceGranularity)); + if(identify->StreamTransferTimeDMA) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimeDMA", "%u", le16toh(identify->StreamTransferTimeDMA)); + if(identify->StreamTransferTimePIO) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimePIO", "%u", le16toh(identify->StreamTransferTimePIO)); + if(identify->TransportMajorVersion) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMajorVersion", "%u", le16toh(identify->TransportMajorVersion)); + if(identify->TransportMinorVersion) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMinorVersion", "%u", le16toh(identify->TransportMinorVersion)); + if(identify->TrustedComputing) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "TrustedComputing", DecodeTrustedComputing(le16toh(identify->TrustedComputing))); + if(identify->UDMAActive) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMAActive", DecodeTransferMode(le16toh(identify->UDMAActive))); + if(identify->UDMASupported) + xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMASupported", DecodeTransferMode(le16toh(identify->UDMASupported))); + if(identify->WRVMode) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVMode", "%u", identify->WRVMode); + if(identify->WRVSectorCountMode3) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode3", "%u", le32toh(identify->WRVSectorCountMode3)); + if(identify->WRVSectorCountMode2) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u", le32toh(identify->WRVSectorCountMode2)); + + xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify"); + xmlTextWriterWriteBase64(xmlWriter, ata_ident, 0, 512); + xmlTextWriterEndElement(xmlWriter); + + if(removable) + { + user_response = ' '; + int anyMedia = FALSE; + + while(user_response != 'N' && user_response != 'n') + { + do + { + printf("Do you have media that you can insert in the drive? (Y/N): "); + scanf("%c", &user_response); + printf("\n"); + }while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n'); + + if(user_response == 'Y' || user_response == 'y') + { + printf("Please insert it in the drive and press any key when it is ready.\n"); + scanf("%c"); + + char mediaManufacturer[256], mediaName[256], mediaModel[256]; + printf("Please write a description of the media type and press enter: "); + gets(mediaName); + printf("Please write the media manufacturer and press enter: "); + gets(mediaManufacturer); + printf("Please write the media model and press enter: "); + gets(mediaModel); + + error = Identify(fd, &ata_ident, &ata_error_chs); + + if(!anyMedia) + xmlTextWriterStartElement(xmlWriter, BAD_CAST "RemovableMedias"); // + + xmlTextWriterStartElement(xmlWriter, BAD_CAST "testedMediaType"); // + + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s", + !error ? "TRUE" : "FALSE"); + + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s", mediaName); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel); + + if(error) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer); + xmlTextWriterEndElement(xmlWriter); // + anyMedia = TRUE; + continue; + } + + free(identify); + identify = malloc(512); + memcpy(identify, ata_ident, 512); + + if(identify->UnformattedBPT) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u", le16toh(identify->UnformattedBPT)); + if(identify->UnformattedBPS) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u", le16toh(identify->UnformattedBPS)); + + uint64_t blocks; + + if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->Cylinders)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->SectorsPerTrack)); + blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) * le16toh(identify->SectorsPerTrack); + xmlTextWriterEndElement(xmlWriter); // + } + + if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 && identify->CurrentSectorsPerTrack != 0) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->CurrentCylinders)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->CurrentSectorsPerTrack)); + if(blocks == 0) + blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) * le16toh(identify->CurrentSectorsPerTrack); + xmlTextWriterEndElement(xmlWriter); // + } + + if(le16toh(identify->Capabilities) & 0x0200) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u", le32toh(identify->LBASectors)); + blocks = le32toh(identify->LBASectors); + } + + if(le16toh(identify->CommandSet2) & 0x0400) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu", le64toh(identify->LBA48Sectors)); + blocks = le64toh(identify->LBA48Sectors); + } + + if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF) + { + if(le16toh(identify->NominalRotationRate) == 0x0001) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE"); + else + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u", le16toh(identify->NominalRotationRate)); + } + } + + uint32_t logicalsectorsize = 0; + uint32_t physicalsectorsize = 0; + + if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 && + (le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000) + { + if(le16toh(identify->PhysLogSectorSize) & 0x1000) + { + if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF) + logicalsectorsize = 512; + else + logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2; + } + else + logicalsectorsize = 512; + + if(le16toh(identify->PhysLogSectorSize) & 0x2000) + physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF)); + else + physicalsectorsize = logicalsectorsize; + } + else + { + logicalsectorsize = 512; + physicalsectorsize = 512; + } + + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize); + if(physicalsectorsize != logicalsectorsize) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize); + if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 && + (le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u", le16toh(identify->LogicalAlignment) & 0x3FFF); + } + + uint16_t longblocksize = 0; + if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF) + longblocksize = le16toh(identify->EccBytes); + + if(le16toh(identify->UnformattedBPS) > logicalsectorsize && (longblocksize == 0 || longblocksize == 516)) + longblocksize = le16toh(identify->UnformattedBPS); + + if(longblocksize > 0) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize); + + if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 && + (le16toh(identify->CommandSet3) & 0x4000) == 0x4000 && + (le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", AtaToCString(identify->MediaManufacturer, 20)); + } + else + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer); + + printf("Trying READ SECTOR(S) in CHS mode...\n"); + error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ SECTOR(S) RETRY in CHS mode...\n"); + error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in CHS mode...\n"); + error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA RETRY in CHS mode...\n"); + error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying SEEK in CHS mode...\n"); + error = Seek(fd, &ata_error_chs, 0, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0) ? "true" : "false"); + + printf("Trying READ SECTOR(S) in LBA mode...\n"); + error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ SECTOR(S) RETRY in LBA mode...\n"); + error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in LBA mode...\n"); + error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA RETRY in LBA mode...\n"); + error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying SEEK in LBA mode...\n"); + error = SeekLba(fd, &ata_error_lba, 0); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0) ? "true" : "false"); + + printf("Trying READ SECTOR(S) in LBA48 mode...\n"); + error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s", (!error && (ata_error_lba48->status & 0x01) != 0x01 && ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in LBA48 mode...\n"); + error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s", (!error && (ata_error_lba48->status & 0x01) != 0x01 && ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false"); + + + printf("Trying READ LONG in CHS mode...\n"); + error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG RETRY in CHS mode...\n"); + error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG in LBA mode...\n"); + error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG RETRY in LBA mode...\n"); + error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + xmlTextWriterEndElement(xmlWriter); // + + if(!anyMedia) + anyMedia = TRUE; + } + } + + if(anyMedia) + xmlTextWriterEndElement(xmlWriter); // + } + else + { + error = Identify(fd, &ata_ident, &ata_error_chs); + + xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // + + free(identify); + identify = malloc(512); + memcpy(identify, ata_ident, 512); + + if(identify->UnformattedBPT) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u", le16toh(identify->UnformattedBPT)); + if(identify->UnformattedBPS) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u", le16toh(identify->UnformattedBPS)); + + uint64_t blocks; + + if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->Cylinders)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->SectorsPerTrack)); + blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) * le16toh(identify->SectorsPerTrack); + xmlTextWriterEndElement(xmlWriter); // + } + + if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 && identify->CurrentSectorsPerTrack != 0) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->CurrentCylinders)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads)); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->CurrentSectorsPerTrack)); + if(blocks == 0) + blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) * le16toh(identify->CurrentSectorsPerTrack); + xmlTextWriterEndElement(xmlWriter); // + } + + if(le16toh(identify->Capabilities) & 0x0200) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u", le32toh(identify->LBASectors)); + blocks = le32toh(identify->LBASectors); + } + + if(le16toh(identify->CommandSet2) & 0x0400) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu", le64toh(identify->LBA48Sectors)); + blocks = le64toh(identify->LBA48Sectors); + } + + if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF) + { + if(le16toh(identify->NominalRotationRate) == 0x0001) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE"); + else + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u", le16toh(identify->NominalRotationRate)); + } + } + + uint32_t logicalsectorsize = 0; + uint32_t physicalsectorsize = 0; + + if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 && + (le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000) + { + if(le16toh(identify->PhysLogSectorSize) & 0x1000) + { + if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF) + logicalsectorsize = 512; + else + logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2; + } + else + logicalsectorsize = 512; + + if(le16toh(identify->PhysLogSectorSize) & 0x2000) + physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF)); + else + physicalsectorsize = logicalsectorsize; + } + else + { + logicalsectorsize = 512; + physicalsectorsize = 512; + } + + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize); + if(physicalsectorsize != logicalsectorsize) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize); + if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 && + (le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u", le16toh(identify->LogicalAlignment) & 0x3FFF); + } + + uint16_t longblocksize = 0; + if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF) + longblocksize = le16toh(identify->EccBytes); + + if(le16toh(identify->UnformattedBPS) > logicalsectorsize && (longblocksize == 0 || longblocksize == 516)) + longblocksize = le16toh(identify->UnformattedBPS); + + if(longblocksize > 0) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize); + + if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 && + (le16toh(identify->CommandSet3) & 0x4000) == 0x4000 && + (le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", AtaToCString(identify->MediaManufacturer, 20)); + } + + printf("Trying READ SECTOR(S) in CHS mode...\n"); + error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ SECTOR(S) RETRY in CHS mode...\n"); + error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in CHS mode...\n"); + error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA RETRY in CHS mode...\n"); + error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying SEEK in CHS mode...\n"); + error = Seek(fd, &ata_error_chs, 0, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0) ? "true" : "false"); + + printf("Trying READ SECTOR(S) in LBA mode...\n"); + error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ SECTOR(S) RETRY in LBA mode...\n"); + error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in LBA mode...\n"); + error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA RETRY in LBA mode...\n"); + error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying SEEK in LBA mode...\n"); + error = SeekLba(fd, &ata_error_lba, 0); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0) ? "true" : "false"); + + printf("Trying READ SECTOR(S) in LBA48 mode...\n"); + error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s", (!error && (ata_error_lba48->status & 0x01) != 0x01 && ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false"); + + printf("Trying READ DMA in LBA48 mode...\n"); + error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s", (!error && (ata_error_lba48->status & 0x01) != 0x01 && ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false"); + + + printf("Trying READ LONG in CHS mode...\n"); + error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG RETRY in CHS mode...\n"); + error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s", (!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG in LBA mode...\n"); + error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + printf("Trying READ LONG RETRY in LBA mode...\n"); + error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s", (!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0) ? "true" : "false"); + + xmlTextWriterEndElement(xmlWriter); // + } + + xmlTextWriterEndElement(xmlWriter); +} \ No newline at end of file diff --git a/DiscImageChef.Device.Report/ata_report.h b/DiscImageChef.Device.Report/ata_report.h new file mode 100644 index 00000000..cdbd1d48 --- /dev/null +++ b/DiscImageChef.Device.Report/ata_report.h @@ -0,0 +1,9 @@ +// +// Created by claunia on 18/12/17. +// + +#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H +#define DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H +#define DIC_ATA_REPORT_ELEMENT "ATA" +void AtaReport(int fd, xmlTextWriterPtr xmlWriter); +#endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H diff --git a/DiscImageChef.Device.Report/atapi_report.c b/DiscImageChef.Device.Report/atapi_report.c index 59c571ee..363433fb 100644 --- a/DiscImageChef.Device.Report/atapi_report.c +++ b/DiscImageChef.Device.Report/atapi_report.c @@ -28,7 +28,7 @@ void AtapiReport(int fd, xmlTextWriterPtr xmlWriter) IdentifyDevice *identify = malloc(512); memcpy(identify, atapi_ident, 512); - xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATAPI_REPORT_ELEMENT); + xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATAPI_REPORT_ELEMENT); // if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020) xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8)); @@ -187,9 +187,9 @@ void AtapiReport(int fd, xmlTextWriterPtr xmlWriter) if(identify->WRVSectorCountMode2) xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u", le32toh(identify->WRVSectorCountMode2)); - xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify"); + xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify"); // xmlTextWriterWriteBase64(xmlWriter, atapi_ident, 0, 512); - xmlTextWriterEndElement(xmlWriter); + xmlTextWriterEndElement(xmlWriter); // - xmlTextWriterEndElement(xmlWriter); + xmlTextWriterEndElement(xmlWriter); // } \ No newline at end of file diff --git a/DiscImageChef.Device.Report/main.c b/DiscImageChef.Device.Report/main.c index 7c851d8f..7a84b4a6 100644 --- a/DiscImageChef.Device.Report/main.c +++ b/DiscImageChef.Device.Report/main.c @@ -10,6 +10,7 @@ #include "atapi.h" #include "atapi_report.h" #include "scsi_report.h" +#include "ata_report.h" #include #define DIC_VERSION "3.99.6.0" @@ -141,6 +142,9 @@ int main(int argc, void *argv[]) if(deviceType == DEVICE_TYPE_ATAPI || deviceType == DEVICE_TYPE_SCSI) ScsiReport(fd, xmlWriter); + if(deviceType == DEVICE_TYPE_ATA) + AtaReport(fd, xmlWriter); + rc = xmlTextWriterEndDocument(xmlWriter); if (rc < 0) { printf("Could not close XML report file.\n"); diff --git a/DiscImageChef.Device.Report/scsi_report.c b/DiscImageChef.Device.Report/scsi_report.c index d8eeaa48..6c73cb64 100644 --- a/DiscImageChef.Device.Report/scsi_report.c +++ b/DiscImageChef.Device.Report/scsi_report.c @@ -525,12 +525,13 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) xmlTextWriterEndElement(xmlWriter); // if(!anyMedia) - { - xmlTextWriterEndElement(xmlWriter); // anyMedia = TRUE; - } } } + + + if(anyMedia) + xmlTextWriterEndElement(xmlWriter); // } else {