HPA_DCO_008 continuation of HPA/DCO integration.

Many changes related to DCO real max sectors and HPA set and real
sectors and how they are processed and used in the PDF creation
function. More testing is required until I'm happy this works
correctly with lots of different hardware including USB adapters
that don't support DCO/HPA and also drives that don't support
DCO/HPA such as the Seagate Enterprise EXOS drives.
This commit is contained in:
PartialVolume
2023-04-03 23:11:41 +01:00
parent 4fc1806880
commit 0b720b155c
5 changed files with 217 additions and 51 deletions

View File

@@ -164,9 +164,12 @@ typedef struct nwipe_context_t_
int DCO_status; // 0 = No DCO found, 1 = DCO detected, 2 = Unknown, unable to checked
u64 DCO_reported_real_max_sectors; // real max sectors as reported by hdparm --dco-identify
u64 DCO_reported_real_max_size; // real max sectors in bytes
u64 Calculated_real_max_size_in_bytes; // This value is determined from all the possible variations for drives that
// don't support DCO/HPA and those that do. Also drives that can't provide
// HPA/DCO due to the chips they use (USB adapters)
char DCO_reported_real_max_size_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // real max size in human readable form i.e 1TB
// etc
u64 HPA_size; // The size of the host protected area in sectors
u64 HPA_sectors; // The size of the host protected area in sectors
char HPA_size_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // Human readable size bytes, KB, MB, GB ..
int HPA_display_toggle_state; // 0 or 1 Used to toggle between "[1TB] [ 33C]" and [HDA STATUS]
time_t HPA_toggle_time; // records a time, then if for instance 3 seconds has elapsed the display changes

View File

