/**************************************************************************** * This file defines the implementation of a simplified FAT32 file system * * supported by the ALMOS-MKH boot-loader. * * * * This implementation only supports block devices with block (sector) * * size of 512 bytes (value stored in BPB_BYTSPERSEC, see below). The * * max size for a single file is 4Gb - 1. * * * * A cluster is a smallest storage allocatable unit on the block device: * * any file (or directory) occupies at least one cluster, and a given * * cluster cannot be shared by 2 different files. This implementation * * supports cluster size of 4Kb (8 sectors, value stored in * * BPB_SECPERCLUS, see below). * * * * For partitioned devices such as hard drives, the first sector of the * * drive is the Master Boot Record defining partitions, while the first * * sector of partitions formatted with a FAT file system is the boot * * sector (Volume Boot Record). * * * * Here is the layout of a partition formatted with a FAT32 file system: * * +--------------------------------------------------------------------+ * * | Reserved Region, composed of: | * * | - Boot Sector (i.e VBR, logical sector 0), | * * | - FS Information Sector (logical sector 1, value stored in | * * | BPB_FSINFO, see below), | * * | - Other reserved sectors (optional). | * * |--------------------------------------------------------------------| * * | FAT Region: contains the File Allocation Table which are maps | * * | of the Data Region, indicating which clusters are used by files | * * | and directories. | * * | This may contains two copies of the FAT data structure (value | * * | stored in BPB_NUMFATS, see below) for the sake of redundancy | * * | checking, although rarely used. | * * |--------------------------------------------------------------------| * * | Data Region: this is where the actual file and directory data | * * | stored. The Root Directory Table is stored in the first cluster | * * | of the Data Region (value stored in BPB_ROOTCLUS, see below). | * * +--------------------------------------------------------------------+ * ****************************************************************************/ #ifndef BOOT_FAT32_H #define BOOT_FAT32_H /**************************************************************************** * Various signature values. * * Warning: don't forget that little-endian representation must be assumed * ****************************************************************************/ #define BOOT_SIGNATURE 0xAA55 #define FSI_SIGNATURE1 0x41615252 #define FSI_SIGNATURE2 0x61417272 #define FSI_SIGNATURE3 0xAA550000 /**************************************************************************** * Master Boot Record structure. * ****************************************************************************/ /* Boot code (first 446 bytes). */ /* Partition table (64 bytes). */ /* offset | size (both in bytes) */ #define FIRST_ENTRY_ACTIVE 446, 1 /* Status of first partition. */ #define FIRST_ENTRY_CHSFRST 447, 3 /* CHS address of first sector. */ #define FIRST_ENTRY_TYPE 450, 1 /* First partition type. */ #define FIRST_ENTRY_CHSLST 451, 3 /* CHS address of last sector. */ #define FIRST_ENTRY_LBAFRST 454, 4 /* LBA of first sector. */ #define FIRST_ENTRY_SIZE 458, 4 /* Count of sectors in partition. */ #define SECOND_ENTRY_ACTIVE 462, 1 /* Status of second partition. */ #define SECOND_ENTRY_CHSFRST 463, 3 /* CHS address of first sector. */ #define SECOND_ENTRY_TYPE 466, 1 /* Second partition type. */ #define SECOND_ENTRY_CHSLST 467, 3 /* CHS address of last sector. */ #define SECOND_ENTRY_LBAFRST 470, 4 /* LBA of first sector. */ #define SECOND_ENTRY_SIZE 474, 4 /* Count of sectors in partition. */ #define THIRD_ENTRY_ACTIVE 478, 1 /* Status of third partition. */ #define THIRD_ENTRY_CHSFRST 479, 3 /* CHS address of first sector. */ #define THIRD_ENTRY_TYPE 482, 1 /* Third partition type. */ #define THIRD_ENTRY_CHSLST 483, 3 /* CHS address of last sector. */ #define THIRD_ENTRY_LBAFRST 486, 4 /* LBA of first sector. */ #define THIRD_ENTRY_SIZE 490, 4 /* Count of sectors in partition. */ #define FOURTH_ENTRY_ACTIVE 494, 1 /* Status of fourth partition. */ #define FOURTH_ENTRY_CHSFRST 495, 3 /* CHS address of first sector. */ #define FOURTH_ENTRY_TYPE 498, 1 /* Fourth partition type. */ #define FOURTH_ENTRY_CHSLST 499, 3 /* CHS address of last sector. */ #define FOURTH_ENTRY_LBAFRST 502, 4 /* LBA of first sector. */ #define FOURTH_ENTRY_SIZE 506, 4 /* Count of sectors in partition. */ /* Signature (last 2 bytes). */ /* offset | size (both in bytes) */ #define MBR_SIGNATURE_POS 510, 2 /* Boot signature. */ /**************************************************************************** * Boot Sector structure. * ****************************************************************************/ /* First 11 bytes. */ /* offset | size (both in bytes) */ #define BS_JMPBOOT 0, 3 /* Jump instruction to boot code. */ #define BS_OEMNAME 3, 8 /* OEM identifier (meaningless). */ /* BIOS Parameter Block (next 25 bytes). */ /* offset | size (both in bytes) */ #define BPB_BYTSPERSEC 11, 2 /* Bytes per logical sector. */ #define BPB_SECPERCLUS 13, 1 /* Logical sectors per cluster. */ #define BPB_RSVDSECCNT 14, 2 /* Count of reserved sectors. */ #define BPB_NUMFATS 16, 1 /* Count of File Allocation Tables. */ #define BPB_ROOTENTCNT 17, 2 /* Must be 0 for FAT32. */ #define BPB_TOTSEC16 19, 2 /* Total sectors count on 16 bits. */ #define BPB_MEDIA 21, 1 /* Media descriptor. */ #define BPB_FATSZ16 22, 2 /* Must be 0 for FAT32. */ #define BPB_SECPERTRK 24, 2 /* Sectors per track for INT 0x13. */ #define BPB_NUMHEADS 26, 2 /* Number of heads for INT 0x13. */ #define BPB_HIDDSEC 28, 2 /* Hidden sectors preceding the partition that contains this FAT volume. */ #define BPB_TOTSEC32 32, 4 /* Total sectors count on 32 bits. */ /* FAT32 Extended BIOS Parameter Block (next 28 bytes). */ /* offset | size (both in bytes) */ #define BPB_FATSZ32 36, 4 /* Sectors per FAT on 32 bits. */ #define BPB_EXTFLAGS 40, 2 /* Mirroring flags. */ #define BPB_FSVER 42, 2 /* Version. */ #define BPB_ROOTCLUS 44, 4 /* Number of first cluster of the root directory. */ #define BPB_FSINFO 48, 2 /* Logical sector number of FS Information Sector. */ #define BPB_BKBOOTSEC 50, 2 /* Logical sector of Backup Boot Sector. */ #define BPB_RESERVED 52, 12 /* Reserved for future expansion. */ /* FAT12/FAT16 Extended BIOS Parameter Block (next 26 bytes). */ /* offset | size (both in bytes) */ #define BS_DRVNUM 64, 1 /* INT 0x13 drive number. */ #define BS_RESERVED1 65, 1 /* Reserved. */ #define BS_BOOTSIG 66, 1 /* Extended boot signature. */ #define BS_VOLID 67, 4 /* Volume ID (serial number). */ #define BS_VOLLAB 71, 11 /* Volume label. */ #define BS_FILSYSTYPE 82, 8 /* File system type: "FAT12 ", "FAT16 " or "FAT " */ /* File system and operating system specific boot code (next 420 bytes). */ /* offset | size (both in bytes) */ #define BS_CODE 90, 420 /* Executable code. */ /* Signature (last 2 bytes). */ /* offset | size (both in bytes) */ #define BS_SIGNATURE 510, 2 /* Boot signature. */ /**************************************************************************** * FS Information Sector structure. * * This sector is used for speeding up access times of certain operations. * ****************************************************************************/ /* offset | size (both in bytes) */ #define FSI_LEADSIG 0, 4 /* Lead signature. */ #define FSI_RESERVED1 4, 480 /* Reserved. */ #define FSI_STRUCSIG 484, 4 /* Another signature. */ #define FSI_FREE_COUNT 488, 4 /* Number of free clusters. */ #define FSI_NXT_FREE 492, 4 /* Most recently allocated cluster. */ #define FSI_RESERVED2 496, 12 /* Reserved. */ #define FSI_TRAILSIG 508, 4 /* Trail signature. */ /**************************************************************************** * File Allocation Table. * * The File Allocation Table is a table that indicates the status and * * location of all data clusters on the disk. It can be * * considered the "table of contents" of a disk. The cluster may be * * available for use, it may be reserved by the operating system, it may * * be unavailable due to a bad sector on the disk, or it may be in use * * by a file. The clusters of a file need not to be right next to each * * other on the disk. The FAT allows the operating system to follow the * * chain of clusters in a file. * * * * Since the first cluster of the Data Region is cluster #2, the first 2 * * entries of the FAT are unused. * * * * Note that despite its name FAT32 uses only 28 bits of the 32 possible * * bits to address the clusters on the disk: the upper 4 bits should be * * left untouched. * ****************************************************************************/ #define FAT_ENTRY_SIZE 4 /* Size of a FAT entry (in bytes) */ /* FAT entry values. */ #define FREE 0x00000000 /* Free cluster. */ #define RESERVED 0x00000001 /* Reserved for internal purposes. */ #define BAD 0x0FFFFFF7 /* Bad sector in cluster. */ // Value in this range should be interpreted as next cluster number. #define USED_MIN 0x00000002 /* Minimum value to be considered as used for data clusters. */ #define USED_MAX 0x0FFFFFEF /* Maximum value to be considered as used for data clusters. */ // Value in this range means this is the last cluster in file. #define EOC_MIN 0x0FFFFFF8 /* Minimum value to be considered as end-of-chain marker. */ #define EOC_MAX 0x0FFFFFFF /* Maximum value to be considered as end-of-chain marker. */ /**************************************************************************** * Directory table. * * A directory table is a special type of file that represents a directory. * * Each file or subdirectory stored within it is represented by a 32-byte * * entry in the table. All directory tables are stored in the Data Region. * * The actual number of entries in a directory stored in the Data Region * * can grow by adding another cluster to the chain in the FAT. * * * * A directory entry simply stores the information needed to know where * * a file's data or a folder's children are stored on the disk. * * * * The only special directory which must always be present is the root * * directory. For FAT32, it can be of variable size and is a cluster, * * just like any other directory is (this is not true for FAT12/FAT16). * * The first cluster of the root directory on a FAT32 volume is stored in * * BPB_ROOTCLUS. * * * * Each entry can be preceded by "fake entries" to support a VFAT long * * filename (LFN, see further below). When such a directory entry is * * encountered, it is given special treatment by the file system. * ****************************************************************************/ #define DIR_ENTRY_SIZE 32 /* Directory entry size (in bytes) */ #define PATH_MAX_SIZE 260 /* Max file path length (bytes) */ #define NAME_MAX_SIZE 256 /* Max file/dir name length (bytes) */ /**************************************************************************** * Standard 8.3 format. * * For a classic 8.3 filename entry, the DIR_NAME field is actually broken * * in 2 parts: the 8-characters main part of the name and the 3-characters * * extension. These 2 parts are "trailing space padded". * * * * Furthermore, all classic 8.3 filenames are uppercase. * ****************************************************************************/ /* offset | size (both in bytes) */ #define DIR_NAME 0, 11 /* Short file name. */ #define DIR_ATTR 11, 1 /* File attributes. */ #define DIR_NTRES 12, 1 /* Reserved for use by WINDOWS NT. */ #define DIR_CRTTIMETENTH 13, 1 /* Millisecond stamp at file creation time. */ #define DIR_CRTTIME 14, 2 /* Time file was created. */ #define DIR_CRTDATE 16, 2 /* Date file was created. */ #define DIR_LSTACCDATE 18, 2 /* Last access date. */ #define DIR_FSTCLUSHI 20, 2 /* High 16 bits of this entry's first cluster number. */ #define DIR_WRTTIME 22, 2 /* Time of last write. */ #define DIR_WRTDATE 24, 2 /* Date of last write. */ #define DIR_FSTCLUSLO 26, 2 /* Low 16 bits of this entry's first cluster number. */ #define DIR_FILESIZE 28, 4 /* This file's size in bytes. */ /* File attributes (DIR_ATTR values). */ #define ATTR_READ_ONLY 0x01 /* Writes to file should fail. */ #define ATTR_HIDDEN 0x02 /* Normal directory listings should not show this file. */ #define ATTR_SYSTEM 0x04 /* File belongs to the system, must not be physically moved. */ #define ATTR_VOLUME_ID 0x08 /* Volume label. */ #define ATTR_DIRECTORY 0x10 /* Container for other files. */ #define ATTR_ARCHIVE 0x20 /* Archive (file marked as dirty). */ #define ATTR_LONG_NAME 0x0F /* The file is part of the long long entry for some other file. */ /* Special values of the first byte DIR_NAME[0] of a FAT directory entry. */ #define FREE_ENTRY 0xE5 /* Directory entry is free. */ #define LAST_ENTRY 0x00 /* No subsequent entry in use. */ /**************************************************************************** * Long File Name format. * * Long File Names are stored on FAT file system using a trick: adding * * (possibly multiple) additional entries to the directory before the * * normal file entry. This means that long file name entries is always * * associated with a regular 8.3 entry that they always immediately * * precede (this because only short directory entries are visible to * * previous versions of MS-DOS). * * * * Note 1: every member of a set of long entries is uniquely numbered and * * the LDIR_ORD field of the last member of the set is or'd with a flag * * indicating that it is in fact the last member of the set. On the other * * hand, this field cannot have values of 0xE5 or 0x00 (see above). * * * * Note 2: an 8-bit checksum is computed on the name contained in the * * short directory entry at the time the short and long directory entries * * are created. This checksum is then placed in every long entry. All 11 * * characters of the name in the short entry are used in the checksum * * calculation. * * * * Note 3: if there are multiple LFN entries, firstly comes the LAST LFN * * entry (the last part of the file name). * ****************************************************************************/ /* offset | size (both in bytes) */ #define LDIR_ORD 0, 1 /* Order of this entry in the sequence of long directory entries. */ #define LDIR_NAME1 1, 10 /* Characters 1-5 of the long name sub-component in this entry. */ #define LDIR_ATTR 11, 1 /* Must be ATTR_LONG_NAME. */ #define LDIR_TYPE 12, 1 /* Always 0. */ #define LDIR_CHKSUM 13, 1 /* Checksum of name in the short directory entry at the end of the long directory set. */ #define LDIR_NAME2 14, 12 /* Characters 6-11 of the long name sub-component in this entry. */ #define LDIR_FSTCLUSLO 26, 2 /* Must be 0. */ #define LDIR_NAME3 28, 4 /* Characters 12-13 of the long name sub-component in this entry. */ /* Last long directory entry mask. */ #define LAST_LONG_ENTRY 0x40 /**************************************************************************** * This structure defines a FAT32 File System descriptor. * ****************************************************************************/ #include typedef struct fat_desc_s { unsigned char block_buffer[512]; /* Buffer for FS Information. */ uint32_t block_buffer_lba; /* LBA of block_buffer. */ uint32_t initialized; /* Status of the FAT32 File System. */ uint32_t sector_size; /* Must be 512 bytes. */ uint32_t cluster_size; /* Must be 4096 bytes. */ uint32_t fat_sectors; /* Count of sectors in FAT Region. */ uint32_t fat_lba; /* LBA of first FAT sector. */ uint32_t data_sectors; /* Count of sectors in Data Region. */ uint32_t data_lba; /* LBA of first data sector. */ uint32_t root_cluster; /* first cluster of root directory. */ uint32_t fsi_lba; /* LBA of FS Information. */ uint32_t free_cluster_hint; /* Start point for free cluster */ uint32_t free_clusters_nr; /* Total number of free clusters. */ } fat_desc_t; /**************************************************************************** * Basic operations of FAT32 File System. * ****************************************************************************/ extern fat_desc_t boot_fat; /**************************************************************************** * This function initializes the FAT32 File System. * * * * @ returns 0 on success, -1 on error. * ****************************************************************************/ int boot_fat32_init(); /**************************************************************************** * This function loads the 'pathname' file into the memory buffer at base * * address 'buff_addr' of 'buff_size'. It uses the 512-byte buffer defined * * in the FAT32 descriptor. * * @ pathname : file to be loaded pathname. * * @ buff_addr : memory address of file containing buffer. * * @ buff_size : size of file containing buffer (in bytes). * * * * @ returns 0 on success, -1 on error. * ****************************************************************************/ int boot_fat32_load( char* pathname, uint32_t buff_addr, uint32_t buff_size ); #endif // BOOT_FAT32_H