blob: acb95a66f9c2e05614594fb099ec8c428dc01146 [file] [log] [blame] [raw]
The top of this file is the filesystem syntax and semantics.
The rest of the file describes the interface used by the filesystem
code.
General FS semantics rules:
-- When listing completions, directories are not labeled any differently
from files (symbolic links, FIFOs, etc. are listed as well).
-- Only regular directories and files are interpreted (i.e. a symbolic
link or FIFO would generate a "Bad file type" error if an attempt
is made to read one... an attempt to read a directory as a file
or vice-versa will also generate a "Bad file type" error).
-- All numbers can be either decimal or hexidecimal. A hexidecimal number
must be preceeded by "0x", and is case insensitive.
VERY IMPORTANT NOTE about devices: The only disk devices accessible from a
bootloader are BIOS-controlled devices. All any PC bootloader knows is
the "device number" (floppies are numbered consecutively starting with 0,
and hard drives are numbered consecutively starting with 0x80). There
is no way to tell if a hard drive is IDE, ESDI, SCSI, etc. GRUB punts
and simply uses the BIOS device number in all circumstances. It is
presumed the OS has some mechanism to translate to the physical
controllers (examples are provided in the Multiboot document). Some
OSes kludge it by requiring disklabels like the *BSDs use (which, might
it be noted, breaks under some circumstances, and may not always be
possible to use).
Device syntax like this ("[]" means optional), but note, no spaces
are allowed!!!
disk/partition -> "(<bios_device>[,<part_num>[,<bsd_subpart_letter>]])"
A shortcut for bios devices are:
fd0 -> 0 (first floppy disk)
fd1 -> 1 (second floppy disk)
...
hd0 -> 0x80 (first hard disk)
hd1 -> 0x81 (second hard disk)
whole disks: "(fd0)" -- first floppy, "(hd0)" -- first hard disk.
PC partitions: "(hd0,0)" -- first hard disk PC partition 0,
"(hd1,3)" or "(0x81,3)" -- second hard disk PC partition 3.
BSD sub-partitions: "(hd0,1,a)" -- first hard disk, first PC
partition contains BSD sub-partitions, BSD sub-partition "a".
"(0)" -- BIOS device 0 (first floppy disk) whole disk.
"(0x80,0)" -- first PC partition on BIOS device 0x80 (first hard disk).
A shortcut for specifying BSD sub-partitions is:
"(<bios_device>,<bsd_subpart_letter>)"
"(hd0,a)" -- first hard disk, searches for first PC partition
containing BSD sub-partitions, then finds the "a" subpartition.
"(fd0,a)" -- first floppy disk, searches for BSD partition "a".
Inheriting from the defaults can be done by the following variations:
-- omitting the drive number completely will use the current
device taken from the current root partition.
"(,0)" looks for the first PC partition on the current disk.
-- omitting the partition information (but using at least one comma
after the bios device number) changes the bios device but
leaves the partition the same.
"(hd1,)" looks for the same partition as the current root but
on hard disk 1.
Interactive device completion (usable on the command-line after the "="
in a command, like "kernel="):
(nothing) -> lists all possible disks (hard and floppy)
"(" -> same
"(h" -> error (doesn't know what "h" means).
"(hd" -> error (doesn't know what "hd" means).
"(hd0" -> lists the first hard disk
"(hd0," -> lists all partitions on the first hard disk
"(hd0,a" -> finds and mounts BSD partition 'a', then reports FS type.
"(hd0,a)" -> same
"(hd0,a)/" -> lists all files in root directory... (becomes file-completion
listing at this point).
NOTE: for any of the completion stuff, it searches back to the beginning
of the line or the most recent space, then uses that string for the
completion listing operation (file, device, partition). It uses the
*cursor* position as the determiner, so, in the above example, one could
have "(hd0,a)/kernel" on the command-line, then move the cursor to the
beginning (with C-a or lots of C-b's), then hit TAB, move it one character
forward (with C-f), hit TAB again, etc. with the same results as the
above example!!!
Block-list syntax like this:
Primitive-block-list -> "<p-b-l>" = "{,<start-num>}+<length>"
example: "1+20" or "+5"
The interpretation of a primitive-block-list is that the first number
is the first block, then a "+", and a block-length (must be greater than
zero). These are all relative to the partition, and must be contained
within the partition boundaries (a whole disk would be "(hd0)"). If
the starting number is omitted, it is presumed to be zero (the first
block).
construction -> "<block-list>" =
"<p-b-l-1>,<p-b-l-2>,...,<p-b-l-N>{\,<length_in_bytes>}"
example: "1+100,200+1,300+300,<length_in_bytes>"
This represents a conglomerate of blocks, all to be loaded as part of
one block-list. If the exact length is omitted, then it is calculated as
the size of all of the blocks.
Absolute-pathname syntax like this:
Directory notation is via a forward slash, always in absolute form (like
a UNIX absolute pathname), like: "/kernel" or "/test/kernel".
Overall filename syntax is:
[<device>][<block-list>][<absolute-pathname>]
<device> is optional (will use the root partition then), but never ignored.
Either <block-list> or <absolute-pathname> must be used when providing
the name for a generic file. If <block-list> is used, all past it in the
filename is ignored (i.e. if you use both, the blocklist takes precedence).
Legal characters as parts of a directory/filename are any normally
printable ascii character (not control-characters of any kind) except
a space (since it is the delimiter of the end of the whole file/device
name string) and "/" (since it is used as a directory delimiter).
So, legal examples are:
"(hd0,a)/kernel"
"/kernel"
"1+20,25+10,15000"
"(hd0,a)1+20"
"(hd0,a)1+20,400+50,500+100"
"1+20,25+10,15000/kernel"
"(hd0,a)1+20,400+500/kernel"
INTERFACE DESCRIPTION
---------------------
This file also describes the generic interface used by the filesystem code.
The "BLK_NOTES" heading below is for the blocklist filesystem.
The "FAT_NOTES" heading below is for the FAT filesystem.
The "FFS_NOTES" heading below is for the FFS filesystem.
General function description:
For any particular partition, it is presumed that only one of the "normal"
filesystems such as FAT, FFS, or ext2fs can be used, so there is
a switch table managed by the functions in "disk_io.c". The notation is
that you can only "mount" one at a time.
The blocklist filesystem has a special place in the system. In addition
to the "normal" filesystem (or even without one mounted), you can access
disk blocks directly (in the indicated partition) via the blocklist
notation. Using the blocklist filesystem doesn't effect any other
filesystem mounts.
Interface description (this was done somewhat hastily, so important
parts might be missing):
Errors generated:
-- look at "fsys_ffs.c" for examples... (yeah, this is a cop-out for
now, I know).
The variables which can be read by the filesystem backend are:
-- "current_drive", a global which contains the current BIOS drive
number (numbered from 0, if a floppy, and numbered from 0x80,
if a hard disk).
-- "current_slice", a global which contains the current partition
type, if a hard disk.
-- "part_length", a global which contains the current partition
length, in sectors.
-- "print_possibilities", a global which is true when the "dir"
function should print the possible completions of a file, and
false when it should try to actually open a file of that name.
-- the "#define FSYS_BUF", which points to a filesystem buffer which
is 32K in size, to use in any way which the filesystem backend
desires.
The variables which need to be written by a filesystem backend are:
-- "filepos", a global which should be the current position in
the file.
NOTE: the value of "filepos" can be changed out from under the
filesystem code in the current implementation. Don't depend on
it being the same for later calls into the back-end code!!!
-- "filemax", a global which should be the length of the file.
-- "debug_fs_func", a global which should be set to the value of
"debug_fs" ONLY during reading of data for the file, not any
other FS data, inodes, FAT tables, whatever, then set to NULL
at all other times (it will be NULL by default). If this isn't
done correctly, then the "testload=" and "install=" commands
won't work correctly!!! (look at "fsys_ffs.c" for details).
The functions expected to be used by the filesystem backend are:
-- "devread", which only reads sectors from within a partition. Sector
0 is the first sector in the partition.
-- If the backend uses the blocklist code (like the FAT filesystem
backend does), then "read" can be used, after setting "blocklist"
to 1.
The functions expected to be defined by the filesystem backend are described
at least moderately in the file "filesys.h". Their usage is fairly evident
from their use in the functions in "disk_io.c", look for the use of the
"fsys_table" array.
NOTE: The semantics are such that then "mount"ing the filesystem, presume
the filesystem buffer "FSYS_BUF" is corrupted, and (re-)load all important
contents. When opening and reading a file, presume that the data from
the "mount" is available, and doesn't get corrupted by the open/read (i.e.
multiple opens and/or reads will be done with only one mount if in the
same filesystem).
BLK_NOTES:
block filesystem info goes like this:
NOTE: a "block-list" is two 4-byte values, representing the start and length
of a set of 512 byte sectors.
<buffer start>
[ cur_filepos, cur_block_list, cur_block_num,
block-list, block-list, block-list, etc.... ]
<buffer end>
The buffer is 32Kbytes long, so the maximum length of such a list is
32Kbytes - 12 bytes.
FAT_NOTES:
The filenames are all mapped to lower-case.
The FAT filesystem actually uses the "blocklist" filesystem as it's read
routine, reading the appropriate FAT entries and placing them into the
blocklist area. (in this case, a portion of the end of the blocklist
buffer area is used for FAT filesystem information)
It concatenates adjacent blocks in the FAT table together when possible
to consolodate the number of blocklists.
NOTE: The above is important, since there is a maximum number of
approx 1800 blocklists. This is generally more than adequate, but
if it runs off the end and a read is attempted in this area, an
"ERR_FILELENGTH" error will be generated.
FFS_NOTES:
Notes on the FFS filesystem implementation and limitations.
Limitations:
-- Only 1 level of indirect blocks is supported. This implies a
limitation in file-length to approx 16MB. If a read past this point
is attempted, an "ERR_FILELENGTH" error is generated.
-- If the "blocksize" is greater than 8Kbytes, various buffers will
overwrite themselves and the whole thing will come apart at the
seams.