@@ -188,8 +188,8 @@ int create_pdf( nwipe_context_t* ptr )
pdf_add_text( pdf, NULL, "Size(Apparent): ", 12, 60, 390, PDF_GRAY );
pdf_set_font( pdf, "Helvetica-Bold" );
snprintf( device_size, sizeof( device_size ), "%s, %lli bytes", c->device_size_text, c->device_size );
if( c->device_size == c->DCO_reported_real_max_size || !strcmp( c->device_type_str, "NVME" )
|| !strcmp( c->device_type_str, "VIRT" ) )
if( ( c->device_size == c->DCO_reported_real_max_size ) || c->device_type == NWIPE_DEVICE_NVME
|| c->device_type == NWIPE_DEVICE_VIRT || c->HPA_status == HPA_NOT_APPLICABLE )
{
pdf_add_text( pdf, NULL, device_size, text_size_data, 145, 390, PDF_DARK_GREEN );
}
@@ -202,7 +202,7 @@ int create_pdf( nwipe_context_t* ptr )
/* Size (Real) */
pdf_add_text( pdf, NULL, "Size(Real):", 12, 60, 370, PDF_GRAY );
pdf_set_font( pdf, "Helvetica-Bold" );
if( !strcmp( c->device_type_str, "NVME" ) || !strcmp( c->device_type_str, "VIRT" )
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|| c->HPA_status == HPA_NOT_APPLICABLE )
{
snprintf( device_size, sizeof( device_size ), "%s, %lli bytes", c->device_size_text, c->device_size );
@@ -231,6 +231,26 @@ int create_pdf( nwipe_context_t* ptr )
snprintf( device_size, sizeof( device_size ), "Unknown" );
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_RED );
}
else
{
/* we are already here because c->DCO_reported_real_max_size < 1 so if HPA enabled then use the
* value we determine from whether HPA set, HPA real exist and if not assume libata's value*/
if( c->HPA_status == HPA_ENABLED )
{
snprintf( device_size,
sizeof( device_size ),
"%s, %lli bytes",
c->device_size_text,
c->Calculated_real_max_size_in_bytes );
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_DARK_GREEN );
}
else
{
/* Sanity check, should never get here! */
snprintf( device_size, sizeof( device_size ), "Sanity: HPA_status = %i", c->HPA_status );
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_RED );
}
}
}
}
@@ -285,8 +305,8 @@ int create_pdf( nwipe_context_t* ptr )
pdf_set_font( pdf, "Helvetica-Bold" );
if( !strcmp( c->wipe_status_txt, "ERASED" )
&& ( c->HPA_status == HPA_DISABLED || !strcmp( c->device_type_str, "NVME" )
|| !strcmp( c->device_type_str, "VIRT" ) ) )
&& ( c->HPA_status == HPA_DISABLED || c->HPA_status == HPA_NOT_APPLICABLE || c->device_type == NWIPE_DEVICE_NVME
|| c->device_type == NWIPE_DEVICE_VIRT ) )
{
pdf_add_text( pdf, NULL, c->wipe_status_txt, 12, 365, 290, PDF_DARK_GREEN );
pdf_add_ellipse( pdf, NULL, 390, 295, 45, 10, 2, PDF_DARK_GREEN, PDF_TRANSPARENT );
@@ -327,7 +347,7 @@ int create_pdf( nwipe_context_t* ptr )
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_redcross_jpg, 60331 );
status_icon = STATUS_ICON_RED_CROSS; // used later on page 2
}
pdf_add_ellipse( pdf, NULL, 390, 275, 45, 10, 2, PDF_RED, PDF_TRANSPARENT );
pdf_add_ellipse( pdf, NULL, 390, 295, 45, 10, 2, PDF_RED, PDF_TRANSPARENT );
}
}
pdf_set_font( pdf, "Helvetica" );
@@ -430,6 +450,43 @@ int create_pdf( nwipe_context_t* ptr )
}
else
{
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|| c->HPA_status == HPA_NOT_APPLICABLE )
{
snprintf( bytes_erased,
sizeof( bytes_erased ),
"%lli, (%.1f%%)",
c->bytes_erased,
(float) ( (float) c->bytes_erased / (float) ( (float) c->device_size ) ) * 100 );
if( c->bytes_erased == c->device_size )
{
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_DARK_GREEN );
}
else
{
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_RED );
}
}
else
{
snprintf( bytes_erased,
sizeof( bytes_erased ),
"%lli, %lli, (%.1f%%)",
c->bytes_erased,
c->Calculated_real_max_size_in_bytes,
(double) ( (double) c->bytes_erased / (double) ( (double) c->Calculated_real_max_size_in_bytes ) )
* 100 );
if( c->bytes_erased == c->Calculated_real_max_size_in_bytes )
{
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_DARK_GREEN );
}
else
{
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_RED );
}
}
#if 0
/* Use real max sectors taken from DCO if not zero */
if( c->DCO_reported_real_max_sectors != 0 )
{
@@ -438,9 +495,9 @@ int create_pdf( nwipe_context_t* ptr )
sizeof( bytes_erased ),
"%lli (%.1f%%)",
c->bytes_erased,
(double) ( (double) c->bytes_erased / (double) ( (double) c->DCO_reported_real_max_sectors * 512 ) )
(double) ( (double) c->bytes_erased / (double) ( (double) c->DCO_reported_real_max_sectors * c->device_sector_size ) )
* 100 );
if( c->bytes_erased == ( c->DCO_reported_real_max_sectors * 512 ) )
if( c->bytes_erased == ( c->DCO_reported_real_max_sectors * c->device_sector_size ) )
{
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_DARK_GREEN );
}
@@ -467,6 +524,7 @@ int create_pdf( nwipe_context_t* ptr )
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_RED );
}
}
#endif
}
pdf_set_font( pdf, "Helvetica" );
@@ -499,40 +557,49 @@ int create_pdf( nwipe_context_t* ptr )
/*******************
* Populate HPA size
*/
pdf_set_font( pdf, "Helvetica-Bold" );
if( c->HPA_status == HPA_ENABLED )
{
snprintf( HPA_size_text, sizeof( HPA_size_text ), "%lli sectors", c->HPA_size );
snprintf( HPA_size_text, sizeof( HPA_size_text ), "%lli sectors", c->HPA_sectors );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_RED );
}
else
{
if( c->HPA_status == HPA_DISABLED )
{
snprintf( HPA_size_text, sizeof( HPA_size_text ), "Zero sectors" );
snprintf( HPA_size_text, sizeof( HPA_size_text ), "No hidden sectors" );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_DARK_GREEN );
}
else
{
if( c->HPA_status == HPA_UNKNOWN )
if( c->HPA_status == HPA_NOT_APPLICABLE )
{
snprintf( HPA_size_text, sizeof( HPA_size_text ), "UNKNOWN" );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_RED );
snprintf( HPA_size_text, sizeof( HPA_size_text ), "Not Applicable" );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_DARK_GREEN );
}
else
{
if( c->HPA_status == HPA_UNKNOWN )
{
snprintf( HPA_size_text, sizeof( HPA_size_text ), "UNKNOWN" );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_RED );
}
}
}
}
pdf_set_font( pdf, "Helvetica" );
/*********************
* Populate HPA status (and size if not applicable, NVMe and VIRT)
*/
if( !strcmp( c->device_type_str, "NVME" ) || !strcmp( c->device_type_str, "VIRT" ) )
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|| c->HPA_status == HPA_NOT_APPLICABLE )
{
snprintf( HPA_status_text, sizeof( HPA_status_text ), "Not applicable to %s", c->device_type_str );
snprintf( HPA_status_text, sizeof( HPA_status_text ), "Not applicable" );
pdf_set_font( pdf, "Helvetica-Bold" );
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_DARK_GREEN );
snprintf( HPA_size_text, sizeof( HPA_size_text ), "Not applicable to %s", c->device_type_str );
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 400, 210, PDF_DARK_GREEN );
pdf_set_font( pdf, "Helvetica" );
}
else

