mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-20 13:42:14 +00:00
Merge pull request #449 from PartialVolume/HPA_DCO_006
HPA_DCO_006 - Add HPA/DCO capability
This commit is contained in:
@@ -818,13 +818,13 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
case HPA_ENABLED:
|
||||
wprintw( main_window, " " );
|
||||
wattron( main_window, COLOR_PAIR( 9 ) );
|
||||
wprintw( main_window, " HPA/DCO Warning, hidden area detected " );
|
||||
wprintw( main_window, " HPA/DCO hidden area detected !! " );
|
||||
wattroff( main_window, COLOR_PAIR( 9 ) );
|
||||
break;
|
||||
|
||||
case HPA_DISABLED:
|
||||
wprintw( main_window, " " );
|
||||
wprintw( main_window, " HPA/DCO GOOD, no hidden areas " );
|
||||
wprintw( main_window, " HPA/DCO Excellent NO hidden areas " );
|
||||
break;
|
||||
|
||||
case HPA_UNKNOWN:
|
||||
|
||||
101
src/hpa_dco.c
101
src/hpa_dco.c
@@ -188,7 +188,7 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
if( strstr( result, "SG_IO: bad/missing sense data" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_UNKNOWN;
|
||||
nwipe_log( NWIPE_LOG_INFO, "[ERROR] SG_IO bad/missing sense data %s", hdparm_cmd_get_hpa );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "SG_IO bad/missing sense data %s", hdparm_cmd_get_hpa );
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -197,7 +197,11 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
{
|
||||
c->HPA_status = HPA_DISABLED;
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO, "[GOOD] The host protected area is disabled on %s", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the host protected area is disabled on %s but this information may or "
|
||||
"may not be correct, as occurs when you get a SG_IO error and 0/1 sectors and it "
|
||||
"says HPA is enabled. Further checks are conducted below..",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
}
|
||||
else
|
||||
@@ -205,7 +209,11 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
if( strstr( result, "hpa is enabled" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_ENABLED;
|
||||
nwipe_log( NWIPE_LOG_WARNING, "The host protected area is enabled on %s", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the host protected area is enabled on %s but this information may "
|
||||
"or may not be correct, as occurs when you get a SG_IO error and 0/1 sectors "
|
||||
"and it says HPA is enabled. Further checks are conducted below..",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
}
|
||||
else
|
||||
@@ -214,7 +222,8 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
{
|
||||
c->HPA_status = HPA_ENABLED;
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"[UNSURE] hdparm reports invalid output, buggy drive firmware on %s?",
|
||||
"hdparm reports invalid output, sector information may be invalid, buggy "
|
||||
"drive firmware on %s?",
|
||||
c->device_name );
|
||||
// We'll assume the HPA values are in the string as we may be able to extract something
|
||||
// meaningful
|
||||
@@ -342,9 +351,41 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
{
|
||||
c->DCO_reported_real_max_sectors = str_ascii_number_to_ll( result );
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"DCO Real max sectors reported as %lli on %s",
|
||||
"hdparm:DCO Real max sectors reported as %lli on %s",
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->device_name );
|
||||
|
||||
/* Validate the real max sectors to detect extreme or impossible
|
||||
* values, so the size must be greater than zero but less than
|
||||
* 200TB (429496729600 sectors). As its 2023 and the largest drive
|
||||
* available is 20TB I wonder if somebody in the future will be looking
|
||||
* at this and thinking, yep we need to increase that value... and I'm
|
||||
* wondering what year that will be. This validation is necessary all
|
||||
* because of a bug in hdparm v9.60 (and maybe other versions) which
|
||||
* produced wildly inaccurate values, often negative.
|
||||
*/
|
||||
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
|
||||
{
|
||||
/* Call nwipe's own low level function to retrieve the drive configuration
|
||||
* overlay and retrieve the real max sectors. We may remove reliance on hdparm
|
||||
* if nwipes own low level drive access code works well.
|
||||
*/
|
||||
c->DCO_reported_real_max_sectors = nwipe_read_dco_real_max_sectors( c->device_name );
|
||||
|
||||
/* Check our real max sectors function is returning sensible data too */
|
||||
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"NWipe:DCO Real max sectors reported as %lli on %s",
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
c->DCO_reported_real_max_sectors = 0;
|
||||
nwipe_log( NWIPE_LOG_INFO, "DCO Real max sectors not found" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -388,7 +429,10 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
* HPA is disabled.
|
||||
*
|
||||
* If 'HPA set' and 'HPA real' are different then it
|
||||
* can be considered that HPA is enabled)
|
||||
* can be considered that HPA is enabled, assuming 'HPA set'
|
||||
* and 'HPA real' are not 0/1 which occurs when a SG_IO error
|
||||
* occurs. That also is checked for as it often indicates a
|
||||
* poor USB device that does not have ATA pass through support.
|
||||
*
|
||||
* However we also need to consider that more recent drives
|
||||
* no longer support HPA/DCO such as the Seagate ST10000NM0016,
|
||||
@@ -434,9 +478,17 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( c->device_type_str, "NVME" ) )
|
||||
/* This occurs when a SG_IO error occurs with USB devices that don't support ATA pass through */
|
||||
if( c->HPA_reported_set == 0 && c->HPA_reported_real == 1 )
|
||||
{
|
||||
c->HPA_status = HPA_NOT_APPLICABLE;
|
||||
c->HPA_status = HPA_UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( c->device_type_str, "NVME" ) )
|
||||
{
|
||||
c->HPA_status = HPA_NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,7 +508,9 @@ int hpa_dco_status( nwipe_context_t* ptr )
|
||||
{
|
||||
if( c->HPA_status == HPA_UNKNOWN )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "HIDDEN AREA INDETERMINATE! on %s", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"HIDDEN AREA INDETERMINATE! on %s, are you using a USB bridge or memory stick?",
|
||||
c->device_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,6 +561,7 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
#define CMD_LEN 16
|
||||
#define BLOCK_MAX 65535
|
||||
#define LBA_MAX ( 1 << 30 )
|
||||
#define SENSE_BUFFER_SIZE 32
|
||||
|
||||
u64 nwipe_real_max_sectors;
|
||||
|
||||
@@ -515,9 +570,14 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
|
||||
sg_io_hdr_t io_hdr;
|
||||
unsigned char buffer[LBA_SIZE]; // Received data block
|
||||
unsigned char sense_buffer[32]; // Sense data
|
||||
unsigned char sense_buffer[SENSE_BUFFER_SIZE]; // Sense data
|
||||
|
||||
int i; // index
|
||||
/* three characters represent one byte of sense data, i.e
|
||||
* two characters and a space "01 AE 67"
|
||||
*/
|
||||
char sense_buffer_hex[( SENSE_BUFFER_SIZE * 3 ) + 1];
|
||||
|
||||
int i, i2; // index
|
||||
int fd; // file descripter
|
||||
|
||||
if( ( fd = open( device, O_RDWR ) ) < 0 )
|
||||
@@ -528,7 +588,7 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
|
||||
/******************************************
|
||||
* Initialise the sg header for reading the
|
||||
* device configuration overlay identify
|
||||
* device configuration overlay identify data
|
||||
*/
|
||||
memset( &io_hdr, 0, sizeof( sg_io_hdr_t ) );
|
||||
io_hdr.interface_id = 'S';
|
||||
@@ -543,12 +603,15 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
|
||||
if( ioctl( fd, SG_IO, &io_hdr ) < 0 )
|
||||
{
|
||||
printf( "ioctl failed\n" );
|
||||
for( i = 0; i < 32; i++ )
|
||||
nwipe_log( NWIPE_LOG_ERROR, "IOCTL command failed retrieving DCO" );
|
||||
i2 = 0;
|
||||
for( i = 0, i2 = 0; i < SENSE_BUFFER_SIZE; i++, i2 += 3 )
|
||||
{
|
||||
/* IOCTL returned an error */
|
||||
printf( "%02x ", sense_buffer[i] ); // WARNING make this an nwipe_log
|
||||
snprintf( &sense_buffer_hex[i2], sizeof( sense_buffer_hex ), "%02x ", sense_buffer[i] );
|
||||
}
|
||||
sense_buffer_hex[i2] = 0; // terminate string
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "Sense buffer from failed DCO identify cmd:%s", sense_buffer_hex );
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -565,9 +628,13 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
| buffer[6];
|
||||
|
||||
/* Don't really understand this but hdparm adds 1 to
|
||||
* the real max sectors too, (starting from 0??)
|
||||
* the real max sectors too, counting zero as sector?
|
||||
* but only increment if it's already greater than zero
|
||||
*/
|
||||
nwipe_real_max_sectors++;
|
||||
if( nwipe_real_max_sectors > 0 )
|
||||
{
|
||||
nwipe_real_max_sectors++;
|
||||
}
|
||||
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO, "func:nwipe_read_dco_real_max_sectors(), DCO real max sectors = %lli", nwipe_real_max_sectors );
|
||||
|
||||
@@ -86,6 +86,19 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
/* initialise characters written */
|
||||
chars_written = 0;
|
||||
|
||||
/* Only log messages with the debug label if the command line --verbose
|
||||
* options has been specified, otherwise just return
|
||||
*/
|
||||
if( level == NWIPE_LOG_DEBUG && nwipe_options.verbose == 0 )
|
||||
{
|
||||
r = pthread_mutex_unlock( &mutex1 );
|
||||
if( r != 0 )
|
||||
{
|
||||
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the date. The rc script uses the same format. */
|
||||
if( level != NWIPE_LOG_NOTIMESTAMP )
|
||||
{
|
||||
@@ -602,16 +615,16 @@ int nwipe_log_sysinfo()
|
||||
if( *( &dmidecode_keywords[keywords_idx][1][0] ) == '0' )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
|
||||
NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
}
|
||||
}
|
||||
/* close */
|
||||
|
||||
@@ -22,17 +22,18 @@
|
||||
#define LOGGING_H_
|
||||
|
||||
/* Maximum size of a log message */
|
||||
#define MAX_LOG_LINE_CHARS 512
|
||||
#define MAX_LOG_LINE_CHARS 1024
|
||||
|
||||
#define MAX_SIZE_OS_STRING 1024 /* Maximum size of acceptable OS string */
|
||||
|
||||
#define MAX_SIZE_OS_STRING 512 /* Maximum size of acceptable OS string */
|
||||
#define OS_info_Line_offset 31 /* OS_info line offset in log */
|
||||
#define OS_info_Line_Length 48 /* OS_info line length */
|
||||
|
||||
typedef enum nwipe_log_t_ {
|
||||
NWIPE_LOG_NONE = 0,
|
||||
NWIPE_LOG_DEBUG, // TODO: Very verbose logging.
|
||||
NWIPE_LOG_INFO, // TODO: Verbose logging.
|
||||
NWIPE_LOG_NOTICE, // Most logging happens at this level.
|
||||
NWIPE_LOG_DEBUG, // Output only when --verbose option used on cmd line.
|
||||
NWIPE_LOG_INFO, // General Info not specifically relevant to the wipe.
|
||||
NWIPE_LOG_NOTICE, // Most logging happens at this level related to wiping.
|
||||
NWIPE_LOG_WARNING, // Things that the user should know about.
|
||||
NWIPE_LOG_ERROR, // Non-fatal errors that result in failure.
|
||||
NWIPE_LOG_FATAL, // Errors that cause the program to exit.
|
||||
|
||||
Reference in New Issue
Block a user