organized reference files, new diagrams, touch sense, other writing ....

master
Ondřej Hruška 7 years ago
parent fdeac680c3
commit 2e51c5fc7a
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 196
      ch.fat16.tex
  2. 96
      ch.gex_units.tex
  3. 10
      ch.hw_buses.tex
  4. 38
      ch.hw_functions.tex
  5. 16
      ch.tinyframe.tex
  6. 82
      ch.wireless.tex
  7. 6
      ctuth-pkg.tex
  8. 5
      document_config.tex
  9. BIN
      img/bulk-read-write.pdf
  10. BIN
      img/disco-touch.jpg
  11. BIN
      img/fat-links.pdf
  12. BIN
      img/nrf-testing.jpg
  13. BIN
      img/rf-gw.pdf
  14. BIN
      img/tsc-wfm-bw.png
  15. BIN
      img/tsc-wfm.png
  16. BIN
      img/tsc-wfm2-bw.png
  17. BIN
      img/tsc-wfm2.png
  18. 0
      references/AD_all-about-direct-digital-synthesis.pdf
  19. BIN
      references/FAT16/FAT12Description_www.dfists.ua.es_~gil.pdf
  20. 517
      references/FAT16/FAT16 Structure Information.html
  21. 1304
      references/FAT16/FAT32 Structure Information.html
  22. 580
      references/FAT16/Long Filename Specification.html
  23. BIN
      references/FAT16/MS_fatgen102.pdf
  24. 319
      references/FAT16/Maverick FAT16 reference/Maverick - FAT16 - LFN.html
  25. 816
      references/FAT16/Maverick FAT16 reference/Maverick - FAT16 structure.html
  26. 323
      references/FAT16/Maverick FAT16 reference/Maverick.css
  27. 944
      references/FAT16/Phobos FAT16 tutorial/Photos FAT tutorial.html
  28. BIN
      references/FAT16/Phobos FAT16 tutorial/images/bootblk.jpg
  29. BIN
      references/FAT16/Phobos FAT16 tutorial/images/bootblk1.jpg
  30. BIN
      references/FAT16/Phobos FAT16 tutorial/images/bootblk2.jpg
  31. BIN
      references/FAT16/Phobos FAT16 tutorial/images/datablk1.jpg
  32. BIN
      references/FAT16/Phobos FAT16 tutorial/images/datablk2.jpg
  33. BIN
      references/FAT16/Phobos FAT16 tutorial/images/datablk3.jpg
  34. BIN
      references/FAT16/Phobos FAT16 tutorial/images/datablk4.jpg
  35. BIN
      references/FAT16/Phobos FAT16 tutorial/images/fat.jpg
  36. BIN
      references/FAT16/Phobos FAT16 tutorial/images/rootdir.jpg
  37. BIN
      references/FAT16/Phobos FAT16 tutorial/images/rootdir1.jpg
  38. BIN
      references/FAT16/Phobos FAT16 tutorial/images/rootdir2.jpg
  39. BIN
      references/FAT16/Phobos FAT16 tutorial/images/rootdir3.jpg
  40. 306
      references/FAT16/Phobos FAT16 tutorial/phobos.css
  41. BIN
      references/Fonstad_MicroelecDevCkt_2006EEd.pdf
  42. 0
      references/Raspberry-Pi-Zero-mech.pdf
  43. 0
      references/STM32/STM32L4_TSC_PPT.pdf
  44. 0
      references/STM32/an_Timers.pdf
  45. 0
      references/STM32/en.STM32F7_WDG_TIMERS_GPTIM.pdf
  46. 0
      references/STM32/en.STM32L4_Peripheral_Touchsense.pdf
  47. 0
      references/STM32/motor_pwm_ppt.pdf
  48. 0
      references/USB/Introduction20to20USB203.020Protocol.pdf
  49. 0
      references/USB/iadclasscode_r10.pdf
  50. 0
      references/USB/resistor_ecn.pdf
  51. 0
      references/USB/usb11.pdf
  52. 0
      references/USB/usbmassbulk_10.pdf
  53. BIN
      thesis.pdf
  54. 9
      thesis.tex

@ -1,3 +1,195 @@
\chapter{The FAT16 Filesystem and Its Emulation} \label{sec:fat16} \chapter{The FAT16 File System and Its Emulation} \label{sec:fat16}
A file system (FS) is used by GEX to provide a comfortable access to the configuration files. By emulating a Mass Storage USB device, the module appears as a thumb drive on the host PC, and the user can edit its configuration using their preferred text editor. The FAT16 file system was selected for its simplicity and a good cross-platform support.
Three variants of the FAT (File Allocation Table) file system exist: FAT12, FAT16, and FAT32. FAT12 was used on floppy disks and it is similar to FAT16, except for additional size constraints and a FAT entry packing scheme. FAT16 and FAT32 are FAT12's later developments from the time when hard disks became more common and the old addressing scheme couldn't support their larger capacity.
This chapter will explain the structure of FAT16 and the challenges faced when trying to emulate it without a physical data storage.
\section{The General Structure of the FAT File System}
The storage medium is organized into \textit{sectors} (or \textit{blocks}), usually 512 bytes long. Those are the smallest addressing unit in the disk structure. The disk starts with a \textit{boot sector}, also called \textit{master boot record} (MBR). That is followed by optional reserved sectors, one or two copies of the file allocation table, and the root directory. All disk areas are aligned to a sector boundary:
\begin{table}[h]
\centering
\begin{tabular}{ll}
\toprule
\textbf{Disk area} & \textbf{Size / Notes} \\
\midrule
Boot sector & 1 sector \\
Reserved sectors & optional \\
FAT 1 & 1 or more sectors, depends on disk size \\
FAT 2 & optional, a back-up copy of FAT 1 \\
Root directory & 1 or more sectors \\
Data area & Organized in \textit{clusters} \\
\bottomrule
\end{tabular}
\caption{\label{tab:fat16-disk-areas}Areas of a FAT-formatted disk}
\end{table}
\subsection{Boot Sector}
This is a 1-sector structure which holds the OS bootstrap code for bootable disks. The first 3 bytes are a jump instruction to the actual bootstrap code located later in the sector. What matters to us when implementing the file system is that the boot sector also contains data fields describing how the disk is organized, what file system is used, who formatted it, etc. The size of the FAT and the root directory is defined here. The exact structure of the boot sector can be found in XXX\todo{add ref link} or in the attached GEX source code.
\subsection{File Allocation Table}
The data area of the disk is organized in clusters, logical allocation units composed of groups of sectors. The use of a larger allocation unit allows the system to use shorter addresses and thus support a larger disk capacity.
The FAT acts as a look-up table combined with linked lists. In FAT16, it is organized in 16-bit fields, each corresponding to one cluster. The first two entries in the allocation table are reserved and hold special values set by the disk formatter and the host OS: a "media descriptor" 0xFFF8 and a "clean/dirty flag" 0xFFFF/0x3FFF.
Files can span multiple clusters; each FAT entry either holds the address of the following file cluster, or a value with a special meaning:
\begin{itemize}
\item 0x0000 - free cluster
\item 0xFFFF - last cluster of the file (still including file data!)
\item 0xFFF7 - bad cluster
\end{itemize}
The bad cluster mark, 0xFFF7, is used for clusters which are known to corrupt data due to a flaw in the storage medium, such us a bad memory cell.
\subsection{Root Directory}
The root directory has the same structure as any other directories, which reside in clusters the same way like ordinary files. The difference is that the root directory is allocated when the disk is formatted and it has a fixed and known position and size. Sub-directories are stored on the disk in a similar way to regular files, therefore they can span multiple sectors and their file count can be much larger than that of the root directory.
\begin{table}
\centering
\begin{tabular}{lll}
\toprule
\textbf{Offset} & \textbf{Size (bytes)} & \textbf{Description}\\
\midrule
0 & 8 & File name (padded with spaces) \\
8 & 3 & File extension \\
11 & 1 & File attributes \\
12 & 10 & Reserved \\
22 & 2 & Creation time \\
24 & 2 & Creation date \\
26 & 2 & Address of the first cluster \\
28 & 4 & File size (bytes) \\
\bottomrule
\end{tabular}
\caption{\label{tab:fat16-dir-entry}Structure of a FAT16 directory entry}
\end{table}
A directory is organized in 32-byte entries representing individual files. Table \ref{tab:fat16-dir-entry} shows the structure of one such entry.
The name and extension fields form together the well-known 8.3 filename format. Longer file names are encoded using a \textit{long file name} (LFN) scheme as special hidden entries stored in the directory table alongside the regular 8.3 entries, ensuring backward compatibility.
The first byte of the file name has a special meaning:
\begin{itemize}
\item 0x00 - indicates that there are no more files when searching the directory
\item 0xE5 - marks a free slot; this is used when a file is deleted
\item 0x05 - indicates that the first byte should actually be 0xE5, which was used in a Japanese character set.
\item Any other value, except 0x20 (space) and characters forbidden in a DOS file name, starts a valid file entry. Generally, only space, A-Z, 0-9, \verb|-| and \verb|_| should be used in file names for maximum compatibility.
\end{itemize}
The attributes field contains flags such as \textit{directory}, \textit{volume label}, \textit{read-only} and \textit{hidden}. Volume label is a special entry in the root directory, which defines the disk's label shown on the host PC. A file with the directory bit set is actually a pointer to a subdirectory, meaning that when we open the linked cluster, we'll find a new directory table.
Figure \ref{fig:fat-example} shows a possible organization of the GEX file system with two INI files, one spanning two clusters, the other being entirely inside one. The clusters need not be used completely; an exact file size is stored in the directory entries.
\begin{figure}[h]
\centering
\includegraphics[scale=1.3] {img/fat-links.pdf}
\caption{\label{fig:fat-example}An example of the GEX virtual file system}
\end{figure}
\section{FAT16 Emulation}
The FAT16 file system is relatively straightforward and easy to implement. This is the reason why an emulation driver for it was developed as part of the open-source ARM mbed DAPLink project. \todo{reference} It is used there for a drag-and-drop flashing of firmware images to the target microcontroller, taking advantage of it working well across different host platforms. ARM mbed uses a browser-based IDE and cloud build servers, thus the end user does not need to install or set up any software or drivers to program a compatible development kit. The GEX firmware adapts several parts of this code, optimizes its RAM usage and further expands its functionality to support our specific use case.
It is not practical or even possible to keep the entire file system in memory, especially with a microcontroller like the STM32F072, which has only 16\,kB of RAM in total. This means that we have to generate and parse disk sectors and clusters on-demand, when the host reads or writes them. The STM32 USB Device library helpfully implements the Mass Storage USB class and provides API endpoints to which we connect our file system emulator. Specifically, those are requests to read and write a sector, and to read disk status and parameters, such as its size.
As shown in table \ref{tab:fat16-disk-areas}, the disk consists of several areas. The boot sector is immutable and can be stored in Flash. The handling of the other areas (FAT, data area) depends on whether we're dealing with a read or write access:
\subsection{Handling a Read Access}
The user can only read files that already exist on the disk, in our case, \verb|UNITS.INI| and \verb|SYSTEM.INI|. Those files are generated from the binary settings storage, and conversely, parsed, line-by-line, without ever existing in their full form. This fact makes our task more challenging, as the files can't be easily measured and there's no obvious way to read a sector from the middle of a longer file. We solve this by implementing two additional functions in the INI file writer: a \textit{read window} and a \textit{dummy read mode}.
A read window is a byte range which we wish to generate. The INI writer discards bytes before the start of the read window, writes those inside the window to our data buffer, and stops when its end is reached. This lets us extract a sector from anywhere in a file. The second function, dummy read, is tied to the window function: we set the start index so high that it's never reached (e.g. 0xFFFFFFFF), and have the writer count discarded characters. When the dummy file generation ends, this character counter holds its size.
Now, just one problem remains: how to tell which sectors contain which part of our files? This is straightforward when we realize that the files change only when the user modifies the settings. After each such change, an algorithm is run which allocates clusters to the files and preserves this information in a holding structure. A subsequent read access simply requires a look into this structure and the corresponding chunk of a file may be served using the read window function. The FAT can be dynamically generated from this information as well.
\subsection{Handling a Write Access}
A file write access is more challenging to emulate than a read access, as the host OS tends to be somewhat unpredictable. In GEX's case we're interested only in the action of overwriting an already existing file, but it's interesting to also analyze other actions the host may perform.
It must be noted that due to the nonexistence of a physical storage medium, it's not possible to read back a file the host has written. The OS may show the written file on the disk, but when the user tried to read it, it either fails, or shows a cached copy. In the DAPLink emulator this is worked around by temporarily reporting that the storage medium has been removed, forcing the host to re-load its contents. In GEX, the loaded INI file will be a newly generated copy, embedding possible error messages as comments.
\subsubsection{File Deletion}
A file is deleted by:
\begin{enumerate}
\item Marking all sectors used by it as free in the FAT
\item Replacing the first character of its name in the directory table by 0xE5 to indicate the slot is free
\end{enumerate}
From the perspective of emulation, we can ignore the FAT access and only detect writes to the directory sectors. This is slightly more complicated when one considers that all disk access is performed in sectors: the emulator must compare the written data with the original bytes to detect what change has been performed. Alternatively, we could parse the written sector as a directory table and compare it with our knowledge of its original contents.
\subsection{File Name Change}
A file is renamed by modifying its directory entry. This can be be detected in a similar way to a file deletion. In the simple case of a short, 8.3 file name, this is a in-place modification of the file entry. Long file names, using the LFN extension, are a complication, as the number of dummy entries might change when the file name is shortened or made longer, and subsequently the following entries in the table may shift or be entirely re-arranged.
\subsection{File Creation}
A new file is created in three steps:
\begin{enumerate}
\item Finding free clusters and chaining them by writing the following cluster addresses (or 0xFFFF for the last cluster) into the FAT
\item Finding and overwriting a free entry in the directory table
\item Writing the file content
\end{enumerate}
It can be expected the host OS first finds the free sectors and a free file entry before performing any write operations, to prevent a potential disk corruption.
To properly handle such a file by the emulator, we could, in theory, find its name from the directory table, which has been updated, and then collect the data written to the corresponding clusters. In practice, confirmed by experiments with a real Linux host, those three steps may happen in any order, and often the content is written before the directory table is updated.
The uncertain order of the written disk areas poses a problem when the file name has any significance, as we can't store the received file data while waiting for the name to be written. The DAPLink mbed flashing firmware solves this by analyzing the content of the first written sector of the file, which may contain the binary NVIC table, or an ASCII pattern typical for Intel hex files.
\subsection{File Content Change}
A change to a file's content is performed in a similar way to the creation of a new file, except instead of creating a new entry in the directory table, an existing one is updated with the new file size. The name of the file may be, again, unknown until the content is written, but we could detect the file by comparing the starting sector with those of all files known to the virtual file system.
In the case of GEX, the detection of a file name is not important; We expect only INI files to be written, and the particular file may be detected by its first section marker, such as \verb|[UNITS]| or \verb|[SYSTEM]|. Should a non-INI file be written by accident, the INI parser will likely detect a syntax error and discard it.
It should be noted that a file could be updated only partially, skipping the clusters which remain unchanged, and there's also no guarantee regarding the order in which the file's sectors are written. This is hard to detect and handle and the current firmware is not able to interpret it correctly, thus such a write operation will fail. Fortunately, this host behavior has not been conclusively observed in practice, but a write operation rarely fails for still unknown reasons and this could be a possible cause.
...

@ -0,0 +1,96 @@
\chapter{Functional Blocks}
This chapter describes all functional blocks (units) implemented in GEX at the time of publication of this work. Each unit supports a different set of binary commands and events. A complete specification of this API is attached in an electronic form. \todo{add the github docs repo as a ref}
\section{Digital Output Unit}
The digital output unit provides a write access to one or more pins of a GPIO port. The group of pins need not be contiguous (e.g. pin 0 and 6 can be accessed as a 2-bit output). All selected pins are accessed simultaneously using the port control registers.
This unit additionally supports pulse generation on any of its pins. It is implemented in software with the timing derived from the system timebase, as the hardware timer outputs, otherwise used for PWM or pulse generation, are available only on several dedicated pins. Two pulse length resolutions are available, depending on the scale: microseconds for pulses shorter than 1\,ms, milliseconds for longer ones.
\todo[inline]{Measure jitter and add it here}
\section{Digital Input Unit}
The digital input unit is the input counterpart of the digital output unit.
In addition to reading the immediate digital levels of the selected pins, this unit can generate asynchronous events on a pin change. The state of the entire input port, together with a microsecond timestamp (as is the case for all asynchronous events), is reported to the host either on a rising, falling, or any pin change.
The pin change event can be configured independently for each pin. In order to receive a pin change event, it must be armed first; The pin can be armed for a single event, or it may be re-armed automatically with a hold-off time. It's further possible to automatically arm selected pin triggers on start-up.
\section{Shift Registers Driver Unit}
The shift registers driver unit is designed for the loading of data into \textit{serial-in, parallel-out} (SIPO) shift registers, such as 74HC4094 or 74HC595. Those are commonly used to control segmented LED displays, LED matrices etc.
This unit handles both the \textit{Shift} and \textit{Store} signals and is capable of loading multiple shift registers simultaneously, reducing visible glitches in the display. It's also possible to set the data lines to arbitrary level(s) before sending the Store pulse, which can be latched and used for some additional feature of the LED display, such as brightness control.
\section{NeoPixel Unit}
The NeoPixel unit implements the protocol needed to control a digital LED strip with WS2812, WS2811, or compatible LED driver chips. The protocol timing is implemented in software, therefore it is available on any GPIO pin of the module. The unit accepts sequences of RGB color values from the host and loads them into the LED strip.
\section{SPI Unit}
The SPI unit provides access to one of the microcontroller's SPI peripherals. It can be configured to use any of the different speeds, clock polarity and phase settings available in its control registers. The unit handles up to 16 slave select (NSS) signals.
Both write-only and read-write (query) transactions are implemented.
\todo[inline]{Query diagram}
\section{I2C Unit}
The I2C unit provides access to one of the microcontroller's I2C peripherals. It can be configured to use either of the three speeds (Standard, Fast and Fast+) and supports both 10-bit and 8-bit addressing.
\section{USART Unit}
The USART unit provides access to one of the microcontroller's USART peripherals. All USART parameters can be configured to match the application's needs.
The clock output and hardware flow control may be enabled, as well as the Driver Enable (DE) output used by RS485 transceivers to switch between a reception and transmission mode.
\section{1-Wire Unit}
The 1-Wire unit implements the Dallas Semiconductor's 1-Wire protocol, most commonly used to interface smart thermometers (DS18x20). The protocol is explained in section \ref{sec:theory-1wire}. This unit implements the basic protocol, as well as the ROM Search algorithm used to recognizes all unique 1-Wire devices connected to the bus.
\section{Frequency Capture Unit}
The frequency capture unit implements both the frequency measurement methods explained in section \ref{sec:theory-fcap}: direct and reciprocal. It can be operated in an on-demand or continuous measurement mode. The unit can be switched to two other modes: pulse counter, and the measurement of a single pulse.
\section{ADC Unit}
The analog/digital converter unit is one of the most complicated units implemented in the project. The unit can measure the voltage on an input pin, either as its immediate value, or averaged with exponential forgetting. Isochronous sampling is available as well: It's possible to capture a fixed-length block of data on demand, or as a response to a triggering condition on any of the enabled input pins. The ADC must continuously sample the inputs to make the averaging and level based triggering possible; As a consequence, a pre-trigger buffer is available that can be read together with the block of samples following a trigger. The ADC unit can also be switched to a continuous streaming mode.
It's possible to activate any number of the 16 analog inputs of the ADC peripheral simultaneously. The maximum continuous sampling frequency, which reaches 70\,ksps with one channel, lowers with an increasing number of enabled channels as the amount of data to transfer to the host increases.
\section{DAC Unit}
The digital/analog unit works with the two-channel DAC peripheral of the microcontroller. It can be used in two modes: DC output, and waveform generation.
The waveform mode implements direct digital synthesis (explained in section \ref{sec:theory-dac-dds}) of a sine, rectangle, sawtooth or triangle wave. The generated frequency can be set with a sub-hertz precision up to the lower tens of kHz. The two outputs can use a different waveform shape, be synchronized, and their phase offset, as well as frequency, is dynamically adjustable.
\section{PWM Unit}
The PWM unit uses a timer/counter to generate a PWM signal. There are four outputs with a common frequency and phase, but independent duty cycles. Each channel can be individually enabled or disabled.
This unit is intended for applications like light dimming, heater regulation, or the control of H-bridges.
\section{Touch Sensing Unit}
The touch sensing unit provides an access to the touch sensing controller. Its function is explained in section \ref{sec:theory-touch}. The unit configures the TSC and reads the output values of each enabled touch pad.

