home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 August / PCWorld_1999-08_cd.bin / dosutils / fips15c / source / check.cpp < prev    next >
C/C++ Source or Header  |  1997-12-20  |  12KB  |  387 lines

  1. /*
  2.     FIPS - the First nondestructive Interactive Partition Splitting program
  3.  
  4.     Module check.cpp
  5.  
  6.     RCS - Header:
  7.     $Header: c:/daten/fips/source/main/RCS/check.cpp 1.4 1995/01/19 00:20:41 schaefer Exp schaefer $
  8.  
  9.     Copyright (C) 1993 Arno Schaefer
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.  
  26.     Report problems and direct all questions to:
  27.  
  28.     schaefer@rbg.informatik.th-darmstadt.de
  29. */
  30.  
  31. #include <stdlib.h>
  32.  
  33. #include "hdstruct.h"
  34. #include "global.h"
  35. #include "fipsspec.h"
  36. #include "input.h"
  37.  
  38.  
  39. /* ----------------------------------------------------------------------- */
  40. /* Consistency check of root sector / partition table                      */
  41. /* ----------------------------------------------------------------------- */
  42.  
  43. void fips_partition_table::correct_physical (const drive_geometry &geometry)
  44. {
  45.     for (int i = 0; i < 4; i++)
  46.     {
  47.         if (partition_info[i].system)
  48.         {
  49.             physical_sector_no start
  50.             (
  51.                 partition_info[i].start_sector_abs,
  52.                 geometry
  53.             );
  54.  
  55.             partition_info[i].start_cylinder = start.cylinder;
  56.             partition_info[i].start_head = start.head;
  57.             partition_info[i].start_sector = start.sector;
  58.             // recalculate 'physical' start sector
  59.  
  60.             physical_sector_no end
  61.             (
  62.                 partition_info[i].start_sector_abs
  63.                 + partition_info[i].no_of_sectors_abs
  64.                 - 1,
  65.                 geometry
  66.             );
  67.  
  68.             partition_info[i].end_cylinder = end.cylinder;
  69.             partition_info[i].end_head = end.head;
  70.             partition_info[i].end_sector = end.sector;
  71.             // recalculate 'physical' end sector
  72.         }
  73.     }
  74. }
  75.  
  76.  
  77. void fips_harddrive::check (boolean final_check)
  78. {
  79.     int i,j,k;
  80.     boolean bootable = false;
  81.     boolean do_correct = false;
  82.  
  83.     byte *root_sector = harddrive::root_sector->data;
  84.     partition_info *parts = partition_table().partition_info;
  85.  
  86.     int order[4] = {-1,-1,-1,-1};
  87.  
  88.     printx ("\nChecking root sector ... ");
  89.  
  90.     if ((root_sector[510] != 0x55) || (root_sector[511] != 0xaa))
  91.         error ("Invalid root sector signature: %02X %02X", root_sector[510], root_sector[511]);
  92.  
  93.     for (i = 0; i < 4; i++)
  94.     {
  95.         if (parts[i].bootable == 0x80)
  96.         {
  97.             if (bootable)
  98.             {
  99.                 warning (false, "More than one active partition");
  100.  
  101.                 printx ("Continue (y/n)? ");
  102.                 if (ask_yes_no () == 'n') exit (-1);
  103.             }
  104.             else bootable = true;
  105.         }
  106.         else if (parts[i].bootable != 0)
  107.         {
  108.             warning (false, "Invalid active flag: partition %u: %02Xh",i+1,parts[i].bootable);
  109.             // must be 0 or 80h
  110.  
  111.             printx ("Do you want to set the flag to zero (y/n)? ");
  112.             if (ask_yes_no () == 'y') parts[i].bootable = 0;
  113.         }
  114.  
  115.         if (parts[i].system)
  116.         {
  117.             if ((parts[i].start_sector == 0) || (parts[i].start_sector > geometry.sectors))
  118.             {
  119.                 if (final_check)
  120.                     error ("Calculation error: Invalid start sector partition %u: %u", i + 1, parts[i].start_sector);
  121.  
  122.                 infomsg ("Partition table inconsistency");
  123.                 do_correct = true;
  124.             }
  125.  
  126.             if ((parts[i].end_sector == 0) || (parts[i].end_sector > geometry.sectors))
  127.             {
  128.                 if (final_check)
  129.                     error ("Calculation error: Invalid end sector partition %u: %u", i + 1, parts[i].end_sector);
  130.  
  131.                 if (!do_correct)
  132.                 {
  133.                     infomsg ("Partition table inconsistency");
  134.                     do_correct = true;
  135.                 }
  136.             }
  137.  
  138.             if
  139.             (
  140.                 (parts[i].start_head > (geometry.heads - 1)) ||
  141.  
  142.                 (parts[i].end_head > (geometry.heads - 1)) ||
  143.  
  144.                 (parts[i].start_sector_abs !=
  145.                 (parts[i].start_cylinder * geometry.heads * geometry.sectors +
  146.                 parts[i].start_head * geometry.sectors + parts[i].start_sector - 1)) ||
  147.                 // physical start sector does not match logical start sector
  148.  
  149.                 ((parts[i].start_sector_abs + parts[i].no_of_sectors_abs - 1) !=
  150.                 (parts[i].end_cylinder * geometry.heads * geometry.sectors +
  151.                 parts[i].end_head * geometry.sectors + parts[i].end_sector - 1))
  152.                 // physical end sector does not match logical end sector
  153.             )
  154.             {
  155.                 if (final_check)
  156.                     error ("Calculation error: Inconsistent table entry for partition %u", i + 1);
  157.  
  158.                 if (!do_correct)
  159.                 {
  160.                     infomsg ("Partition table inconsistency");
  161.                     do_correct = true;
  162.                 }
  163.             }
  164.  
  165.             for (j = 0; j < 4; j++)       // insert partition in ordered table
  166.             {
  167.                 if (order[j] == -1)
  168.                 {
  169.                     order[j] = i;
  170.                     break;
  171.                 }
  172.                 else if (parts[i].start_sector_abs < parts[order[j]].start_sector_abs)
  173.                 {
  174.                     for (k=3;k>j;k--) order[k] = order[k-1];
  175.                     order[j] = i;
  176.                     break;
  177.                 }
  178.             }
  179.         }
  180.         else            // system = 0
  181.         {
  182.             for (j = 0; j < 16; j++)
  183.             {
  184.                 if (root_sector[0x1be + 16 * i + j] != 0)
  185.                 {
  186.                     warning (false, "Invalid partition entry: partition %u", i+1);
  187.                     printx ("Do you want to delete this entry (y/n)? ");
  188.                     if (ask_yes_no () == 'y')
  189.                     {
  190.                         parts[i].bootable = 0;
  191.                         parts[i].start_head = 0;
  192.                         parts[i].start_cylinder = 0;
  193.                         parts[i].start_sector = 0;
  194.                         parts[i].end_head = 0;
  195.                         parts[i].end_cylinder = 0;
  196.                         parts[i].end_sector = 0;
  197.                         parts[i].start_sector_abs = 0;
  198.                         parts[i].no_of_sectors_abs = 0;
  199.                     }
  200.                     break;
  201.                 }
  202.             }
  203.         }
  204.     }
  205.  
  206.     if (do_correct)
  207.     {
  208.         pr_partition_table.correct_physical (geometry);
  209.         printx ("\nPartition table adapted to the current drive geometry:\n\n");
  210.         pr_partition_table.print();
  211.     }
  212.  
  213.     if (!bootable && number == 0x80) warning (true, "No active partition");
  214.  
  215.     for (i = 0; i < 4; i++)
  216.     {
  217.         if ((k = order[i]) != -1)         // valid partition
  218.         {
  219.             if ((parts[k].end_sector != geometry.sectors) || (parts[k].end_head != (geometry.heads - 1)))
  220.                 warning (true, "Partition does not end on cylinder boundary: partition %u", k + 1);
  221.  
  222.             if (i != 0) if ((parts[k].start_sector != 1) || (parts[k].start_head != 0))
  223.                 warning (true, "Partition does not begin on cylinder boundary: partition %u", k + 1);
  224.  
  225.             if (i < 3) if ((j = order[i + 1]) != -1)       // following valid partition
  226.             {
  227.                 if ((parts[k].start_sector_abs + parts[k].no_of_sectors_abs) > parts[j].start_sector_abs)
  228.                     error ("Overlapping partitions: %u and %u", k + 1, j + 1);
  229.  
  230.                 if ((parts[k].start_sector_abs + parts[k].no_of_sectors_abs) < parts[j].start_sector_abs)
  231.                     warning (true, "Free space between partitions: %u and %u", k + 1, j + 1);
  232.             }
  233.         }
  234.     }
  235.  
  236.     printx ("OK\n");
  237. }
  238.  
  239.  
  240. void fips_partition::check (void)
  241. {
  242.     int fat32 = (bpb().sectors_per_fat16 == 0);
  243.  
  244.     printx ("Checking boot sector ... ");
  245.  
  246.     byte *boot_sector = partition::boot_sector->data;
  247.  
  248.     if (boot_sector[0] == 0xeb)
  249.     {
  250.         if (boot_sector[2] != 0x90)
  251.             error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  252.     }
  253.     else if (boot_sector[0] != 0xe9)
  254.         error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  255.  
  256.     if ((boot_sector[510] != 0x55) || (boot_sector[511] != 0xaa))
  257.         error ("Invalid boot sector: %02X %02X", boot_sector[510], boot_sector[511]);
  258.  
  259.     if (bpb().bytes_per_sector != 512)
  260.         error ("Can't handle number of bytes per sector: %u",bpb().bytes_per_sector);
  261.  
  262.     switch (bpb().sectors_per_cluster)
  263.     {
  264.         case 1:case 2:case 4:case 8:case 16:case 32:case 64:case 128: break;
  265.         default:
  266.             error ("Number of sectors per cluster must be a power of 2: actually it is %u",bpb().sectors_per_cluster);
  267.     }
  268.  
  269.     if (!fat32 && bpb().reserved_sectors != 1)
  270.     {
  271.         warning (false, "Number of reserved sectors should be 1: actually it is %u",bpb().reserved_sectors);
  272.         if (ask_correction () == 'y') bpb().reserved_sectors = 1;
  273.     }
  274.  
  275.     if (bpb().no_of_fats != 2)
  276.         error ("Partition must have 2 FATs: actually it has %u",bpb().no_of_fats);
  277.  
  278.     if (bpb().no_of_rootdir_entries % 16)
  279.     {
  280.         warning (false, "Number of root directory entries must be multiple of 16: actually it is %u",bpb().no_of_rootdir_entries);
  281.  
  282.         printx ("Do you want to set the number to the next multiple of 16 (y/n)? ");
  283.         if (ask_yes_no () == 'y')
  284.             bpb().no_of_rootdir_entries += (16 - bpb().no_of_rootdir_entries % 16);
  285.     }
  286.  
  287.     if (!fat32 && bpb().no_of_rootdir_entries == 0)
  288.         error ("Number of root directory entries must not be zero");
  289.  
  290.     if (bpb().media_descriptor != 0xf8)
  291.     {
  292.         warning (false, "Wrong media descriptor byte in boot sector: %02X",bpb().media_descriptor);
  293.         if (ask_correction () == 'y') bpb().media_descriptor = 0xf8;
  294.     }
  295.  
  296.     if (!fat32 && bpb().sectors_per_fat > 256)
  297.     {
  298.         warning (false, "FAT too large: %u sectors",bpb().sectors_per_fat);
  299.  
  300.         printx ("Continue (y/n)? ");
  301.         if (ask_yes_no () == 'n') exit (-1);
  302.     }
  303.  
  304.     if (bpb().sectors_per_fat < (info().no_of_clusters + 1) / 256 + 1)
  305.     {
  306.         warning (false, "FAT too small: %u sectors (should be %u)",bpb().sectors_per_fat, (unsigned int) ((info().no_of_clusters + 1) / 256 + 1));
  307.  
  308.         printx ("Continue (y/n)? ");
  309.         if (ask_yes_no () == 'n') exit (-1);
  310.     }
  311.  
  312.     if (bpb().sectors_per_track != drive->geometry.sectors)
  313.     {
  314.         warning (false, "Sectors per track incorrect: %u instead of %u",bpb().sectors_per_track,(int) drive->geometry.sectors);
  315.         if (ask_correction () == 'y') bpb().sectors_per_track = drive->geometry.sectors;
  316.     }
  317.  
  318.     if (bpb().drive_heads != drive->geometry.heads)
  319.     {
  320.         warning (false, "Number of drive heads incorrect: %u instead of %u",bpb().drive_heads,(int) drive->geometry.heads);
  321.         if (ask_correction () == 'y') bpb().drive_heads = drive->geometry.heads;
  322.     }
  323.  
  324.     if (!fat32 && bpb().hidden_sectors != partition_info->start_sector_abs)
  325.         error ("Number of hidden sectors incorrect: %lu instead of %lu",bpb().hidden_sectors,partition_info->start_sector_abs);
  326.  
  327.     if (info().no_of_clusters <= 4084)
  328.         error ("12-bit FAT not supported: number of clusters is %u",(int) info().no_of_clusters);
  329.  
  330.     if (bpb().no_of_sectors)
  331.     {
  332.         if (partition_info->no_of_sectors_abs > 0xffff)
  333.             error ("Number of sectors (short) must be zero");
  334.  
  335.         if (bpb().no_of_sectors != partition_info->no_of_sectors_abs)
  336.             error ("Number of sectors (short) does not match partition info:\n%u instead of %lu",bpb().no_of_sectors,partition_info->no_of_sectors_abs);
  337.  
  338.         if (partition_info->system != 4)
  339.         {
  340.             warning (true, "Wrong system indicator byte: %u instead of 4",partition_info->system);
  341.             if (ask_correction () == 'y') partition_info->system = 4;
  342.         }
  343.     }
  344.     else
  345.     {
  346.         if (bpb().no_of_sectors_long != partition_info->no_of_sectors_abs)
  347.             error ("Number of sectors (long) does not match partition info:\n%lu instead of %lu",bpb().no_of_sectors_long,partition_info->no_of_sectors_abs);
  348.  
  349.         if (bpb().signature != 0x29)
  350.         {
  351.             warning (false, "Wrong signature: %02Xh",bpb().signature);
  352.             if (ask_correction () == 'y') bpb().signature = 0x29;
  353.         }
  354.  
  355.         if (bpb().sectors_per_fat16 != 0)
  356.         {
  357.             if (partition_info->system != 6)
  358.             {
  359.                 warning (true, "Wrong system indicator byte: %u instead of 6",partition_info->system);
  360.                 if (ask_correction () == 'y') partition_info->system = 6;
  361.             }
  362.         }
  363.         else /* fat32 */
  364.         {
  365.             if (partition_info->system != 0xB && partition_info->system != 0xC)
  366.             {
  367.                 warning (true, "Wrong system indicator byte: %u instead of 0xB or 0xC",partition_info->system);
  368.                 if (ask_correction () == 'y') partition_info->system = 6;
  369.             }
  370.         }
  371.     }
  372.  
  373.     if (fat32)
  374.     {
  375.         byte *fsinfo = partition::fsinfo_sector->data;
  376.         if (fsinfo[0] != 'R' || fsinfo[1] != 'R' ||
  377.             fsinfo[2] != 'a' || fsinfo[3] != 'A' ||
  378.             fsinfo[0x1e4] != 'r' || fsinfo[0x1e5] != 'r' ||
  379.             fsinfo[0x1e6] != 'A' || fsinfo[0x1e7] != 'a')
  380.         {
  381.             error ("Unable to find FAT32 signature on a FAT32 partition");
  382.         }
  383.     }
  384.  
  385.     printx ("OK\n");
  386. }
  387.