home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9101 / utils / boots / boot.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-10-10  |  29.5 KB  |  922 lines

  1. (*========================================================*)
  2. (*                 BOOT.PAS  (Version 2.00b)              *)
  3. (*        Copyright (C) 1991 J. Braun & DMV-Verlag        *)
  4. (*                Compiler:  Turbo Pascal 6.0             *)
  5. (*========================================================*)
  6.  
  7. {.$DEFINE debug}            (* Debugging-Informationen an *)
  8. {$A+,B-,E-,F-,I+,N-,O-,V-,X-,G-,M 9216,0,0}   (* Standard *)
  9. {$IFDEF debug} {$D+,L+,S+,R+} {$ELSE} {$D-,L-,S-,R-}{$ENDIF}
  10.  
  11. PROGRAM BootSwitch;
  12.  
  13. USES
  14.   Dos,
  15.   Absolute,
  16.   DOSCountry,
  17.   Reboot;
  18.  
  19. TYPE
  20.   Str255    = STRING[255];
  21.   tError    = (NoSystem,         NoBootSave,
  22.                WrongParam,       NoDir,
  23.                NoConfig,         NoAutoexec,
  24.                ConfigNotWritten, AutoexecNotWritten,
  25.                NoHardDrive,      UserBreak,
  26.                NoPartSave,       NotInstalled);
  27.   tXtens    = (SYS, BAT);                (* Systemdateien *)
  28.   tYesNo    = (Y, N);
  29.  
  30. CONST
  31.   ErrStr: ARRAY[tError] OF STRING[51] =
  32.    ('Kein oder unbekanntes Betriebssystem auf der Platte',
  33.     'Bootsektor-Sicherungsdatei fehlt',
  34.     'Falscher oder unbekannter Kommandozeilenparameter',
  35.     'Das Verzeichnis mit den Sicherungsdateien fehlt',
  36.     'CONFIG.SYS fehlt',
  37.     'AUTOEXEC.BAT fehlt',
  38.     'CONFIG.SYS kann nicht geschrieben werden',
  39.     'Ich kann die neue AUTOEXEC.BAT nicht schreiben',
  40.     'Ich habe kein Plattenlaufwerk C gefunden',
  41.     'Boot durch Benutzer beendet',
  42.     'Partitions-Sicherungsdatei fehlt',
  43.     'System ist nicht auf der Platte');
  44.  
  45.   OnlyFile    : BYTE    = AnyFile - VolumeID - Directory;
  46.  
  47.   internalFlag: BOOLEAN = FALSE; (* selbes Syst. laden?   *)
  48.   drdos56Flag : BOOLEAN = FALSE; (* DR-DOS 5/6?           *)
  49.   dopartFlag  : BOOLEAN = FALSE; (* Part-Tab. schreiben   *)
  50.   germanFlag  : BOOLEAN = FALSE; (* Msg. deutsch/englisch *)
  51.  
  52.   IoError    : ARRAY[1..2]   OF BOOLEAN    = (FALSE, FALSE);
  53.   StdExt     : ARRAY[tXtens] OF STRING[ 3] = ('SYS', 'BAT');
  54.   StartFiles : ARRAY[tXtens] OF STRING[10] = ('\CONFIG.',
  55.                                               '\AUTOEXEC.');
  56.   YesNo     : ARRAY[tYesNo] OF CHAR       = ('J', 'N');
  57.  
  58.   AbortMsg  : STRING[26] = 'Programm wird abgebrochen!';
  59.   BootDriv  : STRING[ 2] = 'C:';          (* Bootlaufwerk *)
  60.  
  61.   OldSysType: tSystems   = none;          (* akt. System  *)
  62.   NewSysType: tSystems   = none;          (* neues System *)
  63.  
  64.   Copyright : STRING[48] = 'BootSwitch v2.00b, (C) 1991 ' +
  65.                            'DMV-Verlag, Eschwege';
  66.  
  67.   BS        = CHR( 8);    (* Backspace               (^H) *)
  68.   TAB       = CHR( 9);    (* Tabulatorzeichen        (^I) *)
  69.   LF        = CHR(10);    (* LineFeed                (^J) *)
  70.   CR        = CHR(13);    (* Carridge Return = Enter (^M) *)
  71.   CRLF      = CR + LF;    (* DOS-Zeilenumbruch     (^M^J) *)
  72.  
  73. VAR
  74.   OrgDir    : PathStr;   (* Start-Verzeichnis beim Aufruf *)
  75.   CheckPart : ComStr;    (* Partitions-Tabelle schreiben? *)
  76.  
  77.   (* die diversen Puffer für die Platteninformationen:    *)
  78.   BootSectorBuffer: tSectBuffer;     (* Bootsektor        *)
  79.   PartSectorBuffer: tSectBuffer;     (* Partionstabelle   *)
  80.  
  81.   YesOrNo         : CHAR;     (* für Benutzereingaben     *)
  82.   CommLine        : ComStr;   (* Bearb. der Kommandozeile *)
  83.   i               : BYTE;     (* Zählervariable           *)
  84.  
  85. FUNCTION CheckOldSystem: tSystems;
  86. (*         Überprüfung, welches System aktiv ist          *)
  87. VAR
  88.   w         : WORD;
  89.   j, s      : tSystems;
  90.   BufString : Str255;
  91. BEGIN
  92.   BufString := '';
  93.   j         := none;
  94.  
  95.   ReadBootSector(C, BootSectorBuffer);
  96.  
  97.   FOR w := 20 TO MaxBufSize DO
  98.     IF Chr(BootSectorBuffer[w]) IN
  99.       ['A' .. 'Z', 'a' .. 'z', '2', '$'] THEN
  100.       BufString := BufString + CHR(BootSectorBuffer[w]);
  101.  
  102.   FOR s := IBM TO SysCount DO
  103.     IF Pos(SysIDs[s], BufString) > 0 THEN j := s;
  104.  
  105.   IF (j = IBM) AND ((Pos('Laden', BufString) > 0) OR
  106.      (Pos('Loading', BufString) > 0)) THEN
  107.        drdos56Flag := TRUE;
  108.     (* Die Meldung gibt's bei PC-DOS nicht, also: DR-DOS  *)
  109.  
  110.   CheckOldSystem := j;
  111. END;
  112.  
  113. FUNCTION Ask (Message: Str255) : CHAR;
  114. (* Umwandlung des ReadLn-Strings in ein CHAR.             *)
  115. (* Anstelle des 'J' kann auch 'Y' eingegeben werden.      *)
  116. VAR
  117.   s : STRING[1];
  118.   c : CHAR;
  119. BEGIN
  120.   REPEAT
  121.     c := Chr(0);
  122.     Write(Message);
  123.     ReadLn(s);
  124.     IF s <> '' THEN BEGIN
  125.       IF (Pos('Y', s) > 0) OR (Pos('y', s) > 0) OR
  126.          (Pos('J', s) > 0) OR (Pos('j', s) > 0) THEN
  127.         c := YesNo[Y]
  128.       ELSE IF (Pos('N', s) > 0) OR (Pos('n', s) > 0) THEN
  129.         c := YesNo[N];
  130.     END;
  131.   UNTIL c IN [YesNo[Y], YesNo[N]];
  132.   Ask := c;
  133. END;
  134.  
  135. PROCEDURE HelpInfo;
  136. (*        Hilfeanzeige bei Parametern /?  und /H          *)
  137. VAR
  138.   i : tSystems;
  139. BEGIN
  140.   IF germanFlag THEN
  141.     WriteLn(CRLF + 'Aufruf mit:')
  142.   ELSE BEGIN
  143.     WriteLn(CRLF + 'Parameters:');
  144.     ParamMsg[MSDOS][3] := ' '; ParamMsg[DRS][3]   := ' ';
  145.     ParamMsg[MOS][3]   := ' '; ParamMsg[PLS][4]   := ' ';
  146.     ParamMsg[IBM]      := 'PC DOS and DR DOS 5.0';
  147.   END;
  148.  
  149.   FOR i := IBM TO SysCount DO BEGIN
  150.     Write(TAB + 'BOOT /' + Systems[i] + ' f');
  151.     IF germanFlag THEN Write('ü') ELSE Write('o');
  152.     Write('r ' + ParamMsg[i]);
  153.     IF i = OS2 THEN Write('/1.21/1.3');
  154.     WriteLn;
  155.   END;
  156.  
  157.   WriteLn;
  158.  
  159.   IF germanFlag THEN BEGIN
  160.     WriteLn(TAB + 'BOOT /H | /?  dieser Hilfebildschirm');
  161.     WriteLn(TAB + 'BOOT          '
  162.           + 'aktuelle Systeminformationen.');
  163.     WriteLn(TAB + '              '
  164.           + 'Das Präfix ''/'' ist optional.' + LF);
  165.     WriteLn('Die Bootsektor-Dateien sowie die AUTOEXEC.XXX '
  166.           + 'und CONFIG.XXX müssen mit der');
  167.     WriteLn('entsprechenden Dateiendung im Verzeichnis '
  168.           + SysDir + ' sein.');
  169.     WriteLn('Verwenden Sie hierzu das Programm »PREP«.'+LF);
  170.     WriteLn('Wird als zweiter Parameter /P angegeben, '
  171.           + 'wird die Partitionstabelle');
  172.     WriteLn('ebenfalls gesichert und (falls vorhanden) '
  173.           + 'geschrieben.');
  174.  
  175.   END ELSE BEGIN
  176.  
  177.     WriteLn(TAB + 'BOOT /H | /?  this help screen');
  178.     WriteLn(TAB + 'BOOT          system informations');
  179.     WriteLn(TAB + '              '
  180.           + 'the prefix ''/'' is optional.' + LF);
  181.     WriteLn('The files with the '
  182.           + 'stored bootsectors plus AUTOEXEC.XXX');
  183.     WriteLn('and CONFIG.XXX must'
  184.           + ' be in the Directory '+ SysDir + '.');
  185.     WriteLn('The files need to '
  186.           + 'have the correct file extension.');
  187.     WriteLn('This extension must'
  188.           + ' be the same as the commandline');
  189.     WriteLn('parameter for the specified system.' + LF);
  190.     WriteLn('For the correct installation of the systems '
  191.           + 'use »PREP«' + LF);
  192.     WriteLn('To save and write (if the file exists) the '
  193.           + 'partition');
  194.     WriteLn('table, use /p as second command line '
  195.           + 'parameter.');
  196.   END;
  197. END;
  198.  
  199. PROCEDURE Error(Message: tError);
  200. (*                Fehlermeldung, Abbruch                  *)
  201. BEGIN
  202.   ChDir(OrgDir);
  203.   IF Message = UserBreak THEN BEGIN
  204.     WriteLn(ErrStr[Message] + '!');
  205.   END ELSE IF Message = WrongParam THEN BEGIN
  206.     IF germanFlag THEN Write('Fehler: ')
  207.                   ELSE Write('Error: ');
  208.     Write(ErrStr[Message] + '!'+ LF);
  209.     HelpInfo;
  210.   END ELSE BEGIN
  211.     Write(CRLF + 'fatal');
  212.     IF germanFlag THEN Write('er Fehler Nr. ')
  213.                 ELSE Write(' Error No. ');
  214.     Write(BYTE(Message));
  215.     Write(': '+ ErrStr[Message]+'!' + CRLF + AbortMsg + LF);
  216.   END;
  217.   Halt(1)
  218. END;
  219.  
  220.  
  221. FUNCTION FileExistFunc(FileName: PathStr;
  222.                            Attr: BYTE): BOOLEAN;
  223. (*     Gibt's die Datei/das Verzeichnis 'FileName ?'      *)
  224. VAR
  225.   sr: SearchRec;
  226. BEGIN
  227.   FileExistFunc := FALSE;
  228.   sr.Name := '';
  229.   FindFirst(FileName, Attr, sr);
  230.   IF (Pos(FileName, sr.Name) > 0) AND
  231.      (Length(sr.Name) > 0) THEN BEGIN
  232.     FileExistFunc := TRUE;
  233.     Exit;
  234.   END;
  235.   IF (Pos(sr.Name, FileName) > 0) AND
  236.      (Length(sr.Name) > 0) THEN
  237.     FileExistFunc := TRUE;
  238. END;
  239.  
  240. PROCEDURE ChangeDir;
  241. (*   Überprüfen, ob das Sicherungsverzeichnis vorhanden   *)
  242. (*   ist. Im Bedarfsfalle das Verzeichnis auch anlegen.   *)
  243. BEGIN
  244. {$I-}
  245.   IF NOT FileExistFunc(SysDir, Directory) THEN
  246.     MkDir(SysDir);
  247.   ChDir(SysDir);
  248.   IF IOResult <> 0 THEN Error(NoDir); (* Es klappt nicht *)
  249. {$I+}
  250. END;
  251.  
  252. PROCEDURE BootInfo;
  253. (* Informationen zu den Bootsystemen, falls BOOT ohne     *)
  254. (* Kommandozeilen-Parameter aufgerufen wird.              *)
  255. VAR
  256.   i, j : tSystems;
  257. BEGIN
  258.   ChDir(SysDir);
  259.  
  260.   IF IOResult = 0 THEN BEGIN
  261.     IF germanFlag THEN
  262.       WriteLn('Folgende Betriebssysteme sind im '
  263.             + 'Bootswitcher installiert:')
  264.     ELSE
  265.       WriteLn('The following operating systems '
  266.             + 'are installed:');
  267.     WriteLn;
  268.  
  269.     FOR i := IBM TO SysCount DO BEGIN
  270.       IF FileExistFunc(BootFile +
  271.                        Systems[i], OnlyFile) THEN BEGIN
  272.         Write(' ': 5, Names[i]);
  273.  
  274.         IF i = IBM THEN BEGIN
  275.           IF germanFlag THEN Write(' oder DR-DOS 5/6')
  276.                     ELSE Write(' or DR DOS 5/6');
  277.         END;
  278.  
  279.         IF i = DRS THEN Write(' 3.41' + TAB)
  280.                    ELSE Write(TAB + TAB);
  281.  
  282.         IF i <> IBM THEN BEGIN
  283.           IF (Length(Names[i]) < 16) THEN Write(TAB);
  284.           IF (Length(Names[i]) < 11) THEN Write(TAB);
  285.         END;
  286.  
  287.         IF germanFlag THEN Write('Systemdateien ')
  288.                   ELSE Write('System files ');
  289.  
  290.         IF NOT FileExistFunc(BootDriv + '\' +
  291.                SysIDNames[i], OnlyFile) THEN
  292.           WriteLn(SysIDNames[i] + ParamMsg[none])
  293.         ELSE BEGIN
  294.           IF germanFlag THEN WriteLn('vorhanden.')
  295.                     ELSE WriteLn('found.');
  296.         END;
  297.  
  298.       END;
  299.     END;
  300.  
  301.     IF NOT FileExistFunc(BootFile + Systems[OS1],
  302.                           OnlyFile) THEN BEGIN
  303.       IF FileExistFunc(BootDriv + '\' + SysIDNames[OS1],
  304.                           OnlyFile) THEN BEGIN
  305.         IF germanFlag THEN
  306.           WriteLn(' ':5, 'OS2 1.1 nicht im Bootswitcher '
  307.                        + 'aber auf der Platte vorhanden!')
  308.         ELSE
  309.           WriteLn(' ':5, 'OS2 1.1 not in the bootswitch '
  310.                  + 'system but on the harddisk available!');
  311.       END;
  312.     END;
  313.  
  314.     (* wird dieses Bootsystem oder BOOT.COM von OS/2      *)
  315.     (* benutzt?                                           *)
  316.     IF NOT FileExistFunc(BootFile + Systems[OS2],
  317.                           OnlyFile) THEN BEGIN
  318.       IF FileExistFunc(BootDriv + '\' +
  319.                SysIDNames[OS2], OnlyFile) THEN BEGIN
  320.         IF germanFlag THEN
  321.           WriteLn(' ':5, 'OS2 1.2/1.3 nicht im Bootswitcher'
  322.                 + ' aber auf der Platte vorhanden!')
  323.         ELSE
  324.           WriteLn(' ':5, 'OS2 1.2/1.3 not in the bootswitch'
  325.                 + ' system but on the harddisk available!');
  326.       END;
  327.     END;
  328.  
  329.     WriteLn;
  330.  
  331.   END ELSE BEGIN
  332.     IF germanFlag THEN Write('Verzeichnis ') (* Fehler *)
  333.               ELSE Write('Directory ');
  334.     WriteLn(SysDir + ParamMsg[none]);
  335.   END;
  336.  
  337.   i := OldSysType;
  338.  
  339.   IF (i = IBM) AND (drdos56Flag = TRUE) THEN BEGIN
  340.     Names[i] := 'DR-DOS 5/6';
  341.     IF germanFlag THEN BEGIN
  342.       Write('Der aktuelle Bootsektor auf der Festplatte'
  343.           + ' lädt ' + Names[i] + '.');
  344.       IF drdos56Flag THEN
  345.         Write(CR+LF+'Die Bootsektor-Kennung ist "PC-DOS".')
  346.     END ELSE BEGIN
  347.       Write('The actual bootsector on the hard '+
  348.            'disk belongs to '+ Names[i] + '.');
  349.       IF drdos56Flag THEN
  350.         Write(CR + LF + 'The bootsector ID is "PC DOS".')
  351.     END;
  352.   END ELSE WriteLn;
  353. END;
  354.  
  355. FUNCTION CheckParams(Get: Str255): tSystems;
  356. (*             Überprüfung der Kommandozeile              *)
  357. VAR
  358.   i: tSystems;
  359.   j: BYTE;
  360. BEGIN
  361.   FOR i := IBM TO SysCount DO BEGIN
  362.     j := Pos(Systems[i], Get);
  363.     IF j > 0 THEN BEGIN
  364.       CheckParams := i;
  365.       Exit;
  366.     END;
  367.   END;
  368.   Error(WrongParam)
  369. END;
  370.  
  371. PROCEDURE PrepareDisk(FileType: tSystems);
  372. (* Schreiben des Bootsektors und der CONFIG.SYS/AUTOEXEC- *)
  373. (* .BAT-Dateien                                           *)
  374.  
  375.   PROCEDURE pReCopy(FType: tXtens);
  376.   VAR
  377.     f1, f2    : TEXT;
  378.     Line      : Str255;
  379.     SaveName,
  380.     StartName : PathStr;
  381.     i         : BYTE;
  382.   BEGIN
  383.     IF germanFlag THEN Write('Schreibe ')
  384.                   ELSE Write('Writing ');
  385.     FOR i := 2 TO Length(StartFiles[FType]) DO
  386.       Write(StartFiles[FType][i]);
  387.     WriteLn(StdExt[FType] + ' ...');
  388.     StartName := Concat(BootDriv, StartFiles[FType],
  389.                          StdExt[FType]);
  390.     Assign(f1, StartName);
  391.     IF FileExistFunc(StartName, OnlyFile) THEN
  392.       SetFAttr(f1, Archive);
  393.     {$I-}
  394.     ReWrite(f1);
  395.     {$I+}
  396.     IF IOResult <> 0 THEN BEGIN
  397.       IF FType = SYS THEN Error(NoConfig);
  398.       IF FType = BAT THEN Error(NoAutoexec);
  399.     END;
  400.     SaveName := Concat(SysDir, StartFiles[FType],
  401.                         Systems[FileType]);
  402.     Assign(f2, SaveName);
  403.     IF FileExistFunc(SaveName, OnlyFile) THEN
  404.        SetFAttr(f2, Archive);
  405.     {$I-}
  406.     Reset(f2);
  407.     {$I+}
  408.     IF IOResult <> 0 THEN BEGIN
  409.       IF FType = SYS THEN Error(ConfigNotWritten);
  410.       IF FType = BAT THEN Error(AutoexecNotWritten);
  411.     END;
  412.     Line := '';
  413.     WHILE NOT EoF(f2) DO BEGIN
  414.       ReadLn(f2, Line);
  415.       IF Line <> '' THEN WriteLn(f1, Line);
  416.     END;
  417.     Close(f1);
  418.     Close(f2);
  419.   END;
  420.  
  421.   PROCEDURE BootSecFile;
  422.   TYPE
  423.     tBootBlock = RECORD (* Aufbau des Bootblocks bei DOS: *)
  424.                    Jump       : ARRAY[01.. 03] OF BYTE;
  425.                    OEM        : ARRAY[01.. 08] OF CHAR;
  426.                    DiskData   : Absolute.tBPB;
  427.                    DiskLabel  : ARRAY[01.. 11] OF CHAR;
  428.                    FATTypeText: ARRAY[01.. 08] OF CHAR;
  429.                    DosLoader  : ARRAY[00..351] OF BYTE;
  430.                    Messages   : ARRAY[00.. 64] OF CHAR;
  431.                    FileLoader : ARRAY[00.. 30] OF CHAR;
  432.                    EndMarker  : ARRAY[00.. 01] OF CHAR;
  433.                  END;
  434.   VAR
  435.     TempSectorBuffer: tSectBuffer;   (* temporärer Puffer *)
  436.     ABBlock         : tBootBlock ABSOLUTE TempSectorBuffer;
  437.     SBBlock         : tBootBlock ABSOLUTE BootSectorBuffer;
  438.     f               : FILE OF BYTE;
  439.     i               : WORD;
  440.     vName           : PathStr;
  441.     YesOrNo         : CHAR;
  442.   BEGIN
  443.     vName := SysDir + '\' + BootFile + Systems[FileType];
  444.     Assign(f, vName);
  445.     IF FileExistFunc(vName, OnlyFile) THEN
  446.       SetFAttr(f, Archive);
  447.     {$I-}
  448.     Reset(f);
  449.     {$I+}
  450.     IF IOResult <> 0 THEN Error(NoBootSave);
  451.  
  452.     FOR i := 0 TO MaxBufSize DO
  453.       Read(f, BootSectorBuffer[i]);
  454.     Close(f);
  455.     SetFAttr(f, Archive + Hidden);
  456.  
  457.     ReadBootSector(C, TempSectorBuffer);
  458.  
  459.     IF (SBBlock.DiskData.SectorsPerTrack <>
  460.         ABBlock.DiskData.SectorsPerTrack)
  461.     OR (SBBlock.DiskData.Heads <>
  462.         ABBlock.DiskData.Heads)
  463.     OR (SBBlock.DiskData.ReservedSectors <>
  464.         ABBlock.DiskData.ReservedSectors) THEN BEGIN
  465.  
  466.       IF germanFlag THEN BEGIN
  467.         WriteLn('Aktuelle Plattenparameter unterscheiden ' +
  468.                 'sich von den gesicherten!');
  469.         WriteLn('Gesicherte Werte:');
  470.         WITH SBBlock DO BEGIN
  471.           Write(  'Köpfe: ', DiskData.Heads,
  472.                   ' Sektoren gesamt: ');
  473.           IF DiskData.TotalSectors <> 0 THEN
  474.             Write(DiskData.TotalSectors)
  475.           ELSE
  476.             Write(DiskData.BigTotalSectors);
  477.           WriteLn(' Sektoren/Spur: ',
  478.                   DiskData.SectorsPerTrack,
  479.                   ' reserv. Sekt.: ',
  480.                   DiskData.ReservedSectors);
  481.         END;
  482.         WriteLn('Aktuelle Werte:');
  483.         WITH ABBlock DO BEGIN
  484.           Write('Köpfe: ', DiskData.Heads,
  485.                 ' Sektoren gesamt: ');
  486.           IF DiskData.TotalSectors <> 0 THEN
  487.             Write(DiskData.TotalSectors)
  488.           ELSE
  489.             Write(DiskData.BigTotalSectors);
  490.           WriteLn(' Sektoren/Spur: ',
  491.                   DiskData.SectorsPerTrack,
  492.                   ' reserv. Sekt.: ',
  493.                   DiskData.ReservedSectors);
  494.         END;
  495.         YesOrNo := Ask('Soll der Bootsektor wirklich ' +
  496.                        'überschrieben werden? (J/N) ')
  497.       END ELSE BEGIN
  498.         WriteLn('Actual disk parameters differ from the ' +
  499.                  'stored!');
  500.         WriteLn('Stored parameters:');
  501.         WITH SBBlock DO BEGIN
  502.           Write('heads: ', DiskData.Heads,
  503.                 ' total sectors: ');
  504.           IF DiskData.TotalSectors <> 0 THEN
  505.             Write(DiskData.TotalSectors)
  506.           ELSE
  507.             Write(DiskData.BigTotalSectors);
  508.           WriteLn(' sectors/track: ',
  509.                   DiskData.SectorsPerTrack,
  510.                   ' reserv. sect.: ',
  511.                   DiskData.ReservedSectors);
  512.         END;
  513.         WriteLn('Actual parameters:');
  514.         WITH ABBlock DO BEGIN
  515.           Write('heads: ', DiskData.heads,
  516.                 ' total sectors: ');
  517.           IF DiskData.TotalSectors <> 0 THEN
  518.             Write(DiskData.TotalSectors)
  519.           ELSE
  520.             Write(DiskData.BigTotalSectors);
  521.           WriteLn(' sectors/track: ',
  522.                   DiskData.SectorsPerTrack,
  523.                   ' reserv. sect.: ',
  524.                   DiskData.ReservedSectors);
  525.         END;
  526.         YesOrNo := Ask('Shall I overwrite the ' +
  527.                        'bootsector? (Y/N) ');
  528.       END;
  529.  
  530.       IF YesOrNo = 'N' THEN BEGIN
  531.         IF germanFlag THEN
  532.            WriteLn('Bootswitch wurde abgebrochen !')
  533.          ELSE
  534.            WriteLn('Bootswitch aborted !');
  535.         Halt(1);
  536.       END ELSE BEGIN
  537.         IF germanFlag THEN
  538.           WriteLn('Weiter auf eigene Gefahr ...')
  539.         ELSE
  540.           WriteLn('Continued on your own risk ...');
  541.         FOR i := 0 TO MaxInt DO ;        (* Warteschleife *)
  542.       END;
  543.     END;
  544.  
  545.     IF germanFlag THEN
  546.       Write('Schreibe Bootsektor ...')
  547.     ELSE
  548.       Write('Updating bootsector information ...');
  549.  
  550.     WITH SBBlock.DiskData DO BEGIN
  551.     (* Der reservierte Bereichs weicht bei den ver-       *)
  552.     (* schiedenen Betriebssystemversionen voneinander ab. *)
  553.     (* Dies sieht zwar wüst aus, kann aber die Daten der  *)
  554.     (* Festplatte im Zweifelsfalle retten !               *)
  555.     (* DR-DOS benutzt den Bereich der BigTotalSectors     *)
  556.     (* ebenfalls anders als MS-DOS. Er darf deshalb nicht *)
  557.     (* umkopiert bzw. übertragen werden.                  *)
  558.      BytesPerSector   := ABBlock.DiskData.BytesPerSector;
  559.      SectorsPerCluster:= ABBlock.DiskData.SectorsPerCluster;
  560.      ReservedSectors  := ABBlock.DiskData.ReservedSectors;
  561.      NumberOfFATs     := ABBlock.DiskData.NumberOfFATs;
  562.      RootEntries      := ABBlock.DiskData.RootEntries;
  563.      TotalSectors     := ABBlock.DiskData.TotalSectors;
  564.      MediaDescriptor  := ABBlock.DiskData.MediaDescriptor;
  565.      SectorsPerFAT    := ABBlock.DiskData.SectorsPerFAT;
  566.      SectorsPerTrack  := ABBlock.DiskData.SectorsPerTrack;
  567.      Heads            := ABBlock.DiskData.Heads;
  568.      HiddenSectors    := ABBlock.DiskData.HiddenSectors;
  569.     END;
  570.     WriteBootSector(C, BootSectorBuffer);
  571.     WriteLn;
  572.   END;
  573.  
  574.   PROCEDURE PartTableFile;
  575.   VAR
  576.      f    : FILE OF BYTE;
  577.      i    : WORD;
  578.      fName: PathStr;
  579.   BEGIN
  580.    (* Während der Bootsektor unbedingt geschrieben werden *)
  581.    (* muß, ist es bei der Partitionstabelle nicht unbe-   *)
  582.    (* dingt erforderlich - außer wenn zwischenzeitlich in *)
  583.    (* der Partitionstabelle ein Virus verankert wurde (z. *)
  584.    (* B. Stoned) oder ein Bootswitch für den Systemstart  *)
  585.    (* z.B. Coherent-Unix) installiert wurde.              *)
  586.     fName := Concat(SysDir, '\', PartFile,
  587.              Systems[FileType]);
  588.     IF FileExistFunc(fName, OnlyFile) THEN BEGIN
  589.       Assign(f, fName);
  590.       SetFAttr(f, Archive);
  591.       {$I-}
  592.       Reset(f);
  593.       {$I+}
  594.       IF IOResult = 0 THEN BEGIN
  595.         FOR i := 0 TO MaxBufSize DO
  596.           Read(f, PartSectorBuffer[i]);
  597.         Close(f);
  598.         SetFAttr(f, Archive + Hidden);
  599.         IF germanFlag THEN
  600.           WriteLn('Schreibe Partitionstabelle ...')
  601.         ELSE
  602.           WriteLn('Writing partition table...');
  603.         WritePartition(C, PartSectorBuffer);
  604.       END;
  605.     END;
  606.   END;
  607.  
  608. BEGIN
  609.   {$I-}
  610.   ChDir(BootDriv + '\');
  611.   IF IOResult <> 0 THEN Error(NoHardDrive);
  612.   {$I+}
  613.   ChangeDir;
  614.   WriteLn;
  615.   pReCopy(SYS);
  616.   pReCopy(BAT);
  617.  
  618.   IF NOT internalFlag THEN BEGIN
  619.     BootSecFile;
  620.     IF dopartFlag THEN PartTableFile;
  621.   END
  622.  
  623. END;
  624.  
  625. PROCEDURE SaveOldSystem;
  626. (* Sichern des alten Zustandes. CONFIG.SYS und AUTOEXEC.- *)
  627. (* BAT werden mit der richtigen Endung ins \SYSTEM-Ver-   *)
  628. (* zeichnis kopiert, der Bootsektor wird ebenfalls ge-    *)
  629. (* sichert.                                               *)
  630. VAR
  631.   BootFileName,
  632.   PartFileName,
  633.   FileName,
  634.   Name         : PathStr;
  635.   f1, f2       : FILE OF BYTE;
  636.   i, Attr      : WORD;
  637.   FileExists   : BOOLEAN;
  638.   FTime        : LONGINT;
  639.  
  640.   PROCEDURE CopyCfgFile(FType: tXtens);
  641.   VAR
  642.    txt1, txt2 : Text;
  643.    Line       : Str255;
  644.    Name       : PathStr;
  645.   BEGIN
  646.     Name := Concat(BootDriv, StartFiles[FType],
  647.                    StdExt[FType]);
  648.     Assign(txt1, Name);
  649.     {$I-}
  650.     Reset(txt1);
  651.     {$I+}
  652.     IoError[1] := IOResult <> 0;
  653.  
  654.     IF NOT IoError[1] THEN BEGIN
  655.       GetFTime(txt1, FTime);
  656.       Close(txt1);
  657.       GetFAttr(txt1, Attr);
  658.       SetFAttr(txt1, Archive);
  659.       {$I-}
  660.       Reset(txt1);
  661.       {$I+}
  662.       FileName := Concat(SysDir, StartFiles[FType],
  663.                          Systems[OldSysType]);
  664.       Assign(txt2, FileName);
  665.       IF FileExistFunc(FileName, OnlyFile) THEN
  666.          SetFAttr(txt2, Archive);
  667.       {$I-}
  668.       ReWrite(txt2);
  669.       {$I+}
  670.       WHILE NOT EoF(txt1) DO BEGIN
  671.         Line := '';
  672.         ReadLn(txt1, Line);
  673.         IF Line <> '' THEN WriteLn(txt2, Line);
  674.       END;
  675.       Close(txt1);
  676.       Close(txt2);
  677.       SetFAttr(txt1, Attr);
  678.       SetFAttr(txt2, Archive + ReadOnly);
  679.       SetFTime(txt2, FTime);
  680.     END;
  681.   END;
  682.  
  683. BEGIN
  684.   IF germanFlag THEN Write('Sichere ')
  685.                 ELSE Write('Saving ');
  686.   WriteLn(Names[OldSysType] + ':');
  687.  
  688.   IF OldSysType > none THEN BEGIN
  689.     ChangeDir;
  690.     IF NOT internalFlag THEN BEGIN
  691.       BootFileName := Concat(BootFile, Systems[OldSysType]);
  692.       Assign(f1, BootFileName);
  693.       IF FileExistFunc(BootFileName, OnlyFile) THEN
  694.         SetFAttr(f1, Archive);
  695.       {$I-}
  696.       Reset(f1);
  697.       {$I+}
  698.       IF IOResult <> 0 THEN BEGIN      (* dann eben nicht *)
  699.         Write(BootFileName);
  700.         IF germanFlag THEN
  701.           WriteLn(' kann nicht geschrieben werden!')
  702.         ELSE
  703.           WriteLn(': access denied!');
  704.         WriteLn(AbortMsg);
  705.         Halt;
  706.       END ELSE BEGIN
  707.         FOR i := 0 TO MaxBufSize DO
  708.           Write(f1, BootSectorBuffer[i]);
  709.         Close(f1);
  710.         SetFAttr(f1, Archive + Hidden);
  711.         IF germanFlag THEN
  712.           WriteLn('Die Datei ' + BootFileName +
  713.                   ' wurde gesichert.')
  714.         ELSE
  715.           WriteLn('The file ' + BootFileName +
  716.                   ' is backed up.');
  717.       END;
  718.     END;
  719.  
  720.     IF dopartFlag THEN BEGIN
  721.       IF NOT internalFlag THEN BEGIN
  722.         ReadPartition(C, PartSectorBuffer);
  723.         PartFileName := Concat(PartFile,
  724.                                Systems[OldSysType]);
  725.         Assign(f2, PartFileName);
  726.         IF FileExistFunc(PartFileName, OnlyFile) THEN
  727.           SetFAttr(f2, Archive);
  728.         {$I-}
  729.         Reset(f2);
  730.         {$I+}
  731.         IF IOResult <> 0 THEN BEGIN    (* dann eben nicht *)
  732.           IF germanFlag THEN
  733.             WriteLn(PartFileName +
  734.                     ' kann nicht geschrieben werden!')
  735.           ELSE
  736.             WriteLn(PartFileName + ': access denied!');
  737.           FOR i := 0 TO MaxBufSize DO
  738.             Write(f2, PartSectorBuffer[i]);
  739.           Close(f2);
  740.           SetFAttr(f2, Archive + Hidden);
  741.           IF germanFlag THEN
  742.             WriteLn('Die Datei ' + PartFileName +
  743.                     ' wurde gesichert.')
  744.           ELSE
  745.             WriteLn('The file ' + PartFileName +
  746.                     ' is backed up.');
  747.         END;
  748.       END;
  749.     END;
  750.  
  751.     CopyCfgFile(BAT);
  752.     CopyCfgFile(SYS);
  753.  
  754.     IF NOT IoError[1] THEN BEGIN
  755.       FOR i := 2 TO Length(StartFiles[SYS]) DO
  756.         Write(StartFiles[SYS][i]);
  757.       Write(Systems[OldSysType]);
  758.     END;
  759.  
  760.     IF NOT (IoError[1] AND IoError[2]) THEN BEGIN
  761.       IF germanFlag THEN Write(' und ') ELSE Write(' and ');
  762.     END;
  763.  
  764.     IF NOT IoError[2] THEN BEGIN
  765.       FOR i := 2 TO Length(StartFiles[BAT]) DO
  766.         Write(StartFiles[BAT][i]);
  767.       Write(Systems[OldSysType] + ' ');
  768.     END;
  769.  
  770.     IF NOT (IoError[1] OR IoError[2]) THEN BEGIN
  771.       IF germanFlag THEN Write('wurde') ELSE Write('was');
  772.     END;
  773.  
  774.     IF NOT (IoError[1] AND IoError[2]) THEN BEGIN
  775.       IF germanFlag THEN Write('n')
  776.                     ELSE Write(BS + BS + 'ere');
  777.     END;
  778.  
  779.     IF NOT (IoError[1] AND IoError[2]) THEN BEGIN
  780.       IF germanFlag THEN Write(' gesichert.')
  781.                 ELSE Write(' backed up.');
  782.     END;
  783.  
  784.     IF germanFlag THEN BEGIN
  785.       IF IoError[1] THEN
  786.         WriteLn(BootDriv + StartFiles[SYS] + StdExt[SYS]
  787.               + ' fehlte!');
  788.       IF IoError[2] THEN
  789.         WriteLn(BootDriv + StartFiles[BAT] + StdExt[BAT]
  790.               + ' fehlte!');
  791.     END ELSE BEGIN
  792.       IF IoError[1] THEN
  793.         WriteLn(BootDriv + StartFiles[SYS] + StdExt[SYS]
  794.               + ' not found!');
  795.       IF IoError[2] THEN
  796.         WriteLn(BootDriv + StartFiles[BAT] + StdExt[BAT]
  797.               + ' not found!');
  798.     END
  799.   END ELSE Error(NoSystem);
  800. END;
  801.  
  802. PROCEDURE PatchMessages;
  803. BEGIN
  804.   AbortMsg       := 'Program aborted!';
  805.   ParamMsg[none] := ' not found!';
  806.  
  807.   ErrStr[NoSystem]    := 'No or unknown operating system ' +
  808.                        'on the harddisk';
  809.   ErrStr[NoBootSave]  := 'Bootsector backup is missing';
  810.   ErrStr[WrongParam]  :=  'Wrong or unknown commandline ' +
  811.                           'parameter';
  812.   ErrStr[NoDir] := 'Directory with backup files not found';
  813.   ErrStr[NoConfig]    := 'CONFIG backup file is missing';
  814.   ErrStr[NoAutoexec]  := 'AUTOEXEC backup file is missing';
  815.   ErrStr[ConfigNotWritten]   := 'Cannot write CONFIG.SYS';
  816.   ErrStr[AutoexecNotWritten] := 'Cannot write AUTOEXEC.BAT';
  817.   ErrStr[NoHardDrive] := 'No harddisk C: available';
  818.   ErrStr[UserBreak]   := 'Program interrupted by user';
  819.   ErrStr[NoPartSave]  := 'Partition backup file not found';
  820.   ErrStr[NotInstalled]
  821.                  := 'System not on the harddisk available';
  822. END;
  823.  
  824. BEGIN
  825.   IF fGetCountry IN [Austria, Switzerland, Germany] THEN
  826.     germanFlag := TRUE
  827.   ELSE
  828.     PatchMessages;
  829.  
  830.   OldSysType := CheckOldSystem;
  831.  
  832.   IF NOT germanFlag THEN BEGIN
  833.     Names[IBM][7]   := ' '; (* Bindestriche aus  *)
  834.     Names[MSDOS][3] := ' '; (* den Namen löschen *)
  835.     Names[DRS][3]   := ' ';
  836.     Names[MOS][3]   := ' ';
  837.     Names[PLS][4]   := ' ';
  838.   END;
  839.  
  840.   GetDir(0, OrgDir);
  841.   WriteLn(Copyright);
  842.   IF ParamCount = 0 THEN BEGIN
  843.     WriteLn;
  844.     BootInfo;
  845.     ChDir(OrgDir);
  846.     Halt(0);
  847.   END ELSE BEGIN
  848.     CommLine := ParamStr(1);
  849.     IF ParamCount > 1 THEN BEGIN
  850.       CheckPart := ParamStr(2);
  851.       FOR i := 1 TO Length(CheckPart) DO
  852.         CheckPart[i] := UpCase(CheckPart[i]);
  853.       IF Pos('P', CheckPart) > 0 THEN dopartFlag := TRUE;
  854.     END;
  855.     FOR i := 1 TO Length(CommLine) DO
  856.       CommLine[i] := UpCase(CommLine[i]);
  857.     IF (Pos('?', CommLine) > 0) OR
  858.        (Pos('H', CommLine) > 0) THEN HelpInfo
  859.     ELSE BEGIN
  860.       IF OldSysType = none THEN Error(NoSystem);
  861.       NewSysType := CheckParams(CommLine);
  862.       IF OldSysType = NewSysType THEN BEGIN
  863.         IF germanFlag THEN BEGIN
  864.           YesOrNo := Ask(Names[OldSysType]
  865.                 + ' wird bereits gestartet. '
  866.                 + 'Trotzdem nochmals installieren? (J/N) ');
  867.         END ELSE BEGIN
  868.           YesOrNo := Ask(Names[OldSysType] + ' is active.' +
  869.                 + ' Nevertheless install it again? (Y/N) ');
  870.         END;
  871.         internalFlag := TRUE;
  872.         IF YesOrNo = YesNo[Y] THEN BEGIN
  873.           IF dopartFlag THEN BEGIN
  874.           (* Bootsektor und Partitionstabelle brauchen    *)
  875.           (* nicht geschrieben zu werden. Sie sind        *)
  876.           (* sowieso schon auf der Platte aktiv.          *)
  877.             IF germanFlag THEN
  878.                WriteLn('Parameter /p wird ignoriert.')
  879.             ELSE
  880.                WriteLn('Parameter /p will be ignored.');
  881.           END;
  882.         END ELSE Error(UserBreak);
  883.       END ELSE BEGIN
  884.  
  885.        (* sind die Systemdateien des verlangten Betriebs- *)
  886.        (* systems überhaupt auf der Platte verfügbar ?    *)
  887.         IF NOT FileExistFunc(BootDriv + '\' +
  888.                SysIDNames[NewSysType], OnlyFile) THEN
  889.           Error(NotInstalled);
  890.  
  891.        (* Wenn ja, ist das System auch installiert?       *)
  892.         IF NOT FileExistFunc(SysDir + '\' + BootFile +
  893.            Systems[NewSysType], OnlyFile) THEN
  894.           Error(NoBootSave);
  895.  
  896.         IF germanFlag THEN
  897.           YesOrNo := Ask('Bootsystem wird nach '
  898.                         + Names[NewSysType]
  899.                         + ' geändert. Durchführen? (J/N) ')
  900.         ELSE
  901.           YesOrNo := Ask('Bootsystem will be changed to '
  902.                    + Names[NewSysType] + '. Okay? (Y/N) ');
  903.         IF YesOrNo = YesNo[Y] THEN SaveOldSystem
  904.                               ELSE Error(UserBreak);
  905.       END;
  906.  
  907.       IF YesOrNo = YesNo[Y] THEN BEGIN
  908.         PrepareDisk(NewSysType);
  909.         IF germanFlag THEN
  910.           Write('System wird neu gestartet, bitte warten')
  911.         ELSE
  912.           Write('System reboot recommended, please wait');
  913.         WriteLn(' ...');
  914.         WarmBoot;
  915.       END;
  916.     END;
  917.   END;
  918. END.
  919.  
  920. (*========================================================*)
  921. (*                   Ende von BOOT.PAS                    *)
  922.