@ -2,7 +2,7 @@
Hardware buses implemented in GEX are presented in this chapter. The description of each bus is accompanied by several examples of devices that can be interfaced with it. The reader is advised to consult the official specifications and particular devices' datasheets for additional technical details. Hardware buses implemented in GEX are presented in this chapter. The description of each bus is accompanied by several examples of devices that can be interfaced with it. The reader is advised to consult the official specifications and particular devices' datasheets for additional technical details.
\section{UART and USART} \section{UART and USART} \label{sec:theory-usart}
The \textit{Universal Synchronous / Asynchronous Receiver Transmitter} has a long history and is still in widespread use today. It is the protocol used in RS-232, which was once a common way of connecting modems, printers, mice and other devices to personal computers. UART framing is also used in the industrial bus RS-485. The \textit{Universal Synchronous / Asynchronous Receiver Transmitter} has a long history and is still in widespread use today. It is the protocol used in RS-232, which was once a common way of connecting modems, printers, mice and other devices to personal computers. UART framing is also used in the industrial bus RS-485.
@ -27,7 +27,7 @@ RS-232 uses the UART framing, but its logic levels are different: logical 1 is r
\item \textbf{MFRC522} - NFC MIFARE reader/writer IC (also supports other interfaces) \item \textbf{MFRC522} - NFC MIFARE reader/writer IC (also supports other interfaces)
\end{itemize} \end{itemize}
\section{SPI} \section{SPI} \label{sec:theory-spi}
SPI (Serial Peripheral Interface) is a point-to-point or multi-drop master-slave interface based on shift registers. The SPI connection with multiple slave devices is depicted in figure \ref{fig:spi-multislave}. It uses at least 4 wires: SCK (Serial Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) and SS (Slave Select). SS is often marked CSB (Chip Select Bar) or NSS (Negated Slave Select) to indicate it's active low. Slave devices are addressed using their Slave Select input while the data connections are shared. A slave that's not addressed releases the MISO line to a high impedance state so it doesn't interfere in ongoing communication. SPI (Serial Peripheral Interface) is a point-to-point or multi-drop master-slave interface based on shift registers. The SPI connection with multiple slave devices is depicted in figure \ref{fig:spi-multislave}. It uses at least 4 wires: SCK (Serial Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) and SS (Slave Select). SS is often marked CSB (Chip Select Bar) or NSS (Negated Slave Select) to indicate it's active low. Slave devices are addressed using their Slave Select input while the data connections are shared. A slave that's not addressed releases the MISO line to a high impedance state so it doesn't interfere in ongoing communication.
@ -57,7 +57,7 @@ SPI devices often provide a number of control, configuration and status register
\item SPI-interfaced EEPROMs and Flash memories \item SPI-interfaced EEPROMs and Flash memories
\end{itemize} \end{itemize}
\section{I2C} \section{I2C} \label{sec:theory-i2c}
I2C is a two-wire (SDA--\textit{Serial Data}, SCL--\textit{Serial Clock}), open-drain bus that supports multi-master operation. The protocol was developed by Philips Semiconductor (now NXP Semiconductors) and until 2006 implementors were required to pay licensing fees, leading to the development of compatible implementations with different names, such as Atmel's Two Wire Interface (TWI) or Dallas Semiconductor's "Serial 2-wire Interface" (e.g. used in the DS1307 RTC chip). I2C is the basis of the SMBus and PMBus protocols which add additional constraints and rules for a more robust operation. I2C is a two-wire (SDA--\textit{Serial Data}, SCL--\textit{Serial Clock}), open-drain bus that supports multi-master operation. The protocol was developed by Philips Semiconductor (now NXP Semiconductors) and until 2006 implementors were required to pay licensing fees, leading to the development of compatible implementations with different names, such as Atmel's Two Wire Interface (TWI) or Dallas Semiconductor's "Serial 2-wire Interface" (e.g. used in the DS1307 RTC chip). I2C is the basis of the SMBus and PMBus protocols which add additional constraints and rules for a more robust operation.
@ -81,7 +81,7 @@ The bus supports multi-master operation, which leads to the problem of collision
\item Cameras with an SCCB port can be accessed through I2C \item Cameras with an SCCB port can be accessed through I2C
\end{itemize} \end{itemize}
\section{1-Wire} \section{1-Wire} \label{sec:theory-1wire}
The 1-Wire bus, developed by Dallas Semiconductor, uses a single bi-directional data line which can also power the slave devices, reducing the number of required wires to just two (compare with 3 in I2C and 5 in SPI, all including GND). The 1-Wire bus, developed by Dallas Semiconductor, uses a single bi-directional data line which can also power the slave devices, reducing the number of required wires to just two (compare with 3 in I2C and 5 in SPI, all including GND).
@ -111,7 +111,7 @@ Since 1-Wire is a proprietary protocol, there is a much smaller choice of availa
\caption{\label{fig:1w-pulses}The 1-Wire DIO pulse timing (by \textit{Dallas Semiconductor})} \caption{\label{fig:1w-pulses}The 1-Wire DIO pulse timing (by \textit{Dallas Semiconductor})}
\end{figure} \end{figure}
\section{NeoPixel} \section{NeoPixel} \label{sec:theory-neo}
NeoPixel is a marketing name of the \textbf{WS2811}, \textbf{WS2812} and compatible intelligent LED drivers that is commonly used in "addressable LED strips". Those chips include the control logic, PWM drivers and usually the LED diodes all in one miniature package. NeoPixel is a marketing name of the \textbf{WS2811}, \textbf{WS2812} and compatible intelligent LED drivers that is commonly used in "addressable LED strips". Those chips include the control logic, PWM drivers and usually the LED diodes all in one miniature package.

