home *** CD-ROM | disk | FTP | other *** search
/ James Briskly's Game Magazine 2 / JBGM002S.ZIP / SOURCE / CHECK.CPP < prev    next >
C/C++ Source or Header  |  1995-08-22  |  11KB  |  362 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.     printx ("Checking boot sector ... ");
  243.  
  244.     byte *boot_sector = partition::boot_sector->data;
  245.  
  246.     if (boot_sector[0] == 0xeb)
  247.     {
  248.         if (boot_sector[2] != 0x90)
  249.             error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  250.     }
  251.     else if (boot_sector[0] != 0xe9)
  252.         error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  253.  
  254.     if ((boot_sector[510] != 0x55) || (boot_sector[511] != 0xaa))
  255.         error ("Invalid boot sector: %02X %02X", boot_sector[510], boot_sector[511]);
  256.  
  257.     if (bpb().bytes_per_sector != 512)
  258.         error ("Can't handle number of bytes per sector: %u",bpb().bytes_per_sector);
  259.  
  260.     switch (bpb().sectors_per_cluster)
  261.     {
  262.         case 1:case 2:case 4:case 8:case 16:case 32:case 64:case 128: break;
  263.         default:
  264.             error ("Number of sectors per cluster must be a power of 2: actually it is %u",bpb().sectors_per_cluster);
  265.     }
  266.  
  267.     if (bpb().reserved_sectors != 1)
  268.     {
  269.         warning (false, "Number of reserved sectors should be 1: actually it is %u",bpb().reserved_sectors);
  270.         if (ask_correction () == 'y') bpb().reserved_sectors = 1;
  271.     }
  272.  
  273.     if (bpb().no_of_fats != 2)
  274.         error ("Partition must have 2 FATs: actually it has %u",bpb().no_of_fats);
  275.  
  276.     if (bpb().no_of_rootdir_entries % 16)
  277.     {
  278.         warning (false, "Number of root directory entries must be multiple of 16: actually it is %u",bpb().no_of_rootdir_entries);
  279.  
  280.         printx ("Do you want to set the number to the next multiple of 16 (y/n)? ");
  281.         if (ask_yes_no () == 'y')
  282.             bpb().no_of_rootdir_entries += (16 - bpb().no_of_rootdir_entries % 16);
  283.     }
  284.  
  285.     if (bpb().no_of_rootdir_entries == 0)
  286.         error ("Number of root directory entries must not be zero");
  287.  
  288.     if (bpb().media_descriptor != 0xf8)
  289.     {
  290.         warning (false, "Wrong media descriptor byte in boot sector: %02X",bpb().media_descriptor);
  291.         if (ask_correction () == 'y') bpb().media_descriptor = 0xf8;
  292.     }
  293.  
  294.     if (bpb().sectors_per_fat > 256)
  295.     {
  296.         warning (false, "FAT too large: %u sectors",bpb().sectors_per_fat);
  297.  
  298.         printx ("Continue (y/n)? ");
  299.         if (ask_yes_no () == 'n') exit (-1);
  300.     }
  301.  
  302.     if (bpb().sectors_per_fat < (info().no_of_clusters + 1) / 256 + 1)
  303.     {
  304.         warning (false, "FAT too small: %u sectors (should be %u)",bpb().sectors_per_fat, (unsigned int) ((info().no_of_clusters + 1) / 256 + 1));
  305.  
  306.         printx ("Continue (y/n)? ");
  307.         if (ask_yes_no () == 'n') exit (-1);
  308.     }
  309.  
  310.     if (bpb().sectors_per_track != drive->geometry.sectors)
  311.     {
  312.         warning (false, "Sectors per track incorrect: %u instead of %u",bpb().sectors_per_track,(int) drive->geometry.sectors);
  313.         if (ask_correction () == 'y') bpb().sectors_per_track = drive->geometry.sectors;
  314.     }
  315.  
  316.     if (bpb().drive_heads != drive->geometry.heads)
  317.     {
  318.         warning (false, "Number of drive heads incorrect: %u instead of %u",bpb().drive_heads,(int) drive->geometry.heads);
  319.         if (ask_correction () == 'y') bpb().drive_heads = drive->geometry.heads;
  320.     }
  321.  
  322.     if (bpb().hidden_sectors != partition_info->start_sector_abs)
  323.         error ("Number of hidden sectors incorrect: %lu instead of %lu",bpb().hidden_sectors,partition_info->start_sector_abs);
  324.  
  325.     if (info().no_of_clusters <= 4084)
  326.         error ("12-bit FAT not supported: number of clusters is %u",(int) info().no_of_clusters);
  327.  
  328.     if (bpb().no_of_sectors)
  329.     {
  330.         if (partition_info->no_of_sectors_abs > 0xffff)
  331.             error ("Number of sectors (short) must be zero");
  332.  
  333.         if (bpb().no_of_sectors != partition_info->no_of_sectors_abs)
  334.             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);
  335.  
  336.         if (partition_info->system != 4)
  337.         {
  338.             warning (true, "Wrong system indicator byte: %u instead of 4",partition_info->system);
  339.             if (ask_correction () == 'y') partition_info->system = 4;
  340.         }
  341.     }
  342.     else
  343.     {
  344.         if (bpb().no_of_sectors_long != partition_info->no_of_sectors_abs)
  345.             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);
  346.  
  347.         if (bpb().signature != 0x29)
  348.         {
  349.             warning (false, "Wrong signature: %02Xh",bpb().signature);
  350.             if (ask_correction () == 'y') bpb().signature = 0x29;
  351.         }
  352.  
  353.         if (partition_info->system != 6)
  354.         {
  355.             warning (true, "Wrong system indicator byte: %u instead of 6",partition_info->system);
  356.             if (ask_correction () == 'y') partition_info->system = 6;
  357.         }
  358.     }
  359.  
  360.     printx ("OK\n");
  361. }
  362.