#include #include #include #include "io.h" struct directory_entry { uint8_t file_name[8]; uint8_t extension[3]; uint8_t file_attributes; uint8_t reserved1; uint8_t ctime_ms; uint8_t ctime_hms[2]; uint8_t ctime_date[2]; uint8_t atime_date[2]; uint8_t ea_index[2]; uint8_t mtime_hms[2]; uint8_t mtime_date[2]; uint8_t first_cluster[2]; uint8_t file_size[4]; }; int fat12_mkfs(int fd, uint32_t bytes) { uint8_t mbr[512]; const uint16_t sector_size = 512; const uint8_t cluster_size = 8; // 4 kiB cluster sizes match flash erase block size // XXX What happens if this is an even multiple of sectors? uint32_t fat_size = 1 + ((((bytes * 3) / sector_size) / cluster_size) / 2); memset(mbr, 0, sizeof(mbr)); // jmp instruction mbr[0] = 0xeb; mbr[1] = 0x3c; mbr[2] = 0x90; // OEM name memcpy(mbr+3, "Fomu MBR", 8); // Bytes per sector (512) fat12_write_u16(mbr + 0x0b, sector_size); // Sectors per cluster (8), so cluster is 512 * 8 mbr[0x0d] = cluster_size; // Reserved sector count (8 sectors, to pad things to 4096-byte boundaries) fat12_write_u16(mbr + 0x0e, cluster_size); // Number of FATs (1) mbr[0x10] = 1; // Maximum number of root directory entries (16) fat12_write_u16(mbr + 0x11, 32); // Total number of 512-byte sectors fat12_write_u16(mbr + 0x13, bytes / sector_size); // Type of media (0xf8 == fixed disk) mbr[0x15] = 0xf8; // Sectors per FAT fat12_write_u16(mbr + 0x16, fat_size); // Sectors per track fat12_write_u16(mbr + 0x18, 32); // Number of heads fat12_write_u16(mbr + 0x1a, 64); // Hidden sectors mbr[0x1c] = 0x00; mbr[0x1d] = 0x00; mbr[0x1e] = 0x00; mbr[0x1f] = 0x00; // Total number of sectors (unused, since we put it in 0x13) mbr[0x20] = 0; mbr[0x21] = 0; mbr[0x22] = 0; mbr[0x23] = 0; // BIOS drive mbr[0x24] = 0x80; // Unused mbr[0x25] = 0; // Boot signature mbr[0x26] = 0x29; // Serial number mbr[0x27] = 0xf0; mbr[0x28] = 0xb0; mbr[0x29] = 0x00; mbr[0x2a] = 0x07; // Volume Name memcpy(mbr + 0x2b, "Fomu ", 11); // Filesystem memcpy(mbr + 0x36, "FAT12 ", 8); // Signature mbr[0xfe] = 0x55; mbr[0xff] = 0xaa; // Write MBR to disk if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) { return -1; } memset(mbr, 0, sizeof(mbr)); // The first two clusters in the FAT are reserved, and must be 0xff fat12_set_cluster(mbr, 0, 0xff8); // 0xff8 instead of 0xfff indicates "Hard Disk" fat12_set_cluster(mbr, 1, 0xfff); // 0xfff is reserved value // Root directory is only one cluster fat12_set_cluster(mbr, 2, 0xfff); if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) { return -1; } return 0; }