diff --git a/CMakeLists.txt b/CMakeLists.txt index 5996a9d..fab5564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES src/menu/info.c src/menu/fat.c src/menu/list.c + src/menu/test.c #utils src/utils/fs_table.c diff --git a/include/fsctl/fugue/bits/dirent.h b/include/fsctl/fugue/bits/dirent.h index ecaf2ce..8c67406 100644 --- a/include/fsctl/fugue/bits/dirent.h +++ b/include/fsctl/fugue/bits/dirent.h @@ -18,6 +18,7 @@ struct fugue_dirent /* low-level information */ struct { fugue_fs_t fs; + int lfn_prev_idx; } _private; }; diff --git a/include/fsctl/fugue/bits/fat.h b/include/fsctl/fugue/bits/fat.h index 61738a9..38cd6b0 100644 --- a/include/fsctl/fugue/bits/fat.h +++ b/include/fsctl/fugue/bits/fat.h @@ -65,11 +65,11 @@ struct fugue_fat_dir struct fugue_fat_dir_name { struct { - uint8_t :2; + uint8_t _low0 :1; // must be 0 uint8_t last :1; - uint8_t :1; - uint8_t id :4; - } DIR_Secquence; + uint8_t _low1 :1; // must be 0 + uint8_t id :5; + } DIR_Sequence; uint16_t DIR_Char0; uint16_t DIR_Char1; uint16_t DIR_Char2; diff --git a/include/fsctl/fugue/bits/file.h b/include/fsctl/fugue/bits/file.h index 44025dc..baeb586 100644 --- a/include/fsctl/fugue/bits/file.h +++ b/include/fsctl/fugue/bits/file.h @@ -12,6 +12,7 @@ struct fugue_file { char name[210]; + size_t name_len; int type; uint32_t size; }; diff --git a/include/fsctl/menu.h b/include/fsctl/menu.h index bd04faa..c458834 100644 --- a/include/fsctl/menu.h +++ b/include/fsctl/menu.h @@ -2,3 +2,4 @@ #include "fsctl/menu/rom.h" #include "fsctl/menu/info.h" #include "fsctl/menu/list.h" +#include "fsctl/menu/test.h" diff --git a/include/fsctl/menu/test.h b/include/fsctl/menu/test.h new file mode 100644 index 0000000..854a747 --- /dev/null +++ b/include/fsctl/menu/test.h @@ -0,0 +1,13 @@ +#ifndef FSCTL_MENU_TEST_H +#define FSCTL_MENU_TEST_H 1 + +/* test_menu_init() : init menu */ +extern void test_menu_init(void); + +/* test_menu_display() : display menu */ +extern void test_menu_display(void); + +/* test_menu_keyboard() : handle keyboard */ +extern void test_menu_keyboard(int key); + +#endif /* FSCTL_MENU_TEST_H */ diff --git a/src/fugue/core/dirent.c b/src/fugue/core/dirent.c index 125bd0f..6a8098d 100644 --- a/src/fugue/core/dirent.c +++ b/src/fugue/core/dirent.c @@ -29,6 +29,23 @@ static uint8_t _fugue_dirent_checksum(uintptr_t directory) return checksum; } +/* _fugue_dirent_frag_dump() : decode name fragment */ +static int _fugue_dirent_frag_dump(fugue_file_t *file, uint8_t *frag, int n) +{ + while (--n >= 0) + { + file->name[file->name_len] = frag[0]; + if ((frag[0] & 0x80) != 0) { + file->name[file->name_len] = frag[1]; + file->name_len += 1; + } + file->name_len += 1; + frag = &frag[2]; + } + file->name[file->name_len] = '\0'; + return 0; +} + //--- // Public //--- @@ -39,7 +56,7 @@ int fugue_dirent_init(fugue_dirent_t *dirent, fugue_fs_t *fs) if (fs == NULL || dirent == NULL) return -1; memset(dirent, 0x00, sizeof(fugue_dirent_t)); - memcpy(&dirent->_private.fs, &fs, sizeof(fugue_fs_t)); + memcpy(&dirent->_private.fs, fs, sizeof(fugue_fs_t)); dirent->current_dir_addr = (uintptr_t)fs->_private.root; dirent->cluster_addr_start = (uintptr_t)fs->_private.root; dirent->cluster_addr_end = (uintptr_t)fs->_private.root; @@ -86,24 +103,49 @@ int fugue_dirent_name_fetch( // check directory block validity //--- - if (lfn->DIR_Attr != FUGUE_DIR_ATTR_LFN) + if (lfn->DIR_Attr != FUGUE_DIR_ATTR_LFN) { + fugue_logger_write(log, "[WARN] %p: LFN type error\n", lfn); return -1; - if (lfn->DIR_Type != 0x00) + } + if (lfn->DIR_Type != 0x00) { + fugue_logger_write(log, "[WARN] %p: LFN attribute error\n", lfn); return -2; - if (lfn->DIR_FstClus != 0x0000) + } + if (lfn->DIR_FstClus != 0x0000) { + fugue_logger_write(log, "[WARN] %p: cluster info error\n", lfn); return -3; - //TODO : check Secquence validity + } + if (lfn->DIR_Sequence._low0 != 0 || lfn->DIR_Sequence._low1 != 0) { + fugue_logger_write(log, "[WARN] %p: dirty sequence\n", lfn); + return -4; + } if (lfn->checksum != _fugue_dirent_checksum(dirent->current_dir_addr)) { - fugue_logger_write(log, "[WARN] checksum error at %p", lfn); + fugue_logger_write(log, "[WARN] %p: checksum error\n", lfn); return -5; } + //--- + // check sequence validity + //--- + + if (lfn->DIR_Sequence.last != 0) + { + if (dirent->_private.lfn_prev_idx != 0) + fugue_logger_write(log, "[WARN] %p: multiple LFN entry\n", lfn); + dirent->_private.lfn_prev_idx = lfn->DIR_Sequence.id + 1; + } + if (dirent->_private.lfn_prev_idx != lfn->DIR_Sequence.id + 1) { + fugue_logger_write(log, "[WARN] %p: LFN sequence error\n", lfn); + return -6; + } + dirent->_private.lfn_prev_idx = lfn->DIR_Sequence.id; + //--- // Dump name fragment //--- - //TODO: dump - (void)file; - fugue_logger_write(log, "[ERR] name dump error at %p", lfn); + _fugue_dirent_frag_dump(file, (uint8_t*)&lfn->DIR_Char0, 5); + _fugue_dirent_frag_dump(file, (uint8_t*)&lfn->DIR_Char5, 5); + _fugue_dirent_frag_dump(file, (uint8_t*)&lfn->DIR_Char11,2); return -1; } diff --git a/src/fugue/dir.c b/src/fugue/dir.c index 7a21782..5381c09 100644 --- a/src/fugue/dir.c +++ b/src/fugue/dir.c @@ -3,6 +3,7 @@ #include "fsctl/fugue.h" #include "fsctl/fugue/bits/fat.h" #include "fsctl/fugue/dirent.h" +#include "fsctl/fugue/logger.h" #include "fsctl/fugue/utils.h" #include "fsctl/utils/fs_table.h" @@ -31,6 +32,7 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) { struct fugue_fat_dir *dir; fugue_dirent_t dirent_backup; + fugue_logger_t *log; bool error; bool vfat; @@ -43,6 +45,7 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) memset(file, 0x00, sizeof(fugue_file_t)); memcpy(&dirent_backup, dirent, sizeof(fugue_dirent_t)); + log = dirent->_private.fs._private.logger; vfat = false; error = false; @@ -63,7 +66,7 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) { /* handle free directory */ case 0x00: - //fugue_logger_warn("opendir: wierd empty directory block ") + fugue_logger_write(log, "[WARN] opendir: empty dir block\n"); error = true; continue; @@ -73,8 +76,13 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) memcpy(file->name, ".", 2); if (memcmp(dir->DIR_Name, ".. ", 3) == 0) memcpy(file->name, "..", 3); - if (vfat == true) - //fugue_logger_warn("opendir: wierd directory block ") + if (vfat == true) { + fugue_logger_write( + log, + "[WARN] %p:opendir: wierd dir block layout\n", + dir + ); + } file->type = FUGUE_FILE_TYPE_DIR; file->size = FAT_LONG(dir->DIR_FileSize); return 0; @@ -82,7 +90,11 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) /* removed entry */ case 0x05: case 0xe5: - //fugue_logger_notice("opendir : removed entry"); + fugue_logger_write( + log, + "[NOTICE] %p:opendir : removed entry\n", + dir + ); memset(file, 0x00, sizeof(fugue_file_t)); vfat = false; continue; @@ -114,7 +126,11 @@ int fugue_fs_readdir(fugue_dirent_t *dirent, fugue_file_t *file) /* other attribute not handled */ default: - //fugue_logger_warn("opendir : unsupported attribute ") + fugue_logger_write( + log, + "[WARN] %p:opendir : KO attr %02x\n", + dir, dir->DIR_Attr + ); error = true; break; } diff --git a/src/main.c b/src/main.c index 4a04643..15c582c 100644 --- a/src/main.c +++ b/src/main.c @@ -17,6 +17,7 @@ int main(void) info_menu_init(); fat_menu_init(); list_menu_init(); + test_menu_init(); tab = 0; while (1) @@ -26,6 +27,7 @@ int main(void) if (tab == 1) { info_menu_display(); } if (tab == 2) { fat_menu_display(); } if (tab == 3) { list_menu_display(); } + if (tab == 4) { test_menu_display(); } dupdate(); switch (key = getkey().key) @@ -42,11 +44,15 @@ int main(void) case KEY_F4: tab = 3; break; + case KEY_F5: + tab = 4; + break; default: if (tab == 0) { rom_menu_keyboard(key); } if (tab == 1) { info_menu_keyboard(key); } if (tab == 2) { fat_menu_keyboard(key); } if (tab == 3) { list_menu_keyboard(key); } + if (tab == 4) { test_menu_keyboard(key); } } } diff --git a/src/menu/info.c b/src/menu/info.c index 23c9dc2..38446be 100644 --- a/src/menu/info.c +++ b/src/menu/info.c @@ -90,11 +90,15 @@ void info_menu_display(void) dline(391, 1 + y_start, 391, y_start + y_size, C_BLACK); dline(393, 0, 393, 190, C_BLACK); } + if (line_nb == 0) + { + dtext(1, 15, C_BLACK, "No logs for now..."); + } - dprint(300, 15, C_BLACK, "start=%d", logs_line_start); - dprint(300, 26, C_BLACK, "line_nb=%d", line_nb); #if 0 + dprint(300, 15, C_BLACK, "start=%d", logs_line_start); + dprint(300, 26, C_BLACK, "line_nb=%d", line_nb); int y = 0; _printXY(0, ++y, "FS type = %s", fs.props.type); _printXY(0, ++y, "capacity = %d", fs.props.capacity); diff --git a/src/menu/test.c b/src/menu/test.c new file mode 100644 index 0000000..5c05211 --- /dev/null +++ b/src/menu/test.c @@ -0,0 +1,128 @@ +#include "fsctl/menu.h" +#include "fsctl/fugue.h" +#include "fsctl/utils/fs_table.h" +#include "fsctl/utils/display.h" + +//--- +// Internal +//--- + +/* internal information */ +static int test_selected; +static int __find_ls; +static int __find_lb; +static int __find_fs; +static int __find_fb; + +/* test_search() : search Fugue entry using sector */ +static void __test_search( + int *info, + uintptr_t start, + uintptr_t end, + size_t block +) { + uintptr_t saved_start; + fugue_fs_t fs; + int counter; + + dclear(C_WHITE); + _printXY(0, 0, "search from %p...", start); + dupdate(); + + counter = 0; + saved_start = start; + while (start < end) + { + if (fugue_fs_mount(&fs, (void *)start) == 0) { + dclear(C_WHITE); + _printXY(0, 0, "search from %p...", saved_start); + _printXY(0, 1, "- found = %d", counter); + dupdate(); + *info += 1; + } + start += block; + } + + dclear(C_WHITE); +} + +/* test_search_sector() : search Fugue entry using sector */ +static void test_search_sector(int *info, uintptr_t start, uintptr_t end) +{ + __test_search(info, start, end, 512); +} + +/* test_search_byte() : search Fugue entry using byte */ +static void test_search_byte(int *info, uintptr_t start, uintptr_t end) +{ + __test_search(info, start, end, 1); +} + +//--- +// Public +//--- + +/* test_menu_init() : init menu */ +void test_menu_init(void) +{ + test_selected = -1; + __find_ls = 0; + __find_lb = 0; + __find_fs = 0; + __find_fb = 0; +} + +/* test_menu_display() : display menu */ +void test_menu_display(void) +{ + int y; + + y = 0; + switch(test_selected) + { + case 1: + test_search_sector(&__find_ls, 0xa1000000, 0xa2000000); + break; + case 2: + test_search_byte(&__find_ls, 0xa1000000, 0xa2000000); + break; + case 3: + test_search_sector(&__find_ls, 0xa0000000, 0xa1000000); + break; + case 4: + test_search_byte(&__find_ls, 0xa0000000, 0xa1000000); + break; + } + test_selected = -1; + + _printXY(0, ++y, "[1] last 16Mo entry search (sector)"); + _printXY(0, ++y, "[2] last 16Mo entry search (byte)"); + _printXY(0, ++y, "[3] first 16Mo entry search (sector)"); + _printXY(0, ++y, "[4] first 16Mo entry search (byte)"); + _printXY(0, ++y, ""); + _printXY(0, ++y, ""); + _printXY(0, ++y, "last 16Mo sector found = %d", __find_ls); + _printXY(0, ++y, "last 16Mo byte found = %d", __find_lb); + _printXY(0, ++y, "first 16Mo sector found = %d", __find_fs); + _printXY(0, ++y, "first 16Mo byte found = %d", __find_fb); +} + +/* test_menu_keyboard() : handle keyboard */ +void test_menu_keyboard(int key) +{ + switch (key) + { + case KEY_1: + test_selected = 1; + break; + case KEY_2: + test_selected = 2; + break; + case KEY_3: + test_selected = 3; + break; + case KEY_4: + test_selected = 4; + break; + } +}