User:Superleaf1995/lowFS

From OSDev Wiki
Jump to navigation Jump to search

This article is a stub! This page or section is a stub. You can help the wiki by accurately contributing to it.

lowFS stands for Low Filesystem, simple huh?.

Is a table-filesystem designed by me (Superleaf1995) because why not?

In this filesystem each entry points to a portion of a file, this allows loading parts of the file progressively. If any of the tables is damaged, a checksum every 8 entries is made to ensure nothing is wrong. lowFS assumes the disk is a plain array of bytes.

This filesystem also tries to be simple as possible, and be compatible with 16-bit hosts as well as 64-bit ones.

Bootsector

There are three ways to identify a lowFS disk: checking byte 0x02, checking the last 4 bytes of sector 4 or checking the last 4 bytes of the disk. It should contain the characters 'LFFL' (ASCII). Followed by a table:

struct lowFS_megatable {
    uint8_t attribute; // Attribute byte
    uint8_t version; // lowFS version
    union {
        struct lowFS_floppy {
            uint8_t heads;
            uint8_t bytes_per_sector;
            uint16_t sectors_per_track;
        };
        struct lowFS_non_floppy {
            uint32_t n_lba;
        };
    }table;
    uint16_t reserved;
}__attribute__((packed));

Attribute:

Bit Purpose
0 If set, the disk is in big endian, if clear, the disk is in little endian
1 If set, disk has bad sectors
2-7 TBD
  • If all bits are set, the endianess is little, the disk has no bad sectors (assumed) and there are no checksums

Entry

The entry header is basically like a FAT entry, however, this is a header for entries not for files.

struct lowFS_entry_header {
    uint8_t reserved;      // Should always be 0xCC
    uint8_t entry_type;    // Type of entry
    uint32_t name_len;     // Length of the name (variable, upon the OS how to handle)
    uint64_t nn_entry;     // Next part of this entry (pointer)
    uint64_t previous;     // Previous entry header in the chain (pointer)
    uint64_t next_entry;   // Next entry header in the chain (pointer)
    uint64_t size;         // Size of entry (lowFS_entry struct not included). If set to 0, the host must know the size parsing entry type
};
  • nn_entry should be set to 0 if this is the final part of the entry.
  • next_entry should be set to 0 if this is the final part of the chain of entries.

Entry types

Following the entry_t header, follows the contents of the entry. Notice that these varies in size, but always should align to 8-bytes.

If entry_type is set to ENTRY_TYPE_FILEMETADATA (0xF0):

struct lowFS_entry_filemetadata {
    uint64_t filename_len; // length of filename
    uint64_t len; // length of file in bytes
    uint8_t filename[filename_len]; // variable size, kernel should alloc memory for incoming filename
    uint8_t encrypt; // If it's nonzero, the file is encrypted with some TBD encryption system
    uint8_t perm; // use for unix permissions
};
  • Filename should be ended with a NULL character

If entry_type is set to ENTRY_TYPE_FILEPART (0xF2):

struct lowFS_entry_filepart {
    uint64_t clen; // Length of the bytes of the file
    uint8_t content[clen]; // variable size, kernel should alloc memory for incoming file content
    uint16_t checksum; // verifies that the data in the file is correct (First byte of content ANDed by the last one)
};

If entry type is set to ENTRY_TYPE_DIRECTORYMETADATA (0xF4):

struct lowFS_entry_directorymetadata {
    uint64_t dirname_len; // length of dirname
    uint8_t dirname[dirname_len]; // variable size, kernel should alloc memory for incoming dirname
    uint8_t perm; // use for unix permissions
};

Checksum

The checksum is in total, 8-bytes.

The checksum is a simple 2-byte value 0x53BC. This byte is placed after 8 entries (directorymetadata,filepart,etc). This word should be used for hosts that confides that the disk is OK, in this case, it should skip the following 6-bytes.

In case the host wants to read the 6-byte value, it should AND the aforementioned 2-byte value with the previous 2 bytes before the checksum bytes. Regardless of it being a entry header or a regular entry or not. The result should match the checksum. If a FILEPART entry is before the checksum, the following 4-bytes are the higher 4-bytes of the size of the file. Otherwise it's the 4-checksum bytes.

After the checksum, the entries continue as normal.

A checksum cannot be after the last entry or entry header in a chain.

struct lowFS_checksum {
    uint16_t val; // 0x53BC
    uint16_t bf; // Previous 2 bytes ANDed with 0x53BC
    uint32_t fp; // FILEPART size high bytes
};