% Content-encoding: UTF-8
\documentclass[ngerman]{article}
\usepackage[utf8]{inputenc}
\usepackage{multicol,babel}
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{0}

%\newcommand{\code}[1]{\texttt{#1}}

\begin{document}

\renewcommand{\figurename}{Tabelle}

\title{Bootmanager und FAT--Reparatur:\\\hfill Fünfter Fort(h)schritt (HD--Parameter)}
\ifx\shorttitle\undefined\else
\shorttitle{Bootmanager 5 — HD–Parameter}
\fi
\author{Fred Behringer}
\maketitle

Im dritten Teil dieser Serie (VD--Heft 1/2009) habe ich Forth--Worte vorgeschlagen, mit denen man den vollen und schnellen Zugriff auch auf solche Festplatten--Sektoren bekommt, die man wegen ihrer hohen Adresse nicht mehr über die CHS--Adressierung erreichen kann: Es ging um die LBA--Adressierung für Sektoren, die jenseits der 8--GB--(DOS--)Grenze liegen [FB]. Diesmal will ich über die zugehörigen Informationen im MBR sprechen, die in gewisser Weise redundant sind, und darüber, wie man die Redundanz eventuell dazu ausnutzen kann, mit Forth--Mitteln einen zerstörten MBR wiederherzustellen. Einige Festplatten--Parameter erhält man über den erweiterten Interrupt 13h mit dessen Funktion 48h, andere über den MBR, die EBRs und generell über die Bootsektoren der primären Partitionen und der logischen Laufwerke der erweiterten Partition. Ich spreche hauptsächlich über FAT16 und ich bemühe mich, die genannten Informationen per Forth bereitzustellen. Es wird die freie Auswahl der gewünschten Festplatte zugelassen und es wurden Fehlerberücksichtigungs--Mechanismen eingebaut. Die hier entwickelten Programme stützen sich zum Teil auf die Programme in den Teilen 1 bis 3 dieser Artikelserie. Die Programme aus Teil 4 werden nicht benötigt.

\begin{multicols}{2}

\section{Beweggründe}

Versucht man, den \emph{kostenlosen} Partition--Table--Doctor von \url{www.partitiontool.com} [PM] herunterzuladen, tut man sich schon beim Durchhangeln auf der HTML--Page schwer. Beim einfachen Herunterladen der kostenlosen Teile, wobei vom Anwenden noch gar keine Rede ist. Mit Programmen anderer Quellen zum Reparieren einer zerstörten Partitionstabelle ist es ähnlich. Und was für ein Aufwand da getrieben wird! Nur, um herauszubekommen, welche Hexzahl ich wohin zu schreiben habe, um den Bootmanager über die Partitionstabelle des MBRs, des Master--Boot--Records, zum Bootsektor meines Windows--ME--Systems irgendwo an \emph{höherer} Stelle auf der Festplatte zu leiten. Unerträglich, wenn man sich die Mühe gemacht hat, hinter die Kulissen zu schauen, und feststellen muss, dass ein paar Forth--Worte genügen, die Dinge ins Lot zu bringen! 

Natürlich besteht das eigentliche Problem (bei beschädigtem MBR) nicht darin herauszubekommen, wo in der Partitionstabelle des MBRs der herauszufindende Eintrag zu machen ist, sondern welcher Eintrag, wenn dieser, beabsichtigt oder unbeabsichtigt, unzulässig verändert wurde. Ich werde versuchen, Mittel dazu bereitzustellen. Auf dem Weg dorthin hat mich das FreeWare--Programm CWDSKEDT (Christoph--Walter--Disk--Editor) recht gut geleitet [CW]. Es ist für DOS konzipiert, arbeitet aber auch unter Windows bis zu ME. Bis zu einem gewissen Grad würde es sicher reichen, sich eine Sammlung von solchen Fix--und--Fertig--Programmen zurechtzulegen. Aber nur bis zu einem gewissen Grad! Jeden Augenblick stößt man an einen Punkt, an welchem man nicht weiterkommt, weil der eigentliche Durchblick fehlt. Anders bei einem Programmteil, den ich in Forth selbst geformt habe. Da finde ich mich leicht zurecht! Und was noch nicht geht, wird ergänzt! Forth macht's möglich.


\section{Hintergrund}
Im Wikipedia [WI] findet man folgenden Eintrag (nur Auszug relevanter Teile):

\subsection*{Wiki--Anfang 1}
\vspace*{-2ex}
\begin{quote}

Aufbau der Partitionstabelle bei IBM--PC--kompatiblen Computern

Auf Festplatten für IBM--PC--kompatible Computer wird üblicherweise der unten beschriebene Aufbau der Partitionstabelle verwendet. Auf zum PC kompatiblen Speichermedien (z.B. Compact Flash Karten, USB--Stick, Zip--Diskette) ist diese Art von Partitionierung möglich, aber nicht nötig. Auf Speichermedien anderer Systeme (z.B. Workstations, Apple Macintosh, Amiga mit RigidDiskBlock) werden andere Partitionstabellen verwendet, die hier nicht beschrieben werden.
\end{quote}
\vspace*{-4ex}
\subsection*{Wiki--Ende 1}

Ich halte mich an die eben genannten Voraussetzungen. Als Beispiel darf ich die (im Master--Boot--Record, dem MBR, enthaltene) Partitionstabelle meines Experimentier--Computers (AMD--K6--2/500, 384--MB--RAM, 20--GB--HD) angeben (vergleiche Teil 1 dieser Artikelserie [FB] im VD--Heft 3/2008). Man bekommt den MBR über getmbr showsectbuf, und die eigentliche Partitionstabelle erreicht man detailliert aufbereitet über showparttab . Hier der interessierende Auszug:

\begin{footnotesize}
\begin{verbatim}
Offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
     
 0000  eb 48 90 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0
 0010  fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00
                         .  .  .

 0190  61 64 00 20 45 72 72 6f 72 00 bb 01 00 b4 0e cd
 01a0  10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 00 00 00
 01b0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
 01c0  01 00 16 fe 3f 3f 3f 00 00 00 01 b0 0f 00 00 00
 01d0  01 80 05 fe ff ff 80 60 1f 00 80 a3 db 00 00 00
 01e0  01 40 16 fe 3f 7f 40 b0 0f 00 40 b0 0f 00 80 00
 01f0  c1 ff 0c fe ff ff ad 9e b2 01 4e 01 b0 00 55 aa
\end{verbatim}
\end{footnotesize}

\subsection*{Wiki--Anfang 2}
\vspace*{-2ex}
\begin{quote}
Wie unten erläutert, gibt es primäre und erweiterte Partitionstabellen. Ihr Aufbau ist identisch. Die Tabelle fängt bei Offset 1beh des jeweiligen Sektors an und hat maximal 4 Einträge à
 16 Bytes, sie ist also 64 Byte groß. Daran anschließend folgt die \emph{Magic--Number}, die aus den beiden Bytes 55h und aah an den letzten zwei Bytestellen des Sektors besteht.

Die (16 Byte großen) einzelnen Zeilen haben folgende Bedeutung:

\begin{scriptsize}
\begin{verbatim}
Speicherplatz-Adresse (hexadezimal und relativ zum Zeilenanfang) 
 | Größe (Bytes)
 |   | Inhalt
 |   |  |
00   1  Partition bootbar (80 = ja, 00 = nein, 
                           81 = zweite Festplatte usw.)
01   3  CHS-Eintrag des ersten Sektors 
        (CHS = Cylinder,Head,Sector)
04   1  Partitionstyp (06 = FAT16, 05 = erweitert, 
                       0C = FAT32, 16 = 06 versteckt usw.)
05   3  CHS-Eintrag des letzten Sektors
08   4  Startsektor (relativ zum Anfang der Festplatte, 
                     oder zur erweiterten Partitionstabelle)
0C   4  Anzahl der Sektoren in der Partition
\end{verbatim}
\end{scriptsize}

Unbenutzte Einträge sind mit Nullen gefüllt.

\end{quote}
\vspace*{-4ex}
\subsection*{Wiki--Ende 2}
Die CHS--Einträge sind wie folgt kodiert (vergleiche Teil 3 im VD--Heft 1/2009 [FB]):

\begin{center}
\begin{tabular}{lcccl}
Byte 0 &=& H& : &HHHHHHHH\\
Byte 1 &=& S& : &CCSSSSSS\\
Byte 2 &=& C& : &CCCCCCCC\\
\end{tabular}
\end{center}

Die Reihenfolge der Bytes entspricht der Bezeichnung HSC, die übliche Bezeichnung lautet CHS.

Die Reihenfolge der Nummern der Bitstellen in den Bytes ist \texttt{76543210}.
Für die Sektorbits in Byte 1 gilt: \texttt{543210}.
Für die Zylinderbits gilt: \texttt{98 76543210}, wobei \texttt{98} die Überhang--CC--Bitstellen aus Byte 1 sind.

Die Zählung der Köpfe und die der Zylinder beginnt bei 0. Man muss also zur Nummer eines Kopfes oder eines Zylinders noch 1 hinzuzählen, um die Anzahl der beteiligten Köpfe (oder Zylinder) einschließlich des betrachteten zu erhalten. Die Zählung der Sektoren beginnt bei 1. Die Anzahl der Sektoren (im jeweiligen Kopf) ist also mit der Nummer des (gerade noch enthaltenen) Sektors identisch.

Man darf somit bei den Wikipedia--Angaben (siehe gleich) nicht überrascht sein, wenn man \texttt{1023}, \texttt{254}, \texttt{63} liest, und nicht etwa \texttt{1024}, \texttt{255}, \texttt{63} (Angaben dezimal).

Überprüfung des CHS--Eintrags der Windows--ME--Partition bei meinem Experimentier--Computer: Es sind ja eigentlich zwei CHS--Einträge, Anfangs-- und Endwerte. Sie taugen nicht zur Festlegung der Adresse des ME--Bootsektors, da dessen Adress--Wert zu groß ist (und nur per LBA erfasst werden kann): 
HSC--Eintrag,  erster Kopf,  erster Sektor,  erster Zylinder: \texttt{00 01 3ff}, dezimal: \texttt{000 01 1023}
HSC--Eintrag, letzter Kopf, letzter Sektor, letzter Zylinder: \texttt{fe 3f 3ff}, dezimal: \texttt{254 63 1023}

Man beachte, dass bei der Werteangabe (sowohl bei den Anfangswerten wie auch bei den Endwerten) die höchsten beiden Bits von Byte 1 dem höchsten Bit von Byte 2 vorangesetzt werden müssen: 6 Sektor--Bits, 10 Zylinderbits.

Irgendwie scheint mir dieses Ergebnis nur bedingt mit dem bei Wikipedia Gesagten (siehe gleich) zu harmonieren. Besser wäre wohl ein Vergleich mit den Zifferrädern des Kilometerstand--Zählers im Auto bei Überlauf gewesen. Ein Koffer mit Zahlenschloss wäre für den Vergleich auch nicht schlecht. Beim ersten Kopf und beim ersten Sektor der CHS--Zählung liegt bei Überlauf kein Grund vor, in der Partitionstabelle den möglichen Höchststand anzuzeigen.


\subsection*{Wiki--Anfang 3}
\vspace*{-2ex}
\begin{quote}
Da bei modernen Festplatten die Adressierung durch CHS (1024 Zylinder * 255 Heads * 63 Sektoren * 512 Bytes = ca. 8 GB) nicht ausreicht, wird ab dieser Größe immer 1023, 254, 63 für die CHS--Werte angegeben und Position und Größe werden dann ausschließlich durch die Sektorangaben festgelegt. Somit ergibt sich auch die maximale Größe von 2 TB für eine Partition und 4 TB für eine Festplatte (
%(2\^{}32)  
$2^{32}$
* 512 Bytes
 = ca. 2 TB). Die Zylinder und Köpfe werden beginnend bei 0 und die Sektoren beginnend bei 1 gezählt.
\end{quote}
\vspace*{-3ex}
\subsection*{Wiki--Ende 3}

Soweit die Angaben bei Wikipedia. Es folgen ein paar ergänzende Erläuterungen von mir:

Bei der CHS--Adressierung werden die Sektoren tatsächlich ab 1 nummeriert, bei der LBA--Adressierung aber ab 0 ! 

Eine besondere Eigenschaft des Verhältnisses \emph{Anzahl der Vorgänger zur betreffenden Nummer} ist bemerkenswert: Die (Ordnungs--)Zahl 5 beim LBA--Sektor Nummer 5 ist gleichbedeutend mit der (An--)Zahl der bis dato schon durchlaufenen LBA--Sektoren \texttt{0 1 2 3 4}. (5 lässt sich bei dieser Erklärung am Beispiel natürlich durch eine beliebige andere natürliche Zahl n ersetzen.)

Beispiel: Die Eintragung ad 9e b2 01 in der obigen Partitions--Tabelle (im MBR meiner Experimentier--Anlage), also die (Hex--)Zahl \texttt{01b29ead}, gibt die Anzahl der schon durchlaufenen (LBA--)Sektoren wieder (dezimal geschrieben, \texttt{28483245}). Genau so, nämlich als \mbox{\emph{\# preceding sectors}}, wird das auch an verschiedenen Stellen in der Literatur beschrieben. Aber eben diese Zahl kann auch als (LBA--)Sektornummer des Anfangs der betreffenden Partition (hier von Windows ME) aufgefasst werden. Mit anderen Worten: Die Partitionstabelle im MBR trägt schon \emph{von Hause aus} alle Informationen in sich, die nötig sind, um mit einem Bootmanager an die zu bootende Partition zu gelangen --- die verwendete Software braucht das nur gebührend zu berücksichtigen, und sich nicht etwa auf die CHS--Zählung zu verlassen. Aber Achtung: Bei primären Partitionen beginnt die Zählung der LBA--Sektoren am Anfang der Platte, bei den logischen Laufwerken der erweiterten Partition dagegen am Anfang der erweiterten Partition (nicht am Plattenanfang, aber auch nicht etwa beim Anfangssektor (dem EBR) des jeweiligen logischen Laufwerks).


\section{Festplatten--Organisation}

Es gibt pro Festplatte nur einen einzigen MBR. Das ist immer der LBA--Sektor mit der Nummer 0. Alle Primärpartitionen beginnen mit ihrem Bootsektor. (Der MBR gehört zur gesamten Festplatte, nicht etwa nur zur physikalisch ersten Partition.) Vier Partitionen sind (pro Festplatte) möglich. Eine und nur eine dieser Partitionen kann als erweiterte Partition eingerichtet werden. Jedes logische Laufwerk der erweiterten Partition beginnt mit einem MBR--ähnlichen Sektor, dem EBR (Extended--Boot--Record). Die EBRs bilden eine verkettete Liste, über die man sich zum interessierenden logischen Laufwerk durchhangeln kann. Ein Zeiger im EBR ist entweder auf lauter Nullen gesetzt oder weist auf das eventuell vorhandene nächste logische Laufwerk. Der Bootsektor des betreffenden logischen Laufwerks liegt um so viele Sektoren vom EBR entfernt, wie der EBR--Eintrag bei Offset \texttt{1c6} angibt. Normalerweise sind das \texttt{63d} Sektoren, also die Länge eines \emph{Kopfes}.


\section{Little--Endian bei 64 Bit?}

Es gilt bei INTEL--Maschinen (PC--Kompatible gehören dazu) für im Speicher abgelegte Mehr--Byte--Werte die Little--Endian--Vereinbarung: Der RAM--Eintrag \texttt{4e 01 b0 00}, die Anzahl der in meiner Windows--ME--Partition (siehe obige Tabelle) enthaltenen Sektoren, ist als 00b0014e zu lesen! Ich will mal schnell in meinem Forth--System 
die Adresse \texttt{7000} (alle Angaben hexadezimal) als freie RAM--Stelle willkürlich wählen. \texttt{1234 5678 7000 2!} liefert an der Adresse \texttt{7000} die Bytes \texttt{78 56 34 12}, also streng little--endian. Man überzeugt sich davon per \texttt{7000 20 dump}. Versucht man aber, den Wert per \texttt{7000 2@ ud.} wieder hereinzuholen, so erhält man \texttt{56781234} als Anzeige auf dem Bildschirm. Ähnliches Durcheinander, diesmal im RAM, würde bei Eingabe von \texttt{12345678. 7000 2!} auftreten. Bei doppeltgenauen Werten werden oberer und unterer Anteil auf dem Datenstack vertauscht. Der (nach unten wachsende) Stack ist nun aber auch nichts weiter als ein bestimmter RAM--Bereich (2Variablen fallen ebenfalls unter diese Betrachtung). Geht man an den Stack per \texttt{1234 5678 sp@ 20 dump} heran, dann bekommt man (für den Stack--RAM--Bereich) wieder die Little--Endian--Bytefolge \texttt{78 56 34 12}.

Im vorliegenden Artikel tritt bei dem Forth--Wort \verb|get#sects-hd#| (siehe Listing) das Problem auf, einen 64--Bit--Wert aus einem Puffer im RAM auf den Stack zu holen und auf dem Bildschirm darzustellen. Über vierfachgenaue Werte scheint es in Forth keine Empfehlungen zu geben. Soll ich vierfachgenaue Werte aus zwei zweifachgenauen zusammensetzen und ähnliche Vertauschungen auf dem Stack vornehmen wie bei den zweifachgenauen Werten (den Punktzahlen)? Ich trete die Flucht nach vorn an und verlange zum Beispiel, dass die Zahl 123456789abcdef0 in hexadezimalen Vierergruppen als \texttt{1234 5678 9abc def0} (z.B. über die Tastatur) auf den Stack gegeben wird. Sie liegt dann als strenge Little--Endian--Bytefolge im Stack--RAM--Bereich und zwischen Stack, 4Variablen und RAM besteht kein Unterschied mehr. Das Darstellungssystem und die von mir dafür vorgeschlagenen Forthworte \texttt{q@ q! q.} lassen sich leicht auf beliebiggenaue Werte ausdehnen. (Man denke an 80--Bit--Zahlen aus dem Zwischenregister der 80486--FPU, also an fünffachgenaue Werte.)


\section{USB--Sticks als Festplatte}

Was die Kennzahl \texttt{80} für \emph{bootbar} (siehe Tabelle) betrifft, habe ich Experimente mit einem USB--Stick angestellt, und zwar unter Windows ME, da ich hier immer noch den vollen Zugriff auf meine Maschine einerseits, aber auch die USB--2.0--Unterstützung andererseits habe. Den Stick hatte ich über PARTED von einer Live--CD auf FAT16 mit mehreren Partitionen eingerichtet. Ergebnis: Wenn ich in den bisherigen Forth--Programmen der vorliegenden Artikelserie, dort, wo es sinnvoll ist, 81 statt 80 schreibe, dann kann ich alle bisher besprochenen Operationen auch am USB--Stick durchführen. Das gibt mir den Anschluss an den sehr interessanten Artikel \emph{Forth am Stil} von Carsten Strotmann aus dem VD--Heft 2/2006 [CS]. Motto: Ich will nicht immer zeitaufwändig solange im Internet herumsuchen müssen, bis ich ein Programm finde, das das tut, was ich gerade vorhabe (was ja doch nie klappt), nein, ich möchte die Dinge selber machen. In Forth! Nicht, weil Forth die beste aller Sprachen ist --- aber weil Forth mir den leichtesten und schnellsten Zugang bietet. Und ich möchte dabei lernen.

\section{Danksagung und Vorschau}

Viele wichtige Informationen zur vorliegenden Untersuchung habe ich in den MS--Unterlagen [MS] gefunden. Ich bin Johann Sturm vom Vaterstettener Senioren--Computer--Kreis für seine Hinweise auf diese und weitere Quellen zum Thema dankbar.

Demnächst will ich mich mit den Begriffen FAT, Root--Directory, Cluster und mit der Organisation von Dateien, vor allem unter FAT16, auseinandersetzen.

\end{multicols}

\section*{Literatur und Internet--Adressen}\markright{Listing}

\begin{tabular}{ll}
{[CS]} Strotmann, Carsten: & Forth am Stil. Vierte Dimension (2006), Heft 2.\\
{[CW]} Walter, Christoph:  & CWDSKEDT 2.22, Freeware, Christoph--Walter--Diskedit (1999).\\
{[FB]} Behringer, Fred:    & Bootmanager und FAT--Reparatur, Teil 1 bis 4.\\
                           & Vierte Dimension, Hefte 3--4/2008 und 1--2/2009.\\
{[MS]} Windows 2000:       &\url{http://www.microsoft.com/technet/prodtechnol/}...\\
{[PM]} PARTITION MASTER:   &\url{http://www.partition-tool.com} (Easeus). \\
                         & CHENGDU YIWO Tech Development Co., Ltd.(2009).\\
{[WI]} Wikipedia:        &  \url{http://de.wikipedia.org/wiki/Partitionstabelle}
\end{tabular}
\bigskip

\section{Listing}
\begin{quote}
\listinginput{1}{2009-03/listing5.txt}
\end{quote}

\vfill
\begin{center}
\includegraphics[width=0.7\textwidth]{2009-03/Bootsector}
\end{center}
\vfill

\end{document}