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 -> "([,[,]])" 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: "(,)" "(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 -> "" = "{,}+" 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 -> "" = ",,...,{\,}" example: "1+100,200+1,300+300," 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: [][][] is optional (will use the root partition then), but never ignored. Either or must be used when providing the name for a generic file. If 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. [ cur_filepos, cur_block_list, cur_block_num, block-list, block-list, block-list, etc.... ] 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.