View File

@@ -219,6 +219,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
}
next_device->device_size = dev->length * dev->sector_size;
next_device->device_sector_size = dev->sector_size;
Determine_C_B_nomenclature( next_device->device_size, next_device->device_size_txt, NWIPE_DEVICE_SIZE_TXT_LENGTH );
next_device->device_size_text = next_device->device_size_txt;
next_device->result = -2;
@@ -294,6 +295,9 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
*/
check_HPA = 0;
// WARNING TEMP LINE WARNING
// next_device->device_type = NWIPE_DEVICE_ATA;
switch( next_device->device_type )
{
case NWIPE_DEVICE_UNKNOWN:

View File

@@ -462,7 +462,27 @@ int hpa_dco_status( nwipe_context_t* ptr )
* HPA_ENABLED, HPA_UNKNOWN or HPA_NOT_APPLICABLE. The HPA flag
* will be displayed in the GUI and on the certificate and is
* used to determine whether to reset the HPA.
*
*/
/* WARNING temp assignments WARNING
* s=28,r=28,rm=0
*
*/
#if 0
c->HPA_reported_set = 10;
c->HPA_reported_real = 28;
c->DCO_reported_real_max_sectors = 0;
c->HPA_reported_set = 28;
c->HPA_reported_real = 28;
c->DCO_reported_real_max_sectors = 0;
c->HPA_reported_set = 1000;
c->HPA_reported_real = 2048;
c->DCO_reported_real_max_sectors = 2048;
#endif
/* If all three values match and none are zero then there is NO hidden disc area. HPA is disabled. */
if( c->HPA_reported_set == c->HPA_reported_real && c->DCO_reported_real_max_sectors == c->HPA_reported_set
&& c->HPA_reported_set != 0 && c->HPA_reported_real != 0 && c->DCO_reported_real_max_sectors != 0 )
@@ -472,39 +492,47 @@ int hpa_dco_status( nwipe_context_t* ptr )
else
{
/* If HPA set and DCO max sectors are equal it can also be considered that HPA is disabled */
if( ( c->HPA_reported_set == c->DCO_reported_real_max_sectors ) && c->HPA_reported_set != 0 )
if( ( c->HPA_reported_set == c->DCO_reported_real_max_sectors ) && c->HPA_reported_set != 0
&& c->DCO_reported_real_max_sectors != 0 )
{
c->HPA_status = HPA_DISABLED;
}
else
{
if( c->HPA_reported_set != c->DCO_reported_real_max_sectors && c->HPA_reported_set != 0 )
if( c->HPA_reported_set == c->HPA_reported_real && c->DCO_reported_real_max_sectors == 0 )
{
c->HPA_status = HPA_ENABLED;
c->HPA_status = HPA_NOT_APPLICABLE;
}
else
{
/* 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 )
if( c->HPA_reported_set != c->DCO_reported_real_max_sectors && c->HPA_reported_set != 0 )
{
c->HPA_status = HPA_UNKNOWN;
c->HPA_status = HPA_ENABLED;
}
else
{
/* NVMe drives don't support HPA/DCO */
if( !strcmp( c->device_type_str, "NVME" )
|| ( c->HPA_reported_set > 1 && c->DCO_reported_real_max_sectors < 2 ) )
/* 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
{
/* For recent enterprise and new drives that don't provide HPA/DCO anymore */
if( c->HPA_reported_set > 0 && c->HPA_reported_real == 1
&& c->DCO_reported_real_max_sectors < 2 )
/* NVMe drives don't support HPA/DCO */
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|| ( c->HPA_reported_set > 1 && c->DCO_reported_real_max_sectors < 2 ) )
{
c->HPA_status = HPA_NOT_APPLICABLE;
}
else
{
/* For recent enterprise and new drives that don't provide HPA/DCO anymore */
if( c->HPA_reported_set > 0 && c->HPA_reported_real == 1
&& c->DCO_reported_real_max_sectors < 2 )
{
c->HPA_status = HPA_NOT_APPLICABLE;
}
}
}
}
}
@@ -548,31 +576,95 @@ int hpa_dco_status( nwipe_context_t* ptr )
}
}
/* Determine the size of the HPA if it's enabled and store the results in the context.*/
if( c->HPA_status == HPA_ENABLED )
{
c->HPA_size = c->DCO_reported_real_max_sectors - c->HPA_reported_set;
/* Convert the size to a human readable format and save in context */
Determine_C_B_nomenclature( c->HPA_size, c->HPA_size_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
}
else
{
/* HPA not enabled so initialise these values */
c->HPA_size = 0;
c->HPA_size_text[0] = 0;
}
/* create two variables for later use based on real max sectors
* DCO_reported_real_max_size = real max sectors * 512 = bytes
/* -------------------------------------------------------------------
* create two variables for later use based on real max sectors
* DCO_reported_real_max_size = real max sectors * sector size = bytes
* DCO_reported_real_max_size_text = human readable string, i.e 1TB etc.
*/
c->DCO_reported_real_max_size = c->DCO_reported_real_max_sectors * 512;
c->DCO_reported_real_max_size = c->DCO_reported_real_max_sectors * c->device_sector_size;
Determine_C_B_nomenclature(
c->DCO_reported_real_max_size, c->DCO_reported_real_max_size_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
nwipe_dco_real_max_sectors = nwipe_read_dco_real_max_sectors( c->device_name );
/* Analyse all the variations to produce the final real max bytes which takes into
* account drives that don't support DCO or HPA. This result is used in the PDF
* creation functions.
*/
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|| c->HPA_status == HPA_NOT_APPLICABLE )
{
c->Calculated_real_max_size_in_bytes = c->device_size;
}
else
{
/* If the DCO is reporting a real max sectors > 1 then that is what we will use as the real disc size
*/
if( c->DCO_reported_real_max_size > 1 )
{
c->Calculated_real_max_size_in_bytes = c->DCO_reported_real_max_sectors * c->device_sector_size;
}
else
{
/* If HPA is enabled and DCO real max sectors did not exist, then we have to assume - c->HPA_reported_real
* is the value we need, however if that is zero, then c->HPA_reported_set and if that is zero then
* c->device_size as reported by libata
*/
if( c->HPA_reported_real > 0 )
{
c->Calculated_real_max_size_in_bytes = c->HPA_reported_real * c->device_sector_size;
}
else
{
if( c->HPA_reported_set > 0 )
{
c->Calculated_real_max_size_in_bytes = c->HPA_reported_set * c->device_sector_size;
}
else
{
c->Calculated_real_max_size_in_bytes = c->device_size;
}
}
}
}
/* ----------------------------------------------------------------------------------
* Determine the size of the HPA if it's enabled and store the results in the context
*/
if( c->HPA_status == HPA_ENABLED )
{
if( c->Calculated_real_max_size_in_bytes != c->device_size )
{
c->HPA_sectors =
( (u64) ( c->Calculated_real_max_size_in_bytes - c->device_size ) / c->device_sector_size );
}
else
{
c->HPA_sectors = 0;
}
/* Convert the size to a human readable format and save in context */
Determine_C_B_nomenclature( c->HPA_sectors, c->HPA_size_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
}
else
{
/* HPA not enabled so initialise these values */
c->HPA_sectors = 0;
c->HPA_size_text[0] = 0;
}
nwipe_log( NWIPE_LOG_INFO,
"c->Calculated_real_max_size_in_bytes=%lli, c->device_size=%lli, c->device_sector_size=%lli, "
"c->DCO_reported_real_max_size=%lli, c->HPA_sectors=%lli c->device_type=%i ",
c->Calculated_real_max_size_in_bytes,
c->device_size,
c->device_sector_size,
c->DCO_reported_real_max_size,
c->HPA_sectors,
c->device_type );
return set_return_value;
}

View File

@@ -4,7 +4,7 @@
* used by configure to dynamically assign those values
* to documentation files.
*/
const char* version_string = "0.34.81 Development code, not for production use!";
const char* version_string = "0.34.82 Development code, not for production use!";
const char* program_name = "nwipe";
const char* author_name = "Martijn van Brummelen";
const char* email_address = "git@brumit.nl";
@@ -14,4 +14,4 @@ Modifications to original dwipe Copyright Andy Beverley <andy@andybev.com>\n\
This is free software; see the source for copying conditions.\n\
There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\
FOR A PARTICULAR PURPOSE.\n";
const char* banner = "nwipe 0.34.81 Development code, not for production use!";
const char* banner = "nwipe 0.34.82 Development code, not for production use!";