diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/drivers/ao_fat.c | 453 | ||||
| -rw-r--r-- | src/drivers/ao_fat.h | 8 | ||||
| -rw-r--r-- | src/drivers/ao_log_fat.c | 24 | 
3 files changed, 329 insertions, 156 deletions
| diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index 3c72c397..87c4158b 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -601,13 +601,94 @@ ao_fat_setup_fs(void)  }  /* - * State for the current opened file + * State for an open file   */ -static struct ao_fat_dirent	ao_file_dirent; -static uint32_t 		ao_file_offset; -static uint32_t			ao_file_cluster_offset; -static cluster_t		ao_file_cluster; -static uint8_t			ao_file_opened; + +struct ao_file { +	struct ao_fat_dirent	*dirent; +	offset_t		offset; +	offset_t		cluster_offset; +	cluster_t		cluster; +	uint8_t			busy; +}; + +#define AO_FAT_NFILE	8 + +static struct ao_fat_dirent	ao_file_dirent[AO_FAT_NFILE]; + +static struct ao_fat_dirent * +ao_fat_file_dirent_alloc(struct ao_fat_dirent *want) +{ +	int8_t	d; +	struct ao_fat_dirent *free = NULL, *dirent; + +	for (d = 0; d < AO_FAT_NFILE; d++) { + +		dirent = &ao_file_dirent[d]; +		/* See if there's another user of this file already */ +		if (want && dirent->name[0] != 0) { +			if (dirent->entry == want->entry) +				return dirent; +		} else { +			if (!free) { +				free = dirent; +				if (!want) +					break; +			} +		} +	} +	if (free && want) +		*free = *want; +	return free; +} + +static struct ao_file 		ao_file_table[AO_FAT_NFILE]; + +static int8_t +ao_fat_fd_alloc(struct ao_fat_dirent *dirent) +{ +	int8_t	fd; + +	for (fd = 0; fd < AO_FAT_NFILE; fd++) +		if (!ao_file_table[fd].busy) { +			ao_file_table[fd].dirent = ao_fat_file_dirent_alloc(dirent); +			ao_file_table[fd].busy = 1; +			ao_file_table[fd].offset = 0; +			ao_file_table[fd].cluster_offset = 0; +			ao_file_table[fd].cluster = ao_file_table[fd].dirent->cluster; +				 +			return fd; +		} +	return -AO_FAT_EMFILE; +} + +static void +ao_fat_fd_free(int8_t fd) +{ +	struct ao_file *file = &ao_file_table[fd]; +	struct ao_fat_dirent *dirent = file->dirent; +	memset(&ao_file_table[fd], '\0', sizeof (struct ao_file)); + +	/* Check and see if another ao_file references the same dirent */ +	for (fd = 0; fd < AO_FAT_NFILE; fd++) +		if (ao_file_table[fd].dirent == dirent) +			return; +	memset(dirent, '\0', sizeof (struct ao_fat_dirent)); +} + +static struct ao_file * +ao_fat_fd_to_file(int8_t fd) +{ +	struct ao_file *file; +	if (fd < 0 || AO_FAT_NFILE <= fd) +		return NULL; + +	file = &ao_file_table[fd]; +	if (!file->busy) +		return NULL; +	return file; +} +  static uint8_t			ao_filesystem_setup;  static uint8_t			ao_filesystem_status; @@ -628,9 +709,10 @@ ao_fat_setup(void)  		number_cluster = fat_start = root_start = data_start = 0;  		next_free = filesystem_full = 0;  		fat32 = fsinfo_dirty = root_cluster = fsinfo_sector = free_count = 0; -		memset(&ao_file_dirent, '\0', sizeof (ao_file_dirent)); -		ao_file_offset = ao_file_cluster_offset = ao_file_cluster = ao_file_opened = 0; +		/* Reset open file table */ +		memset(&ao_file_table, '\0', sizeof (ao_file_table)); +  		ao_filesystem_status = ao_fat_setup_partition();  		if (ao_filesystem_status != AO_FAT_FILESYSTEM_SUCCESS)  			return ao_filesystem_status; @@ -652,7 +734,7 @@ ao_fat_unmount(void)   */  static uint32_t -ao_fat_current_sector(void) +ao_fat_current_sector(struct ao_file *file)  {  	cluster_t	cluster_offset;  	uint32_t	sector_offset; @@ -660,49 +742,74 @@ ao_fat_current_sector(void)  	cluster_t	cluster;  	DBG("current sector offset %d size %d\n", -	    ao_file_offset, ao_file_dirent.size); +	    file->offset, file->dirent->size); -	if (ao_file_offset > ao_file_dirent.size) +	if (file->offset > file->dirent->size) { +		printf ("file offset %d larger than size %d\n", +			file->offset, file->dirent->size);  		return 0xffffffff; +	} -	sector_offset = ao_file_offset >> SECTOR_SHIFT; +	sector_offset = file->offset >> SECTOR_SHIFT; -	if (!ao_file_cluster || ao_file_offset < ao_file_cluster_offset) { -		ao_file_cluster = ao_file_dirent.cluster; -		ao_file_cluster_offset = 0; -		DBG("\treset to start of file %08x\n", ao_file_cluster); +	if (!file->cluster || file->offset < file->cluster_offset) { +		file->cluster = file->dirent->cluster; +		file->cluster_offset = 0; +		DBG("\treset to start of file %08x\n", file->cluster);  	} -	if (ao_file_cluster_offset + bytes_per_cluster <= ao_file_offset) { +	if (file->cluster_offset + bytes_per_cluster <= file->offset) {  		cluster_t	cluster_distance;  		cluster_offset = sector_offset / sectors_per_cluster; -		cluster_distance = cluster_offset - ao_file_cluster_offset / bytes_per_cluster; +		cluster_distance = cluster_offset - file->cluster_offset / bytes_per_cluster;  		DBG("\tseek forward %d clusters\n", cluster_distance); -		cluster = ao_fat_cluster_seek(ao_file_cluster, cluster_distance); +		cluster = ao_fat_cluster_seek(file->cluster, cluster_distance); -		if (!ao_fat_cluster_valid(cluster)) +		if (!ao_fat_cluster_valid(cluster)) { +			printf ("invalid cluster %08x\n", cluster);  			return 0xffffffff; -		ao_file_cluster = cluster; -		ao_file_cluster_offset = cluster_offset * bytes_per_cluster; +		} +		file->cluster = cluster; +		file->cluster_offset = cluster_offset * bytes_per_cluster;  	}  	sector_index = sector_offset % sectors_per_cluster;  	DBG("current cluster %08x sector_index %d sector %d\n", -	    ao_file_cluster, sector_index, -	    data_start + (uint32_t) (ao_file_cluster-2) * sectors_per_cluster + sector_index); -	return data_start + (uint32_t) (ao_file_cluster-2) * sectors_per_cluster + sector_index; +	    file->cluster, sector_index, +	    data_start + (uint32_t) (file->cluster-2) * sectors_per_cluster + sector_index); +	return data_start + (uint32_t) (file->cluster-2) * sectors_per_cluster + sector_index;  } +/* + * ao_fat_invaldate_cluster_offset + * + * When the file size gets shrunk, invalidate + * any file structures referencing clusters beyond that point + */ +  static void -ao_fat_set_offset(uint32_t offset) +ao_fat_invalidate_cluster_offset(struct ao_fat_dirent *dirent)  { -	DBG("Set offset %d\n", offset); -	ao_file_offset = offset; +	int8_t		fd; +	struct ao_file	*file; + +	for (fd = 0; fd < AO_FAT_NFILE; fd++) { +		file = &ao_file_table[fd]; +		if (!file->busy) +			continue; +		if (file->dirent == dirent) { +			if (file->cluster_offset >= dirent->size) { +				file->cluster_offset = 0; +				file->cluster = dirent->cluster; +			} +		} +	}  } +   /*   * ao_fat_set_size   * @@ -710,32 +817,34 @@ ao_fat_set_offset(uint32_t offset)   * the cluster chain as needed   */  static int8_t -ao_fat_set_size(uint32_t size) +ao_fat_set_size(struct ao_file *file, uint32_t size)  {  	uint8_t		*dent;  	cluster_t	first_cluster;  	cluster_t	have_clusters, need_clusters;  	DBG ("Set size %d\n", size); -	if (size == ao_file_dirent.size) { +	if (size == file->dirent->size) {  		DBG("\tsize match\n");  		return AO_FAT_SUCCESS;  	} -	first_cluster = ao_file_dirent.cluster; -	have_clusters = (ao_file_dirent.size + bytes_per_cluster - 1) / bytes_per_cluster; +	first_cluster = file->dirent->cluster; +	have_clusters = (file->dirent->size + bytes_per_cluster - 1) / bytes_per_cluster;  	need_clusters = (size + bytes_per_cluster - 1) / bytes_per_cluster;  	DBG ("\tfirst cluster %08x have %d need %d\n", first_cluster, have_clusters, need_clusters);  	if (have_clusters != need_clusters) { -		if (ao_file_cluster && size >= ao_file_cluster_offset) { -			cluster_t	offset_clusters = (ao_file_cluster_offset + bytes_per_cluster) / bytes_per_cluster; +		if (file->cluster && size > file->cluster_offset) { +			cluster_t	offset_clusters = (file->cluster_offset + bytes_per_cluster) / bytes_per_cluster;  			cluster_t	extra_clusters = need_clusters - offset_clusters;  			cluster_t	next_cluster;  			DBG ("\tset size relative offset_clusters %d extra_clusters %d\n",  			     offset_clusters, extra_clusters); -			next_cluster = ao_fat_cluster_set_size(ao_file_cluster, extra_clusters); + +			/* Need one more to account for file->cluster, which we already have */ +			next_cluster = ao_fat_cluster_set_size(file->cluster, extra_clusters + 1);  			if (next_cluster == AO_FAT_BAD_CLUSTER)  				return -AO_FAT_ENOSPC;  		} else { @@ -749,17 +858,21 @@ ao_fat_set_size(uint32_t size)  	DBG ("\tupdate directory size\n");  	/* Update the directory entry */ -	dent = ao_fat_root_get(ao_file_dirent.entry); -	if (!dent) +	dent = ao_fat_root_get(file->dirent->entry); +	if (!dent) { +		printf ("dent update failed\n");  		return -AO_FAT_EIO; +	}  	put_u32(dent + 0x1c, size);  	put_u16(dent + 0x1a, first_cluster);  	if (fat32)  		put_u16(dent + 0x14, first_cluster >> 16); -	ao_fat_root_put(dent, ao_file_dirent.entry, 1); +	ao_fat_root_put(dent, file->dirent->entry, 1); -	ao_file_dirent.size = size; -	ao_file_dirent.cluster = first_cluster; +	file->dirent->size = size; +	file->dirent->cluster = first_cluster; +	if (have_clusters > need_clusters) +		ao_fat_invalidate_cluster_offset(file->dirent);  	DBG ("set size done\n");  	return AO_FAT_SUCCESS;  } @@ -803,7 +916,7 @@ ao_fat_root_init(uint8_t *dent, char name[11], uint8_t attr)  static void -ao_fat_dirent_init(uint8_t *dent, uint16_t entry, struct ao_fat_dirent *dirent) +ao_fat_dirent_init(struct ao_fat_dirent *dirent, uint8_t *dent, uint16_t entry)  {  	memcpy(dirent->name, dent + 0x00, 11);  	dirent->attr = dent[0x0b]; @@ -886,14 +999,18 @@ ao_fat_open(char name[11], uint8_t mode)  {  	uint16_t		entry = 0;  	struct ao_fat_dirent	dirent; +	int8_t			status;  	if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS)  		return -AO_FAT_EIO; -	if (ao_file_opened) -		return -AO_FAT_EMFILE; -	 -	while (ao_fat_readdir(&entry, &dirent)) { +	for (;;) { +		status = ao_fat_readdir(&entry, &dirent); +		if (status < 0) { +			if (status == -AO_FAT_EDIREOF) +				return -AO_FAT_ENOENT; +			return status; +		}  		if (!memcmp(name, dirent.name, 11)) {  			if (AO_FAT_IS_DIR(dirent.attr))  				return -AO_FAT_EISDIR; @@ -901,10 +1018,7 @@ ao_fat_open(char name[11], uint8_t mode)  				return -AO_FAT_EPERM;  			if (mode > AO_FAT_OPEN_READ && (dirent.attr & AO_FAT_FILE_READ_ONLY))  				return -AO_FAT_EACCESS; -			ao_file_dirent = dirent; -			ao_fat_set_offset(0); -			ao_file_opened = 1; -			return AO_FAT_SUCCESS; +			return ao_fat_fd_alloc(&dirent);  		}  	}  	return -AO_FAT_ENOENT; @@ -919,49 +1033,62 @@ ao_fat_open(char name[11], uint8_t mode)  int8_t  ao_fat_creat(char name[11])  { -	uint16_t	entry; -	int8_t		status; -	uint8_t		*dent; +	uint16_t		entry; +	int8_t			fd; +	int8_t			status; +	uint8_t			*dent; +	struct ao_file		*file;  	if (ao_fat_setup() != AO_FAT_FILESYSTEM_SUCCESS)  		return -AO_FAT_EIO; -	if (ao_file_opened) -		return -AO_FAT_EMFILE; +	fd = ao_fat_open(name, AO_FAT_OPEN_WRITE); +	if (fd >= 0) { +		file = &ao_file_table[fd]; +		status = ao_fat_set_size(file, 0); +		if (status < 0) { +			ao_fat_close(fd); +			fd = status; +		} +	} else { +		if (fd == -AO_FAT_ENOENT) { +			entry = 0; +			for (;;) { +				dent = ao_fat_root_get(entry); +				if (!dent) { +				 +					if (ao_fat_root_extend(entry)) +						continue; +					fd = -AO_FAT_ENOSPC; +					break; +				} +				if (dent[0] == AO_FAT_DENT_EMPTY || dent[0] == AO_FAT_DENT_END) { +					fd = ao_fat_fd_alloc(NULL); +					if (fd < 0) { +						ao_fat_root_put(dent, entry, 0); +						break; +					} -	status = ao_fat_open(name, AO_FAT_OPEN_WRITE); +					file = &ao_file_table[fd]; +					/* Initialize the dent */ +					ao_fat_root_init(dent, name, AO_FAT_FILE_REGULAR); -	switch (status) { -	case -AO_FAT_SUCCESS: -		status = ao_fat_set_size(0); -		break; -	case -AO_FAT_ENOENT: -		entry = 0; -		for (;;) { -			dent = ao_fat_root_get(entry); -			if (!dent) { -				 -				if (ao_fat_root_extend(entry)) -					continue; -				status = -AO_FAT_ENOSPC; -				break; -			} -				 -			if (dent[0] == AO_FAT_DENT_EMPTY || dent[0] == AO_FAT_DENT_END) { -				ao_fat_root_init(dent, name, AO_FAT_FILE_REGULAR); -				ao_fat_dirent_init(dent, entry,  &ao_file_dirent); -				ao_fat_root_put(dent, entry, 1); -				ao_file_opened = 1; -				ao_fat_set_offset(0); -				status = -AO_FAT_SUCCESS; -				break; -			} else { -				ao_fat_root_put(dent, entry, 0); +					/* Now initialize the dirent from the dent */ +					ao_fat_dirent_init(file->dirent, dent, entry); + +					/* And write the dent to storage */ +					ao_fat_root_put(dent, entry, 1); + +					status = -AO_FAT_SUCCESS; +					break; +				} else { +					ao_fat_root_put(dent, entry, 0); +				} +				entry++;  			} -			entry++;  		}  	} -	return status; +	return fd;  }  /* @@ -970,16 +1097,13 @@ ao_fat_creat(char name[11])   * Close the currently open file   */  int8_t -ao_fat_close(void) +ao_fat_close(int8_t fd)  { -	if (!ao_file_opened) +	struct ao_file *file = ao_fat_fd_to_file(fd); +	if (!file)  		return -AO_FAT_EBADF; -	memset(&ao_file_dirent, '\0', sizeof (struct ao_fat_dirent)); -	ao_file_offset = 0; -	ao_file_cluster = 0; -	ao_file_opened = 0; - +	ao_fat_fd_free(fd);  	ao_fat_sync();  	return AO_FAT_SUCCESS;  } @@ -991,17 +1115,21 @@ ao_fat_close(void)   */  static void * -ao_fat_map_current(int len, cluster_offset_t *offsetp, cluster_offset_t *this_time) +ao_fat_map_current(struct ao_file *file, int len, cluster_offset_t *offsetp, cluster_offset_t *this_time)  {  	cluster_offset_t 	offset;  	sector_t		sector;  	void			*buf; -	offset = ao_file_offset & SECTOR_MASK; -	sector = ao_fat_current_sector(); -	if (sector == 0xffffffff) +	offset = file->offset & SECTOR_MASK; +	sector = ao_fat_current_sector(file); +	if (sector == 0xffffffff) { +		printf ("invalid sector at offset %d\n", file->offset);  		return NULL; +	}  	buf = ao_fat_sector_get(sector); +	if (!buf) +		printf ("sector get failed. Sector %d. Partition end %d\n", sector, partition_end);  	if (offset + len < SECTOR_SIZE)  		*this_time = len;  	else @@ -1016,26 +1144,27 @@ ao_fat_map_current(int len, cluster_offset_t *offsetp, cluster_offset_t *this_ti   * Read from the file   */  int -ao_fat_read(void *dst, int len) +ao_fat_read(int8_t fd, void *dst, int len)  {  	uint8_t			*dst_b = dst;  	cluster_offset_t	this_time;  	cluster_offset_t	offset;  	uint8_t			*buf;  	int			ret = 0; - -	if (!ao_file_opened) +	struct ao_file		*file = ao_fat_fd_to_file(fd); +	if (!file)  		return -AO_FAT_EBADF; -	if (ao_file_offset + len > ao_file_dirent.size) -		len = ao_file_dirent.size - ao_file_offset; +	if (file->offset + len > file->dirent->size) +		len = file->dirent->size - file->offset;  	if (len < 0)  		len = 0;  	while (len) { -		buf = ao_fat_map_current(len, &offset, &this_time); +		buf = ao_fat_map_current(file, len, &offset, &this_time);  		if (!buf) { +			printf ("map_current failed\n");  			ret = -AO_FAT_EIO;  			break;  		} @@ -1045,7 +1174,7 @@ ao_fat_read(void *dst, int len)  		ret += this_time;  		len -= this_time;  		dst_b += this_time; -		ao_fat_set_offset(ao_file_offset + this_time); +		file->offset = file->offset + this_time;  	}  	return ret;  } @@ -1056,26 +1185,27 @@ ao_fat_read(void *dst, int len)   * Write to the file, extended as necessary   */  int -ao_fat_write(void *src, int len) +ao_fat_write(int8_t fd, void *src, int len)  { -	uint8_t		*src_b = src; -	uint16_t	this_time; -	uint16_t	offset; -	uint8_t		*buf; -	int		ret = 0; - -	if (!ao_file_opened) +	uint8_t			*src_b = src; +	cluster_offset_t	this_time; +	cluster_offset_t	offset; +	uint8_t			*buf; +	int			ret = 0; +	struct ao_file		*file = ao_fat_fd_to_file(fd); +	if (!file)  		return -AO_FAT_EBADF; -	if (ao_file_offset + len > ao_file_dirent.size) { -		ret = ao_fat_set_size(ao_file_offset + len); +	if (file->offset + len > file->dirent->size) { +		ret = ao_fat_set_size(file, file->offset + len);  		if (ret < 0)  			return ret;  	}  	while (len) { -		buf = ao_fat_map_current(len, &offset, &this_time); +		buf = ao_fat_map_current(file, len, &offset, &this_time);  		if (!buf) { +			printf ("map_current failed\n");  			ret = -AO_FAT_EIO;  			break;  		} @@ -1085,7 +1215,7 @@ ao_fat_write(void *src, int len)  		ret += this_time;  		len -= this_time;  		src_b += this_time; -		ao_fat_set_offset(ao_file_offset + this_time); +		file->offset = file->offset + this_time;  	}  	return ret;  } @@ -1100,13 +1230,14 @@ ao_fat_write(void *src, int len)   * write   */  int32_t -ao_fat_seek(int32_t pos, uint8_t whence) +ao_fat_seek(int8_t fd, int32_t pos, uint8_t whence)  { -	uint32_t	new_offset = ao_file_offset; - -	if (!ao_file_opened) +	offset_t	new_offset; +	struct ao_file	*file = ao_fat_fd_to_file(fd); +	if (!file)  		return -AO_FAT_EBADF; +	new_offset = file->offset;  	switch (whence) {  	case AO_FAT_SEEK_SET:  		new_offset = pos; @@ -1115,11 +1246,11 @@ ao_fat_seek(int32_t pos, uint8_t whence)  		new_offset += pos;  		break;  	case AO_FAT_SEEK_END: -		new_offset = ao_file_dirent.size + pos; +		new_offset = file->dirent->size + pos;  		break;  	} -	ao_fat_set_offset(new_offset); -	return ao_file_offset; +	file->offset = new_offset; +	return file->offset;  }  /* @@ -1193,7 +1324,7 @@ ao_fat_readdir(uint16_t *entry, struct ao_fat_dirent *dirent)  			return -AO_FAT_EDIREOF;  		}  		if (dent[0] != AO_FAT_DENT_EMPTY && (dent[0xb] & 0xf) != 0xf) { -			ao_fat_dirent_init(dent, *entry, dirent); +			ao_fat_dirent_init(dirent, dent, *entry);  			ao_fat_root_put(dent, *entry, 0);  			(*entry)++;  			return AO_FAT_SUCCESS; @@ -1304,12 +1435,12 @@ ao_fat_parse_name(char name[11])  }  static void -ao_fat_show_cmd(void) +ao_fat_dump_cmd(void)  {  	char		name[11]; -	int8_t		status; +	int8_t		fd;  	int		cnt, i; -	char		buf[64]; +	char		buf[32];  	ao_fat_parse_name(name);  	if (name[0] == '\0') { @@ -1317,31 +1448,27 @@ ao_fat_show_cmd(void)  		return;  	} -	status = ao_fat_open(name, AO_FAT_OPEN_READ); -	if (status) { -		printf ("Open failed: %d\n", status); +	fd = ao_fat_open(name, AO_FAT_OPEN_READ); +	if (fd < 0) { +		printf ("Open failed: %d\n", fd);  		return;  	} -	while ((cnt = ao_fat_read(buf, sizeof(buf))) > 0) { +	while ((cnt = ao_fat_read(fd, buf, sizeof(buf))) > 0) {  		for (i = 0; i < cnt; i++)  			putchar(buf[i]);  	} -	ao_fat_close(); -} - -static void -ao_fat_putchar(char c) -{ +	ao_fat_close(fd);  }  static void  ao_fat_write_cmd(void)  {  	char		name[11]; -	int8_t		status; +	int8_t		fd;  	int		cnt, i;  	char		buf[64];  	char		c; +	int		status;  	ao_fat_parse_name(name);  	if (name[0] == '\0') { @@ -1349,9 +1476,9 @@ ao_fat_write_cmd(void)  		return;  	} -	status = ao_fat_creat(name); -	if (status) { -		printf ("Open failed: %d\n", status); +	fd = ao_fat_creat(name); +	if (fd < 0) { +		printf ("Open failed: %d\n", fd);  		return;  	}  	flush(); @@ -1361,19 +1488,61 @@ ao_fat_write_cmd(void)  			if (c == '\n') putchar ('\r');  			putchar(c); flush();  		} -		if (ao_fat_write(&c, 1) != 1) { -			printf ("Write failure\n"); +		status = ao_fat_write(fd, &c, 1); +		if (status != 1) { +			printf ("Write failure %d\n", status);  			break;  		}  	} -	ao_fat_close(); +	ao_fat_close(fd); +} + +static void +put32(uint32_t a) +{ +	ao_cmd_put16(a >> 16); +	ao_cmd_put16(a); +} + +static void +ao_fat_hexdump_cmd(void) +{ +	char		name[11]; +	int8_t		fd; +	int		cnt, i; +	char		buf[8]; +	uint32_t	addr; + +	ao_fat_parse_name(name); +	if (name[0] == '\0') { +		ao_cmd_status = ao_cmd_syntax_error; +		return; +	} +		 +	fd = ao_fat_open(name, AO_FAT_OPEN_READ); +	if (fd < 0) { +		printf ("Open failed: %d\n", fd); +		return; +	} +	addr = 0; +	while ((cnt = ao_fat_read(fd, buf, sizeof(buf))) > 0) { +		put32(addr); +		for (i = 0; i < cnt; i++) { +			putchar(' '); +			ao_cmd_put8(buf[i]); +		} +		putchar('\n'); +		addr += cnt; +	} +	ao_fat_close(fd);  }  static const struct ao_cmds ao_fat_cmds[] = {  	{ ao_fat_mbr_cmd,	"M\0Show FAT MBR and other info" },  	{ ao_fat_list_cmd,	"F\0List FAT directory" }, -	{ ao_fat_show_cmd,	"S <name>\0Show FAT file" }, +	{ ao_fat_dump_cmd,	"D <name>\0Dump FAT file" },  	{ ao_fat_write_cmd,	"W <name>\0Write FAT file (end with ^D)" }, +	{ ao_fat_hexdump_cmd,	"H <name>\0HEX dump FAT file" },  	{ 0, NULL },  }; diff --git a/src/drivers/ao_fat.h b/src/drivers/ao_fat.h index fe154cdf..01435363 100644 --- a/src/drivers/ao_fat.h +++ b/src/drivers/ao_fat.h @@ -81,20 +81,20 @@ int8_t  ao_fat_creat(char name[11]);  int8_t -ao_fat_close(void); +ao_fat_close(int8_t fd);  int -ao_fat_read(void *dest, int len); +ao_fat_read(int8_t fd, void *dest, int len);  int -ao_fat_write(void *src, int len); +ao_fat_write(int8_t fd, void *src, int len);  #define AO_FAT_SEEK_SET	0  #define AO_FAT_SEEK_CUR	1  #define AO_FAT_SEEK_END	2  int32_t -ao_fat_seek(int32_t pos, uint8_t whence); +ao_fat_seek(int8_t fd, int32_t pos, uint8_t whence);  int8_t  ao_fat_unlink(char name[11]); diff --git a/src/drivers/ao_log_fat.c b/src/drivers/ao_log_fat.c index 6b433b99..af77401c 100644 --- a/src/drivers/ao_log_fat.c +++ b/src/drivers/ao_log_fat.c @@ -21,6 +21,7 @@  static uint8_t	log_year, log_month, log_day;  static uint8_t	log_open; +static int8_t	log_fd;  static uint8_t	log_mutex;  static void @@ -31,24 +32,27 @@ ao_log_open(void)  	sprintf(name,"%04d%02d%02dLOG", 2000 + log_year, log_month, log_day);  	status = ao_fat_open(name, AO_FAT_OPEN_WRITE); -	switch (status) { -	case AO_FAT_SUCCESS: -		ao_fat_seek(0, AO_FAT_SEEK_END); +	if (status >= 0) { +		log_fd = status; +		ao_fat_seek(log_fd, 0, AO_FAT_SEEK_END);  		log_open = 1; -		break; -	case -AO_FAT_ENOENT: +	} else if (status == -AO_FAT_ENOENT) {  		status = ao_fat_creat(name); -		if (status == AO_FAT_SUCCESS) +		if (status == AO_FAT_SUCCESS) { +			log_fd = status;  			log_open = 1; -		break; +		}  	}   }  static void  ao_log_close(void)  { -	log_open = 0; -	ao_fat_close(); +	if (log_open) { +		log_open = 0; +		ao_fat_close(log_fd); +		log_fd = -1; +	}  }  uint8_t @@ -77,7 +81,7 @@ ao_log_mega(struct ao_log_mega *log)  		}  	}  	if (log_open) { -		wrote = ao_fat_write(log, sizeof (*log)) == AO_FAT_SUCCESS; +		wrote = ao_fat_write(log_fd, log, sizeof (*log)) == AO_FAT_SUCCESS;  		ao_fat_sync();  	}  	ao_mutex_put(&log_mutex); | 
