home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 8 / IOPROG_8.ISO / install / fips / source / check.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-25  |  11.5 KB  |  362 lines

  1. /*
  2.  
  3.     FIPS - the First nondestructive Interactive Partition Splitting program
  4.  
  5.  
  6.  
  7.     Module check.cpp
  8.  
  9.  
  10.  
  11.     RCS - Header:
  12.  
  13.     $Header: c:/daten/fips/source/main/RCS/check.cpp 1.4 1995/01/19 00:20:41 schaefer Exp schaefer $
  14.  
  15.  
  16.  
  17.     Copyright (C) 1993 Arno Schaefer
  18.  
  19.  
  20.  
  21.     This program is free software; you can redistribute it and/or modify
  22.  
  23.     it under the terms of the GNU General Public License as published by
  24.  
  25.     the Free Software Foundation; either version 2 of the License, or
  26.  
  27.     (at your option) any later version.
  28.  
  29.  
  30.  
  31.     This program is distributed in the hope that it will be useful,
  32.  
  33.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  
  35.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  36.  
  37.     GNU General Public License for more details.
  38.  
  39.  
  40.  
  41.     You should have received a copy of the GNU General Public License
  42.  
  43.     along with this program; if not, write to the Free Software
  44.  
  45.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  46.  
  47.  
  48.  
  49.  
  50.  
  51.     Report problems and direct all questions to:
  52.  
  53.  
  54.  
  55.     schaefer@rbg.informatik.th-darmstadt.de
  56.  
  57. */
  58.  
  59.  
  60.  
  61. #include <stdlib.h>
  62.  
  63.  
  64.  
  65. #include "hdstruct.h"
  66.  
  67. #include "global.h"
  68.  
  69. #include "fipsspec.h"
  70.  
  71. #include "input.h"
  72.  
  73.  
  74.  
  75.  
  76.  
  77. /* ----------------------------------------------------------------------- */
  78.  
  79. /* Consistency check of root sector / partition table                      */
  80.  
  81. /* ----------------------------------------------------------------------- */
  82.  
  83.  
  84.  
  85. void fips_partition_table::correct_physical (const drive_geometry &geometry)
  86.  
  87. {
  88.  
  89.     for (int i = 0; i < 4; i++)
  90.  
  91.     {
  92.  
  93.         if (partition_info[i].system)
  94.  
  95.         {
  96.  
  97.             physical_sector_no start
  98.  
  99.             (
  100.  
  101.                 partition_info[i].start_sector_abs,
  102.  
  103.                 geometry
  104.  
  105.             );
  106.  
  107.  
  108.  
  109.             partition_info[i].start_cylinder = start.cylinder;
  110.  
  111.             partition_info[i].start_head = start.head;
  112.  
  113.             partition_info[i].start_sector = start.sector;
  114.  
  115.             // recalculate 'physical' start sector
  116.  
  117.  
  118.  
  119.             physical_sector_no end
  120.  
  121.             (
  122.  
  123.                 partition_info[i].start_sector_abs
  124.  
  125.                 + partition_info[i].no_of_sectors_abs
  126.  
  127.                 - 1,
  128.  
  129.                 geometry
  130.  
  131.             );
  132.  
  133.  
  134.  
  135.             partition_info[i].end_cylinder = end.cylinder;
  136.  
  137.             partition_info[i].end_head = end.head;
  138.  
  139.             partition_info[i].end_sector = end.sector;
  140.  
  141.             // recalculate 'physical' end sector
  142.  
  143.         }
  144.  
  145.     }
  146.  
  147. }
  148.  
  149.  
  150.  
  151.  
  152.  
  153. void fips_harddrive::check (boolean final_check)
  154.  
  155. {
  156.  
  157.     int i,j,k;
  158.  
  159.     boolean bootable = false;
  160.  
  161.     boolean do_correct = false;
  162.  
  163.  
  164.  
  165.     byte *root_sector = harddrive::root_sector->data;
  166.  
  167.     partition_info *parts = partition_table().partition_info;
  168.  
  169.  
  170.  
  171.     int order[4] = {-1,-1,-1,-1};
  172.  
  173.  
  174.  
  175.     printx ("\nChecking root sector ... ");
  176.  
  177.  
  178.  
  179.     if ((root_sector[510] != 0x55) || (root_sector[511] != 0xaa))
  180.  
  181.         error ("Invalid root sector signature: %02X %02X", root_sector[510], root_sector[511]);
  182.  
  183.  
  184.  
  185.     for (i = 0; i < 4; i++)
  186.  
  187.     {
  188.  
  189.         if (parts[i].bootable == 0x80)
  190.  
  191.         {
  192.  
  193.             if (bootable)
  194.  
  195.             {
  196.  
  197.                 warning (false, "More than one active partition");
  198.  
  199.  
  200.  
  201.                 printx ("Continue (y/n)? ");
  202.  
  203.                 if (ask_yes_no () == 'n') exit (-1);
  204.  
  205.             }
  206.  
  207.             else bootable = true;
  208.  
  209.         }
  210.  
  211.         else if (parts[i].bootable != 0)
  212.  
  213.         {
  214.  
  215.             warning (false, "Invalid active flag: partition %u: %02Xh",i+1,parts[i].bootable);
  216.  
  217.             // must be 0 or 80h
  218.  
  219.  
  220.  
  221.             printx ("Do you want to set the flag to zero (y/n)? ");
  222.  
  223.             if (ask_yes_no () == 'y') parts[i].bootable = 0;
  224.  
  225.         }
  226.  
  227.  
  228.  
  229.         if (parts[i].system)
  230.  
  231.         {
  232.  
  233.             if ((parts[i].start_sector == 0) || (parts[i].start_sector > geometry.sectors))
  234.  
  235.             {
  236.  
  237.                 if (final_check)
  238.  
  239.                     error ("Calculation error: Invalid start sector partition %u: %u", i + 1, parts[i].start_sector);
  240.  
  241.  
  242.  
  243.                 infomsg ("Partition table inconsistency");
  244.  
  245.                 do_correct = true;
  246.  
  247.             }
  248.  
  249.  
  250.  
  251.             if ((parts[i].end_sector == 0) || (parts[i].end_sector > geometry.sectors))
  252.  
  253.             {
  254.  
  255.                 if (final_check)
  256.  
  257.                     error ("Calculation error: Invalid end sector partition %u: %u", i + 1, parts[i].end_sector);
  258.  
  259.  
  260.  
  261.                 if (!do_correct)
  262.  
  263.                 {
  264.  
  265.                     infomsg ("Partition table inconsistency");
  266.  
  267.                     do_correct = true;
  268.  
  269.                 }
  270.  
  271.             }
  272.  
  273.  
  274.  
  275.             if
  276.  
  277.             (
  278.  
  279.                 (parts[i].start_head > (geometry.heads - 1)) ||
  280.  
  281.  
  282.  
  283.                 (parts[i].end_head > (geometry.heads - 1)) ||
  284.  
  285.  
  286.  
  287.                 (parts[i].start_sector_abs !=
  288.  
  289.                 (parts[i].start_cylinder * geometry.heads * geometry.sectors +
  290.  
  291.                 parts[i].start_head * geometry.sectors + parts[i].start_sector - 1)) ||
  292.  
  293.                 // physical start sector does not match logical start sector
  294.  
  295.  
  296.  
  297.                 ((parts[i].start_sector_abs + parts[i].no_of_sectors_abs - 1) !=
  298.  
  299.                 (parts[i].end_cylinder * geometry.heads * geometry.sectors +
  300.  
  301.                 parts[i].end_head * geometry.sectors + parts[i].end_sector - 1))
  302.  
  303.                 // physical end sector does not match logical end sector
  304.  
  305.             )
  306.  
  307.             {
  308.  
  309.                 if (final_check)
  310.  
  311.                     error ("Calculation error: Inconsistent table entry for partition %u", i + 1);
  312.  
  313.  
  314.  
  315.                 if (!do_correct)
  316.  
  317.                 {
  318.  
  319.                     infomsg ("Partition table inconsistency");
  320.  
  321.                     do_correct = true;
  322.  
  323.                 }
  324.  
  325.             }
  326.  
  327.  
  328.  
  329.             for (j = 0; j < 4; j++)       // insert partition in ordered table
  330.  
  331.             {
  332.  
  333.                 if (order[j] == -1)
  334.  
  335.                 {
  336.  
  337.                     order[j] = i;
  338.  
  339.                     break;
  340.  
  341.                 }
  342.  
  343.                 else if (parts[i].start_sector_abs < parts[order[j]].start_sector_abs)
  344.  
  345.                 {
  346.  
  347.                     for (k=3;k>j;k--) order[k] = order[k-1];
  348.  
  349.                     order[j] = i;
  350.  
  351.                     break;
  352.  
  353.                 }
  354.  
  355.             }
  356.  
  357.         }
  358.  
  359.         else            // system = 0
  360.  
  361.         {
  362.  
  363.             for (j = 0; j < 16; j++)
  364.  
  365.             {
  366.  
  367.                 if (root_sector[0x1be + 16 * i + j] != 0)
  368.  
  369.                 {
  370.  
  371.                     warning (false, "Invalid partition entry: partition %u", i+1);
  372.  
  373.                     printx ("Do you want to delete this entry (y/n)? ");
  374.  
  375.                     if (ask_yes_no () == 'y')
  376.  
  377.                     {
  378.  
  379.                         parts[i].bootable = 0;
  380.  
  381.                         parts[i].start_head = 0;
  382.  
  383.                         parts[i].start_cylinder = 0;
  384.  
  385.                         parts[i].start_sector = 0;
  386.  
  387.                         parts[i].end_head = 0;
  388.  
  389.                         parts[i].end_cylinder = 0;
  390.  
  391.                         parts[i].end_sector = 0;
  392.  
  393.                         parts[i].start_sector_abs = 0;
  394.  
  395.                         parts[i].no_of_sectors_abs = 0;
  396.  
  397.                     }
  398.  
  399.                     break;
  400.  
  401.                 }
  402.  
  403.             }
  404.  
  405.         }
  406.  
  407.     }
  408.  
  409.  
  410.  
  411.     if (do_correct)
  412.  
  413.     {
  414.  
  415.         pr_partition_table.correct_physical (geometry);
  416.  
  417.         printx ("\nPartition table adapted to the current drive geometry:\n\n");
  418.  
  419.         pr_partition_table.print();
  420.  
  421.     }
  422.  
  423.  
  424.  
  425.     if (!bootable && number == 0x80) warning (true, "No active partition");
  426.  
  427.  
  428.  
  429.     for (i = 0; i < 4; i++)
  430.  
  431.     {
  432.  
  433.         if ((k = order[i]) != -1)         // valid partition
  434.  
  435.         {
  436.  
  437.             if ((parts[k].end_sector != geometry.sectors) || (parts[k].end_head != (geometry.heads - 1)))
  438.  
  439.                 warning (true, "Partition does not end on cylinder boundary: partition %u", k + 1);
  440.  
  441.  
  442.  
  443.             if (i != 0) if ((parts[k].start_sector != 1) || (parts[k].start_head != 0))
  444.  
  445.                 warning (true, "Partition does not begin on cylinder boundary: partition %u", k + 1);
  446.  
  447.  
  448.  
  449.             if (i < 3) if ((j = order[i + 1]) != -1)       // following valid partition
  450.  
  451.             {
  452.  
  453.                 if ((parts[k].start_sector_abs + parts[k].no_of_sectors_abs) > parts[j].start_sector_abs)
  454.  
  455.                     error ("Overlapping partitions: %u and %u", k + 1, j + 1);
  456.  
  457.  
  458.  
  459.                 if ((parts[k].start_sector_abs + parts[k].no_of_sectors_abs) < parts[j].start_sector_abs)
  460.  
  461.                     warning (true, "Free space between partitions: %u and %u", k + 1, j + 1);
  462.  
  463.             }
  464.  
  465.         }
  466.  
  467.     }
  468.  
  469.  
  470.  
  471.     printx ("OK\n");
  472.  
  473. }
  474.  
  475.  
  476.  
  477.  
  478.  
  479. void fips_partition::check (void)
  480.  
  481. {
  482.  
  483.     printx ("Checking boot sector ... ");
  484.  
  485.  
  486.  
  487.     byte *boot_sector = partition::boot_sector->data;
  488.  
  489.  
  490.  
  491.     if (boot_sector[0] == 0xeb)
  492.  
  493.     {
  494.  
  495.         if (boot_sector[2] != 0x90)
  496.  
  497.             error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  498.  
  499.     }
  500.  
  501.     else if (boot_sector[0] != 0xe9)
  502.  
  503.         error ("Invalid jump instruction in boot sector: %02X %02X %02X", boot_sector[0], boot_sector[1], boot_sector[2]);
  504.  
  505.  
  506.  
  507.     if ((boot_sector[510] != 0x55) || (boot_sector[511] != 0xaa))
  508.  
  509.         error ("Invalid boot sector: %02X %02X", boot_sector[510], boot_sector[511]);
  510.  
  511.  
  512.  
  513.     if (bpb().bytes_per_sector != 512)
  514.  
  515.         error ("Can't handle number of bytes per sector: %u",bpb().bytes_per_sector);
  516.  
  517.  
  518.  
  519.     switch (bpb().sectors_per_cluster)
  520.  
  521.     {
  522.  
  523.         case 1:case 2:case 4:case 8:case 16:case 32:case 64:case 128: break;
  524.  
  525.         default:
  526.  
  527.             error ("Number of sectors per cluster must be a power of 2: actually it is %u",bpb().sectors_per_cluster);
  528.  
  529.     }
  530.  
  531.  
  532.  
  533.     if (bpb().reserved_sectors != 1)
  534.  
  535.     {
  536.  
  537.         warning (false, "Number of reserved sectors should be 1: actually it is %u",bpb().reserved_sectors);
  538.  
  539.         if (ask_correction () == 'y') bpb().reserved_sectors = 1;
  540.  
  541.     }
  542.  
  543.  
  544.  
  545.     if (bpb().no_of_fats != 2)
  546.  
  547.         error ("Partition must have 2 FATs: actually it has %u",bpb().no_of_fats);
  548.  
  549.  
  550.  
  551.     if (bpb().no_of_rootdir_entries % 16)
  552.  
  553.     {
  554.  
  555.         warning (false, "Number of root directory entries must be multiple of 16: actually it is %u",bpb().no_of_rootdir_entries);
  556.  
  557.  
  558.  
  559.         printx ("Do you want to set the number to the next multiple of 16 (y/n)? ");
  560.  
  561.         if (ask_yes_no () == 'y')
  562.  
  563.             bpb().no_of_rootdir_entries += (16 - bpb().no_of_rootdir_entries % 16);
  564.  
  565.     }
  566.  
  567.  
  568.  
  569.     if (bpb().no_of_rootdir_entries == 0)
  570.  
  571.         error ("Number of root directory entries must not be zero");
  572.  
  573.  
  574.  
  575.     if (bpb().media_descriptor != 0xf8)
  576.  
  577.     {
  578.  
  579.         warning (false, "Wrong media descriptor byte in boot sector: %02X",bpb().media_descriptor);
  580.  
  581.         if (ask_correction () == 'y') bpb().media_descriptor = 0xf8;
  582.  
  583.     }
  584.  
  585.  
  586.  
  587.     if (bpb().sectors_per_fat > 256)
  588.  
  589.     {
  590.  
  591.         warning (false, "FAT too large: %u sectors",bpb().sectors_per_fat);
  592.  
  593.  
  594.  
  595.         printx ("Continue (y/n)? ");
  596.  
  597.         if (ask_yes_no () == 'n') exit (-1);
  598.  
  599.     }
  600.  
  601.  
  602.  
  603.     if (bpb().sectors_per_fat < (info().no_of_clusters + 1) / 256 + 1)
  604.  
  605.     {
  606.  
  607.         warning (false, "FAT too small: %u sectors (should be %u)",bpb().sectors_per_fat, (unsigned int) ((info().no_of_clusters + 1) / 256 + 1));
  608.  
  609.  
  610.  
  611.         printx ("Continue (y/n)? ");
  612.  
  613.         if (ask_yes_no () == 'n') exit (-1);
  614.  
  615.     }
  616.  
  617.  
  618.  
  619.     if (bpb().sectors_per_track != drive->geometry.sectors)
  620.  
  621.     {
  622.  
  623.         warning (false, "Sectors per track incorrect: %u instead of %u",bpb().sectors_per_track,(int) drive->geometry.sectors);
  624.  
  625.         if (ask_correction () == 'y') bpb().sectors_per_track = drive->geometry.sectors;
  626.  
  627.     }
  628.  
  629.  
  630.  
  631.     if (bpb().drive_heads != drive->geometry.heads)
  632.  
  633.     {
  634.  
  635.         warning (false, "Number of drive heads incorrect: %u instead of %u",bpb().drive_heads,(int) drive->geometry.heads);
  636.  
  637.         if (ask_correction () == 'y') bpb().drive_heads = drive->geometry.heads;
  638.  
  639.     }
  640.  
  641.  
  642.  
  643.     if (bpb().hidden_sectors != partition_info->start_sector_abs)
  644.  
  645.         error ("Number of hidden sectors incorrect: %lu instead of %lu",bpb().hidden_sectors,partition_info->start_sector_abs);
  646.  
  647.  
  648.  
  649.     if (info().no_of_clusters <= 4084)
  650.  
  651.         error ("12-bit FAT not supported: number of clusters is %u",(int) info().no_of_clusters);
  652.  
  653.  
  654.  
  655.     if (bpb().no_of_sectors)
  656.  
  657.     {
  658.  
  659.         if (partition_info->no_of_sectors_abs > 0xffff)
  660.  
  661.             error ("Number of sectors (short) must be zero");
  662.  
  663.  
  664.  
  665.         if (bpb().no_of_sectors != partition_info->no_of_sectors_abs)
  666.  
  667.             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);
  668.  
  669.  
  670.  
  671.         if (partition_info->system != 4)
  672.  
  673.         {
  674.  
  675.             warning (true, "Wrong system indicator byte: %u instead of 4",partition_info->system);
  676.  
  677.             if (ask_correction () == 'y') partition_info->system = 4;
  678.  
  679.         }
  680.  
  681.     }
  682.  
  683.     else
  684.  
  685.     {
  686.  
  687.         if (bpb().no_of_sectors_long != partition_info->no_of_sectors_abs)
  688.  
  689.             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);
  690.  
  691.  
  692.  
  693.         if (bpb().signature != 0x29)
  694.  
  695.         {
  696.  
  697.             warning (false, "Wrong signature: %02Xh",bpb().signature);
  698.  
  699.             if (ask_correction () == 'y') bpb().signature = 0x29;
  700.  
  701.         }
  702.  
  703.  
  704.  
  705.         if (partition_info->system != 6)
  706.  
  707.         {
  708.  
  709.             warning (true, "Wrong system indicator byte: %u instead of 6",partition_info->system);
  710.  
  711.             if (ask_correction () == 'y') partition_info->system = 6;
  712.  
  713.         }
  714.  
  715.     }
  716.  
  717.  
  718.  
  719.     printx ("OK\n");
  720.  
  721. }
  722.  
  723.