2 * Copyright © 2013 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 #include <openssl/md5.h>
32 ao_mutex_get(uint8_t *mutex)
37 ao_mutex_put(uint8_t *mutex)
42 ao_panic(uint8_t panic)
44 printf ("panic %d\n", panic);
48 #define AO_PANIC_BUFIO 15
50 #define ao_cmd_success 0
52 uint8_t ao_cmd_status;
53 uint32_t ao_cmd_lex_u32;
60 #define ao_cmd_register(x)
69 uint64_t total_reads, total_writes;
72 ao_sdcard_read_block(uint32_t block, uint8_t *data)
75 lseek(fs_fd, block * 512, 0);
76 return read(fs_fd, data, 512) == 512;
80 ao_sdcard_write_block(uint32_t block, uint8_t *data)
83 lseek(fs_fd, block * 512, 0);
84 return write(fs_fd, data, 512) == 512;
94 snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -C %s 16384", fs, fs);
95 if (system (cmd) != 0) {
96 fprintf(stderr, "'%s' failed\n", cmd);
106 #include "ao_bufio.c"
108 check_bufio(char *where)
112 for (b = 0; b < AO_NUM_BUF; b++) {
113 if (ao_bufio[b].busy) {
114 printf ("%s: buffer %d busy. block %d seqno %u\n",
115 where, b, ao_bufio[b].block, ao_bufio[b].seqno & 0xffff);
127 /* Get the next cluster entry in the chain */
129 ao_fat_entry_raw_read(uint16_t cluster, uint8_t fat)
137 sector = cluster >> (SECTOR_SHIFT - 1);
138 offset = (cluster << 1) & SECTOR_MASK;
139 buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector);
142 ret = get_u16(buf + offset);
143 ao_fat_sector_put(buf, 0);
152 printf ("\n **** FAT ****\n\n");
153 for (e = 0; e < number_cluster; e++) {
154 if ((e & 0xf) == 0x0)
155 printf ("%04x: ", e);
156 printf (" %04x", ao_fat_entry_raw_read(e, 0));
157 if ((e & 0xf) == 0xf)
166 struct ao_fat_dirent dirent;
168 printf (" **** Root directory ****\n");
169 while (ao_fat_readdir(&entry, &dirent)) {
170 printf ("%04x: %-8.8s.%-3.3s %02x %04x %d\n",
179 printf (" **** End of root directory ****\n");
183 fatal(char *msg, ...)
190 vfprintf(stderr, msg, l);
202 for (e = 0; e < number_cluster; e++) {
203 uint16_t v = ao_fat_entry_raw_read(e, 0);
204 for (f = 1; f < number_fat; f++) {
205 if (ao_fat_entry_raw_read(e, f) != v)
206 fatal ("fats differ at %d\n", e);
212 check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used)
214 uint16_t clusters = 0;
220 for (cluster = first_cluster;
221 (cluster & 0xfff8) != 0xfff8;
222 cluster = ao_fat_entry_raw_read(cluster, 0))
224 if (!ao_fat_cluster_valid(cluster))
225 fatal("file %d: invalid cluster %04x\n", dent, cluster);
227 fatal("file %d: duplicate cluster %04x\n", dent, cluster);
238 uint16_t cluster, chain;
243 used = calloc(1, number_cluster);
245 for (r = 0; r < root_entries; r++) {
246 uint8_t *dent = ao_fat_root_get(r);
249 uint16_t first_cluster;
253 fatal("cannot map dent %d\n", r);
254 memcpy(name, dent+0, 11);
255 first_cluster = get_u16(dent + 0x1a);
256 size = get_u32(dent + 0x1c);
257 ao_fat_root_put(dent, r, 0);
259 if (name[0] == AO_FAT_DENT_END) {
263 clusters = check_file(r, first_cluster, used);
264 if (size > clusters * bytes_per_cluster)
265 fatal("file %d: size %u beyond clusters %d (%u)\n",
266 r, size, clusters, clusters * bytes_per_cluster);
267 if (size <= (clusters - 1) * bytes_per_cluster)
268 fatal("file %d: size %u too small clusters %d (%u)\n",
269 r, size, clusters, clusters * bytes_per_cluster);
271 for (; r < root_entries; r++) {
272 uint8_t *dent = ao_fat_root_get(r);
274 fatal("cannot map dent %d\n", r);
275 if (dent[0] != AO_FAT_DENT_END)
276 fatal("found non-zero dent past end %d\n", r);
277 ao_fat_root_put(dent, r, 0);
280 for (cluster = 0; cluster < 2; cluster++) {
281 chain = ao_fat_entry_raw_read(cluster, 0);
283 if ((chain & 0xfff8) != 0xfff8)
284 fatal("cluster %d: not marked busy\n", cluster);
286 for (; cluster < number_cluster; cluster++) {
287 chain = ao_fat_entry_raw_read(cluster, 0);
290 if (used[cluster] == 0)
291 fatal("cluster %d: marked busy, but not in any file\n", cluster);
293 if (used[cluster] != 0)
294 fatal("cluster %d: marked free, but foudn in file\n", cluster);
299 #define NUM_FILES 512
300 #define LINES_FILE 1000
302 uint32_t sizes[NUM_FILES];
304 unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH];
307 main(int argc, char **argv)
312 unsigned char md5_check[MD5_DIGEST_LENGTH];
323 check_bufio("after setup");
324 printf (" **** Creating %d files\n", NUM_FILES);
326 for (id = 0; id < NUM_FILES; id++) {
327 sprintf(name, "D%07dTXT", id);
328 if (ao_fat_creat(name) == AO_FAT_SUCCESS) {
331 check_bufio("file created");
333 for (j = 0; j < 1000; j++) {
335 sprintf (line, "Hello, world %d %d\r\n", id, j);
337 ao_fat_write((uint8_t *) line, len);
338 MD5_Update(&ctx, line, len);
342 MD5_Final(&md5[id][0], &ctx);
344 printf ("MD5 write %d:", id);
345 for (j = 0; j < MD5_DIGEST_LENGTH; j++)
346 printf(" %02x", md5[id][j]);
349 check_bufio("file written");
353 check_bufio("all files created");
354 printf (" **** All done creating files\n");
357 printf (" **** Comparing %d files\n", NUM_FILES);
359 for (id = 0; id < NUM_FILES; id++) {
361 sprintf(name, "D%07dTXT", id);
362 if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) {
366 while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) {
367 MD5_Update(&ctx, buf, len);
370 MD5_Final(md5_check, &ctx);
373 printf ("MD5 read %d:", id);
374 for (j = 0; j < MD5_DIGEST_LENGTH; j++)
375 printf(" %02x", md5_check[j]);
378 if (memcmp(md5_check, &md5[id][0], sizeof (md5_check)) != 0)
379 fatal ("checksum failed file %d\n", id);
380 check_bufio("file shown");
384 printf ("\n **** Total IO: read %llu write %llu\n", total_reads, total_writes);