mkfs: first working version
It can create a basic filesystem of arbitrary size. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
		
							
								
								
									
										11
									
								
								src/fat12.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/fat12.c
									
									
									
									
									
								
							@@ -1,5 +1,16 @@
 | 
			
		||||
#include "fat12.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void fat12_write_u8(void *ptr, uint8_t val) {
 | 
			
		||||
    ((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t fat12_read_u8(void *ptr) {
 | 
			
		||||
    uint16_t val = 0;
 | 
			
		||||
    val |= (((uint8_t *)ptr)[0] << 0) & 0xff;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fat12_write_u16(void *ptr, uint16_t val) {
 | 
			
		||||
    ((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
 | 
			
		||||
    ((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								src/mkfat.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								src/mkfat.c
									
									
									
									
									
								
							@@ -2,31 +2,40 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "fat12.h"
 | 
			
		||||
#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];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Create a FAT12 filesystem using the given file descriptor,
 | 
			
		||||
// with length _bytes_.
 | 
			
		||||
// It will define a root directory size and padding size so that the file sectors
 | 
			
		||||
// end up on 4096-byte boundaries.
 | 
			
		||||
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
 | 
			
		||||
    const uint32_t sector_size  = 512;
 | 
			
		||||
    uint32_t cluster_size = 4096 / sector_size; // 4 kiB cluster sizes match flash erase block size
 | 
			
		||||
    if (bytes > 16000) {
 | 
			
		||||
        // We run out of clusters just below 16 megabytes.  Use bigger cluseters.
 | 
			
		||||
        cluster_size = 8192 / sector_size;
 | 
			
		||||
    }
 | 
			
		||||
    const uint32_t reserved_sectors = 1; // The MBR is the only reserved sector
 | 
			
		||||
 | 
			
		||||
    // XXX What happens if this is an even multiple of sectors?
 | 
			
		||||
    // Size of FAT (in bytes)
 | 
			
		||||
    uint32_t fat_size = 1 + ((((bytes * 3) / sector_size) / cluster_size) / 2);
 | 
			
		||||
    uint32_t fat_size_sectors = ((fat_size - 1) / sector_size) + 1;
 | 
			
		||||
 | 
			
		||||
    uint32_t root_directory_sector_count = cluster_size - (fat_size_sectors + reserved_sectors);
 | 
			
		||||
    uint32_t root_directory_entry_count = (sector_size / sizeof(struct fat_directory_entry)) * root_directory_sector_count;
 | 
			
		||||
 | 
			
		||||
    // fprintf(stderr, "bytes: %d\n", bytes);
 | 
			
		||||
    // fprintf(stderr, "sector_size: %d\n", sector_size);
 | 
			
		||||
    // fprintf(stderr, "cluster_size: %d\n", cluster_size);
 | 
			
		||||
    // fprintf(stderr, "reserved_sectors: %d\n", reserved_sectors);
 | 
			
		||||
    // fprintf(stderr, "fat_size: %d\n", fat_size);
 | 
			
		||||
    // fprintf(stderr, "fat_size_sectors: %d\n", fat_size_sectors);
 | 
			
		||||
    // fprintf(stderr, "root_directory_sector_count: %d\n", root_directory_sector_count);
 | 
			
		||||
    // fprintf(stderr, "root_directory_entry_count: %d\n", root_directory_entry_count);
 | 
			
		||||
    // fprintf(stderr, "\n");
 | 
			
		||||
 | 
			
		||||
    memset(mbr, 0, sizeof(mbr));
 | 
			
		||||
 | 
			
		||||
@@ -42,25 +51,25 @@ int fat12_mkfs(int fd, uint32_t bytes) {
 | 
			
		||||
    fat12_write_u16(mbr + 0x0b, sector_size);
 | 
			
		||||
 | 
			
		||||
    // Sectors per cluster (8), so cluster is 512 * 8
 | 
			
		||||
    mbr[0x0d] = cluster_size;
 | 
			
		||||
    fat12_write_u8(mbr + 0x0d, cluster_size);
 | 
			
		||||
 | 
			
		||||
    // Reserved sector count (8 sectors, to pad things to 4096-byte boundaries)
 | 
			
		||||
    fat12_write_u16(mbr + 0x0e, cluster_size);
 | 
			
		||||
    fat12_write_u16(mbr + 0x0e, reserved_sectors);
 | 
			
		||||
 | 
			
		||||
    // Number of FATs (1)
 | 
			
		||||
    mbr[0x10] = 1;
 | 
			
		||||
    fat12_write_u8(mbr + 0x10, 1);
 | 
			
		||||
 | 
			
		||||
    // Maximum number of root directory entries (16)
 | 
			
		||||
    fat12_write_u16(mbr + 0x11, 32);
 | 
			
		||||
    fat12_write_u16(mbr + 0x11, root_directory_entry_count);
 | 
			
		||||
 | 
			
		||||
    // Total number of 512-byte sectors
 | 
			
		||||
    fat12_write_u16(mbr + 0x13, bytes / sector_size);
 | 
			
		||||
 | 
			
		||||
    // Type of media (0xf8 == fixed disk)
 | 
			
		||||
    mbr[0x15] = 0xf8;
 | 
			
		||||
    fat12_write_u8(mbr + 0x15, 0xf8);
 | 
			
		||||
 | 
			
		||||
    // Sectors per FAT
 | 
			
		||||
    fat12_write_u16(mbr + 0x16, fat_size);
 | 
			
		||||
    fat12_write_u16(mbr + 0x16, fat_size_sectors);
 | 
			
		||||
 | 
			
		||||
    // Sectors per track
 | 
			
		||||
    fat12_write_u16(mbr + 0x18, 32);
 | 
			
		||||
@@ -69,31 +78,31 @@ int fat12_mkfs(int fd, uint32_t bytes) {
 | 
			
		||||
    fat12_write_u16(mbr + 0x1a, 64);
 | 
			
		||||
 | 
			
		||||
    // Hidden sectors
 | 
			
		||||
    mbr[0x1c] = 0x00;
 | 
			
		||||
    mbr[0x1d] = 0x00;
 | 
			
		||||
    mbr[0x1e] = 0x00;
 | 
			
		||||
    mbr[0x1f] = 0x00;
 | 
			
		||||
    // 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;
 | 
			
		||||
    // mbr[0x20] = 0;
 | 
			
		||||
    // mbr[0x21] = 0;
 | 
			
		||||
    // mbr[0x22] = 0;
 | 
			
		||||
    // mbr[0x23] = 0;
 | 
			
		||||
 | 
			
		||||
    // BIOS drive
 | 
			
		||||
    mbr[0x24] = 0x80;
 | 
			
		||||
    fat12_write_u8(mbr + 0x24, 0x80);
 | 
			
		||||
 | 
			
		||||
    // Unused
 | 
			
		||||
    mbr[0x25] = 0;
 | 
			
		||||
    fat12_write_u8(mbr + 0x25, 0);
 | 
			
		||||
 | 
			
		||||
    // Boot signature
 | 
			
		||||
    mbr[0x26] = 0x29;
 | 
			
		||||
    fat12_write_u8(mbr + 0x26, 0x29);
 | 
			
		||||
 | 
			
		||||
    // Serial number
 | 
			
		||||
    mbr[0x27] = 0xf0;
 | 
			
		||||
    mbr[0x28] = 0xb0;
 | 
			
		||||
    mbr[0x29] = 0x00;
 | 
			
		||||
    mbr[0x2a] = 0x07;
 | 
			
		||||
    fat12_write_u8(mbr + 0x27, 0xf0);
 | 
			
		||||
    fat12_write_u8(mbr + 0x28, 0xb0);
 | 
			
		||||
    fat12_write_u8(mbr + 0x29, 0x00);
 | 
			
		||||
    fat12_write_u8(mbr + 0x2a, 0x07);
 | 
			
		||||
 | 
			
		||||
    // Volume Name
 | 
			
		||||
    memcpy(mbr + 0x2b, "Fomu       ", 11);
 | 
			
		||||
@@ -102,8 +111,8 @@ int fat12_mkfs(int fd, uint32_t bytes) {
 | 
			
		||||
    memcpy(mbr + 0x36, "FAT12   ", 8);
 | 
			
		||||
 | 
			
		||||
    // Signature
 | 
			
		||||
    mbr[0xfe] = 0x55;
 | 
			
		||||
    mbr[0xff] = 0xaa;
 | 
			
		||||
    fat12_write_u8(mbr + 0xfe, 0x55);
 | 
			
		||||
    fat12_write_u8(mbr + 0xff, 0xaa);
 | 
			
		||||
 | 
			
		||||
    // Write MBR to disk
 | 
			
		||||
    if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) {
 | 
			
		||||
@@ -112,16 +121,33 @@ int fat12_mkfs(int fd, uint32_t bytes) {
 | 
			
		||||
 | 
			
		||||
    memset(mbr, 0, sizeof(mbr));
 | 
			
		||||
 | 
			
		||||
    // The first two clusters in the FAT are reserved, and must be 0xff
 | 
			
		||||
    // The first two clusters in the FAT are reserved
 | 
			
		||||
    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);
 | 
			
		||||
    // fat12_set_cluster(mbr, 2, 0xfff);
 | 
			
		||||
 | 
			
		||||
    if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fill in the rest of the FAT
 | 
			
		||||
    uint32_t fat_sector;
 | 
			
		||||
    memset(mbr, 0, sizeof(mbr));
 | 
			
		||||
    for (fat_sector = 1; fat_sector < fat_size_sectors; fat_sector++) {
 | 
			
		||||
        if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fill in the root directory
 | 
			
		||||
    uint32_t root_directory_sector;
 | 
			
		||||
    for (root_directory_sector = 0; root_directory_sector < cluster_size; root_directory_sector++) {
 | 
			
		||||
        if (pang_write(fd, mbr, sizeof(mbr)) != sizeof(mbr)) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user