@ -2,7 +2,7 @@
In addition to communication buses, described in chapter \ref{ch:hw_buses}, GEX implements several measurement and output functions that take advantage of the microcontroller's peripheral blocks, such as timers/counters and DAC. The more complicated ones are described here; simpler functions, such as the raw GPIO access, will be described later together with their control API. In addition to communication buses, described in chapter \ref{ch:hw_buses}, GEX implements several measurement and output functions that take advantage of the microcontroller's peripheral blocks, such as timers/counters and DAC. The more complicated ones are described here; simpler functions, such as the raw GPIO access, will be described later together with their control API.
\section{Frequency Measurement} \section{Frequency Measurement} \label{sec:theory-fcap}
Applications like motor speed measurement and the reading of a VCO (voltage-controlled-oscillator) or VCO-based sensor's output demand a tool capable of measuring frequency. This can be done using a laboratory instrument such as the Agilent 53131A. A low cost solution is to use a timer/counter peripheral of a microcontroller, such as the STM32F072 used in GEX. Applications like motor speed measurement and the reading of a VCO (voltage-controlled-oscillator) or VCO-based sensor's output demand a tool capable of measuring frequency. This can be done using a laboratory instrument such as the Agilent 53131A. A low cost solution is to use a timer/counter peripheral of a microcontroller, such as the STM32F072 used in GEX.
@ -48,13 +48,19 @@ A good approach to a universal measurement, when we don't know the expected freq
The system clock's frequency, which we use to measure pulse lengths and to gate the pulse counter, will be affected by tolerances of the used components, the layout of the PCB, temperature effects etc., causing measurement errors. A higher accuracy could be achieved using a temperature-compensated oscillator (TCO), or, in the direct method, by using the synchronization pulse provided by a GPS receiver to time the measurement interval. The system clock's frequency, which we use to measure pulse lengths and to gate the pulse counter, will be affected by tolerances of the used components, the layout of the PCB, temperature effects etc., causing measurement errors. A higher accuracy could be achieved using a temperature-compensated oscillator (TCO), or, in the direct method, by using the synchronization pulse provided by a GPS receiver to time the measurement interval.
\section{Waveform Generation}
\section{Analog Signal Acquisition} \label{sec:theory-adc}
\todo[inline]{Explain ADC operation and basic concepts / types}
\section{Waveform Generation} \label{sec:theory-dac}
A waveform generator is a useful tool in many experiments and measurements. A sine stimulus is the basis of a lock-in amplifier; it can be used to measure impedance; with a frequency sweep, we can obtain the frequency response of an analog filter, etc. We can, of course, generate other waveforms, such as a triangle, ramp, or rectangle wave. A waveform generator is a useful tool in many experiments and measurements. A sine stimulus is the basis of a lock-in amplifier; it can be used to measure impedance; with a frequency sweep, we can obtain the frequency response of an analog filter, etc. We can, of course, generate other waveforms, such as a triangle, ramp, or rectangle wave.
The DAC peripheral can produce a DC level on the output pin based on a control word. When we periodically change its digital input, it produces an analog waveform. The DAC peripheral can produce a DC level on the output pin based on a control word. When we periodically change its digital input, it produces an analog waveform.
\subsection{Waveform Generation with DMA and a Timer} \subsection{Waveform Generation with DMA and a Timer} \label{sec:theory-dac-simple}
A straightforward implementation of the waveform generator is illustrated in figure \ref{fig:wavegen-naive}. This approach has its advantages: it's simple and works entirely in the background, with no interrupt handling required. It could even be implemented entirely in software, using a loop periodically updating the DAC values, of course such approach is less flexible and we would run into problems with asynchronous interrupts. A straightforward implementation of the waveform generator is illustrated in figure \ref{fig:wavegen-naive}. This approach has its advantages: it's simple and works entirely in the background, with no interrupt handling required. It could even be implemented entirely in software, using a loop periodically updating the DAC values, of course such approach is less flexible and we would run into problems with asynchronous interrupts.
@ -68,7 +74,7 @@ The highest achievable output frequency largely depends on the size of our look-
A major disadvantage of this simple generation method is given by the limitations of the used timer, which defines the output frequency. Its output trigger fires when the internal counter reaches a pre-defined value, after which the counting register is reset. The counting speed is derived from the system clock frequency $f_\mathrm{c}$ using a prescaller $P$ and the set maximum value $N$. Only output frequencies that can be exactly expressed as $f=f_\mathrm{c}/(P\cdot N \cdot \mathrm{TableSize})$ can be accurately produced. Still, this simple and efficient method may be used where fine tuning is not required to take advantage of its fully asynchronous operation. A major disadvantage of this simple generation method is given by the limitations of the used timer, which defines the output frequency. Its output trigger fires when the internal counter reaches a pre-defined value, after which the counting register is reset. The counting speed is derived from the system clock frequency $f_\mathrm{c}$ using a prescaller $P$ and the set maximum value $N$. Only output frequencies that can be exactly expressed as $f=f_\mathrm{c}/(P\cdot N \cdot \mathrm{TableSize})$ can be accurately produced. Still, this simple and efficient method may be used where fine tuning is not required to take advantage of its fully asynchronous operation.
\subsection{Direct Digital Synthesis} \subsection{Direct Digital Synthesis} \label{sec:theory-dac-dds}
There are situations where the simple waveform generation method is not sufficient, particularly when a fine tuning or on-line frequency and phase changes are required. Those are the strengths of a signal generation method called \textit{Direct Digital Synthesis} (DDS). There are situations where the simple waveform generation method is not sufficient, particularly when a fine tuning or on-line frequency and phase changes are required. Those are the strengths of a signal generation method called \textit{Direct Digital Synthesis} (DDS).
@ -89,11 +95,35 @@ DDS may be implemented in hardware, including the look-up table, often together
\todo[inline]{screenshots of a real demo, also reference to all-about-direct-digital-synthesis.pdf} \todo[inline]{screenshots of a real demo, also reference to all-about-direct-digital-synthesis.pdf}
\section{Touch Sensing} \label{sec:theory-touch}
The used microcontroller, STM32F072, includes a touch sensing controller (TSC) peripheral block. It can be accessed from GEX as a demonstration of capacitive touch sensing, and could possibly be used for simple touch sensors as well, such as measuring the level of water in a tank.
\begin{figure}[h]
\centering
\includegraphics[width=0.5\textwidth] {img/disco-touch.jpg}
\caption{\label{fig:disco-touch}The touch slider on a STM32F072 Discovery board}
\end{figure}
The TSC requires a specific topology with a sampling capacitor connected close to the microcontroller pin, which may not be possible on a universal GEX module; for this reason, the touch sensing feature is best demonstrated on the STM32F072 Discovery development kit, which includes a 4-segment touch slider shown in figure \ref{fig:disco-touch}.
The principle of capacitive touch sensing is well explained in the microcontroller's reference manual \todo{ref}. A key part of the TSC is a set of analog switches, which can be combined to form several different signal paths between the external pins, Vdd, GND, and an analog comparator. Two input pins are needed for every touch sensing channel: the sensing pad connects to one, the other is connected through a sampling capacitor (47\,nF on the Discovery board) to GND.
Capacitive sensing is a sequential process described in the following steps:
\begin{enumerate}
\item The sensing capacitor is discharged by connecting its free end to GND.
\item The sensing pad is connected to Vdd and, acting as a capacitor, charged to 3.3\,V. It stores a small amount of charge, depending on its capacitance---this is the variable property we are trying to measure.
\item The free terminals of the two capacitors (the sensing pad and the sampling capacitor) are connected together and their voltages reach an equilibrium as a portion of the stored charge leaves the sensing pad and flows into the bigger capacitor.
\item The steps (2) and (3) are repeated the sampling capacitor's voltage exceeds a fixed threshold (set to a half of the supply voltage). The number of cycles needed to charge the sampling capacitor corresponds to the capacitance of the sensing pad.
\end{enumerate}
\begin{figure}
\centering
\includegraphics[width=.9\textwidth] {img/tsc-wfm-bw.png} \\
\vspace{5mm}
\includegraphics[width=.9\textwidth] {img/tsc-wfm2-bw.png}
\caption{\label{fig:tsc-wfm}A voltage waveform measured on the touch sensing pad. The bottom side of the envelope equals the sampling capacitor's voltage---this is the phase where both capacitors are connected. The detailed view (middle) shows the individual charging cycles. The bottom screenshot captures the entire waveform after the analog comparator was disabled.}
\end{figure}

@ -4,7 +4,7 @@ GEX can be controlled through a hardware UART, the USB or over a wireless link.
The communication is organized in transactions. A transaction consists of one or more messages going in either direction. Messages can be stand-alone, or chained with a response or a follow-up message using the transaction ID. Both peers, GEX and the client application running on the PC, are equal in the communication: either side can independently initiate a transaction at any time. The communication is organized in transactions. A transaction consists of one or more messages going in either direction. Messages can be stand-alone, or chained with a response or a follow-up message using the transaction ID. Both peers, GEX and the client application running on the PC, are equal in the communication: either side can independently initiate a transaction at any time.
GEX uses a framing library \textit{TinyFrame}, developed likewise by the author, but kept as a separate project for easier re-use in different applications. The library implements frame building and parsing, checksum calculation and a system of message listeners. An interested reader may find more technical details and the API in its documentation. GEX uses a framing library \textit{TinyFrame}, developed likewise by the author but kept as a separate project for easier re-use in different applications. The library implements frame building and parsing, checksum calculation and a system of message listeners.
\section{Frame Structure} \section{Frame Structure}
@ -90,11 +90,19 @@ The following table lists all frame types used by GEX. It is divided into four l
\section{Bulk Read and Write Transactions} \section{Bulk Read and Write Transactions}
The bulk read and write transactions are generic, multi-message exchanges which are used to transfer the INI configuration files. They could possibly be used by some future unit requiring to transfer a large amount of data (e.g. to read image data from a camera). The bulk read and write transactions are generic, multi-message exchanges which are used to transfer the INI configuration files. They could additionally be used by some future unit requiring to transfer a large amount of data (e.g. to read image data from a camera).
The reason for splitting a long file into multiple messages, rather than sending it all in one, lies in the hardware limitations of the platform, specifically its small amount of RAM (the STM32F072 has only 16\,kB). A message cannot be processed until its payload checksum is received and verified; however, the configuration file can have several kilobytes, owning to the numerous explanatory comments, which would require a prohibitively large buffer. Further, the GEX module may need some time to process a part of the message before it can receive more data, which is easily achieved by this multi-part transport where each chunk must be confirmed before proceeding to the next. The reason for splitting a long file into multiple messages, rather than sending it all in one, lies in the hardware limitations of the platform, specifically its small amount of RAM (the STM32F072 has only 16\,kB). A message cannot be processed until its payload checksum is received and verified; however, the configuration file can have several kilobytes, owning to the numerous explanatory comments, which would require a prohibitively large data buffer. The chunked transaction could, additionally, be extended to support message re-transmission on timeout without sending the entire file again.
A read or write transaction can be aborted by a frame 0x08 (Bulk Abort) at any time, though aborting a write transaction may leave the configuration in a corrupt state. As hinted in the introduction of this chapter, a transaction is defined by sharing a common frame ID. Thus, all frames in a bulk transaction must have the same ID, otherwise the ID listeners won't be called and the transaction will fail. A read or write transaction can be aborted by a frame 0x08 (Bulk Abort) at any time, though aborting a write transaction may leave the configuration in a corrupted state. As hinted in the introduction of this chapter, a transaction is defined by sharing a common frame ID. Thus, all frames in a bulk transaction must have the same ID, otherwise the ID listeners won't be called for the subsequent messages, and the transaction will time out.
Figure \ref{fig:bulk-rw} shows a diagram of the bulk read and write data flow.
\begin{figure}
\centering
\includegraphics[scale=1.5]{img/bulk-read-write.pdf}
\caption{\label{fig:bulk-rw}A diagram of the bulk read and write transaction.}
\end{figure}
\subsection{Bulk Read} \subsection{Bulk Read}

@ -1,14 +1,92 @@
\chapter{Wireless Interface} \chapter{Wireless Interface}
Four methods of a wireless connection have been considered: Bluetooth (e.g. with CC2541), WiFi with ESP8266, LoRA or GFSK-modulated 868\,MHz link with SX1276, and a 2.4\,GHz link with NRF24L01+. Bluetooth was dismissed early for its complexity and ESP8266 for its high consumption in continuous reception mode, although both solutions might be viable for certain applications and with more time for evaluation. The SX1276 and NRF24L01+ have both been tested using the first GEX prototype, confirming its usefulness as a hardware development tool. Four methods of a wireless connection have been considered: Bluetooth (e.g. with CC2541), WiFi with ESP8266, LoRA or GFSK-modulated 868\,MHz link with SX1276, and a 2.4\,GHz link with nRF24L01+. Bluetooth was dismissed early for its complexity and ESP8266 for its high consumption in continuous reception mode, although both solutions might be viable for certain applications and with more time for evaluation.
\section{Comparing SX1276 vs. NRF24L01+} The Semtech SX1276 and Nordic Semiconductor nRF24L01+ transceivers have both been tested using the first GEX prototype, confirming its usefulness as a hardware development tool, and it's been confirmed they could fulfill the requirements of the application.
\begin{figure}[h]
\centering
\includegraphics[width=.7\textwidth]{img/nrf-testing.jpg}
\caption{Test setup with a GEX prototype controlling two nRF24L01+ modules}
\end{figure}
\section{Comparing SX1276 vs. nRF24L01+}
The two transceivers are compared in table \ref{fig:nrf-sx-comparison}. It's apparent that each has its strengths and weaknesses.
\begin{table}[h]
\centering
\begin{tabulary}{\textwidth}{lLL}
\toprule
\textbf{Parameter} & \textbf{SX1276} & \textbf{nRF24L01+} \\
\midrule
\textbf{Connection} & SPI (4 pins) + up to 6 IRQ & SPI (4 pins), CE, IRQ \\
\textbf{Frequency band} & 868\,MHz or 433\,MHz & 2.4\,GHz \\
\textbf{Data rate} & up to 300\,kbps & 250--2000\,kbps \\
\textbf{Modulation} & (G)FSK, (G)MSK, OOK, LoRa & GFSK \\
% \textbf{Bandwidth} & 7--500\,kHz per channel & 0.7--2\,MHz per channel \\
\textbf{Range (est.)} & 2\,km to 20\,km LOS & up to 1\,km LOS \\
\textbf{Consumption Rx} & 10.8--12\,mA & 12.6--13.5\,mA \\
\textbf{Consumption Tx} & 20--120\,mA & 7--11.3\,mA \\
\textbf{Idle power (max)} & 1\,$\mu$A sleep, 2\,mA stand-by & 0.9\,$\mu$A sleep, 320\,$\mu$A stand-by \\
\textbf{Max packet size} & 300 bytes & 32 bytes \\
\textbf{Reset} & NRESET pin & Vdd disconnect \\
\textbf{Extra} & LoRa FHSS, packet engine & ShockBurst protocol engine \\
\textbf{Price} & \$7.3 & \$1.6 \\
\bottomrule
\end{tabulary}
\caption[Comparison of the SX1276 and nRF24L01+ wireless transceivers]{\label{fig:nrf-sx-comparison}Comparison of the SX1276 and nRF24L01+ wireless transceivers (price from DigiKey @ 10 pieces, May 6th 2018)}
\end{table}
SX1276 supports additional modulation modes, including a proprietary LoRa scheme with a frequency-hopping spread spectrum modulation that can be received at a distance up to 20\,km in ideal conditions. The long-range capability is reflected in a higher consumption during transmission. However, its consumption in receiver mode is slightly lower than that of the nRF24L01+.
nRF24L01+ provides higher data rates at short distances. Its power consumption is comparable or lower than that of the SX1276. It lacks a dedicated reset pin, but that can be easily worked around using an external transistor to momentarily disconnect its Vdd pin.
Both devices implement some form of a packet engine with error checking; that of the nRF24L01+, called ShockBurst, is more advanced as it implements acknowledgment responses and automatic re-transmission, leading to a potentially more robust communication without an additional overhead on the side of the microcontroller.
\section{Integration of the nRF24L01+ into GEX}
The nRF24L01+ was selected to be integrated into GEX thanks to its inclusion of the ShockBurst engine, higher possible data rates and significantly lower price. The SX1276, nonetheless, remains an interesting option that could be used as an alternative in the future, should the need for a long range communication arise.
A separate device, the \textit{GEX wireless gateway}, was developed to provide the PC connection to a nRF24L01+ module. It is based on the STM32F103 microcontroller in its smallest package (LQFP48), selected for it's low cost and good availability.
\subsection{The Wireless Gateway Protocol}
\begin{wrapfigure}[17]{r}{0.38\textwidth}
\vspace{-1em}
\centering
\includegraphics[scale=0.9]{img/rf-gw.pdf}
\caption{A block diagram of the wireless connection}
\end{wrapfigure}
The gateway presents itself to the host as a CDC/ACM device, much like the GEX modules themselves (here called \textit{nodes}) when connected over USB. It implements a simple protocol which encapsulates the binary data sent to or from a connected node. The wrapped GEX protocol (chapter \ref{sec:tinyframe}) remains unchanged.
The gateway has a 4-byte network ID, a number derived from the microcontroller's unique ID. The network ID must be entered into all nodes that wish to communicate with it. Additionally, each module must be assigned a unique 1-byte number, which, together with the four network ID bytes, uniquely identifies the node. The gateway can connect to up to 6 nodes at once.
All messages sent to or from the gateway are a multiple of 64 bytes long, padded with zeros if shorter. The message starts with a control byte, determining the message type (table \ref{fig:rf-dongle-commands}).
\begin{table}[h]
\centering
\begin{tabulary}{\textwidth}{lL}
\toprule
\textbf{Function} & \textbf{Message structure} \\
\midrule
Send a message & 'm' (\verb|u8|)address (\verb|u16|)length (\verb|u8[]|)payload \\
Restart \& remove nodes & 'r' \\
Add nodes & 'n' (\verb|u8|)count (\verb|u8[]|)addresses \\
Get the network ID & 'i' \\
Response to 'i' & 0x01 (\verb|u8[4]|)net\_id \\
Received message & 0x02 (\verb|u8|)address (\verb|u8|)length (\verb|u8[]|)data \\
\bottomrule
\end{tabulary}
\caption[Wireless gateway commands and messages]{\label{fig:rf-dongle-commands}Wireless gateway commands and messages; control characters in the printable range are shown as ASCII}
\end{table}
The gateway may be restarted using the 'r' command when the PC application starts. Then it adds all node addresses with the 'n' command and can begin communication. The 'i' command, reading the network ID, can additionally be used as a ping command to verify the USB connection.
\todo[inline]{Add additional commands. Also remove magic bytes form the real messages, they're useless}

@ -799,11 +799,17 @@
% Redefine the enumerate labels. The first two levels are boxed, % Redefine the enumerate labels. The first two levels are boxed,
% the other two are not. % the other two are not.
%\def\labelenumi{{\normalfont\itembox[ctubluedarkbg][white]{\bfseries\theenumi.}}} %\def\labelenumi{{\normalfont\itembox[ctubluedarkbg][white]{\bfseries\theenumi.}}}
% CUSTOM XXX removed the enumi boxes
\iffalse
\def\labelenumi{{\normalfont\itembox{\theenumi.}}} \def\labelenumi{{\normalfont\itembox{\theenumi.}}}
\def\labelenumii{{\normalfont\itembox(0.1em)(0.1em){\theenumii.}}} \def\labelenumii{{\normalfont\itembox(0.1em)(0.1em){\theenumii.}}}
\def\labelenumiii{{\normalfont(\theenumiii)}} \def\labelenumiii{{\normalfont(\theenumiii)}}
\def\labelenumiv{{\normalfont(\theenumiv)}} \def\labelenumiv{{\normalfont(\theenumiv)}}
\fi
\leftmargini22.2pt \leftmargini22.2pt
\labelsep6pt \labelsep6pt

@ -14,6 +14,8 @@
\usepackage{cprotect} \usepackage{cprotect}
\usepackage{framed} \usepackage{framed}
\usepackage{subcaption} \usepackage{subcaption}
\usepackage{tabularx}
\usepackage{tabulary}
\usepackage{flafter} % ensures embeds won't go before their references \usepackage{flafter} % ensures embeds won't go before their references
\usepackage{enumitem} % better list spacing \usepackage{enumitem} % better list spacing
@ -22,6 +24,9 @@
\usepackage{makecell} \usepackage{makecell}
\newminted{ini}{frame=leftline,autogobble=true}
\newcommand{\uF}{\micro\farad} \newcommand{\uF}{\micro\farad}
\newcommand{\nF}{\nano\farad} \newcommand{\nF}{\nano\farad}
\newcommand{\cm}{\centi\metre} \newcommand{\cm}{\centi\metre}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@ -0,0 +1,517 @@
<html>
<!-- http://home.teleport.com/~brainy/fat16.htm -->
<head>
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>FAT16 Structure Information</title>
</head>
<body>
<p align="center"><strong><u><big>FAT16 Structure Information - Written by Jack Dobiash</big></u></strong></p>
<p align="center"><em><small>Updated : June 17th, 1999</small></em></p>
<p>Looking for FAT32 Info?&nbsp; Go <a href="http://home.teleport.com/~brainy/fat32.htm">here</a>.<br>
Looking for Informaton on how to Read and Write to your Hard Drive?&nbsp; Go <a
href="http://home.teleport.com/~brainy/diskaccess.htm">here</a>.</p>
<p>I've written this page for anyone who wishes to write software that can do low-level
reading and writing of a hard drive, and needs to know what the underlying structure of a
FAT16 Drive is, in order to interpret the information properly.&nbsp; Basically I've
searched all over the web, and have compiled this information in one spot. &nbsp;&nbsp;
Hopefully it can be of use to someone.&nbsp; I don't guarantee that all of this
information is correct or complete, but so far is seems to have been working for me.
&nbsp;</p>
<p>A lot of the number references I've made in this document are in Hexadecimal.&nbsp; Any
that are have an 'h' after them.&nbsp; Also, just in case my terminology may be different
from yours; a 'WORD' is 2 Bytes and a 'DOUBLE WORD' is 4 Bytes.</p>
<p>&nbsp;</p>
<p><u><strong>Master Boot Record</strong></u></p>
<blockquote>
<p>The Master Boot Record is the same for pretty much all Operating Systems.&nbsp; It is
located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1.&nbsp; It
is the first piece of code that your computer runs after it has checked all of your
hardware (POST) and turned control of loading software over the hard drive.&nbsp; It also
contains the partition table, which defines the different sections of your hard
drive.&nbsp; Basically if anything happens to this little 512 byte section, your hard
drive is brain dead.&nbsp; Kinda scary, eh? :)</p>
</blockquote>
<div align="left">
<table border="1" width="455" height="79">
<tr>
<td width="44" height="25">Offset</td>
<td width="269" height="25">Description</td>
<td width="52" height="25">Size</td>
</tr>
<tr>
<td width="44" height="25">000h</td>
<td width="269" height="25">Executable Code (Boots Computer)</td>
<td width="52" height="25">446 Bytes</td>
</tr>
<tr>
<td width="44" height="22">1BEh</td>
<td width="269" height="1">1st Partition Entry (See Next Table)</td>
<td width="52" height="22">16 Bytes</td>
</tr>
<tr>
<td width="44" height="17">1CEh</td>
<td width="269" height="17">2nd Partition Entry</td>
<td width="52" height="17">16 Bytes</td>
</tr>
<tr>
<td width="44" height="12">1DEh</td>
<td width="269" height="12">3rd Partition Entry</td>
<td width="52" height="12">16 Bytes</td>
</tr>
<tr>
<td width="44" height="20">1EEh</td>
<td width="269" height="20">4th Partition Entry</td>
<td width="52" height="20">16 Bytes</td>
</tr>
<tr>
<td width="44" height="16">1FEh</td>
<td width="269" height="16">Executable Marker (55h AAh)</td>
<td width="52" height="16">2 Bytes</td>
</tr>
</table>
</div>
<p><br>
<strong>Partition Entry (Part of MBR)</strong></p>
<div align="left">
<table border="1" width="523" height="236">
<tr>
<td width="47" height="7">Offset</td>
<td width="328" height="7">Description</td>
<td width="130" height="7">Size</td>
</tr>
<tr>
<td width="47" height="8">00h</td>
<td width="328" height="8">Current State of Partition (00h=Inactive, 80h=Active)</td>
<td width="130" height="8">1 Byte</td>
</tr>
<tr>
<td width="47" height="18">01h</td>
<td width="328" height="18">Beginning of Partition - Head</td>
<td width="130" height="18">1 Byte</td>
</tr>
<tr>
<td width="47" height="19">02h </td>
<td width="328" height="19">Beginning of Partition - Cylinder/Sector (See Below)</td>
<td width="130" height="19">1 Word</td>
</tr>
<tr>
<td width="47" height="15">04h</td>
<td width="328" height="15">Type of Partition (See List Below)</td>
<td width="130" height="15">1 Byte</td>
</tr>
<tr>
<td width="47" height="13">05h</td>
<td width="328" height="13">End of Partition - Head</td>
<td width="130" height="13">1 Byte</td>
</tr>
<tr>
<td width="47" height="15">06h</td>
<td width="328" height="15">End of Partition - Cylinder/Sector</td>
<td width="130" height="15">1 Word</td>
</tr>
<tr>
<td width="47" height="22">08h</td>
<td width="328" height="22">Number of Sectors Between the MBR and the First Sector in the
Partition</td>
<td width="130" height="22">1 Double Word</td>
</tr>
<tr>
<td width="47" height="22">0Ch</td>
<td width="328" height="22">Number of Sectors in the Partition</td>
<td width="130" height="22">1 Double Word</td>
</tr>
</table>
</div>
<p><br>
<strong>Cylinder/Sector Encoding</strong></p>
<blockquote>
<p>I guess back in the days of 10MB hard drives and 8086's, code was at a premium. &nbsp;
So they did everything they could to preserve space.&nbsp; Unfortunately now we have to
live with it, but luckily they created new ways of translating the system so the 1024
Cylinder Limit (2^10) isn't too big of a problem, for newer computers, at least. &nbsp;
Older ones usually need some sort of Disk Overlay program to make them see the whole hard
drive.&nbsp;&nbsp; </p>
<p>Anyway, to get the Sector out of this, you need to apply an AND mask ($3F) to it.
&nbsp; To get the Cylinder, you take the high byte and OR it with the low byte that has
been AND masked with ($C0) and then Shifted Left Two.&nbsp; It's not very easy to explain,
so I'll just show you how I did it with two routines I made (In Pascal) for Encoding and
Decoding the Cylinder/Sector.&nbsp; Hopefully even if you don't know Pascal you'll be able
to read it.</p>
<p>Function CylSecEncode(Cylinder, Sector : Word) : Word;<br>
Begin<br>
&nbsp;&nbsp;&nbsp; CylSecEncode := (Lo(Cylinder) shl 8) or (Hi(Cylinder) shl 6) or Sector;<br>
End;<br>
<br>
Procedure CylSecDecode(Var Cylinder, Sector : Word; CylSec : Word);<br>
Begin<br>
&nbsp;&nbsp;&nbsp; Cylinder := Hi(CylSec) or ((Lo(CylSec) and $C0) shl 2);<br>
&nbsp;&nbsp;&nbsp; Sector := (CylSec and $3F);<br>
End;<br>
</p>
</blockquote>
<div align="left">
<table border="1" width="418" height="48">
<tr>
<td width="10" height="23">15</td>
<td width="13" height="23">14</td>
<td width="18" height="23">13</td>
<td width="7" height="23">12</td>
<td width="12" height="23">11</td>
<td width="20" height="23">10</td>
<td width="19" height="23">9</td>
<td width="20" height="23">8</td>
<td width="36" height="23">7</td>
<td width="29" height="23">6</td>
<td width="20" height="23">5</td>
<td width="22" height="23">4</td>
<td width="21" height="23">3</td>
<td width="22" height="23">2</td>
<td width="25" height="23">1</td>
<td width="23" height="23">0</td>
</tr>
<tr>
<td width="184" height="13" colspan="8">Cylinder Bits 7 to 0</td>
<td width="67" height="13" colspan="2">Cylinder Bits 9+8</td>
<td width="149" height="13" colspan="6">Sector Bits 5 to 0</td>
</tr>
</table>
</div>
<p><br>
<strong>Partition Type Listing</strong></p>
<blockquote>
<p>There are more than just these shown, but I've only included that ones relevant to MS
Operating Systems.</p>
</blockquote>
<div align="left">
<table border="1" width="418" height="57">
<tr>
<td width="52" height="23">Value</td>
<td width="354" height="23">Description</td>
</tr>
<tr>
<td width="52" height="10">00h</td>
<td width="354" height="10">Unknown or Nothing</td>
</tr>
<tr>
<td width="52" height="13">01h</td>
<td width="354" height="13">12-bit FAT</td>
</tr>
<tr>
<td width="52" height="0">04h</td>
<td width="354" height="0">16-bit FAT (Partition Smaller than 32MB)</td>
</tr>
<tr>
<td width="52" height="8">05h</td>
<td width="354" height="8">Extended MS-DOS Partition</td>
</tr>
<tr>
<td width="52" height="7">06h</td>
<td width="354" height="7">16-bit FAT (Partition Larger than 32MB)</td>
</tr>
<tr>
<td width="52" height="6">0Bh</td>
<td width="354" height="6">32-bit FAT (Partition Up to 2048GB)</td>
</tr>
<tr>
<td width="52" height="10">0Ch</td>
<td width="354" height="10">Same as 0BH, but uses LBA<sub>1</sub> 13h Extensions</td>
</tr>
<tr>
<td width="52" height="12">0Eh</td>
<td width="354" height="12">Same as 06H, but uses LBA<sub>1</sub> 13h Extensions</td>
</tr>
<tr>
<td width="52" height="1">0Fh</td>
<td width="354" height="1">Same as 05H, but uses LBA<sub>1</sub> 13h Extensions</td>
</tr>
</table>
</div>
<p><br>
<u><strong>Reading Multiple Partitions</strong></u></p>
<blockquote>
<p>Since FAT16 is limited to 2GB per partition, drives that use it tend to have multiple
partitions.&nbsp; The first partition is the Primary Partition, and everything else is
stored in the Extended Partition.&nbsp; It's a little tricky when it comes to reading
those extra partitions though (not a lot, just a little).&nbsp; The first record in the
partition table shows where the Primary partition is (how big it is, where it starts, and
where it ends).&nbsp; The second entry in the partition table shows where the Entire
Extended Partition is (which may include more than just one partition).&nbsp; To read any
more partitions, you go to the where it says the Extended Partition starts, and read the
first sector.&nbsp; It acts just like the MBR.&nbsp; It'll have blank where the code is
supposed to be, and in the partition table it will have for it's first entry the next
Partition in the Drive, and if there are anymore, there will be another Extended
partition, just like before.&nbsp; However, all references to Sector Numbers are made
using the that new MBR point as the reference, making it a virtual drive.&nbsp; Just
incase this doesn't make much sense (and by the way I explain things I can understand if
it doesn't), let me show you how a drive with three partitions is setup.</p>
<p>MBR of Whole Drive</p>
<p>&nbsp;&nbsp;&nbsp; Entry #1 - Points to Partition #1<br>
&nbsp;&nbsp;&nbsp; Entry #2 - Points to the Entire Extended Partition</p>
<p>You would read the first sector of that Extended Partition, and see another MBR
Structure.</p>
<p>MBR of Extended Partition</p>
<p>&nbsp;&nbsp;&nbsp; Entry #1 - Points to Partition #2<br>
&nbsp;&nbsp;&nbsp; Entry #2 - Points to Rest of Extended Partition after Partition #2</p>
<p>Now, all references to Sector Numbers (most specifically the entry at Offset 08h) in
those Entries wouldn't be referenced from the start of the drive, but from the start of
the Extended Partition.&nbsp; However, the CHS (Cylinder, Head, Sector) numbers would
still be right.</p>
<p>Once again, you would read the first sector of that Extended Partition, and see the
next MBR.</p>
<p>MBR of Rest of Extended Partition</p>
<p>&nbsp;&nbsp;&nbsp; Entry #1 - Points to Partition #3<br>
&nbsp;&nbsp;&nbsp; No Entry #2, since this was the Last Partition</p>
<p>If there were another partition, the pattern would continue just like before, until the
last one was reached.</p>
</blockquote>
<p>&nbsp;</p>
<p><br>
<u><strong>FAT16 Boot Record</strong></u></p>
<blockquote>
<p>This information is located in the first sector of every partition.</p>
</blockquote>
<div align="left">
<table border="1" width="518" height="192">
<tr>
<td width="60" height="19">Offset</td>
<td width="329" height="19">Description</td>
<td width="110" height="19">Size</td>
</tr>
<tr>
<td width="60" height="10">00h</td>
<td width="329" height="10">Jump Code + NOP</td>
<td width="110" height="10">3 Bytes</td>
</tr>
<tr>
<td width="60" height="25">03h</td>
<td width="329" height="25">OEM Name</td>
<td width="110" height="25">8 Bytes</td>
</tr>
<tr>
<td width="60" height="6">0Bh</td>
<td width="329" height="6">Bytes Per Sector</td>
<td width="110" height="6">1 Word</td>
</tr>
<tr>
<td width="60" height="7">0Dh</td>
<td width="329" height="7">Sectors Per Cluster</td>
<td width="110" height="7">1 Byte</td>
</tr>
<tr>
<td width="60" height="12">0Eh</td>
<td width="329" height="12">Reserved Sectors</td>
<td width="110" height="12">1 Word</td>
</tr>
<tr>
<td width="60" height="7">10h</td>
<td width="328" height="7">Number of Copies of FAT</td>
<td width="111" height="7">1 Byte</td>
</tr>
<tr>
<td width="60" height="4">11h</td>
<td width="328" height="4">Maximum Root Directory Entries</td>
<td width="111" height="4">1 Word</td>
</tr>
<tr>
<td width="60" height="5">13h</td>
<td width="328" height="5">Number of Sectors in Partition Smaller than 32MB</td>
<td width="111" height="5">1 Word</td>
</tr>
<tr>
<td width="60" height="8">15h</td>
<td width="328" height="8">Media Descriptor (F8h for Hard Disks)</td>
<td width="111" height="8">1 Byte</td>
</tr>
<tr>
<td width="60" height="4">16h</td>
<td width="328" height="4">Sectors Per FAT</td>
<td width="111" height="4">1 Word</td>
</tr>
<tr>
<td width="61" height="14">18h</td>
<td width="328" height="14">Sectors Per Track</td>
<td width="111" height="14">1 Word</td>
</tr>
<tr>
<td width="61" height="23">1Ah</td>
<td width="328" height="23">Number of Heads</td>
<td width="111" height="23">1 Word</td>
</tr>
<tr>
<td width="61" height="22">1Ch</td>
<td width="328" height="22">Number of Hidden Sectors in Partition</td>
<td width="111" height="22">1 Double Word</td>
</tr>
<tr>
<td width="61" height="22">20h</td>
<td width="328" height="22">Number of Sectors in Partition</td>
<td width="111" height="22">1 Double Word</td>
</tr>
<tr>
<td width="61" height="22">24h</td>
<td width="328" height="22">Logical Drive Number of Partition</td>
<td width="111" height="22">1 Word</td>
</tr>
<tr>
<td width="61" height="22">26h</td>
<td width="328" height="22">Extended Signature (29h)</td>
<td width="111" height="22">1 Byte</td>
</tr>
<tr>
<td width="61" height="22">27h</td>
<td width="328" height="22">Serial Number of Partition</td>
<td width="111" height="22">1 Double Word</td>
</tr>
<tr>
<td width="61" height="22">2Bh</td>
<td width="328" height="22">Volume Name of Partition</td>
<td width="111" height="22">11 Bytes</td>
</tr>
<tr>
<td width="61" height="22">36h</td>
<td width="328" height="22">FAT Name (FAT16)</td>
<td width="111" height="22">8 Bytes</td>
</tr>
<tr>
<td width="61" height="22">3Eh</td>
<td width="328" height="22">Executable Code</td>
<td width="111" height="22">448 Bytes</td>
</tr>
<tr>
<td width="61" height="22">1FEh</td>
<td width="328" height="22">Executable Marker (55h AAh)</td>
<td width="111" height="22">2 Bytes</td>
</tr>
</table>
</div>
<p><br>
<br>
<u><strong>FAT16 Drive Layout</strong></u></p>
<div align="left">
<table border="1" width="521" height="64">
<tr>
<td width="374" height="23">Offset</td>
<td width="111" height="23">Description</td>
</tr>
<tr>
<td width="374" height="10">Start of Partition</td>
<td width="111" height="10">Boot Sector</td>
</tr>
<tr>
<td width="374" height="14">Start + # of Reserved Sectors</td>
<td width="111" height="14">Fat Tables</td>
</tr>
<tr>
<td width="374" height="-1">Start + # of Reserved + (# of Sectors Per FAT * 2)</td>
<td width="111" height="-1">Root Directory Entry</td>
</tr>
<tr>
<td width="374" height="3">Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum
Root Directory Entries * 32) / Bytes per Sector) </td>
<td width="111" height="3">Data Area (Starts with Cluster #2)</td>
</tr>
</table>
</div>
<p>&nbsp;</p>
<p><u><strong>Cluster Meaning (FAT Table Entries)</strong></u></p>
<blockquote>
<p>A Cluster is a Group of Sectors on the Hard Drive that have information in them. &nbsp;
A 16K Cluster has 32 Sectors in it (512*32=16384).&nbsp; Each Cluster is given a spot in
the FAT Table.&nbsp; When you look at an Entry in the FAT, the number there tells you
whether or not that cluster has data in it, and if so, if it is the end of the data or
there is another cluster after it.&nbsp; All Data on a Partition starts with Cluster #2
(Right after Root Directory). &nbsp;&nbsp; If the FAT Entry is 0, then there is no data in
that cluster.&nbsp; If the FAT Entry is FFFFh, then it is the last entry in the
chain.&nbsp; </p>
</blockquote>
<div align="left">
<table border="1" width="430" height="78">
<tr>
<td width="247" height="19">FAT Code Range</td>
<td width="171" height="19">Meaning</td>
</tr>
<tr>
<td width="247" height="11">0000h</td>
<td width="171" height="11">Available Cluster</td>
</tr>
<tr>
<td width="247" height="10">0002h-FFEFh</td>
<td width="171" height="10">Used, Next Cluster in File</td>
</tr>
<tr>
<td width="247" height="7">FFF0h-FFF6h</td>
<td width="171" height="7">Reserved Cluster</td>
</tr>
<tr>
<td width="247" height="4">FFF7h</td>
<td width="171" height="4">BAD Cluster</td>
</tr>
<tr>
<td width="247" height="9">FFF8h-FFFF</td>
<td width="171" height="9">Used, Last Cluster in File</td>
</tr>
</table>
</div>
<p><u><strong>Directory Table</strong></u></p>
<blockquote>
<p>Another aspect when looking at a File System at Low Level is the Directory Table.
&nbsp; The Directory Table is what stores all of the File and Directory Entries.
&nbsp;Someone else has already written a good resource for this information on the net, so
go <a href="http://home.teleport.com/~brainy/lfn.htm">here</a> to look at it.&nbsp; The
link doesn't work anymore, but luckily I saved the page a while back, so i'll just post it
on my site.</p>
</blockquote>
<p>&nbsp;</p>
<p>Footnotes</p>
<p>1 - LBA = Logical Block Addressing - Uses the Int 13h Extensions built into newer
BIOS's to access data above the 8GB
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
barrier, or to access strickly in LBA mode, instead of CHS (Cylinder, Head, Sector).</p>
<p align="center"><a href="http://home.teleport.com/~brainy">Home</a> <a
href="http://home.teleport.com/~brainy/rps.html">Reference Point Software</a> <a
href="http://home.teleport.com/~brainy/fat32.htm">FAT32 Structure Information</a> FAT16
Structure Information <a href="http://home.teleport.com/~brainy/diskaccess.htm">Disk Access
Information</a> <br>
<a href="http://home.teleport.com/~brainy/bio.html">About Me</a> <a
href="http://home.teleport.com/~brainy/links.html">Links</a> <a
href="http://home.teleport.com/~brainy/dobiash.html">Dobiash?</a></p>
</body>
</html>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,580 @@
<!doctype html public "-//w3c//DTD HTML 3.2//EN">
<html>
<!-- http://home.teleport.com/~brainy/lfn.htm -->
<!-- http://members.aol.com/vindaci/pub/doc/lfn/lfn.html -->
<!-- Copyright (c)1996-1998 vinDaci -->
<head>
<title>Long Filename Specification</title>
</head>
<body>
<h2 align="center">Long Filename Specification</h2>
<font size="-1">
<p align="center">by vinDaci</font> <font size="-2"><br>
fourth release</font> <font size="-1"><br>
First Release: November 18th, 1996</font> <font size="-1"><br>
Last Update: January 6th, 1998 (Document readability update)</font> </p>
<hr>
<h3>Compatibility</h3>
<p>Long filename (here on forth referred to as &quot;LFN&quot;) design for Windows95 is
designed to be 99% compatible with the old DOS 8.3 format. The 1% discripency comes in
when old DOS programs can detect the <em>presence</em> of LFN (but unfortunately not the
LFN itself), which in no way interferes with regular program operations except for perhaps
low-level disk utility programs (such as disk error fixing programs, disk optimization
programs, anti-virus program, etc.) <a name="background"></p>
<hr>
<h3>DOS 8.3 Filename Background</h3>
<p>I trust that anyone who wish to know the details of LFN has at least a small knowledge
in DOS 8.3 filename specification. In this document, however, I'll assume you know very
little about the 8.3 filename specs, however. What you need to know in order to understand
this documentation is that 8.3 filenames are stored in a place on the disk called the <dfn>directory
table</dfn>. This place contains the list of filenames and other information associated
with each file, such as the file date, time, size, attributes, etc. (Note: Contrary to
some belief, the directory table is <em>not</em> the same as the FAT -- e-mail me if you
wish to know what FAT is.) </p>
<p>The file attributes, mentioned above, play some big roles in LFN. It is important to
note that a file's attributes are may consist of one or more of the following: </p>
<div align="center"><center>
<table width="50%" border="1">
<tr>
<td><code>Archive</code> </td>
</tr>
<tr>
<td><code>Read-Only</code> </td>
</tr>
<tr>
<td><code>System</code> </td>
</tr>
<tr>
<td><code>Hidden</code> </td>
</tr>
<tr>
<td><code>Directory</code> </td>
</tr>
<tr>
<td><code>Volume</code> </td>
</tr>
</table>
</center></div>
<p>Most programmers are aware of the Archive, Read-Only, System, and Hidden attrbiutes,
but for those of you who don't know, please allow me to explain what each of these
attributes is/does:
<ul>
<li>The <dfn>Archive attribute</dfn> tells that a file has been backed up (though most
programs just ignore this). </li>
<li>The <dfn>Read-Only attribute</dfn> keeps a file from accidentally getting overwritten;
note that any program can unset this attribute should it know how to detect this attribute
and unset it -- that's why it is used just to keep a file from <em>accidentally</em>
getting overwritten. </li>
<li>The <dfn>System attribute</dfn> tells that the file is used for some important operation
so it should not be messed with except by the program that created it; any file with this
attribute cannot be seen with the <kbd>DIR</kbd> command except with the <kbd>/a</kbd> or <kbd>/as</kbd>
arguments in DOS 5 and above. </li>
<li>The <dfn>Hidden</dfn> attribute tells that a file should normally be hidden from the
user's view. Any file with this attribute cannot be seen with <kbd>DIR</kbd> command
either, except with the <kbd>/a</kbd> or <kbd>/ah</kbd> arguments in DOS 5 and above. </li>
</ul>
<p>And the explanation of the other attributes (the <em>really</em> important ones):
<ul>
<li>The <dfn>Directory attribute</dfn> is used to tell that a file is not actually a file
but a directory. This type of file contains a pointer to a part of the disk that contains
another directory table; this directory table that's pointed to is the subdirectory of the
directory that has the pointer. In another words, when you &quot;CD&quot; to that file,
you go into the directory table the file points to, making it look as though you are
&quot;inside&quot; that directory. In reality, you only switch the directory tables. </li>
<li>The <dfn>volume attribute</dfn> too is used to tell that a file is not actually a file.
This attribute is used to indicate the volume label of the drive (the name of the disk). A
file with this attribute can never be displayed with the <kbd>DIR</kbd> command.
Furthermore, there can be only one file with this attribute on the entire disk, and this
file must be in the root directory of the disk. <br>
&nbsp;&nbsp;&nbsp;&nbsp; The volume attribute has a funny story attached to it -- There
not only exists a file with the volume attribute, but a copy of the volume label is also
located in the boot sector (the very beginning of the disk that has weird code and disk
info on it) as a readable text. But when you view a directory with the <kbd>DIR</kbd>
command, the one that actually gets displayed is the volume attributed file's name, not
the volume label in the boot sector. Furthermore, even though files with volume attribute
is hidden from the <kbd>DIR</kbd> command, programs, when retrieving filenames, can
retrieve volume labels.</a> All these factors about volume attributes come into a big
factor when we look at Long Filenames. </li>
</ul>
<p>As an addendum, it might be interesting to note that each 8.3 file entry is 32 bytes
long but that not all 32 bytes are used to store data -- some of them are plainly left as
blank bytes. In Windows95 version of the directory table, however, all 32 bytes are used. </p>
<hr>
<h3>General Specification</h3>
<p>Just like DOS 8.3 filenames, Windows95 LFNs are also stored on directory tables,
side-by-side with DOS 8.3 filenames. On top of that, to achieve compatibility with old DOS
programs Microsoft designed LFN in a way so it resembles the old DOS 8.3 format.
Furthermore, an 8.3 format version of LFN (<code>tttttt~n.xxx</code>) is also present next
to each LFN entry for compatibility with non-LFN supporting programs. <a
name="organization"></p>
<hr>
<h3>Organization</h3>
<p>From a low-level point-of-view, a normal directory table that only contains 8.3
filenames look like this: </p>
<div align="center"><center>
<table width="50%" border="1">
<tr>
<td><code>...</code> </td>
</tr>
<tr>
<td><code>8.3 entry</code> </td>
</tr>
<tr>
<td><code>8.3 entry</code> </td>
</tr>
<tr>
<td><code>8.3 entry</code> </td>
</tr>
<tr>
<td><code>8.3 entry</code> </td>
</tr>
</table>
</center></div>
<p>If you look at a directory table that contains LFN entries, however, this is what you
will see: </p>
<div align="center"><center>
<table width="50%" border="1">
<tr>
<td><code>...</code> </td>
</tr>
<tr>
<td><code>LFN entry 3</code> </td>
</tr>
<tr>
<td><code>LFN entry 2</code> </td>
</tr>
<tr>
<td><code>LFN entry 1</code> </td>
</tr>
<tr>
<td><code>8.3 entry (tttttt~n.xxx)</code> </td>
</tr>
</table>
</center></div>
<p>Notice that Long Filenames can be pretty long, so LFN entries in a 8.3 directory
structure can take up several 8.3 directory entry spaces. This is why the above file entry
has several LFN entries for a single 8.3 file entry. </p>
<p>Despite taking up 8.3 filename spaces, Long Filenames do not show up with the <kbd>DIR</kbd>
command or with any other program, even the ones that do not recognize the LFN. How, then,
do LFN entries get hidden from DOS? The answer is quite simple: By giving LFN entries
&quot;Read-only, System, Hidden, and Volume&quot; attributes. (If you do not know details
about file attributes, read the above text about </a><a href="#background">DOS 8.3
Filename Background</a>.) </p>
<p>A special attention should be given to the fact that this combination of attributes --
Read-only, System, Hidden, Volume -- is not possible to make under normal circumstances
using common utilities found in the market place (special disk-editing programs, such as
Norton Disk Editor, is an exception.) </p>
<p>This technique of setting Read-only, System, Hidden, Volume attributes works because
most programs ignore files with volume attributes altogether, and even if they don't, they
won't display any program that has system or hidden attributes set. And since the
Read-only attribute is set, programs won't write anything over it. However, you can view
&quot;parts&quot; of the LFN entries if any program is designed to show Volume attributed
files. </p>
<a name="storage">
<hr>
<h3>Storage Organization</h3>
<p>To understand the LFN storage organization within a directory table, it is important to
understand the 8.3 storage organization. This is mainly due to the fact that LFN entries
are stored similar to 8.3 filenames to avoid conflicts with DOS applications. </p>
<p>The format of the traditional DOS 8.3 is as follows: </p>
<div align="center"><center>
<table width="80%" border="1">
<tr>
<th width="15%" align="center">Offset </th>
<th width="15%" align="center">Length </th>
<th width="*" align="left">&nbsp;&nbsp;Value </th>
</tr>
<tr>
<td align="center">0 </td>
<td align="center">8 bytes </td>
<td align="left">&nbsp;&nbsp;Name </td>
</tr>
<tr>
<td align="center">8 </td>
<td align="center">3 bytes </td>
<td align="left">&nbsp;&nbsp;Extension </td>
</tr>
<tr>
<td align="center">11 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Attribute (<code>00ARSHDV</code>) <br>
&nbsp;&nbsp;<code>0</code>: unused bit <br>
&nbsp;&nbsp;<code>A</code>: archive bit, <br>
&nbsp;&nbsp;<code>R</code>: read-only bit <br>
&nbsp;&nbsp;<code>S</code>: system bit <br>
&nbsp;&nbsp;<code>D</code>: directory bit <br>
&nbsp;&nbsp;<code>V</code>: volume bit </td>
</tr>
<tr>
<td align="center">22 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Time </td>
</tr>
<tr>
<td align="center">24 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Date </td>
</tr>
<tr>
<td align="center">26 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Cluster (desc. below) </td>
</tr>
<tr>
<td align="center">28 </td>
<td align="center">dword </td>
<td align="left">&nbsp;&nbsp;File Size </td>
</tr>
</table>
</center></div>
<p align="center">Note: <dfn>WORD</dfn> = 2 bytes, <dfn>DWORD</dfn> = 4 bytes </p>
<p>Everything above you should know what they are except perhaps for the cluster. The
cluster is a value representing another part of the disk, normally used to tell where the
beginning of a file is. In case of a directory, it is the cluster that tells where the
subdirectory's directory table starts. </p>
<p>You may not know this, but LFN specification not only added the capability of having
longer filenames, but it also improved the capability of 8.3 filenames as well. This new
8.3 filename improvements are accomplished by using the unused directory table spaces
(Remember how I told you that 8.3 filenames take up 32 bytes but not all 32 bytes are
used? Now it's all used up!) This new format is as follows -- try comparing it with the
traditional format shown above!: </p>
<div align="center"><center>
<table width="80%" border="1">
<tr>
<th width="15%" align="center">Offset </th>
<th width="15%" align="center">Length </th>
<th width="*" align="left">&nbsp;&nbsp;Value </th>
</tr>
<tr>
<td align="center">0 </td>
<td align="center">8 bytes </td>
<td align="left">&nbsp;&nbsp;Name </td>
</tr>
<tr>
<td align="center">8 </td>
<td align="center">3 bytes </td>
<td align="left">&nbsp;&nbsp;Extension </td>
</tr>
<tr>
<td align="center">11 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Attribute (<code>00ARSHDV</code>) </td>
</tr>
<tr>
<td align="center">12 </td>
<td align="center">byte </td>
<td align="left" nowrap>&nbsp;&nbsp;NT (Reserved for WindowsNT; <br>
&nbsp;&nbsp;always 0) </td>
</tr>
<tr>
<td align="center">13 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Created time; millisecond portion </td>
</tr>
<tr>
<td align="center">14 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Created time; hour and minute </td>
</tr>
<tr>
<td align="center">16 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Created date </td>
</tr>
<tr>
<td align="center">18 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Last accessed date </td>
</tr>
<tr>
<td align="center">20 </td>
<td align="center">word </td>
<td align="left" nowrap>&nbsp;&nbsp;Extended Attribute <br>
&nbsp;&nbsp;(reserved for OS/2; always 0) </td>
</tr>
<tr>
<td align="center">22 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Time </td>
</tr>
<tr>
<td align="center">24 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Date </td>
</tr>
<tr>
<td align="center">26 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Cluster </td>
</tr>
<tr>
<td align="center">28 </td>
<td align="center">dword </td>
<td align="left">&nbsp;&nbsp;File Size </td>
</tr>
</table>
</center></div>
<p>In any case, this new 8.3 filename format is the format used with the LFN. As for the
LFN format itself (seen </a><a href="#organization">previously</a>) is stored
&quot;backwards&quot;, with the first entry toward the bottom and the last entry at the
top, right above the new 8.3 filename entry. </p>
<p>Each LFN entry is stored as follows: </p>
<div align="center"><center>
<table width="80%" border="1">
<tr>
<th width="15%" align="center">Offset </th>
<th width="15%" align="center">Length </th>
<th width="*" align="left">&nbsp;&nbsp;Value </th>
</tr>
<tr>
<td align="center">0 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Ordinal field (desc. below) </td>
</tr>
<tr>
<td align="center">1 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 1 (desc. below) </td>
</tr>
<tr>
<td align="center">3 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 2 </td>
</tr>
<tr>
<td align="center">5 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 3 </td>
</tr>
<tr>
<td align="center">7 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 4 </td>
</tr>
<tr>
<td align="center">9 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 5 </td>
</tr>
<tr>
<td align="center">11 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Attribute </td>
</tr>
<tr>
<td align="center">12 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Type (reserved; always 0) </td>
</tr>
<tr>
<td align="center">13 </td>
<td align="center">byte </td>
<td align="left">&nbsp;&nbsp;Checksum (desc. below) </td>
</tr>
<tr>
<td align="center">14 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 6 </td>
</tr>
<tr>
<td align="center">16 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 7 </td>
</tr>
<tr>
<td align="center">18 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 8 </td>
</tr>
<tr>
<td align="center">20 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 9 </td>
</tr>
<tr>
<td align="center">22 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 10 </td>
</tr>
<tr>
<td align="center">24 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 11 </td>
</tr>
<tr>
<td align="center">26 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Cluster (unused; always 0) </td>
</tr>
<tr>
<td align="center">28 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 12 </td>
</tr>
<tr>
<td align="center">30 </td>
<td align="center">word </td>
<td align="left">&nbsp;&nbsp;Unicode character 13 </td>
</tr>
</table>
</center></div>
<p>Throughout this entry, you see &quot;unicode characters&quot;. Unicode characters are
2-byte long characters (as opposed to ASCII characters that are 1-byte long each) that
support not only traditional latin alphabet characters and arabic numbers but they also
support the languages of the rest of the world, including the CJK trio (Chinese, Japanese,
Korean), Arabic, Hebrew, etc. Plus you have some space left over for more math and science
symbols. Unicode characters are still going through revisions (on their second revision as
I am writing, I believe) but Windows95 has left spaces to more fully support unicodes in
the future. You can keep up with the Unicode development by visiting the Unicode webpage
at <a href="http://www.unicode.org/">www.unicode.org</a>. Note that, in the 2-byte unicode
character, the first byte is always the character and the second byte is always the blank,
as opposed to having the first byte blank and the second byte blank. There is a perfectly
logical explanation for this but it's kind of long to get into at the moment so e-mail me
if you are curious. (If you have a computer dictionary, look up &quot;little endian&quot;
and it'll explain everything.) For our purposes, though, just treat every other word as an
ASCII character as long as the following byte is a blank character. Anyways, notice that,
in order to maintain the compatibility with older programs, the attribute byte and the
cluster word had to be kept. Because of this, each unicode character had to be scattered
throughout the entry. </p>
<p>By now you probably noticed that there is no file information (size, date, etc.) stored
in the LFN entry. Any information about the file itself is stored in the 8.3 filename,
located below all the LFN entries (as <a href="#organization">mentioned before</a>). </p>
<p>The checksum is created from the shortname data. The steps/equation used to calculate
this checksum is as follows: </p>
<div align="center"><center>
<table width="80%" border="1">
<tr>
<th>Step # </th>
<th>Task </th>
</tr>
<tr>
<td align="center">1 </td>
<td align="left">&nbsp;&nbsp; Take the ASCII value of the first character. This is your
first sum. </td>
</tr>
<tr>
<td align="center">2 </td>
<td align="left">&nbsp;&nbsp; Rotate all the bits of the sum rightward by one bit. </td>
</tr>
<tr>
<td align="center">3 </td>
<td align="left">&nbsp;&nbsp; Add the ASCII value of the next character with the value
from above. This is your next sum. </td>
</tr>
<tr>
<td align="center">4 </td>
<td align="left">&nbsp;&nbsp; Repeat steps 2 through 3 until you are all through with the
11 characters in the 8.3 filename. </td>
</tr>
</table>
</center></div>
<p align="center">In C/C++, the above steps look like this: </p>
<div align="center"><center>
<table width="80%" border="0">
<tr>
<td><br>
<code>for (sum = i = 0; i &lt; 11; i++) {</code> <br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;sum = (((sum &amp; 1) &lt;&lt; 7) | ((sum &amp; 0xfe)
&gt;&gt; 1)) + name[i];</code> <br>
<code>}</code> </td>
</tr>
</table>
</center></div>
<p>This resulting checksum value is stored in each of the LFN entry to ensure that the
short filename it points to indeed is the currently 8.3 entry it should be pointing to. </p>
<p>Also, note that any file with a name that does not fill up the 8.3 spaces completely
leaves a trace of space characters (ASCII value 32) in the blank spaces. These blank
spaces do go into the calculation of the checksum and does not get left out of the
calculation. </p>
<p>I'm sure you're dying to know what the ordinal field is. This byte of information tells
the order of the LFN entries (1st LFN entry, 2nd LFN entry, etc.) If it's out of order,
something is wrong! How Windows95 would deal with LFN when such a thing happen is a
mystery to me. <br>
&nbsp;&nbsp; An example of how ordinal field work: The first LFN entry, located at the
very bottom as we have <a href="#organization">seen before</a>, has an ordinal field value
1; the second entry (if any -- remember that a LFN doesn't always have to be tens of
characters long), located just before the first entry, has an ordinal field value of 2;
etc. As an added precaution, the last entry has a marking on the ordinal field that tells
that it is the last entry. This marking is done by setting the 6th bit of the ordinal
field. </p>
<p>That is basically all there is to long filenames. But before we end this conversation
(while we're on the subject of LFN,) I think it would be interesting to note that, since
any long filename can be up to 255 bytes long and each entry can hold up to 13 characters,
there can only be up to 20 entries of LFN per file. That means it only needs 5 bits (0th
bit to 4th bit) of the ordinal field. And with the 6th bit used to mark the last entry,
two bits are left for open usage -- the 5th and the 7th bit. Whether or not Microsoft is
going to do anything with these bits -- or why Microsoft used the 6th bit to indicate the
last entry instead of 7th or 5th bit and limited the file length to 255 bits -- remains to
be a mystery only Microsoft will keep to itself. </p>
<hr>
<h3>Credit</h3>
<p><font size="-1">Much the information in this documentation has been gathered from
Norton Utilities for Windows95 user's manual. Detailed researches were done using Norton
Utilities Disk Edit. The checksum calculation was graciously donated by Jacob Verhoeks to <code>comp.os.msdos.programmer</code>
Newsgroup as a reply to my request. Apparently the file Mr. Verhoeks used to get me the
checksum code, <code>vfat.txt</code>, that comes with newer Linux operating systems have
some good information on Windows95 LFN. BTW, I just (like, right now) found out that
checksum algorithm is also in Ralf Brown's Interrupt List. </font></p>
<hr>
<p>Copyright ©1996-1998 vinDaci </p>
</body>
</html>

Binary file not shown.

@ -0,0 +1,319 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<!-- http://www.maverick-os.dk/FileSystemFormats/VFAT_LongFileNames.html -->
<HTML LANG="en">
<HEAD>
<TITLE>Maverick - The Operating System</TITLE>
<META NAME="author" CONTENT="Lasse Krogh Thygesen">
<META NAME="copyright" CONTENT="(C) 1999 Lasse Krogh Thygesen">
<META NAME="keywords" CONTENT="maverick,operating system,os,x86,intel,ata,ide,eide,atapi,pic,pit,dma,protected mode,pmode">
<META NAME="description" CONTENT="">
<LINK REL="stylesheet" TYPE="text/css" HREF="Maverick.css">
</HEAD>
<BODY>
<DIV CLASS="MiniMenu">
[<A HREF="FAT32_FileSystem.html" TITLE="FAT32 File System">Previous</A>]
- [<A HREF="../Mainmenu_NoFrames.html" TITLE="Go to main menu">Main menu</A>]
- [<A HREF="../FileFormats/FileFormatID.html" TITLE="File Format ID">Next</A>]<BR>
</DIV>
<H1 CLASS="PreTitle">Specifications</H1>
<H1>VFAT Long File Names</H1>
<H1 CLASS="SubTitle">Usage: Stores long filenames (LFN) for Windows</H1>
<HR>
<DIV ID="Introduction">
<H2>Introduction</H2>
This isn't a file system in itself, but a kind of sub file system, which can be placed over a FAT12, FAT16 or FAT32 file system. The VFAT system is a way of hiding long file names in the directory structure of the FAT file systems.<BR>
<BR>
The filenames are stored using unicode characters which are 16 bit long.<BR>
<BR>
<BR>
</DIV>
<DIV ID="CoexistenceWithFAT">
<H2>Coexistence with FAT12, FAT16 & FAT32</H2>
Depending on the length of the long filename, the system will create a number of invalid 8.3 entries in the Directory Table, these are the LFN (Long Filename) entries. These <ABBR TITLE="Long Filename">LFN</ABBR> entries are stored with the with the last LFN entry topmost, and the first LFN entry just above a valid Directory Entry. So when looked upon from the top and down, the Directory Table looks something like this:<BR>
<BR>
<DIV ID="DirectoryExample" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Directory Example">
<CAPTION>
Directory Example
</CAPTION>
<COLGROUP>
<COL WIDTH="20%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="40%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="40%" ALIGN="Center" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Entry Nr.</TH>
<TH ALIGN="Center" VALIGN="Middle">Without LFN Entries</TH>
<TH ALIGN="Center" VALIGN="Middle">With LFN Entries</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>...</TD><TD>...</TD><TD>...</TD></TR>
<TR><TD>n</TD><TD>Normal 1</TD><TD>Normal 1</TD></TR>
<TR><TD>n+1</TD><TD>Normal 2</TD><TD>LFN for Normal 2 - Part 3</TD></TR>
<TR><TD>n+2</TD><TD>Normal 3</TD><TD>LFN for Normal 2 - Part 2</TD></TR>
<TR><TD>n+3</TD><TD>Normal 4</TD><TD>LFN for Normal 2 - Part 1</TD></TR>
<TR><TD>n+4</TD><TD>Normal 5</TD><TD>Normal 2</TD></TR>
<TR><TD>n+5</TD><TD>Normal 6</TD><TD>Normal 3</TD></TR>
<TR><TD>...</TD><TD>...</TD><TD>...</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
The LFN entries have the Volume Name, Hidden, System and the Read-Only flags set. So most programs won't display them because of the Volume Name flag (Volume entries are rarely displayed), and they won't be overwridden because of the Read-Only flag.<BR>
<BR>
<BR>
</DIV>
<DIV ID="DirectoryEntries">
<H2>Directory Entries</H2>
The VFAT Directory Format, can coexist on a normal FATxx system. The LFN entries are hidden from normal programs, and available to those who know how to read them. But in addition to the LFN entries the VFAT Directory Format enhances the original structure of the Directory Table as found in FAT16. The Directory Table can still be read by older applications, but all the unused space from the FAT16 format, is now used to store some additional information. This is the format of the VFAT Directory entries:<BR>
<BR>
<DIV ID="DirectoryEntryStructure" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Structure of the VFAT Directory Entries">
<CAPTION>
Structure of the VFAT Directory Entries
</CAPTION>
<COLGROUP>
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Offset</TH>
<TH ALIGN="Center" VALIGN="Middle">Size</TH>
<TH ALIGN="Center" VALIGN="Middle">Description</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>00h</TD><TD>8 bytes</TD><TD>Filename</TD></TR>
<TR><TD>08h</TD><TD>3 bytes</TD><TD>Filename extension</TD></TR>
<TR><TD>0Bh</TD><TD>1 bytes</TD><TD><A HREF="#FlagByte">Flag byte</A></TD></TR>
<TR><TD>0Ch</TD><TD>1 bytes</TD><TD>NT - Reserved for Windows NT - Should always be 0000h</TD></TR>
<TR><TD>0Dh</TD><TD>1 bytes</TD><TD>Creation Time - Millisecond</TD></TR>
<TR><TD>0Eh</TD><TD>2 bytes</TD><TD>Creation Time - Hour & Minute</TD></TR>
<TR><TD>10h</TD><TD>2 bytes</TD><TD>Created Date</TD></TR>
<TR><TD>12h</TD><TD>2 bytes</TD><TD>Last Accessed Data</TD></TR>
<TR><TD>14h</TD><TD>2 bytes</TD><TD>Starting cluster (High word) on FAT32 file systems, else 0000h</TD></TR>
<TR><TD>16h</TD><TD>2 bytes</TD><TD>Time</TD></TR>
<TR><TD>18h</TD><TD>2 bytes</TD><TD>Date</TD></TR>
<TR><TD>1Ah</TD><TD>2 bytes</TD><TD>Starting cluster (Low word)</TD></TR>
<TR><TD>1Ch</TD><TD>4 bytes</TD><TD>File size in bytes</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="FlagByte">
<H3>Flag Byte</H3>
The flag byte defines a set of flags which is set for directories, volume name, hidden files, system files, etc. These are the flags:<BR>
<BR>
<DIV ID="Flags" CLASS="Centered">
<TABLE WIDTH="60%" SUMMARY="Flags in the flag byte">
<CAPTION>
Flags in the flag byte
</CAPTION>
<COLGROUP SPAN="8" WIDTH="3%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable" COLSPAN="2">Unused</TD>
<TD CLASS="BitTable">A</TD>
<TD CLASS="BitTable">D</TD>
<TD CLASS="BitTable">V</TD>
<TD CLASS="BitTable">S</TD>
<TD CLASS="BitTable">H</TD>
<TD CLASS="BitTable">R</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="Achieved">
<H4>Achieved Flag</H4>
The A flag is set by a backup program, so that the user/program knows which files that has been backed up. This flag is not used correctly by many user and perhaps also by many operating systems.<BR>
<BR>
</DIV>
<DIV ID="System">
<H4>System</H4>
This flag shows that the file/directory is important for the system, and shouldn't be manipulated.<BR>
<BR>
</DIV>
<DIV ID="Hidden">
<H4>Hidden</H4>
This flag tell the system and programs that the file should be hidden for the user. But in a lot of programs this can be overwritten by the user.<BR>
<BR>
</DIV>
<DIV ID="ReadOnly">
<H4>Read Only</H4>
The flag is used to prevent programs from not automatically overwriting or deleting this file/directory.<BR>
<BR>
</DIV>
<DIV ID="Directory">
<H4>Directory</H4>
This flag is set, when an entry in the directory table is not pointing to the beginning of a file, but to another directory table. A sub-directory. The sub-directory is placed in the cluster, where the Starting Cluster field points to. The format of this sub-directory table is identical to the root directory table.<BR>
<BR>
</DIV>
<DIV ID="VolumeName">
<H4>Volume Name</H4>
When this flag is set, the directory entry is not pointing to a file, but to nothing. The only information used from this entry is the filename (8 bytes) plus the filename extension (3 bytes). These bytes form an 11 bytes long volume label (without any .) There may be only <B>one</B> valid entry on the entire disk with this flag set. And preferably this entry should be among the first 3 entries in the root directory table, if not, then MS-DOS can have trouble displaying the right volume label. This volume name should be the same as the one in the boot sector. The latter one is infact rarely used.<BR>
<BR>
<BR>
</DIV>
<DIV ID="LFNEntry">
<H2>LFN Entry</H2>
The LFN entries are, as described, placed above the real directory entry, for which they contain the long filename. The first 13 letters are in the first entry, letters 14-26 are in the second LFN entry, letters 27-39 are in the third LFN entry, and so on until the filename has ended. The maximum length of a filename has been limited to 255, even though this scheme has the potential to make them 1664 bytes long, Microsoft - who designed FAT32 - decided not to. The structure of each LFN entry is as follows:<BR>
<BR>
<DIV ID="LFNEntryStructure" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Structure of a LFN Entry">
<CAPTION>
Structure of a LFN Entry
</CAPTION>
<COLGROUP>
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Offset</TH>
<TH ALIGN="Center" VALIGN="Middle">Size</TH>
<TH ALIGN="Center" VALIGN="Middle">Description</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>00h</TD><TD>1 bytes</TD><TD><A HREF="#OrdinalField">Ordinal field</A></TD></TR>
<TR><TD>01h</TD><TD>2 bytes</TD><TD>Unicode Character 1</TD></TR>
<TR><TD>03h</TD><TD>2 bytes</TD><TD>Unicode Character 2</TD></TR>
<TR><TD>05h</TD><TD>2 bytes</TD><TD>Unicode Character 3</TD></TR>
<TR><TD>07h</TD><TD>2 bytes</TD><TD>Unicode Character 4</TD></TR>
<TR><TD>09h</TD><TD>2 bytes</TD><TD>Unicode Character 5</TD></TR>
<TR><TD>0Bh</TD><TD>1 bytes</TD><TD><A HREF="#FlagByte">Flag byte</A></TD></TR>
<TR><TD>0Ch</TD><TD>1 bytes</TD><TD>Reserved - Always 00h</TD></TR>
<TR><TD>0Dh</TD><TD>1 bytes</TD><TD><A HREF="#Checksum">Checksum</A></TD></TR>
<TR><TD>0Eh</TD><TD>2 bytes</TD><TD>Unicode Character 6</TD></TR>
<TR><TD>10h</TD><TD>2 bytes</TD><TD>Unicode Character 7</TD></TR>
<TR><TD>12h</TD><TD>2 bytes</TD><TD>Unicode Character 8</TD></TR>
<TR><TD>14h</TD><TD>2 bytes</TD><TD>Unicode Character 9</TD></TR>
<TR><TD>16h</TD><TD>2 bytes</TD><TD>Unicode Character 10</TD></TR>
<TR><TD>18h</TD><TD>2 bytes</TD><TD>Unicode Character 11</TD></TR>
<TR><TD>1Ah</TD><TD>2 bytes</TD><TD>Always 0000h</TD></TR>
<TR><TD>1Ch</TD><TD>2 bytes</TD><TD>Unicode Character 12</TD></TR>
<TR><TD>1Eh</TD><TD>2 bytes</TD><TD>Unicode Character 13</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
Only the cluster word (offset 1Ah) and the flag byte (offset 0Bh), are required for compatibility reasons.<BR>
<BR>
</DIV>
<DIV ID="OrdinalField">
<H3>Ordinal Field</H3>
The ordinal field is used to tell the system which number the LFN entry has, in the LFN string. The first LFN entry will have a value of 01h. The second LFN entry, if there is one, will have a value of 02h, and so on it continues. When a LFN entry contains the last character in the name the Last LFN bit is set (bit 6 in the Ordinal Field).<BR>
<BR>
<DIV ID="OrdinalFieldStructurePartTwo" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="LFN Numbering Field">
<CAPTION>
The Ordinal Field
</CAPTION>
<COLGROUP SPAN="8" WIDTH="3%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable">Deleted LFN</TD>
<TD CLASS="BitTable">Last LFN</TD>
<TD CLASS="BitTable" COLSPAN="6">LFN Number</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="Checksum">
<H3>Calculating the Checksum</H3>
The Checksum byte in each LFN entry is there to make sure that the LFN entry points to the right file. The checksum value is calculated on the basis of the 8.3 filename, which is present in the valid Directory Table entry. Spaces (ASCII: 20h) are also calculated. The algorithm for calculating the checksum is:<BR>
<BR>
<OL>
<LI>The ASCII value of the first character is the base sum.</LI>
<LI>Rotate the sum bitwise one bit to the right.</LI>
<LI>Add the ASCII value of the next character to the sum.</LI>
<LI>Repeat step 2 and 3 until all 11 characters has been added.</LI>
</OL>
<BR>
</DIV>
<DIV ID="UnicodeCharacters">
<H3>Unicode Characters</H3>
The Unicode characters in the specification is a 16 bit value, where the lower 8 bits represent the respective ASCII value and the upper 8 bits are clear. The means that the LFN names are just ASCII style names, with extra holes.<BR>
<BR>
<BR>
</DIV>
<DIV ID="Conclusion">
<H2>Conclusion</H2>
The VFAT Directory Format is a very clever way to add long filename support to the older FAT file systems, while still maintaining compatibility. It is however strange why Microsoft (who designed FAT32) didn't implemented native support for long filenames in FAT32 when they created it a few years back.<BR>
<BR>
</DIV>
</BODY>
</HTML>

@ -0,0 +1,816 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<!-- http://www.maverick-os.dk/FileSystemFormats/FAT16_FileSystem.html -->
<HTML LANG="en">
<HEAD>
<TITLE>Maverick - The Operating System</TITLE>
<META NAME="author" CONTENT="Lasse Krogh Thygesen">
<META NAME="copyright" CONTENT="(C) 1999 Lasse Krogh Thygesen">
<META NAME="keywords" CONTENT="maverick,operating system,os,x86,intel,ata,ide,eide,atapi,pic,pit,dma,protected mode,pmode">
<META NAME="description" CONTENT="">
<LINK REL="stylesheet" TYPE="text/css" HREF="Maverick.css">
</HEAD>
<BODY>
<DIV CLASS="MiniMenu">
[<A HREF="FAT12_FileSystem.html" TITLE="FAT12 File System">Previous</A>]
- [<A HREF="../Mainmenu_NoFrames.html" TITLE="Go to main menu">Main menu</A>]
- [<A HREF="FAT32_FileSystem.html" TITLE="FAT32 File System">Next</A>]<BR>
</DIV>
<H1 CLASS="PreTitle">Specifications</H1>
<H1>FAT16 File System</H1>
<H1 CLASS="SubTitle">Used: On machines with small harddrives running MS-DOS, Windows 95/98</H1>
<HR>
<DIV ID="Introduction">
<H2>Introduction</H2>
This is the 16-bit version of the FAT file system. The 16-bit part describes the way units are allocated on the drive. The FAT16 file system uses a 16-bit number to identify each allocation unit (called cluster), and this gives it a total of 65.536 clusters. The size of each cluster is defined in the boot sector of the volume (volume = partition). The File System ID number usually associated with FAT16 volumes are 04h and 06h. The first is used on volumes with less than 65536 sectors (typical this is on drives less than 32 Mb in size), and the latter one is used on volumes with more than 65536 sectors. There is also another variant which is used with the LBA address mode, that variant has a File System ID of 0Eh. <SPAN CLASS="Note">I do not know if the LBA variant is different from the CHS type. So far I don't se why anything should be changed to support LBA addresses.</SPAN><BR>
<BR>
</DIV>
<DIV ID="BasicStructure">
<H3>Basic Structure</H3>
The FAT16 file system structure contains the following regions:<BR>
<BR>
<DIV ID="FAT16Structure" CLASS="Centered">
<TABLE WIDTH="40%" SUMMARY="FAT16 File System Structure">
<CAPTION>
FAT16 File System Structure
</CAPTION>
<COLGROUP>
<COL WIDTH="100%" ALIGN="Center" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Region</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>Reserved Region (incl. Boot Sector)</TD></TR>
<TR><TD>File Allocation Table (FAT)</TD></TR>
<TR><TD>Root Directory</TD></TR>
<TR><TD>Data Region</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
The first sector (boot sector) contain information which is used to calculate the sizes and locations of the other regions. The boot sector also contain code to boot the operating system installed on the volume. The data region is split up into logical blocks called clusters. Each of these clusters has an accompanying entry in the FAT region. The cluster specific entry can either contain a value of the next cluster which contain data from the file, or a so called End-of-file value which means that there are no more clusters which contain data from the file. The root directory and its sub-directories contain filename, dates, attribute flags and starting cluster information about the filesystem objects.<BR>
<BR>
<BR>
</DIV>
<DIV ID="BootSector">
<H2>Boot Sector</H2>
The first sector in the reserved region is the boot sector. Though this sector is typical 512 bytes in can be longer depending on the media. The boot sector typical start with a 3 byte jump instruction to where the bootstrap code is stored, followed by an 8 byte long string set by the creating operating system. This is followed by the BIOS Parameter Block, and then by an Extended BIOS Parameter Block. Finally the boot sector contain boot code and a signature.<BR>
<BR>
<DIV ID="BootSectorStructure" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Structure of the FAT16 Boot sector">
<CAPTION>
Structure of the FAT16 Boot sector
</CAPTION>
<COLGROUP>
<COL WIDTH="10%" ALIGN="Center" VALIGN="Middle">
<COL WIDTH="10%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="10%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Part</TH>
<TH ALIGN="Center" VALIGN="Middle">Offset</TH>
<TH ALIGN="Center" VALIGN="Middle">Size</TH>
<TH ALIGN="Center" VALIGN="Middle">Description</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>Code</TD><TD>0000h</TD><TD>3 bytes</TD><TD>Code to jump to the bootstrap code.</TD></TR>
<TR><TD>OS Name</TD><TD>0003h</TD><TD>8 bytes</TD><TD>Oem ID - Name of the formatting OS</TD></TR>
<TR><TD ROWSPAN="12">BIOS Para- meter Block</TD><TD>000Bh</TD><TD>2 bytes</TD><TD><A HREF="#BytesPerSector">Bytes per Sector</A></TD></TR>
<TR><TD>000Dh</TD><TD>1 bytes</TD><TD><A HREF="#SectorsPerCluster">Sectors per Cluster</A> - Usual there is 512 bytes per sector.</TD></TR>
<TR><TD>000Eh</TD><TD>2 bytes</TD><TD><A HREF="#ReservedSectors">Reserved sectors</A> from the start of the volume.</TD></TR>
<TR><TD>0010h</TD><TD>1 bytes</TD><TD><A HREF="#NumberOfFATs">Number of FAT copies</A> - Usual 2 copies are used to prevent data loss.</TD></TR>
<TR><TD>0011h</TD><TD>2 bytes</TD><TD><A HREF="#RootEntriesCount">Number of possible root entries</A> - 512 entries are recommended.</TD></TR>
<TR><TD>0013h</TD><TD>2 bytes</TD><TD><A HREF="#SmallNumberOfSectors">Small number of sectors</A> - Used when volume size is less than 32 Mb.</TD></TR>
<TR><TD>0015h</TD><TD>1 bytes</TD><TD><A HREF="#MediaDescriptor">Media Descriptor</A></TD></TR>
<TR><TD>0016h</TD><TD>2 bytes</TD><TD><A HREF="#SectorsPerFAT">Sectors per FAT</A></TD></TR>
<TR><TD>0018h</TD><TD>2 bytes</TD><TD><A HREF="#SectorsPerTrack">Sectors per Track</A></TD></TR>
<TR><TD>001Ah</TD><TD>2 bytes</TD><TD><A HREF="#NumberOfHeads">Number of Heads</A></TD></TR>
<TR><TD>001Ch</TD><TD>4 bytes</TD><TD><A HREF="#HiddenSectors">Hidden Sectors</A></TD></TR>
<TR><TD>0020h</TD><TD>4 bytes</TD><TD><A HREF="#LargeNumberOfSectors">Large number of sectors</A> - Used when volume size is greater than 32 Mb.</TD></TR>
<TR><TD ROWSPAN="6">Ext. BIOS Para- meter Block</TD><TD>0024h</TD><TD>1 bytes</TD><TD><A HREF="#DriveNumber">Drive Number</A> - Used by some bootstrap code, fx. MS-DOS.</TD></TR>
<TR><TD>0025h</TD><TD>1 bytes</TD><TD><A HREF="#Reserved">Reserved</A> - Is used by Windows NT to decide if it shall check disk integrity.</TD></TR>
<TR><TD>0026h</TD><TD>1 bytes</TD><TD><A HREF="#ExtendedBootSignature">Extended Boot Signature</A> - Indicates that the next three fields are available.</TD></TR>
<TR><TD>0027h</TD><TD>4 bytes</TD><TD><A HREF="#VolumeSerialNumber">Volume Serial Number</A></TD></TR>
<TR><TD>002Bh</TD><TD>11 bytes</TD><TD><A HREF="#VolumeLabel">Volume Label</A> - Should be the same as in the root directory.</TD></TR>
<TR><TD>0036h</TD><TD>8 bytes</TD><TD><A HREF="#FileSystemType">File System Type</A> - The string should be 'FAT16 '</TD></TR>
<TR><TD>Code</TD><TD>003Eh</TD><TD>448 bytes</TD><TD><A HREF="#BootstrapCode">Bootstrap code</A> - May schrink in the future.</TD></TR>
<TR><TD>Sig.</TD><TD>01FEh</TD><TD>2</TD><TD><A HREF="#BootSectorSignature">Boot sector signature</A> - This is the AA55h signature.</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
<BR>
</DIV>
<DIV ID="BIOSParameterBlock">
<H3>BIOS Parameter Block</H3>
The BIOS Parameter Block contains basic information about the overall structure of the FAT file system. That is information such as sector and cluster size, location information of FAT copies, the root directory size etc..<BR>
<BR>
<DIV ID="BytesPerSector">
<H4>Bytes Per Sector</H4>
This value is the number of bytes in each physical sector. The allowed values are: 512, 1024, 2048 or 4096 bytes. A lot of code outthere are assuming 512 bytes per sectors, so any other values can give compatibility problems.<BR>
<BR>
</DIV>
<DIV ID="SectorsPerCluster">
<H4>Sectors Per Cluster</H4>
This is the number of sectors per cluster. The allowed values are: 1, 2, 4, 8, 16, 32 or 128. But de-facto is that most combinations of 'BytesPerCluster' * 'SectorsPerCluster' which gives a total value over 32 Kb per cluster, are not supported on many system.<BR>
<BR>
</DIV>
<DIV ID="ReservedSectors">
<H4>Reserved Sectors</H4>
Since the reserved region always contain the boot sector a zero value in this field is not allowed. The usual setting of this value is 1. The value is used to calculate the location for the first sector containing the FAT.<BR>
<BR>
</DIV>
<DIV ID="NumberOfFATs">
<H4>Number of FAT copies</H4>
This is the number of FAT copies in the file system. The recommended value is 2 (and then have two FAT copies), but other values are validm though they may not be supported on some system. The usage of two copies are to prevent data loss if one or part of one FAT copy is corrupted.<BR>
<BR>
</DIV>
<DIV ID="RootEntriesCount">
<H4>Root Entries Count</H4>
This value contain the number of entries in the root directory. Its recommended that the number of entries is an even multiple of the BytesPerSector values. The recommended value for FAT16 volumes is 512 entries (compatibility reasons).<BR>
<BR>
</DIV>
<DIV ID="SmallNumberOfSectors">
<H4>Small Number of Sectors</H4>
This field states the total number of sectors in the volume. That includes the number of sectors occupied by the four regions which the FAT16 file system consist of. For FAT16 volumes that use less than 65536 sectors this field is used. The File System Id in the MBR is then 04h. For FAT16 volumes that use more the 65535 sectors the <A HREF="#LargeNumberOfSectors">Large Number of Sectors</A> field is used and this one should be set to 0h.<BR>
<BR>
</DIV>
<DIV ID="MediaDescriptor">
<H4>Media Descriptor</H4>
These are the possible media descriptors values in the FAT boot sector. <SPAN CLASS="Note">This is the same value which must be in the low byte in the first entry of the FAT.</SPAN><BR>
<BR>
<DIV ID="MediaDescriptors" CLASS="Centered">
<TABLE WIDTH="60%" SUMMARY="The possible media descriptors">
<CAPTION>
Media Descriptors
</CAPTION>
<COLGROUP>
<COL WIDTH="20%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="20%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="60%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Hex Value</TH>
<TH ALIGN="Center" VALIGN="Middle">Capacity</TH>
<TH ALIGN="Center" VALIGN="Middle">Physical Format</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>F0</TD><TD>2.88 MB</TD><TD>3.5-inch, 2-sided, 36-sector</TD></TR>
<TR><TD>F0</TD><TD>1.44 MB</TD><TD>3.5-inch, 2-sided, 18-sector</TD></TR>
<TR><TD>F8</TD><TD>?</TD><TD>Fixed disk</TD></TR>
<TR><TD>F9</TD><TD>720 KB</TD><TD>3.5-inch, 2-sided, 9-sector</TD></TR>
<TR><TD>F9</TD><TD>1.2 MB</TD><TD>5.25-inch, 2-sided, 15-sector</TD></TR>
<TR><TD>FA</TD><TD>?</TD><TD>?</TD></TR>
<TR><TD>FB</TD><TD>?</TD><TD>?</TD></TR>
<TR><TD>FC</TD><TD>180 KB</TD><TD>5.25-inch, 1-sided, 9-sector</TD></TR>
<TR><TD>FD</TD><TD>360 KB</TD><TD>5.25-inch, 2-sided, 9-sector</TD></TR>
<TR><TD>FE</TD><TD>160 KB</TD><TD>5.25-inch, 1-sided, 8-sector</TD></TR>
<TR><TD>FF</TD><TD>320 KB</TD><TD>5.25-inch, 2-sided, 8-sector</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
<BR>
</DIV>
<DIV ID="SectorsPerFAT">
<H4>Sectors Per FAT</H4>
This is the number of sectors occupied by one copy of the FAT.<BR>
<BR>
</DIV>
<DIV ID="SectorsPerTrack">
<H4>Sectors Per Track</H4>
This value is used when the volume is on a media which have a geometry, that is when the <ABBR TITLE="Logical Block Address">LBA</ABBR> number is broken down into a Cylinder-Head-Sector address. This field represents the multiple of the max. Head and Sector value used when the volume was formatted. The field itself is used to check if the LBA to <ABBR TITLE="Cylinder-Head-Sector">CHS</ABBR> translation has changed, since the formatting. And for calculating the correct Cylinder, Head and Sector values for the translation algorithm.<BR>
<BR>
</DIV>
<DIV ID="NumberOfHeads">
<H4>Number of Heads</H4>
This value is used when the volume is on a media which have a geometry, that is when the <ABBR TITLE="Logical Block Address">LBA</ABBR> number is broken down into a Cylinder-Head-Sector address. This field represents the Head value used when the volume was formatted. The field itself is used to check if the LBA to <ABBR TITLE="Cylinder-Head-Sector">CHS</ABBR> translation has changed, since the formatting. And for calculating the correct Cylinder, Head and Sector values for the translation algorithm.<BR>
<BR>
</DIV>
<DIV ID="HiddenSectors">
<H4>Hidden Sectors</H4>
When the volume is on a media that is partitioned, this value contains the number of sectors preceeding the first sector of the volume.<BR>
<BR>
</DIV>
<DIV ID="LargeNumberOfSectors">
<H4>Large Number of Sectors</H4>
This field states the total number of sectors in the volume. That includes the number of sectors occupied by the four regions which the FAT16 file system consist of. For FAT16 volumes that use more than 65535 sectors this field is used. The File System Id in the MBR is then 06h. For FAT16 volumes that use less than 65536 sectors the <A HREF="#SmallNumberOfSectors">Small Number of Sectors</A> field is used and this one should be set to 0h.<BR>
<BR>
</DIV>
<BR>
</DIV>
<DIV ID="ExtendedBIOSParameterBlock">
<H3>Extended BIOS Parameter Block</H3>
The Extended BIOS Parameter Block contains information that is only used in the FAT16 file system.<BR>
<BR>
<DIV ID="DriveNumber">
<H4>Drive Number</H4>
This is the int 13h drive number of the drive. The value 00h is used for the first floppy drive and the value 80h is used for the first harddrive. MS-DOS's bootstrap uses this value to find the correct drive.<BR>
<BR>
</DIV>
<DIV ID="Reserved">
<H4>Reserved</H4>
Reserved byte. It was original used to store the cylinder on which the boot sector is located. But Windows NT uses this byte to store two flags. The lowest bit would indicates that a check disk should be run at boot time, and the second lowest flag indicates that a surface scan should be run.<BR>
<BR>
</DIV>
<DIV ID="ExtendedBootSignature">
<H4>Extended Boot Signature</H4>
If this byte contain a value of 29h it indicates that the following three fields are available.<BR>
<BR>
</DIV>
<DIV ID="VolumeSerialNumber">
<H4>Volume Serial Number</H4>
This value is a 32 bit random number, which, combined with the <A HREF="#VolumeLabel">volume label</A>, makes is possible to track removable media and check if the correct one is inserted.<BR>
<BR>
</DIV>
<DIV ID="VolumeLabel">
<H4>Volume Label</H4>
This 11 byte long string should match the volume label entry in the root directory. If no such entry is available this field should contain the string 'NO NAME ' (11 bytes long string). When updating the volume label, both, this field and the entry in the root directory should be updated.<BR>
<BR>
</DIV>
<DIV ID="FileSystemType">
<H4>File System Type</H4>
This 8 byte long string should be used for informational display only. Thats because its sometime incorrectly set. The field should contain the string 'FAT16 ' (8 bytes long string).<BR>
<BR>
</DIV>
<BR>
</DIV>
<DIV ID="BootstrapCode">
<H3>Bootstrap Code</H3>
The bootstrap code is different between operating system and versions which are intended to be loaded of this FAT16 volume. The responsability of the bootstrap code is to continue the boot sequence. If ex. MS-DOS is installed the bootstrap code will locate the file IO.SYS in the file system, load part of it into memory and then jump to a specific entrypoint in IO.SYS. What the bootstrap code does is vary between operating system.<BR>
<BR>
<BR>
</DIV>
<DIV ID="BootSectorSignature">
<H3>Boot Sector Signature</H3>
The word at offset 1FEh should contain the signature AA55h. This will indicate to the BIOS that the sector is executable. The signature is also used by other applications when validating that the correct sector has been loaded. <SPAN CLASS="Note">No matter what the Bytes Per Sector value is this signature should always be at offset 1FEh.</SPAN><BR>
<BR>
<BR>
</DIV>
<DIV ID="FileAllocationTable">
<H2>File Allocation Table</H2>
The <ABBR TITLE="File Allocation Table">FAT</ABBR> structure contain linked lists of files in the file system. Any file or directory entry in a (sub)directory list contain a cluster number for the first chunk of the file/directory. This cluster number also has an associated entry in the FAT. At this entry in the FAT a single word value either points to the next cluster/chunk or it contain an End-of-file value. These are the valid values:<BR>
<BR>
<DIV ID="ValidFATValue" CLASS="Centered">
<TABLE WIDTH="60%" SUMMARY="Valid FAT16 values">
<CAPTION>
Valid FAT16 values
</CAPTION>
<COLGROUP>
<COL WIDTH="30%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Value</TH>
<TH ALIGN="Center" VALIGN="Middle">Description</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>0000h</TD><TD>Free cluster</TD></TR>
<TR><TD>0001h - 0002h</TD><TD>Not allowed</TD></TR>
<TR><TD>0003h - FFEFh</TD><TD>Number of the next cluster</TD></TR>
<TR><TD>FFF7h</TD><TD>One or more bad sectors in cluster</TD></TR>
<TR><TD>FFF8h - FFFFh</TD><TD>End-of-file</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
Each FAT copy start with a value of FFxxh for the first cluster, where xx is equal to the <A HREF="#MediaDescriptor">Media Descriptor</A> field in the BIOS Parameter Block. The FAT entry for the second cluster is set to the End-of-file value (FFFFh). The two highest bits of this value may be used for dirty volume flags in the following way.<BR>
<BR>
<DIV ID="FATValue" CLASS="Centered">
<TABLE WIDTH="60%" SUMMARY="FAT Entry Value for 2nd cluster">
<CAPTION>
FAT Entry Value for 2nd cluster
</CAPTION>
<COLGROUP SPAN="32" WIDTH="6%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">15</TH>
<TH CLASS="BitTable">14</TH>
<TH CLASS="BitTable">13</TH>
<TH CLASS="BitTable">12</TH>
<TH CLASS="BitTable">11</TH>
<TH CLASS="BitTable">10</TH>
<TH CLASS="BitTable">9</TH>
<TH CLASS="BitTable">8</TH>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable">C</TD>
<TD CLASS="BitTable">E</TD>
<TD CLASS="BitTable" COLSPAN="14">These bits must be set</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
<TBODY>
<TR>
<TD CLASS="NoColor" COLSPAN="15" ALIGN="Left">
C = If clear then the volume may be dirty because it was not cleanly dismounted. If the bit is set then the volume is clean.<BR>
</TD>
</TR>
<TR>
<TD CLASS="NoColor" COLSPAN="15" ALIGN="Left">
E = If clear a read/write error was encountered during the last time the volume was mounted. If the bit is set then no read/write error was encountered.<BR>
</TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
It should be noted that the last entry in the FAT should be calculated by taking the number of clusters in the data area, and not relying on the <A HREF="#SectorsPerFAT">Sectors Per FAT</A> field in the BIOS Parameter Block. This is because the number of entries in the FAT doesn't have to be an even multiple of the bytes per sector value.<BR>
<BR>
The maximum size of each FAT copy is 128 Kb (2 * 65536).<BR>
<BR>
<BR>
</DIV>
<DIV ID="DirectoryEntry">
<H2>Directory Entry Structure</H2>
Each of the entries in a directory list is 32 byte long. The only directory which is in a fixed location is the root directory. This is also the only directory which may contain an entry with the Volume Label attribute set. The size of the <A HREF="#RootEntriesCount">root directory</A> is defined in the BIOS Parameter Block.<BR>
<BR>
Sub-directories are created by allocating a cluster which then are cleared so it doesn't contain any directory entries. Two default entries are then created: The '.' entry point to the directory itself, and the '..' entry points to the parent directory. If the contents of a sub-directory grows beyond what can be in the cluster a new cluster is allocated in the same way as for files.<BR>
<BR>
This is the format of the directory entries:<BR>
<BR>
<DIV ID="DirectoryEntryStructure" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Structure of the Directory Entries">
<CAPTION>
Structure of the Directory Entries
</CAPTION>
<COLGROUP>
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="15%" ALIGN="Center" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">Offset</TH>
<TH ALIGN="Center" VALIGN="Middle">Size</TH>
<TH ALIGN="Center" VALIGN="Middle">Description</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>00h</TD><TD>8 bytes</TD><TD><A HREF="#FilenameAndExtension">Filename</A></TD></TR>
<TR><TD>08h</TD><TD>3 bytes</TD><TD><A HREF="#FilenameAndExtension">Filename Extension</A></TD></TR>
<TR><TD>0Bh</TD><TD>1 bytes</TD><TD><A HREF="#AttributeByte">Attribute Byte</A></TD></TR>
<TR><TD>0Ch</TD><TD>1 bytes</TD><TD><A HREF="#ReservedForWindowsNT">Reserved</A> for Windows NT</TD></TR>
<TR><TD>0Dh</TD><TD>1 bytes</TD><TD><A HREF="#CreationTimeMillisecond">Creation</A> - Millisecond stamp (actual 100th of a second)</TD></TR>
<TR><TD>0Eh</TD><TD>2 bytes</TD><TD><A HREF="#CreationTimeDate">Creation Time</A></TD></TR>
<TR><TD>10h</TD><TD>2 bytes</TD><TD><A HREF="#CreationTimeDate">Creation Date</A></TD></TR>
<TR><TD>12h</TD><TD>2 bytes</TD><TD><A HREF="#LastAccessDate">Last Access Date</A></TD></TR>
<TR><TD>14h</TD><TD>2 bytes</TD><TD><A HREF="#ReservedForFAT32">Reserved for FAT32</A></TD></TR>
<TR><TD>16h</TD><TD>2 bytes</TD><TD><A HREF="#LastWriteTime">Last Write Time</A></TD></TR>
<TR><TD>18h</TD><TD>2 bytes</TD><TD><A HREF="#LastWriteDate">Last Write Date</A></TD></TR>
<TR><TD>1Ah</TD><TD>2 bytes</TD><TD><A HREF="#StatingCluster">Starting cluster</A></TD></TR>
<TR><TD>1Ch</TD><TD>4 bytes</TD><TD><A HREF="#FileSize">File size</A> in bytes</TD></TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="FilenameAndExtension">
<H4>Filename & Extension</H4>
The filename is 8 byte long. Shorter names must be trailing padded with space bytes (ASCII: 20h). The extension is 3 byte long and shorter names also have to be trailing padded. The characters allowed in the filename and extension are basicly the uppercase letters of the english alphabet, plus the digits 0 to 9.<BR>
<BR>
The first byte in the filename is treated special. The following rules apply:<BR>
<OL>
<LI>A value of 00h is interpertated as 'stop the search, there is no more entries in this directory'.</LI>
<LI>A value of 05h is should be replaced with the ASCII character E5h. The character is used in Japan.</LI>
<LI>Must not contain the value 20h.</LI>
<LI>A value of E5h is interpertated as 'the entry is free'.</LI>
<LI>Any of the values mentioned below are allowed.</LI>
</OL>
<BR>
The following characters are not allowed in the filename or its extension:<BR>
<OL>
<LI>Any character below 20h, except the 05h character.</LI>
<LI>Any character in the following list: 22h ("), 2Ah (*), 2Bh (+), 2Ch (,), 2Eh (.), 2Fh (/), 3Ah (:), 3Bh (;), 3Ch (<), 3Dh (=), 3Eh (>), 3Fh (?), 5Bh ([), 5Ch (\), 5Dh (]), 7Ch (|).</LI>
</OL>
<BR>
For compatibility reasons it is recommended to limit the characters to:<BR>
<OL>
<LI>Any uppercase characters from A to Z.</LI>
<LI>Any digit from 0 to 1.</LI>
<LI>Any of the following characters: #, $, %, &, ', (, ), -, @</LI>
</OL>
<BR>
</DIV>
<DIV ID="AttributeByte">
<H4>Attribute Byte</H4>
The attribute byte defines a set of flags which can be set for directories, volume name, hidden files, system files, etc. These are the flags:<BR>
<BR>
<DIV ID="Flags" CLASS="Centered">
<TABLE WIDTH="60%" SUMMARY="Flags in the Attribute byte">
<CAPTION>
Flags in the Attribute byte
</CAPTION>
<COLGROUP SPAN="8" WIDTH="3%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable" COLSPAN="2">Reserved</TD>
<TD CLASS="BitTable">A</TD>
<TD CLASS="BitTable">D</TD>
<TD CLASS="BitTable">V</TD>
<TD CLASS="BitTable">S</TD>
<TD CLASS="BitTable">H</TD>
<TD CLASS="BitTable">R</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="ReadOnly">
<H5>Read Only</H5>
This flag is used to prevent programs from not automatically overwriting or deleting this entry.<BR>
<BR>
</DIV>
<DIV ID="Hidden">
<H6>Hidden</H6>
This flag indicates to the system that the file should be hidden when doing normal directory listings. But in a lot of programs this can be overwritten by the user.<BR>
<BR>
</DIV>
<DIV ID="System">
<H5>System</H5>
This flag indicates that the file/directory is important for the system, and shouldn't be manipulated without any concern.<BR>
<BR>
</DIV>
<DIV ID="VolumeName">
<H5>Volume Name</H5>
When this flag is set, the directory entry is not pointing to a file, but to nothing. Thus the the Starting cluster must point the cluster 0. The only information used from this entry is the filename (8 bytes) plus the filename extension (3 bytes). These bytes form an 11 byte long volume label (without any .) There may be only <B>one</B> valid entry in the entire volume with this flag set. This entry must be in the root directory and preferably among the first entries, if not, then MS-DOS can have trouble displaying the right volume label if there are long file names present. This volume name should be the same as the one in the boot sector.<BR>
<BR>
<DIV ID="Directory">
<H5>Directory</H5>
This flag is set, when an entry in the directory table is not pointing to the beginning of a file, but to another directory table. A sub-directory. The sub-directory is placed in the cluster, which the Starting Cluster field points to. The format of this sub-directory table is identical to the root directory table.<BR>
<BR>
</DIV>
<DIV ID="Achieve">
<H5>Achieve Flag</H5>
This flag is used by backup utilities. The flag is set when ever a file is created, renamed or changed. Backup utilities can then use this flag to determine which files that has been modified since the last backup.<BR>
<BR>
<BR>
</DIV>
<DIV ID="ReservedForWindowsNT">
<H4>Reserved for Windows NT</H4>
This byte is used by Windows NT. It set the value to 0 when the file is created and then never look at it again. For what purpose it uses it is unknown.<BR>
<BR>
</DIV>
<DIV ID="CreationTimeMillisecond">
<H4>Creation Time - Millisecond</H4>
Due to size limitations this field (1 byte) only contains the millisecond stamp in counts of 10 milliseconds. Therefore valid values are between 0 and 199 inclusive.<BR>
<BR>
</DIV>
<DIV ID="CreationTimeDate">
<H4>Creation Time & Date</H4>
The 16 bit time field contain the time of day when this entry was created. The 16 bit date field contain the date when the entry was created. These two values never change. Both the <A HREF="#TimeFormat">time</A> field and the <A HREF="#DateFormat">date</A> field are in a special format.<BR>
<BR>
</DIV>
<DIV ID="LastAccessDate">
<H4>Last Access Date</H4>
This 16 bit field contain the date when the entry was last read or written to. In case of writes this field of cause contain the same value as the <A HREF="#LastWriteDate">Last Write Date</A> field. The <A HREF="#DateFormat">date</A> field is the same special format as the other dates.<BR>
<BR>
</DIV>
<DIV ID="ReservedForFAT32">
<H4>Reserved for FAT32</H4>
This word is reserved for the FAT32 File System. When used in that file system it will contain the high word of the starting cluster. In the FAT16 File System this word should be set to 0.<BR>
<BR>
</DIV>
<DIV ID="LastWriteTime">
<H4>Last Write Time</H4>
This 16 bit field is set to the time when the last write occured. When the entry is create this field and the <A HREF="#CreationTimeDate">Creation Time</A> field should contain the same values. In case the entry is a directory entry this field should change when the contents of the sub-directory changes.<BR>
<BR>
The field is in the special format described below:<BR>
<DIV ID="TimeFormat" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Time Format">
<CAPTION>
Time Format
</CAPTION>
<COLGROUP SPAN="32" WIDTH="6%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">15</TH>
<TH CLASS="BitTable">14</TH>
<TH CLASS="BitTable">13</TH>
<TH CLASS="BitTable">12</TH>
<TH CLASS="BitTable">11</TH>
<TH CLASS="BitTable">10</TH>
<TH CLASS="BitTable">9</TH>
<TH CLASS="BitTable">8</TH>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable" COLSPAN="5">Hours (0-23)</TD>
<TD CLASS="BitTable" COLSPAN="6">Minutes (0-59)</TD>
<TD CLASS="BitTable" COLSPAN="5">Seconds (0-29)</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
<TBODY>
<TR>
<TD ALIGN="Left" CLASS="NoColor" COLSPAN="16"><SPAN CLASS="Note">Seconds are counted with 2 seconds interval, so a value of 29 in this field gives 58 seconds.</SPAN></TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="LastWriteDate">
<H4>Last Write Date</H4>
This 16 bit field is set to the date when the last write occured. When the entry is create this field and the <A HREF="#CreationTimeDate">Creation Date</A> field should contain the same values. In case the entry is a directory entry this field should change when the contents of the sub-directory changes.<BR>
<BR>
The field is in the special format described below:<BR>
<DIV ID="DateFormat" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="Date Format">
<CAPTION>
Date Format
</CAPTION>
<COLGROUP SPAN="32" WIDTH="6%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<COLGROUP>
<COL WIDTH="4%" ALIGN="Center" VALIGN="Middle">
</COLGROUP>
<THEAD>
<TR>
<TH CLASS="BitTable">15</TH>
<TH CLASS="BitTable">14</TH>
<TH CLASS="BitTable">13</TH>
<TH CLASS="BitTable">12</TH>
<TH CLASS="BitTable">11</TH>
<TH CLASS="BitTable">10</TH>
<TH CLASS="BitTable">9</TH>
<TH CLASS="BitTable">8</TH>
<TH CLASS="BitTable">7</TH>
<TH CLASS="BitTable">6</TH>
<TH CLASS="BitTable">5</TH>
<TH CLASS="BitTable">4</TH>
<TH CLASS="BitTable">3</TH>
<TH CLASS="BitTable">2</TH>
<TH CLASS="BitTable">1</TH>
<TH CLASS="BitTable">0</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD CLASS="BitTable" COLSPAN="7">Years from 1980 (0-127 -> 1980-2107)</TD>
<TD CLASS="BitTable" COLSPAN="4">Month of year (1-12)</TD>
<TD CLASS="BitTable" COLSPAN="5">Day of month (1-31)</TD>
<TH CLASS="BitTable">0000h</TH>
</TR>
</TBODY>
<TBODY>
<TR>
<TD ALIGN="Left" CLASS="NoColor" COLSPAN="16"></TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
</DIV>
<DIV ID="FirstCluster">
<H4>First Cluster</H4>
This 16-bit field points to the starting cluster number of entrys data. If the entry is a directory this entry point to the cluster which contain the beginning of the sub-directory. If the entry is a file then this entry point to the cluster holding the first chunk of data from the file.<BR>
<BR>
</DIV>
<DIV ID="FileSize">
<H4>File Size</H4>
This 32-bit field count the total file size in bytes. For this reason the file system driver must not allow more than 4 Gb to be allocated to a file. For other entries than files then file size field should be set to 0.<BR>
<BR>
</DIV>
<BR>
</DIV>
<DIV ID="CalculationAlgorithms">
<H2>Calculation Algorithms</H2>
How to calculate the starting location of each region. The VolumeStart variable contain a <ABBR TITLE="Logical Block Addressing">LBA address</ABBR> of the first sector in the volume. On drives which are not partitioned the VolumeStart value is 0. On drives which are partitioned the VolumeStart variable contain the sector number at which the partition start.<BR>
<BR>
<DIV ID="RegionCalculations" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="How to calculate regions and their sizes">
<CAPTION>
How to calculate regions and their size (in sectors)
</CAPTION>
<COLGROUP>
<COL WIDTH="30%" ALIGN="Right" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">What to calculate</TH>
<TH ALIGN="Center" VALIGN="Middle">How to calculate it</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>ReservedRegion start =</TD><TD>VolumeStart</TD></TR>
<TR><TD>FATRegion start =</TD><TD><SPAN CLASS="PreviousCalculated">ReservedRegion</SPAN> + <A HREF="#ReservedSectors">ReservedSectors</A></TD></TR>
<TR><TD>RootDirectoryRegion start =</TD><TD><SPAN CLASS="PreviousCalculated">FATRegion</SPAN> + (<A HREF="#NumberOfFATs">NumberOfFATs</A> * <A HREF="#SectorsPerFAT">SectorsPerFAT</A>)</TD></TR>
<TR><TD>DataRegion start =</TD><TD><SPAN CLASS="PreviousCalculated">RootDirectoryRegion</SPAN> + ((<A HREF="#RootEntriesCount">RootEntiesCount</A> * 32) / <A HREF="#BytesPerSector">BytesPerSector</A>)</TD></TR>
<TR><TD>ReservedRegion size =</TD><TD><A HREF="#ReservedSectors">ReservedSectors</A></TD></TR>
<TR><TD>FATRegion size =</TD><TD><A HREF="#NumberOfFATs">NumberOfFATs</A> * <A HREF="#SectorsPerFAT">SectorsPerFAT</A></TD></TR>
<TR><TD>RootDirectoryRegion size =</TD><TD>(<A HREF="#RootEntriesCount">RootEntiesCount</A> * 32) / <A HREF="#BytesPerSector">BytesPerSector</A> (Remember to round up, if there is a remainder)</TD></TR>
<TR><TD>DataRegion size =</TD><TD><A HREF="#LargeNumberOfSectors">TotalNumberOfSectors</A> - (<SPAN CLASS="PreviousCalculated">ReservedRegion_Size</SPAN> + <SPAN CLASS="PreviousCalculated">FATRegion_Size</SPAN> + <SPAN CLASS="PreviousCalculated">RootDirectoryRegion_Size</SPAN>)</TD></TR>
</TBODY>
<TBODY>
<TR>
<TD ALIGN="Center" CLASS="NoColor" COLSPAN="2">
Previous calculated values which are used again, are marked with <SPAN CLASS="PreviousCalculated">this color</SPAN>.
</TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
<BR>
<DIV ID="FATRelatedValues" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="How to calculate FAT related values">
<CAPTION>
How to calculate FAT related values
</CAPTION>
<COLGROUP>
<COL WIDTH="30%" ALIGN="Right" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">What to calculate</TH>
<TH ALIGN="Center" VALIGN="Middle">How to calculate it</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>Location of n'th FAT copy</TD><TD><SPAN CLASS="PreviousCalculated">ReservedRegion</SPAN> + (N * <A HREF="#ReservedSectors">SectorsPerFAT</A>)</TD></TR>
<TR><TD>Number of FAT entries</TD><TD><SPAN CLASS="PreviousCalculated">DataRegion_Size</SPAN> / <A HREF="#SectorsPerCluster">SectorsPerCluster</A> (Remember to round down if there is a remainder)</TD></TR>
<TR><TD>Which FAT sector contain the Nth cluster entry I need ?</TD><TD><SPAN CLASS="PreviousCalculated">Location of FAT copy</SPAN> + (( N * 2) / <A HREF="#BytesPerSector">BytesPerSector</A>)</TD></TR>
</TBODY>
<TBODY>
<TR>
<TD ALIGN="Center" CLASS="NoColor" COLSPAN="2">
Previous calculated values which are used again, are marked with <SPAN CLASS="PreviousCalculated">this color</SPAN>.
</TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
<BR>
<DIV ID="OtherValues" CLASS="Centered">
<TABLE WIDTH="90%" SUMMARY="How to calculate other values">
<CAPTION>
How to calculate other values
</CAPTION>
<COLGROUP>
<COL WIDTH="30%" ALIGN="Right" VALIGN="Top">
<COL WIDTH="70%" ALIGN="Left" VALIGN="Top">
</COLGROUP>
<THEAD>
<TR>
<TH ALIGN="Center" VALIGN="Middle">What to calculate</TH>
<TH ALIGN="Center" VALIGN="Middle">How to calculate it</TH>
</TR>
</THEAD>
<TBODY>
<TR><TD>First sector of cluster N =</TD><TD><SPAN CLASS="PreviousCalculated">DataRegion</SPAN> + ((N - 2) * <A HREF="#SectorsPerCluster">SectorsPerCluster</A>)</TD></TR>
</TBODY>
<TBODY>
<TR>
<TD ALIGN="Center" CLASS="NoColor" COLSPAN="2">
Previous calculated values which are used again, are marked with <SPAN CLASS="PreviousCalculated">this color</SPAN>.
</TD>
</TR>
</TBODY>
</TABLE>
</DIV>
<BR>
<BR>
</DIV>
<DIV ID="SpecialNotes">
<H2>Special Notes</H2>
When creating a FAT16 volume special care should be taken to ensure best compatibility. Following these rules ensure the best compatibility:<BR>
<UL>
<LI>A FAT16 partition may not have less than 4085 clusters or more than 65524 clusters.</LI>
</UL>
<BR>
<BR>
</DIV>
<DIV ID="Conclusion">
<H2>Conclusion</H2>
The FAT family of file systems are relative simple file systems. The complexity can be enhanced by adding support for long file names, using the <A HREF="VFAT_LongFileNames.html">VFAT Long File Names</A>. Also have a look at the <A HREF="FAT32_FileSystem.html">32 bit version</A> of the FAT file system.<BR>
</DIV>
</BODY>
</HTML>

@ -0,0 +1,323 @@
/* External Style Sheet
for the
Maverick Operating System website
Cascading Style Sheet Level 2
*/
/* Body general styles */
BODY {
background-color: #FFFFFF;
color: #202020;
font-family: sans-serif;
font-size: 8pt;
font-weight: normal;
letter-spacing: normal; /* normal, or a lenght in em units */
margin: 0.5em; /* sets all the margins */
text-align: left; /* left, right, center, justify */
text-decoration: none; /* none, underline, overline, line-through, blink */
text-indent: 0; /* either a legnht in em units or a percentage */
text-transform: none; /* capitalize, uppercase, lowercase, none, inherit */
white-space: normal; /* normal, pre, nowrap */
word-spacing: normal; /* normal, or a lenght in em units */
}
BODY.Menu {
background-color: #F0F0FF;
color: #000000;
}
BODY.Title {
background-color: #F0F0FF;
color: #000000;
margin: 0em;
}
/* General styles */
.Calculation {
color: #000080;
}
.Centered {
text-align: center;
}
.Code {
background-color: #E0E0E0;
border-color: #000000;
border-style: solid;
border-width: 1px;
font-family: monospace;
font-size: 7pt;
font-weight: normal;
margin-left: 2em;
margin-right: 2em;
padding: 10px;
text-align: left;
white-space: pre;
}
.Copyright {
font-size: 6pt;
margin: 1em;
text-align: center;
}
.Date {
font-size: 10pt;
font-weight: bold;
}
.DefinitionTerm {
background-color: #C0FFC0;
font-weight: bolder;
}
.DefinitionData {
background-color: #F0F0FF;
}
.Important {
color: #FF0000;
font-weight: bold;
font-size: 110%;
}
.MiniMenu {
font-size: 6pt;
text-align: right;
}
.Note {
color: #FF0000;
}
.Note:before {
content: "Note: ";
font-weight: bold;
}
.PreviousCalculated {
color: #8000FF;
}
.Recomendation {
color: #FF0000;
}
.Reserved {
color: #FF0000;
}
.Revision {
font-size: 7pt;
text-align: right;
}
/* Anchor (link) styles */
A {
text-decoration: none;
}
A:link {
color: #0000FF;
}
A:visited {
color: #0000FF;
}
A:hover {
color: #FF0000;
}
A:active {
color: #FF0000;
}
/* Styles for headlines in 6 different levels */
H1 {
font-family: sans-serif;
font-size: 24pt;
font-weight: bold;
margin: 0em;
text-align: center;
}
H1.Menu {
font-size: 10pt;
text-decoration: underline overline;
text-transform: uppercase;
}
H1.PreTitle {
color: #505050;
font-size: 10pt;
}
H1.SubTitle {
color: #505050;
font-size: 10pt;
}
H2 {
font-size: 14pt;
margin: 0em;
text-align: left;
}
H2.Menu {
font-size: 9pt;
font-weight: normal;
margin: 0em;
text-align: left;
text-decoration: underline;
text-transform: lowercase;
}
H3 {
font-size: 10pt;
font-weight: bold;
margin: 0em;
}
H3.Menu {
font-size: 9pt;
font-weight: italic;
margin: 0em;
text-align: left;
text-decoration: underline;
text-transform: lowercase;
}
H4 {
font-size: 9pt;
font-weight: normal;
margin: 0em;
text-decoration: underline;
}
H5 {
font-size: 9pt;
font-style: italic;
font-weight: normal;
margin: 0em;
}
H6 {
font-size: 9pt;
font-style: oblique;
font-weight: normal;
margin: 0em;
}
/* Styles for other elements */
HR {
color: #505050;
text-align: right;
height: 1px;
}
P {
margin: 0px;
margin-top: 0.1em;
margin-bottom: 0.9em;
}
/* Styles for tables */
TABLE, TR, TD, TH, CAPTION {
font-family: sans-serif;
font-size: 8pt;
}
TD {
background-color: #F0F0FF;
}
TH {
background-color: #C0C0FF;
}
TD.BitTable {
font-size: 7pt;
text-align: center;
}
TH.BitTable {
font-size: 7pt;
font-weight: normal;
text-align: center;
}
TD.Code {
background-color: #E0E0E0;
border-color: #000000;
border-style: solid;
border-width: 1px;
font-size: 6pt;
font-weight: normal;
margin-left: 1em;
margin-right: 1em;
padding: 1px;
text-align: center;
}
TD.NoColor {
background-color: transparent;
background-color: #FFFFFF; /* This line is for Netscape */
}
TH.NoColor {
background-color: transparent;
background-color: #FFFFFF; /* This line is for Netscape */
}
CAPTION {
font-size: 9pt;
font-weight: normal;
}
/* Styles for unordered, ordered and definition lists */
DL {
margin: 0em;
}
DD {
margin: 0em;
}
DT {
font-family: sans-serif;
font-size: 10pt;
font-weight: bold;
margin-left: 0.2em;
margin-top: 1.5em;
}
UL {
margin: 0em;
margin-left: 2em;
}
OL {
margin: 0em;
margin-left: 2em;
}
/* end of file */

@ -0,0 +1,944 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- http://www.tavi.co.uk/phobos/fat.html -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<link rel="stylesheet" type="text/css" href="phobos.css" />
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<meta name="keywords" content="PHOBOS, FAT, file system" />
<title>A tutorial on the FAT file system</title>
</head>
<!-- T I T L E ============================================================ -->
<body>
<table class="titlebox">
<tr>
<td class="smalltitle" align="center">Phobos</td>
<td class="subtitle">A tutorial on the FAT file system</td>
<td align="right" class="smalltitle"></td>
</tr>
</table>
<!-- B O D Y ============================================================== -->
<hr />
<!-- M a i n ============================================================== -->
<h2>Introduction</h2>
<p>
This page is intended to provide an introduction to the original File
Allocation Table (FAT) file system. This file system was used on all
versions of MS-DOS and PC-DOS, and on early versions of Windows; it is
still used on floppy disks formatted by Windows and some other systems.
Modified versions are also still supported by Windows on hard disks, if
required.
</p>
<p>
The FAT file system is heavily based on the <em>file map</em> model in
terms of its on-disk layout; that model was around for many years before
Microsoft inherited the initial FAT file system from the original
writers of DOS (Seattle Computer Products). It is a reasonably simple,
reasonably robust file system.
</p>
<p>
There are three basic variants of the FAT file system, which differ
mainly in the construction of the actual file allocation table. Floppy
disks and small hard disks usually use the <em>12-bit</em> version,
which was superseded by the <em>16-bit</em> version as hard disks became
bigger. This in turn was superseded by the <em>32-bit</em> version as
disks became bigger still. We shall concentrate on the 16-bit version,
since the 12-bit version can be tricky for beginners, and the 32-bit
version is more complex than needed for this tutorial.
</p>
<h3>Overview</h3>
<p>
Any disk is made up of <em>surfaces</em> (one for each head),
<em>tracks</em> and <em>sectors</em>. However, for simplicity, we can
consider a disk as a simple storage area made up just of a number of
sectors. Further, these sectors are considered to be numbered
consecutively, the first being numbered 0, the second numbered 1, etc.;
we will not worry about the physical location of any sector on the
actual disk. Because we want to emphasise that the location of a sector is
irrelevant to the actual disk structure, and because sectors have their
own numbers within each track, we shall call these sectors
<em>blocks</em> from now on; as previously stated, they form a linear,
densely numbered list.
</p>
<p>
All blocks are the same size, 512 bytes, on practically all FAT file
systems. Howewer, large disks can have too many blocks for comfort, so
blocks are sometimes grouped together in pairs (or fours, or eights,
etc...); each such grouping is called an <em>allocation unit</em>. The
FAT file system actually works in allocation units, not blocks, but for
simplicity we shall assume in the description below that each allocation
unit contains exactly one block, which means that we can use the terms
interchangeably.
</p>
<h3>A note on numerical values</h3>
<p>
Hexadecimal numbers are indicated using the convention commonly used in
C; that is, a leading <samp>0x</samp>. The decimal number
<samp>17</samp> would thus be written as <samp>0x11</samp> in
hexadecimal notation here.
</p>
<p>
Values in the FAT file system are either stored in <em>bytes</em> (8 bit
values, 0-255 unsigned) or in <em>words</em> (pairs of bytes, 16 bit
values, 0-65535 unsigned). Note that the first byte of a pair is the
least significant byte, and the second byte of a pair is the most
significant byte. For example, if the byte at position 3 has a value of
0x15, and the byte at position 4 has a value of 0x74, they together make
up a word with value 0x7415 (not 0x1574).
</p>
<p>
There are occasional 32-bit values (<em>doublewords</em>), and these use
a similar approach (in this case 4 bytes, with least significant byte
stored first).
</p>
<p>
Lastly, note that individual bits within a byte or word are numbered
from the least significant end (right hand end), starting with bit 0.
</p>
<h2>The disk format</h2>
<p>
This section describes the <em>on-disk structure</em> of a FAT file
system; that is, how the various areas of the disk are laid out, and
what is stored in them.
</p>
<h3>Basic layout</h3>
<p>
All disks using the FAT file system are divided into several areas. The
following table summarises the areas in the order that they appear on
the disk, starting at block 0:
</p>
<table class="spec" width="70%" cellpadding="3">
<tr>
<th class="spec">Area description</th>
<th class="spec">Area size</th>
</tr>
<tr>
<td class="spec"><a href="#boot_block">Boot block</a></td>
<td class="spec">1 block</td>
</tr>
<tr>
<td class="spec"><a href="#file_allocation_table">File Allocation
Table</a> (may be multiple copies)</td>
<td class="spec">Depends on file system size</td>
</tr>
<tr>
<td class="spec">Disk <a href="#root_directory">root directory</a></td>
<td class="spec">Variable (selected when disk is formatted)</td>
</tr>
<tr>
<td class="spec">File data area</td>
<td class="spec">The rest of the disk</td>
</tr>
</table>
<h3 id="boot_block">The boot block</h3>
<p>
The boot block occupies just the first block of the disk. It holds a
special program (the <em>bootstrap program</em>) which is used for
loading the operating system into memory. It would thus appear to be
fairly irrelevant to this discussion.
</p>
<p>
However, in the FAT file system it also contains several important data
areas which help to describe the rest of the file system. Thus, to
understand how a particular disk is laid out, it is necessary first to
understand at least part of the contents of the boot block. The relevant
areas are shown in the following table, together with their byte offsets
from the start of the boot block. We will see, later, which of these are
actually important to us.
</p>
<table class="spec" width="70%" cellpadding="3">
<tr>
<th class="spec">Offset from start</th>
<th class="spec">Length</th>
<th class="spec">Description</th>
</tr>
<tr>
<td class="spec">0x00</td>
<td class="spec">3 bytes</td>
<td class="spec">Part of the bootstrap program.</td>
</tr>
<tr>
<td class="spec">0x03</td>
<td class="spec">8 bytes</td>
<td class="spec">Optional manufacturer description.</td>
</tr>
<tr>
<td class="spec">0x0b</td>
<td class="spec">2 bytes</td>
<td class="spec">Number of bytes per block (almost always 512).</td>
</tr>
<tr>
<td class="spec">0x0d</td>
<td class="spec">1 byte</td>
<td class="spec">Number of blocks per allocation unit.</td>
</tr>
<tr>
<td class="spec">0x0e</td>
<td class="spec">2 bytes</td>
<td class="spec">Number of reserved blocks. This is the number of blocks on the disk
that are not actually part of the file system; in most cases this is
exactly 1, being the allowance for the boot block.</td>
</tr>
<tr>
<td class="spec">0x10</td>
<td class="spec">1 byte</td>
<td class="spec">Number of <a href="#file_allocation_table">File Allocation
Tables.</a></td>
</tr>
<tr>
<td class="spec">0x11</td>
<td class="spec">2 bytes</td>
<td class="spec">Number of <a href="#root_directory">root directory</a> entries
(including unused ones).</td>
</tr>
<tr>
<td id="offset_0x13">0x13</td>
<td class="spec">2 bytes</td>
<td class="spec">Total number of blocks in the entire disk. If the disk size is
larger than 65535 blocks (and thus will not fit in these two bytes),
this value is set to zero, and the true size is stored at
<a href="#offset_0x20">offset 0x20</a>.</td>
</tr>
<tr>
<td class="spec">0x15</td>
<td class="spec">1 byte</td>
<td class="spec"><a href="#media_descriptor">Media Descriptor</a>. This
is rarely used, but still exists.
.</td>
</tr>
<tr>
<td class="spec">0x16</td>
<td class="spec">2 bytes</td>
<td class="spec">The number of blocks occupied by one copy of the
<a href="#file_allocation_table">File Allocation Table</a>.</td>
</tr>
<tr>
<td class="spec">0x18</td>
<td class="spec">2 bytes</td>
<td class="spec">The number of blocks per track. This information is present
primarily for the use of the bootstrap program, and need not concern us
further here.</td>
</tr>
<tr>
<td class="spec">0x1a</td>
<td class="spec">2 bytes</td>
<td class="spec">The number of heads (disk surfaces). This information is present
primarily for the use of the bootstrap program, and need not concern us
further here.</td>
</tr>
<tr>
<td class="spec">0x1c</td>
<td class="spec">4 bytes</td>
<td class="spec">The number of <em>hidden blocks</em>. The use of this is largely
historical, and it is nearly always set to 0; thus it can be
ignored.</td>
</tr>
<tr>
<td id="offset_0x20">0x20</td>
<td class="spec">4 bytes</td>
<td class="spec">Total number of blocks in the entire disk (see also
<a href="#offset_0x13">offset 0x13</a>).</td>
</tr>
<tr>
<td class="spec">0x24</td>
<td class="spec">2 bytes</td>
<td class="spec">Physical drive number. This information is present primarily for the
use of the bootstrap program, and need not concern us further here.</td>
</tr>
<tr>
<td class="spec">0x26</td>
<td class="spec">1 byte</td>
<td class="spec">Extended Boot Record Signature This information is present
primarily for the use of the bootstrap program, and need not concern us
further here.</td>
</tr>
<tr>
<td class="spec">0x27</td>
<td class="spec">4 bytes</td>
<td class="spec">Volume Serial Number. Unique number used for identification of a
particular disk.</td>
</tr>
<tr>
<td class="spec">0x2b</td>
<td class="spec">11 bytes</td>
<td class="spec">Volume Label. This is a string of characters for human-readable
identification of the disk (padded with spaces if shorter); it is
selected when the disk is formatted.</td>
</tr>
<tr>
<td class="spec">0x36</td>
<td class="spec">8 bytes</td>
<td class="spec">File system identifier (padded at the end with spaces if
shorter).</td>
</tr>
<tr>
<td class="spec">0x3e</td>
<td class="spec">0x1c0 bytes</td>
<td class="spec">The remainder of the bootstrap program.</td>
</tr>
<tr>
<td class="spec">0x1fe</td>
<td class="spec">2 bytes</td>
<td class="spec">Boot block 'signature' (0x55 followed by 0xaa).</td>
</tr>
</table>
<h4 id="media_descriptor">The Media Descriptor</h4>
<p>
Historically, the size and type of disk were difficult for the operating
system to determine by hardware interrogation alone. A 'magic byte' was
thus used to classify disks. This are still present, but rarely used,
and its contents are known as the Media Descriptor. Generally, for hard
disks, this is set to 0xf0.
</p>
<h3 id="file_allocation_table">The File Allocation Table (FAT)</h3>
<p>
The FAT occupies one or more blocks immediately following the boot
block. Commonly, part of its last block will remain unused, since it is
unlikely that the required number of entries will exactly fill a
complete number of blocks. If there is a second FAT, this immediately
follows the first (but starting in a new block). This is repeated for
any further FATs.
</p>
<p>
Note that multiple FATs are used particularly on floppy disks, because
of the higher likelihood of errors when reading the disk. If the FAT is
unreadable, files cannot be accessed and another copy of the FAT must be
used. On hard disks, there is often only one FAT.
</p>
<p>
In the case of the 16-bit FAT file system, each entry in the FAT is two bytes in length
(i.e. 16 bits). The disk data area is divided into <em>clusters</em>, which are the same thing
as allocation units, but numbered differently (instead of being numbered from the start
of the disk, they are numbered from the start of the disk data area). So, the cluster number
is the allocation unit number, minus a constant value which is the size of the areas in between
the start of the disk and the start of the data area.
</p>
<p class="warning">
Well, almost. The clusters are numbered starting at 2, not 0! So the
above calculation has to have 2 added to it to get the cluster number of
a given allocation unit...and a cluster number is converted to an
allocation unit number by subtracting 2...!
</p>
<p>
So, how does the FAT work? Simply, there is one entry in the FAT for
every cluster (data area block) on the disk. Entry N relates to cluster
N. Clusters 0 and 1 don't exist (because of the 'fiddle by 2' above),
and those FAT entries are special. The first byte of the first entry is
a copy of the <a href="#media_descriptor">media descriptor</a> byte, and
the second byte is set to 0xff. Both bytes in the second entry are set to
0xff.
</p>
<p>
What does a normal FAT entry for a cluster contain? It contains the
<em>successor cluster number</em> - that is, the number of the cluster
that follows this one in the file to which the current cluster belongs.
The last cluster of a file has the value 0xffff in its FAT entry to
indicate that there are no more clusters.
</p>
<h3 id="root_directory">The Root Directory</h3>
<p>
The root directory contains an entry for each file whose name appears at
the <em>root</em> (the top level) of the file system. Other directories
can appear within the root directory; they are called
<em>subdirectories</em>. The main difference between the two is that
space for the root directory is allocated statically, when the disk is
formatted; there is thus a finite upper limit on the number of files
that can appear in the root directory.
</p>
<p>
Subdirectories are just files with special data in them, so they can be
as large or small as desired.
</p>
<p>
The format of all directories is the same. Each entry is 32 bytes (0x20)
in size, so a single block can contain 16 of them. The following table
shows a summary of a single directory entry; note that the offset is
merely from the start of that particular entry, not from the start of
the block.
</p>
<table class="spec" width="50%" cellpadding="3">
<tr>
<th class="spec">Offset</th>
<th class="spec">Length</th>
<th class="spec">Description</th>
</tr>
<tr>
<td class="spec">0x00</td>
<td class="spec">8 bytes</td>
<td class="spec"><a href="#filename">Filename</a></td>
</tr>
<tr>
<td class="spec">0x08</td>
<td class="spec">3 bytes</td>
<td class="spec"><a href="#filename_extension">Filename extension</a></td>
</tr>
<tr>
<td class="spec">0x0b</td>
<td class="spec">1 byte</td>
<td class="spec"><a href="#file_attributes">File attributes</a></td>
</tr>
<tr>
<td class="spec">0x0c</td>
<td class="spec">10 bytes</td>
<td class="spec">Reserved</td>
</tr>
<tr>
<td class="spec">0x16</td>
<td class="spec">2 bytes</td>
<td class="spec"><a href="#file_time">Time created or last updated</a></td>
</tr>
<tr>
<td class="spec">0x18</td>
<td class="spec">2 bytes</td>
<td class="spec"><a href="#file_date">Date created or last updated</a></td>
</tr>
<tr>
<td class="spec">0x1a</td>
<td class="spec">2 bytes</td>
<td class="spec"><a href="#starting_cluster">Starting cluster number</a> for file</td>
</tr>
<tr>
<td class="spec">0x1c</td>
<td class="spec">4 bytes</td>
<td class="spec"><a href="#file_size">File size in bytes</a></td>
</tr>
</table>
<h4 id="filename">The Filename</h4>
<p>
The eight bytes from offset 0x00 to 0x07 represent the filename. The
first byte of the filename indicates its status. Usually, it contains a
normal filename character (e.g. 'A'), but there are some special values:
</p>
<dl>
<dt>0x00</dt>
<dd>Filename never used.</dd>
<dt>0xe5</dt>
<dd>The filename has been used, but the file has been deleted.</dd>
<dt>0x05</dt>
<dd>The first character of the filename is actually 0xe5.</dd>
<dt>0x2e</dt>
<dd>The entry is for a directory, not a normal file. If the second byte
is also 0x2e, the cluster field contains the cluster number of this
directory's parent directory. If the parent directory is the root
directory (which is statically allocated and doesn't have a cluster
number), cluster number 0x0000 is specified here.</dd> <dt>Any other
character</dt>
<dd>This is the first character of a real filename.</dd>
</dl>
<p>
If a filename is fewer than eight characters in length, it is padded
with space characters.
</p>
<h4 id="filename_extension">The Filename Extension</h4>
<p>
The three bytes from offset 0x08 to 0x0a indicate the filename
extension. There are no special characters. Note that the dot used to
separate the filename and the filename extension is implied, and is not
actually stored anywhere; it is just used when referring to the file.
If the filename extension is fewer than three characters in length, it
is padded with space characters.
</p>
<h4 id="file_attributes">The File Attributes</h4>
<p>
The single byte at offset 0x0b contains flags that provide information
about the file and its permissions, etc. The flags are single bits, and
have meanings as follows. Each bit is given as its numerical value, and
these are combined to give the actual attribute value:
</p>
<dl id="attribute_values">
<dt>0x01</dt>
<dd>Indicates that the file is read only.</dd>
<dt>0x02</dt>
<dd>Indicates a hidden file. Such files can be displayed
if it is really required.</dd>
<dt>0x04</dt>
<dd>Indicates a system file. These are hidden as well.</dd>
<dt>0x08</dt>
<dd>Indicates a special entry containing the disk's volume label,
instead of describing a file. This kind of entry appears only in the
root directory.</dd>
<dt>0x10</dt>
<dd>The entry describes a subdirectory.</dd>
<dt>0x20</dt>
<dd>This is the archive flag. This can be set and cleared by the
programmer or user, but is always set when the file is modified. It is
used by backup programs.</dd>
<dt>0x40</dt>
<dd>Not used; must be set to 0.</dd>
<dt>0x80</dt>
<dd>Not used; must be set to 0.</dd>
</dl>
<h4 id="file_time">The File Time</h4>
<p>
The two bytes at offsets 0x16 and 0x17 are treated as a 16 bit value;
remember that the least significant byte is at offset 0x16. They contain
the time when the file was created or last updated. The time is mapped
in the bits as follows; the first line indicates the byte's offset, the
second line indicates (in decimal) individual bit numbers in the 16 bit
value, and the third line indicates what is stored in each bit.
</p>
<pre>
&lt;------- 0x17 --------&gt; &lt;------- 0x16 --------&gt;
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
h h h h h m m m m m m x x x x x
</pre>
<p>
where:
</p>
<dl>
<dt><samp>hhhhh</samp></dt>
<dd>indicates the binary number of hours (0-23)</dd>
<dt><samp>mmmmmm</samp></dt>
<dd>indicates the binary number of minutes (0-59)</dd>
<dt><samp>xxxxx</samp></dt>
<dd>indicates the binary number of two-second periods (0-29),
representing seconds 0 to 58.</dd>
</dl>
<h4 id="file_date">The File Date</h4>
<p>
The two bytes at offsets 0x18 and 0x19 are treated as a 16 bit value;
remember that the least significant byte is at offset 0x18. They contain
the date when the file was created or last updated. The date is mapped
in the bits as follows; the first line indicates the byte's offset, the
second line indicates (in decimal) individual bit numbers in the 16 bit
value, and the third line indicates what is stored in each bit.
</p>
<pre>
&lt;------- 0x19 --------&gt; &lt;------- 0x18 --------&gt;
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
y y y y y y y m m m m d d d d d
</pre>
<p>
where:
</p>
<dl>
<dt><samp>yyyyyyy</samp></dt>
<dd>indicates the binary year offset from 1980 (0-119), representing the
years 1980 to 2099</dd>
<dt><samp>mmmm</samp></dt>
<dd>indicates the binary month number (1-12)</dd>
<dt><samp>ddddd</samp></dt>
<dd>indicates the binary day number (1-31)</dd>
</dl>
<h4 id="starting_cluster">The Starting Cluster Number</h4>
<p>
The two bytes at offsets 0x1a and 0x1b are treated as a 16 bit value;
remember that the least significant byte is at offset 0x1a. The first
cluster for data space on the disk is always numbered as 0x0002. This
strange arrangement is because the first two entries in the FAT are
reserved for other purposes.
</p>
<h4 id="file_size">The File Size</h4>
<p>
The four bytes at offsets 0x1c to 0x1f are treated as a 32 bit value;
remember that the least significant byte is at offset 0x1c. They hold
the actual file size, in bytes.
</p>
<h2>Worked examples</h2>
<p>
The best way to understand how to use the above information is to work
though some simple examples.
</p>
<h3>Interpreting the contents of a block</h3>
<p>
We assume that there is a tool available to display the contents of a
block in both hexadecimal and as ASCII characters. Most such tools will
display unusual ASCII characters (e.g. carriage return) as a dot. For
example, here is a display of a typical boot block:
</p>
<p class="center">
<img src="images/bootblk.jpg" alt="Boot block - example" />
</p>
<p>
As an illustration, one field in the boot block has been highlighted in
red (the highlight appears twice, once for the hexadecimal
representation and once for the ASCII representation). The numbers down
the left hand side are the offsets (from the start of the block) of the
first byte on that row, and the first row of digits along the top are
the offset of each byte within the row. We can thus easily see that the
highlighted area starts at offset 0x36.
</p>
<p>
The area in question is (look back at the boot block layout) the file
system type, in this case FAT16. To save us looking up each byte in a
table of ASCII characters, we can simply consult the equivalent
representation on the right hand side. 0x46 represents F, 0x41
represents A, and so on.
</p>
<h3>Example 1 - find the root directory</h3>
<p>
To find the root directory, we need to examine the file system data in
the boot block. So, let's look again at the boot block of our example
disk:
</p>
<p class="center">
<img src="images/bootblk1.jpg" alt="Boot block - find root directory" />
</p>
<p>
We know that the root directory appears immediately after the last copy
of the FAT. So what we need to find out is the size of the FAT, and how
many copies there are. We also need to know the size of anything else
that appears before the FAT(s); there is just the single block of the
boot block. So, the number of blocks that appear before the root
directory is given by:
</p>
<pre>
(size of FAT)*(number of FATs) + 1
</pre>
<p>
All we need to do, then, is discover these values. First, we know that
the number of FATs is stored at offset 0x10 (highlighted in green
above); this tells us that there is just one FAT. Next, we need to know
the size of a FAT; this is at offsets 0x16 and 0x17, where we find 0x14
and 0x00 respectively (highlighted in red above). Remember that these
two bytes together make up a 16 bit value, with the least significant
byte stored first; in other words, the value is 0x0014 (in decimal, 20).
So, the total number of blocks that precede the root directory is given
by:
</p>
<pre>
0x0014*1 + 1 => 0x0015 (decimal 21)
</pre>
<p>
We should thus find the root directory in block 0x15, so let's look at
it...
</p>
<p class="center">
<img src="images/rootdir.jpg" alt="Root directory" />
</p>
<p>
It seems to have something occupying the first 0x20 bytes, and it's...a
directory entry! We won't go into detail here, but detailed examination
of those bytes would show that it's the special entry for the disk
label. There don't appear to be any more entries in this directory.
</p>
<h3>Example 2 - find the attributes of a file</h3>
<p>
In this example, the file FOOBAR.TXT has been created on the same disk,
and it appears in the root directory. We wish to find out which
attribute flags are set on the file.
</p>
<p>
First, we need to find the root directory; we have already done this in
example 1. Let's take a look at it after FOOBAR.TXT has been created:
</p>
<p class="center">
<img src="images/rootdir1.jpg" alt="Root directory" />
</p>
<p>
We can see fairly easily that the second directory entry (the one at
offset 0x20) is that for FOOBAR.TXT. Remember that the dot between the
filename and the filename extension is not actually stored, but is
implied. We see the filename (highlighted in red) and the filename
extension (highlighted in blue). We know that the attribute byte appears
at offset 0x0b, and it is highlighted in green here.
</p>
<p>
The value of the attribute byte is 0x21. We can express this in binary
as:
</p>
<pre>
0 0 1 0 0 0 0 1
</pre>
<p>
Taking each of the bits separately, and making a hexadecimal number out
of them, we get:
</p>
<pre>
0 0 1 0 0 0 0 0 => 0x20
0 0 0 0 0 0 0 1 => 0x01
</pre>
<p>
Our <a href="#attribute_values">table of attribute values</a> shows that
0x20 means that the 'archive flag' is set, and 0x01 indicates that the
file is read-only.
</p>
<h3>Example 3 - find the date of a file</h3>
<p>
Here, we want the date attached to a particular file (only one date is
kept, which is the date of creation or last modification). The file in
question is FOOBAR.TXT again.
</p>
<p>
Let's look once more at the root directory; we have already done this in
example 2, and indeed we already know that FOOBAR.TXT has a directory
entry at offset 0x20:
</p>
<p class="center">
<img src="images/rootdir3.jpg" alt="Root directory" />
</p>
<p>
This time we are interested in the file date, and we know from our
<a href="#root_directory">root directory layout</a> that this is at
offset 0x18 within each directory entry. Thus, the date for FOOBAR.TXT
is at offset 0x20+0x18, or 0x38 (highlighted in red above). Once again,
this is a 16 bit value with the least significant byte stored first. The
bytes are 0x65 and 0x39 respectively, so reversing these and putting
them together gives a value of 0x3965.
</p>
<p>
Now all we have to do is analyse the components of this value. An easy
way is first to convert it to binary, and this is even easier if we take
it one hexadecimal digit at a time:
</p>
<pre>
3 9 6 5
| | | |
V V V V
0 0 1 1 1 0 0 1 0 1 1 0 0 1 0 1
</pre>
<p>
Let's push all the digits together:
</p>
<pre>
0 0 1 1 1 0 0 1 0 1 1 0 0 1 0 1
</pre>
<p>
Now we can split them again on boundaries corresponding to the
individual components of the date, as defined in the
<a href="#file_date">file date format</a>. Then we convert each part
back to decimal:
</p>
<pre>
0 0 1 1 1 0 0 1 0 1 1 0 0 1 0 1
| | |
V V V
28 11 5
(year) (month) (day)
</pre>
<p>
Remember that the year is based at 1980, so if we add 1980 to 28, we get
2008. The entire date is thus the 5th of November 2008.
</p>
<h3>Example 4 - find the data blocks for a file</h3>
<p>
Here, we wish to find out the numbers of the blocks containing data for
a particular file which has now been added to the disk. The name of the
file is NETWORK.VRS.
</p>
<p>
Once again, we find the root directory. Here are its latest contents,
after NETWORK.VRS has been created:
</p>
<p class="center">
<img src="images/rootdir2.jpg" alt="Root directory" />
</p>
<p>
Note that the third directory entry (starting at offset 0x40) is that
for NETWORK.VRS. We know that the starting cluster number for the file
data occupies bytes at offsets 0x1a and 0x1b in a particular directory
entry; thus the bytes we want are at offsets 0x5a and 0x5b (we just
added 0x40, the offset of the start of the entry). These (highlighted in
red) contain 0x4e and 0x0f respectively, and, remembering that the first
byte is the least significant one, the number we want is 0x0f4e.
Incidentally, the next four bytes (highlighted in blue) are the file
size, again with the least significant byte first. These are 0x92, 0x06,
0x00, 0x00 respectively, making a value of 0x00000692. This (in decimal)
is 1682. So, this file is <strong>1682</strong> bytes long.
</p>
<p>
Let's review what we know so far...
</p>
<ul>
<li>The starting cluster of the file is cluster 0x0f4e.</li>
<li>The root directory starts at block 0x15.</li>
<li>The first allocation unit starts at the first block after the root
directory.</li>
</ul>
<p>
What else do we need to know? We know where the root directory starts,
but not where it ends. So we need the size of the root directory, in
blocks. Let's look once again at the boot block:
</p>
<p class="center">
<img src="images/bootblk2.jpg" alt="Boot block - find root directory" />
</p>
<p>
What we need to find this time is the maximum number of entries in the root
directory; this is fixed when the disk is formatted. We know from the
<a href="#boot_block">boot block layout</a> that this appears in the two
bytes starting at offset 0x11 in the boot block (these are highlighted
in red above). These bytes contain 0x40 and 0x00 respectively, so
(arranging as usual) this gives us a value of 0x0040 (64 in decimal). So
there are 64 root directory entries. We know that one directory entry
occupies 32 bytes, so the total space occupied by the root directory is
64*32 bytes, or 2048 bytes. Each block is 512 bytes, so the number of
blocks occupied by the root directory is 2048 divided by 512...that is,
4.
</p>
<p>
So, the root directory starts at block 0x15. Thus the first allocation
unit starts at 0x15+4, or 0x19. So, to convert an allocation unit number
to a block number, we need to add the constant value 0x19.
And to convert a cluster number (which is what appears in the root
directory) to a block number, we need to add 0x17, to allow for that
strange offset of 2.
</p>
<p>
We now know that the first data block of the file is at cluster
number 0xf4e (see above). Adding the constant we have discovered, we
find that this is block number 0xf4e+0x17, or 0xf65. Let's look at block
0xf65:
</p>
<p class="center">
<img src="images/datablk1.jpg" alt="Data block 1" />
</p>
<p>
Well, that certainly looks like the start of a poem! Each line of the
text is separated by a special character called <em>newline</em>, which
has the code 0x0a (decimal 10). The first few of these are highlighted
in red.
</p>
<p>
We have nearly finished. There is obviously more of this file, and for us
to find the rest of it, we need to consult the FAT. Recall that the
starting <em>cluster</em> number of the file (the block we just looked
at) is 0xf4e. Each entry in the FAT is two bytes in size, so we'll find
the entry for that cluster at offset 0xf4e*2 in the FAT, which is offset
0x1e9c (it's easier to add the value twice than attempt multiplication).
We know that one disk block (and thus one block of the FAT) is 0x200
bytes in size, so we just need to divide 0x1e9c by 0x200. This sounds
hard, but it isn't. You can find tools for this, or do it yourself.
Let's look at these two numbers in binary:
</p>
<pre>
0x0200 => 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0x1e9c => 0 0 0 1 1 1 1 0 1 0 0 1 1 1 0 0
</pre>
<p>
The first number is a power of two, so to divide by it we simply shift
the second number right - in this case by nine places:
</p>
<pre>
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 => 0x0f
</pre>
<p>
So the entry we want is in block 0x0f of the FAT. The remainder from our
division is of course all the bits we lost when we shifted:
</p>
<pre>
0 1 0 0 1 1 1 0 0 => 0x9c
</pre>
<p>
so this is the byte offset of the entry within the FAT block.
</p>
<p>
We need to find FAT block 0x0f. We know the FAT starts in block 1 of the
disk (see earlier), so block 0x0f of the FAT will be in disk block
0x0f+1, or block 0x10. Let's look at that block:
</p>
<p class="center">
<img src="images/fat.jpg" alt="FAT block" />
</p>
<p>
We need to look at the FAT entry (two bytes) at offset 0x9c; this is
highlighted in red above, and resolves to the 16 bit value 0x0f4f. This
is actually the very next cluster, numerically, from the one we have
just looked at (this will not always be the case), so we can apply a bit
of common sense and deduce that the second data block of the file appears
immediately after the first; thus, the first two blocks are at 0xf65 and
0xf66. Here is block 0xf66:
</p>
<p class="center">
<img src="images/datablk2.jpg" alt="Data block 2" />
</p>
<p>
which certainly looks like the continuation of the poem. If we look at
the FAT entry for this new cluster (which, since it's the next block,
will also be the next cluster and thus in the next FAT entry), it is
highlighted in blue above, and contains the value 0x0f50. This is the
very next block and cluster:
</p>
<p class="center">
<img src="images/datablk3.jpg" alt="Data block 3" />
</p>
<p>
We continue this (again, it's the next block and cluster) and we find
0x0f51 as the cluster number (highlighted in green above). Here is that block:
</p>
<p class="center">
<img src="images/datablk4.jpg" alt="Data block 4" />
</p>
<p>
Lastly, we look at the FAT entry for this block/cluster (highlighted in
black). This time the entry is 0xffff, which indicates that there are no
more blocks in the file. We have finished!
</p>
<h2>Conclusion</h2>
<p>
If you've managed to get this far (and understood it all) you have a
good working understanding of the 16-bit FAT file system. You should be
able to analyse a disk, and see if it is corrupted. You may even be able
to repair it!
</p>
<!-- E n d o f M a i n ================================================ -->
<hr />
<!-- F o o t e r ========================================================== -->
<script type="text/javascript"><!--
amazon_ad_tag="thmlimapr-21";
amazon_ad_width="728";
amazon_ad_height="90";
amazon_color_background="EBE8C0";
amazon_color_border="386424";
amazon_color_logo="DDD37F";
amazon_color_text="38352A";
amazon_color_link="34338B";
amazon_ad_logo="hide";
amazon_ad_title="Bob's books - books.tavi.co.uk"; //--></script>
<script type="text/javascript" src="http://www.assoc-amazon.co.uk/s/asw.js"></script>
<hr />
<p><a href="http://validator.w3.org/check/referer">
<img style="border:0" src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0!" height="31" width="88" /></a>
<a href="http://jigsaw.w3.org/css-validator">
<img style="border:0" src="http://jigsaw.w3.org/css-validator/images/vcss"
alt="Valid CSS!" /></a>
</p>
<p class="footnote">
This site is copyright
&copy; 2017
<a href="mail.html">Bob Eager</a>
<br />Last updated:
27 Nov 2017
</p>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

@ -0,0 +1,306 @@
a:hover {
color: red;
}
hr {
height: 1px;
border-top: none;
}
body {
background-color: #FAEBD7; /* antiquewhite */
}
h1,h2,h3,h4,h5,h6 {
font-family: sans-serif;
color: #00008B; /* darkblue */
}
table.titlebox {
text-align: center;
width: 100%;
}
td.title {
font-family: sans-serif;
font-weight: bold;
color: blue;
font-size: 220%;
text-align: center;
width: 70%;
}
td.subtitle {
font-family: sans-serif;
font-weight: bold;
color: red;
font-size: 150%;
text-align: center;
width: 70%;
}
td.smalltitle {
font-family: sans-serif;
font-weight: bold;
color: #00008B; /* darkblue */
font-size: 150%;
width: 15%;
}
td.sidebox {
background-color: #FAEBD7; /* antiquewhite */
width: 15%;
}
table.sidebar {
font-family: serif;
font-size: 90%;
color: black;
background-color: white;
text-align: center;
}
td.main {
background-color: #FAEBD7; /* antiquewhite */
font-family: serif;
font-size: 100%;
color: black;
width: 85%;
}
table.spec {
background-color: white;
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
border-style: solid;
border-width: medium;
border-color: black;
width: 80%;
}
img {
border-style: solid;
border-width: medium;
border-color: black;
}
th.spec {
border-collapse: collapse;
border-style: solid;
border-width: thin;
border-color: black;
}
td.spec {
border-collapse: collapse;
border-style: solid;
border-width: thin;
border-color: black;
}
table.doc {
background-color: white;
font-family: serif;
font-size: 100%;
color: black;
}
td.docname {
padding-left: 3%;
}
td.doclink {
text-align: center;
}
td.docinfo {
padding-left: 3%;
}
table.info {
background-color: white;
font-family: serif;
font-size: 100%;
color: black;
}
th.infotitle {
width: 80%;
}
th.infolink {
width: 20%;
}
td.infotitle {
text-align: left;
padding-left: 3%;
width: 80%;
}
td.infolink {
text-align: center;
width: 20%;
}
table.file {
background-color: white;
font-family: serif;
font-size: 100%;
color: black;
}
td.fversion {
text-align: center;
}
td.flink {
text-align: center;
}
td.fname {
padding-left: 3%;
}
table.ver {
background-color: white;
font-family: serif;
font-size: 100%;
color: black;
}
td.verfeat {
text-align: left;
}
td.vername {
padding-left: 2%;
}
td.verblank {
background-color: #D3D3D3; /* lightgrey */
}
table.mail {
width: 80%;
}
td.maillabel {
width: 22%;
text-align: left;
}
td.mailinput {
width: 78%;
text-align:left;
}
td.mailcontrol1 {
width: 25%;
}
td.mailcontrol2 {
width: 75%;
}
table.exeheader {
background-color: white;
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
border-style: ridge;
border-color: black;
width: 80%;
}
th.exeoffset {
border-style: ridge;
border-color: black;
width: 15%;
}
th.exesize {
border-style: ridge;
border-color: black;
width: 10%;
}
th.exedesc {
border-style: ridge;
border-color: black;
width: 75%;
}
td.exeoffset {
text-align: center;
border-style: ridge;
border-color: black;
width: 15%;
}
td.exesize {
text-align: center;
border-style: ridge;
border-color: black;
width: 10%;
}
td.exedesc {
border-style: ridge;
border-color: black;
width: 75%;
}
table.registers {
background-color: white;
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
border-style: ridge;
border-color: black;
width: 70%;
}
th.registersreg {
border-style: ridge;
border-color: black;
width: 15%;
}
th.registersvalue {
border-style: ridge;
border-color: black;
width: 85%;
}
td.registersreg {
border-style: ridge;
border-color: black;
text-align: center;
width: 15%;
}
td.registersvalue {
border-style: ridge;
border-color: black;
width: 85%;
}
p.center {
text-align: center;
}
p.footnote {
font-size: smaller;
}
p.warning {
color: red;
font-weight: bold;
border: thick red solid;
}
div.display {
text-align: center;
}

Binary file not shown.

@ -43,19 +43,12 @@
\input{ch.hw_buses} \input{ch.hw_buses}
\input{ch.hw_functions} \input{ch.hw_functions}
\part{Firmware Implementation} \part{Implementation}
\input{ch.fw_structure} \input{ch.fw_structure}
\input{ch.tinyframe} \input{ch.tinyframe}
\input{ch.wireless} \input{ch.wireless}
\input{ch.gex_units} \input{ch.gex_units}
\part{Hardware Design}
\input{ch.prototype1_hw}
\appendix % začátek příloh \appendix % začátek příloh

Loading…
Cancel
Save