| |
| 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. |