diff --git a/ce/Makefile b/ce/Makefile index bef00fc..f18e1e3 100644 --- a/ce/Makefile +++ b/ce/Makefile @@ -6,6 +6,7 @@ $(eval $(call add_lib,libaux)) $(eval $(call add_lib,libarena)) $(eval $(call add_lib,libioutil)) $(eval $(call add_lib,libterminal)) +$(eval $(call add_lib,libfat)) $(eval $(call add_include,libkb)) cflags += -DPRINTF_INCLUDE_CONFIG_H=1 diff --git a/ce/interp.c b/ce/interp.c index 44490c6..27121e8 100644 --- a/ce/interp.c +++ b/ce/interp.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -296,6 +297,30 @@ static void mkvol (struct context* context, const char* volume, const char* str_ cprintf (context, "ERROR Could not create volume: %s\n", str_status[-ret]); } +static void format (struct context* context, const char* device, const char* str_fs_type) { + int fs_type; + + if (strcmp (str_fs_type, "tar") == 0) { + fs_type = FS_TARFS; + } else if (strcmp (str_fs_type, "fat16") == 0) { + fs_type = FS_FAT16; + } else if (strcmp (str_fs_type, "fat32") == 0) { + fs_type = FS_FAT32; + } else { + cprintf (context, "ERROR Unknown filesystem '%s'\n", str_fs_type); + return; + } + + struct fatfs_ctx ctx; + + int ret = fat_format_drive (&ctx, device, fs_type); + + if (ret < 0) + cprintf (context, "ERROR Could not format drive: %s\n", str_status[-ret]); + else + cprintf (context, "OK\n"); +} + static void help (struct context* context) { cprintf (context, "Available commands:\n"); cprintf (context, "help\n"); @@ -337,7 +362,7 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) { if (cmd->args[0] != NULL) ls (context, cmd->args[0]); else - cprintf (context, "No directory path provided\n"); + cprintf (context, "ERROR No directory path provided\n"); } else if (strcmp (cmd->name, "quit") == 0) { quit1 (context); } else if (strcmp (cmd->name, "mkfile") == 0) { @@ -350,7 +375,7 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) { if (cmd->args[0] != NULL) edit (context, cmd->args[0]); else - cprintf (context, "No file path provided\n"); + cprintf (context, "ERROR No file path provided\n"); } else if (strcmp (cmd->name, "terminfo") == 0) { terminfo (context); } else if (strcmp (cmd->name, "cls") == 0) { @@ -359,7 +384,12 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) { if ((cmd->args[0] != NULL) && (cmd->args[1] != NULL) && (cmd->args[2] != NULL)) mkvol (context, cmd->args[0], cmd->args[1], cmd->args[2]); else - cprintf (context, "No volume key, filesystem type or device key provided\n"); + cprintf (context, "ERROR No volume key, filesystem type or device key provided\n"); + } else if (strcmp (cmd->name, "format") == 0) { + if ((cmd->args[0] != NULL) && (cmd->args[1] != NULL)) + format (context, cmd->args[0], cmd->args[1]); + else + cprintf (context, "ERROR No device key or filesystem type provided\n"); } else { char volume[VOLUME_MAX]; const char* path; diff --git a/libfat/Makefile b/libfat/Makefile index 27f7797..00ce6c8 100644 --- a/libfat/Makefile +++ b/libfat/Makefile @@ -1,7 +1,7 @@ include ../make/ufuncs.mk $(eval $(call add_include,libsystem)) -$(eval $(call add_lib,libstring)) +$(eval $(call add_include,libstring)) cflags += -D"FAT_PRINTF(a)" diff --git a/libfat/_fatctx.h b/libfat/_fatctx.h index 08cd444..0033340 100644 --- a/libfat/_fatctx.h +++ b/libfat/_fatctx.h @@ -8,6 +8,7 @@ struct fatfs_ctx { struct fatfs _fs; struct fat_list _open_file_list; struct fat_list _free_file_list; + char device_name[0x100]; }; #endif // _KERNEL_FS_FATFS_CTX_H diff --git a/libfat/libfat.c b/libfat/libfat.c index 2ac9f0a..22c73cc 100644 --- a/libfat/libfat.c +++ b/libfat/libfat.c @@ -1,3 +1,103 @@ +#include +#include #include +#include +#include +#include +#include +#include -int a; +static void translate (size_t fs_block, size_t fs_block_count, size_t fs_block_size, + size_t device_sector_size, size_t* out_phys_sector, + size_t* out_sector_count) { + size_t ratio = fs_block_size / device_sector_size; + + if (out_phys_sector != NULL) + *out_phys_sector = fs_block * ratio; + + if (out_sector_count != NULL) + *out_sector_count = fs_block_count * ratio; +} + +static int fat_diskio_read (struct fatfs_ctx* ctx, uint32_t sector, uint8_t* buffer, + uint32_t sector_count) { + (void)ctx; + + int ret; + size_t sector_size; + size_t phys_sector, phys_sector_count; + + if (sector_count == 0) + return 0; + + if ((ret = device_do (ctx->device_name, XDRV_GET_SECTOR_SIZE, §or_size, NULL, NULL, NULL)) < + 0) + return 0; + + translate (sector, sector_count, FAT_SECTOR_SIZE, sector_size, &phys_sector, &phys_sector_count); + + if ((ret = device_do (ctx->device_name, XDRV_READ, &phys_sector, &phys_sector_count, buffer, + NULL)) < 0) + return 0; + + return 1; +} + +static int fat_diskio_write (struct fatfs_ctx* ctx, uint32_t sector, uint8_t* buffer, + uint32_t sector_count) { + (void)ctx; + + int ret; + size_t sector_size; + size_t phys_sector, phys_sector_count; + + if (sector_count == 0) + return 0; + + if ((ret = device_do (ctx->device_name, XDRV_GET_SECTOR_SIZE, §or_size, NULL, NULL, NULL)) < + 0) + return 0; + + translate (sector, sector_count, FAT_SECTOR_SIZE, sector_size, &phys_sector, &phys_sector_count); + + if ((ret = device_do (ctx->device_name, XDRV_WRITE, &phys_sector, &phys_sector_count, buffer, + NULL)) < 0) + return 0; + + return 1; +} + +int fat_format_drive (struct fatfs_ctx* ctx, const char* device_key, int fs_type) { + memset (ctx, 0, sizeof (*ctx)); + memcpy (ctx->device_name, device_key, sizeof (ctx->device_name) - 1); + + size_t total_size = 0; + device_do (device_key, XDRV_GET_SIZE, &total_size, NULL, NULL, NULL); + + if (total_size == 0) + return -ST_NOT_FOUND; + + size_t sectors = ((total_size + FAT_SECTOR_SIZE) / FAT_SECTOR_SIZE); + + fl_init (ctx); + ctx->_fs.disk_io.read_media = &fat_diskio_read; + ctx->_fs.disk_io.write_media = &fat_diskio_write; + + int r = -1; + + switch (fs_type) { + case FS_FAT16: + r = fatfs_format_fat16 (ctx, &ctx->_fs, sectors, "mop3 fat16"); + break; + case FS_FAT32: + r = fatfs_format_fat32 (ctx, &ctx->_fs, sectors, "mop3 fat32"); + break; + default: + break; + } + + if (r < 0) + return -ST_FORMAT_ERROR; + + return ST_OK; +} diff --git a/libfat/libfat.h b/libfat/libfat.h index 27e085b..6413f0c 100644 --- a/libfat/libfat.h +++ b/libfat/libfat.h @@ -1,4 +1,9 @@ #ifndef _LIBFAT_LIBFAT_H #define _LIBFAT_LIBFAT_H +#include <_fat.h> +#include <_fatctx.h> + +int fat_format_drive (struct fatfs_ctx* ctx, const char* device_key, int fs_type); + #endif // _LIBFAT_LIBFAT_H