X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftest%2Fao_fat_test.c;h=3f94703443a98af2bcc576e6fb136436ff76e998;hb=c7b606e93a4e4fbd2c0e883352ed74619ee24cf7;hp=22ac03ad2dd059fe617c9adc827c080eb255bc93;hpb=d1fe0654b45cc8f944394308cf29945b537becc4;p=fw%2Faltos diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 22ac03ad..3f947034 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #include #include +#include #define AO_FAT_TEST @@ -40,7 +42,7 @@ void ao_panic(uint8_t panic) { printf ("panic %d\n", panic); - exit(1); + abort(); } #define AO_PANIC_BUFIO 15 @@ -64,9 +66,12 @@ struct ao_cmds { int fs_fd; +uint64_t total_reads, total_writes; + uint8_t ao_sdcard_read_block(uint32_t block, uint8_t *data) { + ++total_reads; lseek(fs_fd, block * 512, 0); return read(fs_fd, data, 512) == 512; } @@ -74,45 +79,308 @@ ao_sdcard_read_block(uint32_t block, uint8_t *data) uint8_t ao_sdcard_write_block(uint32_t block, uint8_t *data) { + ++total_writes; lseek(fs_fd, block * 512, 0); return write(fs_fd, data, 512) == 512; } +char *fs = "fs.fat"; + void ao_sdcard_init(void) { - fs_fd = open("fat.fs", 2); + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -C %s 16384", fs, fs); + if (system (cmd) != 0) { + fprintf(stderr, "'%s' failed\n", cmd); + exit(1); + } + fs_fd = open(fs, 2); + if (fs_fd < 0) { + perror (fs); + exit(1); + } } #include "ao_bufio.c" +void +check_bufio(char *where) +{ + int b; + + for (b = 0; b < AO_NUM_BUF; b++) { + if (ao_bufio[b].busy) { + printf ("%s: buffer %d busy. block %d seqno %u\n", + where, b, ao_bufio[b].block, ao_bufio[b].seqno & 0xffff); + abort(); + } + } +} + + +void +check_fat(void); + #include "ao_fat.c" +/* Get the next cluster entry in the chain */ +static uint16_t +ao_fat_entry_raw_read(uint16_t cluster, uint8_t fat) +{ + uint32_t sector; + uint16_t offset; + uint8_t *buf; + uint16_t ret; + +// cluster -= 2; + sector = cluster >> (SECTOR_SHIFT - 1); + offset = (cluster << 1) & SECTOR_MASK; + buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + if (!buf) + return 0; + ret = get_u16(buf + offset); + ao_fat_sector_put(buf, 0); + return ret; +} + +void +dump_fat(void) +{ + int e; + + printf ("\n **** FAT ****\n\n"); + for (e = 0; e < number_cluster; e++) { + if ((e & 0xf) == 0x0) + printf ("%04x: ", e); + printf (" %04x", ao_fat_entry_raw_read(e, 0)); + if ((e & 0xf) == 0xf) + putchar ('\n'); + } +} + +void +fat_list(void) +{ + uint16_t entry = 0; + struct ao_fat_dirent dirent; + + printf (" **** Root directory ****\n"); + while (ao_fat_readdir(&entry, &dirent)) { + printf ("%04x: %-8.8s.%-3.3s %02x %04x %d\n", + entry, + dirent.name, + dirent.name + 8, + dirent.attr, + dirent.cluster, + dirent.size); + } + + printf (" **** End of root directory ****\n"); +} + +void +fatal(char *msg, ...) +{ + dump_fat(); + fat_list(); + + va_list l; + va_start(l, msg); + vfprintf(stderr, msg, l); + va_end(l); + + abort(); +} + +void +check_fat(void) +{ + int e; + int f; + + for (e = 0; e < number_cluster; e++) { + uint16_t v = ao_fat_entry_raw_read(e, 0); + for (f = 1; f < number_fat; f++) { + if (ao_fat_entry_raw_read(e, f) != v) + fatal ("fats differ at %d\n", e); + } + } +} + +uint16_t +check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) +{ + uint16_t clusters = 0; + uint16_t cluster; + + if (!first_cluster) + return 0; + + for (cluster = first_cluster; + (cluster & 0xfff8) != 0xfff8; + cluster = ao_fat_entry_raw_read(cluster, 0)) + { + if (!ao_fat_cluster_valid(cluster)) + fatal("file %d: invalid cluster %04x\n", dent, cluster); + if (used[cluster]) + fatal("file %d: duplicate cluster %04x\n", dent, cluster); + used[cluster] = 1; + clusters++; + } + return clusters; +} + +void +check_fs(void) +{ + uint16_t r; + uint16_t cluster, chain; + uint8_t *used; + + check_fat(); + + used = calloc(1, number_cluster); + + for (r = 0; r < root_entries; r++) { + uint8_t *dent = ao_fat_root_get(r); + uint16_t clusters; + uint32_t size; + uint16_t first_cluster; + uint8_t name[11]; + + if (!dent) + fatal("cannot map dent %d\n", r); + memcpy(name, dent+0, 11); + first_cluster = get_u16(dent + 0x1a); + size = get_u32(dent + 0x1c); + ao_fat_root_put(dent, r, 0); + + if (name[0] == AO_FAT_DENT_END) { + break; + } + + clusters = check_file(r, first_cluster, used); + if (size > clusters * bytes_per_cluster) + fatal("file %d: size %u beyond clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + if (size <= (clusters - 1) * bytes_per_cluster) + fatal("file %d: size %u too small clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + } + for (; r < root_entries; r++) { + uint8_t *dent = ao_fat_root_get(r); + if (!dent) + fatal("cannot map dent %d\n", r); + if (dent[0] != AO_FAT_DENT_END) + fatal("found non-zero dent past end %d\n", r); + ao_fat_root_put(dent, r, 0); + } + + for (cluster = 0; cluster < 2; cluster++) { + chain = ao_fat_entry_raw_read(cluster, 0); + + if ((chain & 0xfff8) != 0xfff8) + fatal("cluster %d: not marked busy\n", cluster); + } + for (; cluster < number_cluster; cluster++) { + chain = ao_fat_entry_raw_read(cluster, 0); + + if (chain != 0) { + if (used[cluster] == 0) + fatal("cluster %d: marked busy, but not in any file\n", cluster); + } else { + if (used[cluster] != 0) + fatal("cluster %d: marked free, but foudn in file\n", cluster); + } + } +} + +#define NUM_FILES 512 +#define LINES_FILE 1000 + +uint32_t sizes[NUM_FILES]; + +unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH]; + int main(int argc, char **argv) { - uint8_t data[15]; - int len; + char name[12]; + int id; + MD5_CTX ctx; + unsigned char md5_check[MD5_DIGEST_LENGTH]; + + if (argv[1]) + fs = argv[1]; + ao_fat_init(); - ao_fat_test(); - if (ao_fat_open("DATALOG TXT")) { - printf ("DATALOG.TXT\n"); - while ((len = ao_fat_read(data, sizeof (data))) > 0) { - write(1, data, len); + + check_bufio("top"); + ao_fat_setup(); + + check_fs(); + check_bufio("after setup"); + printf (" **** Creating %d files\n", NUM_FILES); + + for (id = 0; id < NUM_FILES; id++) { + sprintf(name, "D%07dTXT", id); + if (ao_fat_creat(name) == AO_FAT_SUCCESS) { + int j; + char line[64]; + check_bufio("file created"); + MD5_Init(&ctx); + for (j = 0; j < 1000; j++) { + int len; + sprintf (line, "Hello, world %d %d\r\n", id, j); + len = strlen(line); + ao_fat_write((uint8_t *) line, len); + MD5_Update(&ctx, line, len); + sizes[id] += len; + } + ao_fat_close(); + MD5_Final(&md5[id][0], &ctx); + if (id == 0) { + printf ("MD5 write %d:", id); + for (j = 0; j < MD5_DIGEST_LENGTH; j++) + printf(" %02x", md5[id][j]); + printf ("\n"); + } + check_bufio("file written"); } - ao_fat_close(); -// ao_fat_unlink("DATALOG TXT"); } - if (ao_fat_open("NEWFILE TXT")) { - printf ("NEWFILE.TXT\n"); - while ((len = ao_fat_read(data, sizeof (data))) > 0) { - write(1, data, len); + + check_bufio("all files created"); + printf (" **** All done creating files\n"); + check_fs(); + + printf (" **** Comparing %d files\n", NUM_FILES); + + for (id = 0; id < NUM_FILES; id++) { + char buf[337]; + sprintf(name, "D%07dTXT", id); + if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { + int len; + + MD5_Init(&ctx); + while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { + MD5_Update(&ctx, buf, len); + } + ao_fat_close(); + MD5_Final(md5_check, &ctx); + if (id == 0) { + int j; + printf ("MD5 read %d:", id); + for (j = 0; j < MD5_DIGEST_LENGTH; j++) + printf(" %02x", md5_check[j]); + printf ("\n"); + } + if (memcmp(md5_check, &md5[id][0], sizeof (md5_check)) != 0) + fatal ("checksum failed file %d\n", id); + check_bufio("file shown"); } - ao_fat_close(); - } - if (ao_fat_creat ("NEWFILE TXT")) { - for (len = 0; len < 4095; len++) - ao_fat_write((uint8_t *) "hello, world!\n", 14); - ao_fat_close(); } + + printf ("\n **** Total IO: read %llu write %llu\n", total_reads, total_writes); return 0; }