diff --git a/include/openseachest_util_options.h b/include/openseachest_util_options.h index adb0343e..068041a5 100644 --- a/include/openseachest_util_options.h +++ b/include/openseachest_util_options.h @@ -529,6 +529,14 @@ extern "C" #define TELEMETRY_DATA_AREA_LONG_OPT_STRING "telemetryDataArea" #define TELEMETRY_DATA_AREA_LONG_OPT { TELEMETRY_DATA_AREA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ZERO_VERIFY_FLAG runZeroVerify + #define ZERO_VERIFY_MODE_FLAG runZeroVerifyMode + #define ZERO_VERIFY_VARS \ + bool ZERO_VERIFY_FLAG = false; \ + int ZERO_VERIFY_MODE_FLAG = 0; /*0 = full, 1 = quick*/ + #define ZERO_VERIFY_LONG_OPT_STRING "zeroVerify" + #define ZERO_VERIFY_LONG_OPT { ZERO_VERIFY_LONG_OPT_STRING, required_argument, NULL, 0 } + //Generic read test options #define GENERIC_TEST_MODE_FLAG genericTestMode #define GENERIC_TEST_MODE_VAR int genericTestMode = 0; //0 = read, 1 = write, 2 = verify @@ -3474,8 +3482,11 @@ extern "C" void print_Persistent_Reservations_Preempt_Abort_Help(bool shortHelp); + void print_Zero_Verify_Help(bool shortHelp); void print_NVME_Health_Help(bool shortHelp); + void print_Delay_CMD_Segment_Help(bool shortHelp); + void print_Low_Level_Info_Help(bool shortHelp); void print_Force_NVMe_Commit_Action_Help(bool shortHelp); diff --git a/src/openseachest_util_options.c b/src/openseachest_util_options.c index f67b40b7..88c5058e 100644 --- a/src/openseachest_util_options.c +++ b/src/openseachest_util_options.c @@ -86,26 +86,26 @@ void print_Elevated_Privileges_Text(void) //TODO: handle the various linux/unix/unix-like OSs with more ifdefs here #if defined (__linux__) #if defined (VMK_CROSS_COMP) - printf("In ESXi, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In ESXi, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In ESXi, put sudo before the command. This may require inputting your login password.\n"); + printf("In ESXi, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #else - printf("In Linux, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In Linux, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In Linux, put sudo before the command. This may require inputting your login password.\n"); + printf("In Linux, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #endif #elif defined (__FreeBSD__) - printf("In FreeBSD, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In FreeBSD, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In FreeBSD, put sudo before the command. This may require inputting your login password.\n"); + printf("In FreeBSD, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #elif defined (__sun) - printf("In Solaris, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In Solaris, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In Solaris, put sudo before the command. This may require inputting your login password.\n"); + printf("In Solaris, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #else //generic unix/unix-like case //TODO: Add more OS specific ifdefs to customize messages above - printf("In Linux/Unix, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In Linux/Unix, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In Linux/Unix, put sudo before the command. This may require inputting your login password.\n"); + printf("In Linux/Unix, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #endif #else //generic, who knows what OS this is case printf("In Windows, open the Command Prompt using \"Run as administrator\".\n"); - printf("In Linux/Unix, put sudo before the SeaChest command. This may require inputting your login password.\n"); - printf("In Linux/Unix, log in to a root terminal (su), then execute the SeaChest command. This requires the root password.\n"); + printf("In Linux/Unix, put sudo before the command. This may require inputting your login password.\n"); + printf("In Linux/Unix, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #endif return; } @@ -2748,7 +2748,7 @@ void print_Show_DST_Log_Help(bool shortHelp) void print_Force_SCSI_Help(bool shortHelp) { printf("\t--%s\n", FORCE_SCSI_LONG_OPT_STRING); - if(!shortHelp) + if (!shortHelp) { printf("\t\tUsing this option will force the current drive to\n"); printf("\t\tbe treated as a SCSI drive. Only SCSI commands will\n"); @@ -2759,7 +2759,7 @@ void print_Force_SCSI_Help(bool shortHelp) void print_Force_ATA_Help(bool shortHelp) { printf("\t--%s\n", FORCE_ATA_LONG_OPT_STRING); - if(!shortHelp) + if (!shortHelp) { printf("\t\tUsing this option will force the current drive to\n"); printf("\t\tbe treated as a ATA drive. Only ATA commands will\n"); @@ -3018,79 +3018,82 @@ int parse_Device_Handle_Argument(char * optarg, bool *allDrives, bool *userHandl return 254;//one of the required parameters is missing. handleList is checked below... } /*get the number out of optarg to tack onto the device handle*/ - if (strcmp(optarg, "all") == 0) + if (NULL != optarg) { - /*this is a request to run on all drives.*/ - *allDrives = true; - } - else - { - *userHandleProvided = true; -#if defined(_WIN32) -#define WINDOWS_MAX_HANDLE_STRING_LENGTH 50 - char windowsHandle[WINDOWS_MAX_HANDLE_STRING_LENGTH] = { 0 }; - char *deviceHandle = &windowsHandle[0]; - char *physicalDeviceNumber; /*making this a string in case the handle is two or more digits long*/ - /*make sure the user gave us "PD" for the device handle...*/ - if (_strnicmp(optarg, "PD", 2) == 0) + if (strcmp(optarg, "all") == 0) { - physicalDeviceNumber = strpbrk(optarg, "0123456789"); - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "\\\\.\\PhysicalDrive%s", physicalDeviceNumber); + /*this is a request to run on all drives.*/ + *allDrives = true; } -#if defined(ENABLE_CSMI) - else if (strncmp(optarg, "csmi", 4) == 0) + else { - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); - } + *userHandleProvided = true; +#if defined(_WIN32) +#define WINDOWS_MAX_HANDLE_STRING_LENGTH 50 + char windowsHandle[WINDOWS_MAX_HANDLE_STRING_LENGTH] = { 0 }; + char *deviceHandle = &windowsHandle[0]; + char *physicalDeviceNumber; /*making this a string in case the handle is two or more digits long*/ + /*make sure the user gave us "PD" for the device handle...*/ + if (_strnicmp(optarg, "PD", 2) == 0) + { + physicalDeviceNumber = strpbrk(optarg, "0123456789"); + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "\\\\.\\PhysicalDrive%s", physicalDeviceNumber); + } +#if defined(ENABLE_CSMI) + else if (strncmp(optarg, "csmi", 4) == 0) + { + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); + } #endif - else if (strncmp(optarg, "\\\\.\\", 4) == 0) - { - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); - } - /*If we want to add another format for accepting a handle, then add an else-if here*/ - else /*we have an invalid handle*/ - { - printf("Error: %s is an invalid handle format for this tool.\n", optarg); - exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); - } + else if (strncmp(optarg, "\\\\.\\", 4) == 0) + { + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); + } + /*If we want to add another format for accepting a handle, then add an else-if here*/ + else /*we have an invalid handle*/ + { + printf("Error: %s is an invalid handle format for this tool.\n", optarg); + exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); + } #else - char *deviceHandle = optarg; + char *deviceHandle = optarg; #endif - ++(*deviceCount);/*increment this variable if we've made it this far.*/ - /*The code below is where this function gets complicated. Be very careful changing anything below this comment.*/ - if (!*handleList) - { - /*allocate the list and add this handle to it.*/ - *handleList = C_CAST(char**, calloc((*deviceCount), sizeof(char*))); - if (!*handleList) - { - perror("error allocating memory for handle list\n"); - return 255; - } - } - else - { - /*list already allocated, so reallocate and add this next handle to it.*/ - char **temp = C_CAST(char**, realloc(*handleList, (*deviceCount) * sizeof(char*))); - if (!temp) - { - perror("error reallocating memory for handle list\n"); - return 255; - } - *handleList = temp; - } - /*the list has been allocated, now put the handle we've received into the list*/ - /*start by allocating memory for the handle at the new list location*/ - size_t handleListNewHandleLength = strlen(deviceHandle) + 1; - (*handleList)[(*deviceCount) - 1] = C_CAST(char*, calloc(handleListNewHandleLength, sizeof(char))); - if (!(*handleList)[(*deviceCount) - 1]) - { - perror("error allocating memory for adding device handle to list\n"); - return 255; - } - /*copy the handle into memory*/ - snprintf((*handleList)[(*deviceCount) - 1], handleListNewHandleLength, "%s", deviceHandle); + ++(*deviceCount);/*increment this variable if we've made it this far.*/ + /*The code below is where this function gets complicated. Be very careful changing anything below this comment.*/ + if (!*handleList) + { + /*allocate the list and add this handle to it.*/ + *handleList = C_CAST(char**, calloc((*deviceCount), sizeof(char*))); + if (!*handleList) + { + perror("error allocating memory for handle list\n"); + return 255; + } + } + else + { + /*list already allocated, so reallocate and add this next handle to it.*/ + char **temp = C_CAST(char**, realloc(*handleList, (*deviceCount) * sizeof(char*))); + if (!temp) + { + perror("error reallocating memory for handle list\n"); + return 255; + } + *handleList = temp; + } + /*the list has been allocated, now put the handle we've received into the list*/ + /*start by allocating memory for the handle at the new list location*/ + size_t handleListNewHandleLength = strlen(deviceHandle) + 1; + (*handleList)[(*deviceCount) - 1] = C_CAST(char*, calloc(handleListNewHandleLength, sizeof(char))); + if (!(*handleList)[(*deviceCount) - 1]) + { + perror("error allocating memory for adding device handle to list\n"); + return 255; + } + /*copy the handle into memory*/ + snprintf((*handleList)[(*deviceCount) - 1], handleListNewHandleLength, "%s", deviceHandle); + } } return 0; } @@ -4328,6 +4331,21 @@ void print_Persistent_Reservations_Preempt_Abort_Help(bool shortHelp) } } +void print_Zero_Verify_Help(bool shortHelp) +{ + printf("\t--%s [full | quick]\n", ZERO_VERIFY_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to verify drive content, whether it's set to zero or not.\n"); + printf("\t\tThis operation will read user accessible address and validate if content at\n"); + printf("\t\tthat address is zero or not.\n"); + printf("\t\tValidation modes:\n"); + printf("\t\t full - Complete drive will be scanned for verification.\n"); + printf("\t\t quick - 0.1%% of total capacity will be scanned for ID and OD validation along with\n"); + printf("\t\t 2 random addresses from 10000 equal size sections each.\n\n"); + } +} + void print_Partition_Info_Help(bool shortHelp) { printf("\t--%s\n", PARTITION_INFO_LONG_OPT_STRING); @@ -4471,3 +4489,4 @@ void print_DCO_Disable_Features_Help(bool shortHelp) printf("\t\t different system or add-in card to work around this.\n\n"); } } + diff --git a/utils/C/openSeaChest/openSeaChest_Erase.c b/utils/C/openSeaChest/openSeaChest_Erase.c index 2c7a260f..078bb4d5 100644 --- a/utils/C/openSeaChest/openSeaChest_Erase.c +++ b/utils/C/openSeaChest/openSeaChest_Erase.c @@ -41,11 +41,18 @@ #include "drive_info.h" #include "format.h" #include "platform_helper.h" +#include "generic_tests.h" //////////////////////// // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Erase"; -const char *buildVersion = "4.1.1"; +const char *buildVersion = "4.2.0"; + +typedef enum _eSeaChestEraseExitCodes +{ + SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE = UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE, //Zero validation failure + SEACHEST_ERASE_EXIT_MAX_ERROR //don't acutally use this, just for memory allocation below +}eSeaChestEraseExitCodes; //////////////////////////// // functions to declare // @@ -136,7 +143,7 @@ int32_t main(int argc, char *argv[]) HOURS_TIME_VAR MINUTES_TIME_VAR SECONDS_TIME_VAR - + ZERO_VERIFY_VARS #if defined (ENABLE_CSMI) CSMI_FORCE_VARS CSMI_VERBOSE_VAR @@ -211,6 +218,7 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_FORCE_SAT_LONG_OPT, NVM_FORMAT_LONG_OPT, NVM_FORMAT_OPTIONS_LONG_OPTS, + ZERO_VERIFY_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -392,7 +400,7 @@ int32_t main(int argc, char *argv[]) } } } - #if !defined(DISABLE_TCG_SUPPORT) +#if !defined(DISABLE_TCG_SUPPORT) else if (strcmp(longopts[optionIndex].name, TCG_SID_LONG_OPT_STRING) == 0) { snprintf(TCG_SID_FLAG, TCG_SID_BUF_LEN, "%s", optarg); @@ -401,7 +409,7 @@ int32_t main(int argc, char *argv[]) { snprintf(TCG_PSID_FLAG, TCG_PSID_BUF_LEN, "%s", optarg); } - #endif +#endif else if (strcmp(longopts[optionIndex].name, FORMAT_UNIT_LONG_OPT_STRING) == 0) { FORMAT_UNIT_FLAG = true; @@ -634,7 +642,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "zeropad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -643,7 +651,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "spacepad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -652,7 +660,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "fpad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -661,7 +669,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "leftAlign") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -670,7 +678,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "rightAlign") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -679,7 +687,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "uppercase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -688,7 +696,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "lowercase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -697,7 +705,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "invertcase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -764,7 +772,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_CANNOT_OPEN_FILE); } //read contents into buffer - if(0 == fread(PATTERN_BUFFER, sizeof(uint8_t), M_Min(PATTERN_BUFFER_LENGTH, get_File_Size(patternFile)), patternFile)) + if (0 == fread(PATTERN_BUFFER, sizeof(uint8_t), M_Min(PATTERN_BUFFER_LENGTH, get_File_Size(patternFile)), patternFile)) { printf("Unable to read contents of the file \"%s\" for the pattern.\n", filename); fclose(patternFile); @@ -801,6 +809,23 @@ int32_t main(int argc, char *argv[]) } } } + else if (strncmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ZERO_VERIFY_LONG_OPT_STRING))) == 0) + { + ZERO_VERIFY_FLAG = true; + if (strcmp(optarg, "full") == 0) + { + ZERO_VERIFY_MODE_FLAG = ZERO_VERIFY_TYPE_FULL; + } + else if (strcmp(optarg, "quick") == 0) + { + ZERO_VERIFY_MODE_FLAG = ZERO_VERIFY_TYPE_QUICK; + } + else + { + print_Error_In_Cmd_Line_Args(ZERO_VERIFY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } break; case PROGRESS_SHORT_OPT: //get test progress for a specific test PROGRESS_CHAR = optarg; @@ -1152,6 +1177,7 @@ int32_t main(int argc, char *argv[]) || FORMAT_UNIT_FLAG || DISPLAY_LBA_FLAG || NVM_FORMAT_FLAG + || ZERO_VERIFY_FLAG )) { utility_Usage(true); @@ -1787,6 +1813,34 @@ int32_t main(int argc, char *argv[]) } #endif + if (ZERO_VERIFY_FLAG) + { + ret = zero_Verify_Test(&deviceList[deviceIter], ZERO_VERIFY_MODE_FLAG, HIDE_LBA_COUNTER); + switch (ret) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Zero Validation Test passed.\n"); + } + break; + case VALIDATION_FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Zero Validation failed.\n"); + } + exitCode = SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Operation failure.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (sanitize) { int sanitizeResult = UNKNOWN; @@ -2509,7 +2563,7 @@ int32_t main(int argc, char *argv[]) } if (localStartLBA != UINT64_MAX) { - if(localStartLBA > deviceList[deviceIter].drive_info.deviceMaxLba) + if (localStartLBA > deviceList[deviceIter].drive_info.deviceMaxLba) { localStartLBA = deviceList[deviceIter].drive_info.deviceMaxLba; } @@ -2593,7 +2647,7 @@ int32_t main(int argc, char *argv[]) localRange = 1; } } - if(localStartLBA > deviceList[deviceIter].drive_info.deviceMaxLba) + if (localStartLBA > deviceList[deviceIter].drive_info.deviceMaxLba) { localStartLBA = deviceList[deviceIter].drive_info.deviceMaxLba; } @@ -2819,7 +2873,26 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + int totalErrorCodes = SEACHEST_ERASE_EXIT_MAX_ERROR - SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE; + ptrToolSpecificxitCode seachestEraseExitCodes = C_CAST(ptrToolSpecificxitCode, calloc(totalErrorCodes, sizeof(toolSpecificxitCode))); + //now set up all the exit codes and their meanings + if (seachestEraseExitCodes) + { + for (int exitIter = UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE; exitIter < SEACHEST_ERASE_EXIT_MAX_ERROR; ++exitIter) + { + seachestEraseExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCode = exitIter; + switch (exitIter) + { + case SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE: + snprintf(seachestEraseExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCodeString, TOOL_EXIT_CODE_STRING_MAX_LENGTH, "Zero Validation Failure"); + break; + //TODO: add more exit codes here! + default://We shouldn't ever hit the default case! + break; + } + } + } + print_SeaChest_Util_Exit_Codes(totalErrorCodes, seachestEraseExitCodes, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -2874,6 +2947,8 @@ void utility_Usage(bool shortUsage) #if !defined(DISABLE_TCG_SUPPORT) print_TCG_SID_Help(shortUsage); #endif + print_Zero_Verify_Help(shortUsage); + //SATA Only Options printf("\n\tSATA Only:\n\t=========\n"); print_ATA_Security_Force_SAT_Security_Protocol_Help(shortUsage); diff --git a/utils/C/openSeaChest/openSeaChest_Security.c b/utils/C/openSeaChest/openSeaChest_Security.c index eb3dba6b..a06e7298 100644 --- a/utils/C/openSeaChest/openSeaChest_Security.c +++ b/utils/C/openSeaChest/openSeaChest_Security.c @@ -33,6 +33,7 @@ #include "disable_data_locking.h" #endif #include "ata_Security.h" +#include "generic_tests.h" //Uncomment this if we want the command line option to set an ATA security password. //This is currently removed because we may not be able to unlock it behind some devices due to poor implementation on SAT with ATA security active @@ -42,7 +43,13 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Security"; -const char *buildVersion = "3.2.2"; +const char *buildVersion = "3.3.0"; + +typedef enum _eSeaChestSecurityExitCodes +{ + SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE = UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE, //Zero validation failure + SEACHEST_SECURITY_EXIT_MAX_ERROR //don't acutally use this, just for memory allocation below +}eSeaChestSecurityExitCodes; //////////////////////////// // functions to declare // @@ -94,6 +101,8 @@ int32_t main(int argc, char *argv[]) //scan output flags SCAN_FLAGS_UTIL_VARS DISPLAY_LBA_VAR + HIDE_LBA_COUNTER_VAR + ZERO_VERIFY_VARS #if !defined(DISABLE_TCG_SUPPORT) TCG_DEVICE_INFO_VAR TCG_SID_VARS @@ -190,6 +199,8 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_UNLOCK_OP_LONG_OPT, ATA_SECURITY_DISABLE_OP_LONG_OPT, ATA_SECURITY_FREEZELOCK_OP_LONG_OPT, + HIDE_LBA_COUNTER_LONG_OPT, + ZERO_VERIFY_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -290,7 +301,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "zeropad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -299,7 +310,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "spacepad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -308,7 +319,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "fpad") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.fpadded = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.spacePadded || ATA_SECURITY_PASSWORD_MODIFICATIONS.zeroPadded) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -317,7 +328,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "leftAlign") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -326,7 +337,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "rightAlign") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.leftAligned) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -335,7 +346,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "uppercase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -344,7 +355,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "lowercase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -353,7 +364,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(optarg, "invertcase") == 0) { ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase = true; - if ( ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) + if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase || ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) { //todo: print error saying invalid argument combination. exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -439,7 +450,7 @@ int32_t main(int argc, char *argv[]) else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING))) == 0) { uint64_t masterIDOut = 0; - if(!get_And_Validate_Integer_Input(optarg, &masterIDOut)) + if (!get_And_Validate_Integer_Input(optarg, &masterIDOut)) { print_Error_In_Cmd_Line_Args(ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -525,6 +536,23 @@ int32_t main(int argc, char *argv[]) } } } + else if (strncmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ZERO_VERIFY_LONG_OPT_STRING))) == 0) + { + ZERO_VERIFY_FLAG = true; + if (strcmp(optarg, "full") == 0) + { + ZERO_VERIFY_MODE_FLAG = ZERO_VERIFY_TYPE_FULL; + } + else if (strcmp(optarg, "quick") == 0) + { + ZERO_VERIFY_MODE_FLAG = ZERO_VERIFY_TYPE_QUICK; + } + else + { + print_Error_In_Cmd_Line_Args(ZERO_VERIFY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } break; case ':'://missing required argument exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; @@ -916,7 +944,8 @@ int32_t main(int argc, char *argv[]) || ATA_SECURITY_SET_PASSWORD_OP #endif //ENABLE_ATA_SET_PASSWORD || ATA_SECURITY_ERASE_OP - )) + || ZERO_VERIFY_FLAG + )) { utility_Usage(true); free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); @@ -1132,7 +1161,7 @@ int32_t main(int argc, char *argv[]) continue; } } - + if (FORCE_SCSI_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1141,7 +1170,7 @@ int32_t main(int argc, char *argv[]) } deviceList[deviceIter].drive_info.drive_type = SCSI_DRIVE; } - + if (FORCE_ATA_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1228,6 +1257,34 @@ int32_t main(int argc, char *argv[]) show_Test_Unit_Ready_Status(&deviceList[deviceIter]); } + if (ZERO_VERIFY_FLAG) + { + ret = zero_Verify_Test(&deviceList[deviceIter], ZERO_VERIFY_MODE_FLAG, HIDE_LBA_COUNTER); + switch (ret) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Zero Validation Test passed.\n"); + } + break; + case VALIDATION_FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Zero Validation failed.\n"); + } + exitCode = SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Operation failure.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (DISPLAY_LBA_FLAG) { uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); @@ -1565,14 +1622,14 @@ int32_t main(int argc, char *argv[]) } #endif //#if !defined(DISABLE_TCG_SUPPORT) - if(ATA_SECURITY_UNLOCK_OP) + if (ATA_SECURITY_UNLOCK_OP) { ataSecurityPassword ataPassword; memset(&ataPassword, 0, sizeof(ataSecurityPassword)); ataPassword.passwordType = ATA_SECURITY_USING_MASTER_PW; memcpy(ataPassword.password, ATA_SECURITY_PASSWORD, ATA_SECURITY_PASSWORD_BYTE_COUNT);//ATA_SECURITY_PASSWORD_BYTE_COUNT shouldn't ever be > 32. Should be caught above. ataPassword.passwordLength = ATA_SECURITY_PASSWORD_BYTE_COUNT; - switch(run_Unlock_ATA_Security(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) + switch (run_Unlock_ATA_Security(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) { case SUCCESS: printf("Successfully unlocked ATA security\n"); @@ -1589,14 +1646,14 @@ int32_t main(int argc, char *argv[]) } explicit_zeroes(&ataPassword, sizeof(ataSecurityPassword)); } - if(ATA_SECURITY_DISABLE_OP) + if (ATA_SECURITY_DISABLE_OP) { ataSecurityPassword ataPassword; memset(&ataPassword, 0, sizeof(ataSecurityPassword)); ataPassword.passwordType = ATA_SECURITY_USING_MASTER_PW; memcpy(ataPassword.password, ATA_SECURITY_PASSWORD, ATA_SECURITY_PASSWORD_BYTE_COUNT);//ATA_SECURITY_PASSWORD_BYTE_COUNT shouldn't ever be > 32. Should be caught above. ataPassword.passwordLength = ATA_SECURITY_PASSWORD_BYTE_COUNT; - switch(run_Disable_ATA_Security_Password(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) + switch (run_Disable_ATA_Security_Password(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) { case SUCCESS: printf("Successfully disabled ATA security password\n"); @@ -1623,7 +1680,7 @@ int32_t main(int argc, char *argv[]) ataPassword.masterPWIdentifier = ATA_SECURITY_MASTER_PW_ID; memcpy(ataPassword.password, ATA_SECURITY_PASSWORD, ATA_SECURITY_PASSWORD_BYTE_COUNT);//ATA_SECURITY_PASSWORD_BYTE_COUNT shouldn't ever be > 32. Should be caught above. ataPassword.passwordLength = ATA_SECURITY_PASSWORD_BYTE_COUNT; - switch(run_Set_ATA_Security_Password(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) + switch (run_Set_ATA_Security_Password(&deviceList[deviceIter], ataPassword, ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) { case SUCCESS: printf("Successfully set ATA security password\n"); @@ -1688,9 +1745,9 @@ int32_t main(int argc, char *argv[]) } } - if(ATA_SECURITY_FREEZELOCK_OP) + if (ATA_SECURITY_FREEZELOCK_OP) { - switch(run_Freeze_ATA_Security(&deviceList[deviceIter], ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) + switch (run_Freeze_ATA_Security(&deviceList[deviceIter], ATA_SECURITY_FORCE_SAT_VALID, ATA_SECURITY_FORCE_SAT)) { case SUCCESS: printf("Successfully froze ATA security\n"); @@ -1738,7 +1795,7 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SAT_INFO_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, LOWLEVEL_INFO_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, ATA_SECURITY_INFO_OP_LONG_OPT_STRING); - printf("\t%s -d %s --%s enhanced\n", util_name, deviceHandleExample, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING); + printf("\t%s -d %s --%s enhanced\n", util_name, deviceHandleExample, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING); printf("\t%s -d %s --%s enhanced --%s AutoATAWindowsString12345678901 --%s user\n", util_name, deviceHandleExample, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING, ATA_SECURITY_PASSWORD_LONG_OPT_STRING, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s AutoATAWindowsString12345678901 --%s user\n", util_name, deviceHandleExample, ATA_SECURITY_DISABLE_OP_LONG_OPT_STRING, ATA_SECURITY_PASSWORD_LONG_OPT_STRING, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING); #if defined ENABLE_ATA_SET_PASSWORD @@ -1748,7 +1805,26 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + int totalErrorCodes = SEACHEST_SECURITY_EXIT_MAX_ERROR - SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE; + ptrToolSpecificxitCode seachestSecurityExitCodes = C_CAST(ptrToolSpecificxitCode, calloc(totalErrorCodes, sizeof(toolSpecificxitCode))); + //now set up all the exit codes and their meanings + if (seachestSecurityExitCodes) + { + for (int exitIter = UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE; exitIter < SEACHEST_SECURITY_EXIT_MAX_ERROR; ++exitIter) + { + seachestSecurityExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCode = exitIter; + switch (exitIter) + { + case SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE: + snprintf(seachestSecurityExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCodeString, TOOL_EXIT_CODE_STRING_MAX_LENGTH, "Zero Validation Failure"); + break; + //TODO: add more exit codes here! + default://We shouldn't ever hit the default case! + break; + } + } + } + print_SeaChest_Util_Exit_Codes(totalErrorCodes, seachestSecurityExitCodes, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -1798,6 +1874,7 @@ void utility_Usage(bool shortUsage) print_TCG_Info_Help(shortUsage); print_TCG_SID_Help(shortUsage); #endif + print_Zero_Verify_Help(shortUsage); printf("\n\tSATA Only:\n\t=========\n"); print_ATA_Security_Force_SAT_Security_Protocol_Help(shortUsage);