From 0b720b155c020956f7edfa7f3616fe26e309ca9d Mon Sep 17 00:00:00 2001 From: PartialVolume <22084881+PartialVolume@users.noreply.github.com> Date: Mon, 3 Apr 2023 23:11:41 +0100 Subject: [PATCH] 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. --- src/context.h | 5 +- src/create_pdf.c | 101 +++++++++++++++++++++++++------ src/device.c | 4 ++ src/hpa_dco.c | 154 +++++++++++++++++++++++++++++++++++++---------- src/version.c | 4 +- 5 files changed, 217 insertions(+), 51 deletions(-) diff --git a/src/context.h b/src/context.h index 0440e4e..e2275b1 100644 --- a/src/context.h +++ b/src/context.h @@ -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 diff --git a/src/create_pdf.c b/src/create_pdf.c index 8e0cc18..b778843 100644 --- a/src/create_pdf.c +++ b/src/create_pdf.c @@ -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 diff --git a/src/device.c b/src/device.c index 8abfa72..2feb6d9 100644 --- a/src/device.c +++ b/src/device.c @@ -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: diff --git a/src/hpa_dco.c b/src/hpa_dco.c index 2fb7f60..d5fb3dc 100644 --- a/src/hpa_dco.c +++ b/src/hpa_dco.c @@ -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; } diff --git a/src/version.c b/src/version.c index aa99462..dc7cd5c 100644 --- a/src/version.c +++ b/src/version.c @@ -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 \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!";