commit some source

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2019-06-03 09:57:25 +08:00
parent 2afca97177
commit 5fb4ea8474
7 changed files with 297 additions and 0 deletions

14
include/fat12.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef PANG_O_LIN_FAT12_H__
#define PANG_O_LIN_FAT12_H__
#include <stdint.h>
void fat12_write_u16(void *ptr, uint16_t val);
uint16_t fat12_read_u16(void *ptr);
void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value);
uint32_t fat12_get_cluster(void *fat, uint32_t cluster);
int fat12_defrag(int fd);
int fat12_mkfs(int fd, uint32_t bytes);
#endif /* PANG_O_LIN_FAT12_H__ */

14
include/io.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef PANG_O_LIN_IO_H__
#define PANG_O_LIN_IO_H__
#include <sys/types.h>
#ifdef unix
#include <unistd.h>
#endif
ssize_t pang_write(int fd, const void *buf, size_t count);
ssize_t pang_read(int fd, void *buf, size_t count);
off_t pang_seek(int fd, off_t offset, int whence);
#endif /* PANG_O_LIN_IO_H__ */

45
src/defrag.c Normal file
View File

@ -0,0 +1,45 @@
#include "io.h"
#define try(x) do { int i = (x); if (i == -1) { return -1 } } while (0)
int fat12_defrag(int fd) {
uint8_t buf[512];
// Read in MBR and figure out where the FAT begins and ends
try(pang_seek(fd, 0, SEEK_SET));
// Actually read in the MBR
try(pang_read(fd, buf, sizeof(buf)));
// We only operate on 512-byte sector sizes
if (fat12_read_u16(buf + 0x0b) != 512) {
return -2;
}
// We require the cluster size to be 4096 (8 * 512)
if (buf[0x0d] != 8) {
return -2;
}
// To ensure the erase block is correct, require 4096-bytes
// of reserved data
if (fat12_read_u16(buf + 0x0e) != 4096) {
return -2;
}
// Also, we only support 1 FAT
if (buf[0x10] != 1) {
return -2;
}
// 32 root entries keeps it padded correctly.
if (fat12_read_u16(mbr + 0x11, 32) != 32) {
return -2;
}
// Total number of 512-byte sectors
fat12_write_u16(mbr + 0x13, bytes / sector_size);
return 0;
}

41
src/fat12.c Normal file
View File

@ -0,0 +1,41 @@
#include "fat12.h"
void fat12_write_u16(void *ptr, uint16_t val) {
((uint8_t *)ptr)[0] = (val >> 0) & 0xff;
((uint8_t *)ptr)[1] = (val >> 8) & 0xff;
}
uint16_t fat12_read_u16(void *ptr) {
uint16_t val = 0;
val |= (((uint8_t *)ptr)[0] << 0) & 0x00ff;
val |= (((uint8_t *)ptr)[1] << 8) & 0xff00;
return val;
}
void fat12_set_cluster(void *fat, uint32_t cluster, uint32_t value) {
uint32_t offset = (cluster * 3) / 2;
if (cluster&1) {
((uint8_t *)fat)[offset] = (((uint8_t *)fat)[offset] & 0x0f) | ((value << 4) & 0xf0);
((uint8_t *)fat)[offset + 1] = value >> 4;
}
else {
((uint8_t *)fat)[offset] = value;
((uint8_t *)fat)[offset + 1] = (((uint8_t *)fat)[offset] & 0xf0) | ((value >> 8) & 0x0f);
}
}
uint32_t fat12_get_cluster(void *fat, uint32_t cluster) {
uint32_t offset = (cluster * 3) / 2;
uint32_t value = 0;
if (cluster&1) {
value |= (((uint8_t *)fat)[offset] >> 4) & 0x00f;
value |= (((uint8_t *)fat)[offset + 1] << 4) & 0xff0;
}
else {
value |= ((uint8_t *)fat)[offset];
value |= (((uint8_t *)fat)[offset + 1] << 8) & 0xf00;
}
return value;
}

15
src/io.c Normal file
View File

@ -0,0 +1,15 @@
#include "io.h"
#ifdef unix
ssize_t pang_write(int fd, const void *buf, size_t count) {
return write(fd, buf, count);
}
ssize_t pang_read(int fd, void *buf, size_t count) {
return read(fd, buf, count);
}
off_t pang_seek(int fd, off_t offset, int whence) {
return lseek(fd, offset, whence);
}
#endif

127
src/mkfat.c Normal file
View File

@ -0,0 +1,127 @@
#include <stdint.h>
#include <unistd.h>
#include <string.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];
};
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;
}

View File

@ -0,0 +1,41 @@
#include <stdint.h>
#include <stdio.h>
#include "fat12.h"
static uint8_t sample_fat12[] = {
0xF0, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60,
0x00, 0x07, 0x80, 0x00, 0xFF, 0xAF, 0x00, 0x14,
0xC0, 0x00, 0x0D, 0xE0, 0x00, 0x0F, 0x00, 0x01,
0x11, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, 0x15, 0x60,
0x01, 0x19, 0x70, 0xFF, 0xF7, 0xAF, 0x01, 0xFF,
0x0F, 0x00, 0x00, 0x70, 0xFF, 0x00, 0x00, 0x00,
};
static uint16_t fat12_compare[] = {
0xff0, 0xfff, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008,
0xfff, 0x00a, 0x014, 0x00c, 0x00d, 0x00e, 0x00f, 0x010,
0x011, 0xfff, 0x000, 0xfff, 0x015, 0x016, 0x019, 0xff7,
0xff7, 0x01a, 0xfff, 0x000, 0x000, 0xff7, 0x000, 0x000,
};
int main(int argc, char **argv) {
int i;
uint8_t generated_fat12[sizeof(sample_fat12)];
for (i = 0; i < sizeof(fat12_compare) / sizeof(*fat12_compare); i++) {
uint32_t cluster = fat12_get_cluster(sample_fat12, i);
fprintf(stderr, "GET: %2d: %03x (%03x) %s\n", i, cluster, fat12_compare[i], cluster == fat12_compare[i] ? "Ok" : "Error");
}
for (i = 0; i < sizeof(fat12_compare) / sizeof(*fat12_compare); i++) {
fat12_set_cluster(generated_fat12, i, fat12_compare[i]);
}
for (i = 0; i < sizeof(sample_fat12) / sizeof(*sample_fat12); i++) {
fprintf(stderr, "PUT: %2d: %02x (%02x) %s\n",
i,
generated_fat12[i], sample_fat12[i],
generated_fat12[i] == sample_fat12[i] ? "Ok" : "Error");
}
}