From c4a635322a44f2faebe79bd93f3ec95cf8eebf1d Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Mon, 21 Oct 2019 05:51:56 +0300 Subject: [PATCH] Extend sector numbers to 64 bit, dump hash and bytes of read data. --- .gitignore | 4 ++ cio.c | 2 +- kofu.c | 178 ++++++++++++++++++++++++++++++++-------------------- kofuse.c | 18 +++--- kolibri.asm | 15 ++++- kolibri.h | 51 +++++++++------ makefile | 4 +- 7 files changed, 169 insertions(+), 103 deletions(-) diff --git a/.gitignore b/.gitignore index d7b4461..ccf0066 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ mkfilepattern *.img.info t_*.out .gdb_history +kolibri.fas +kolibri.sym +kolibri.lst +kolibri.prp diff --git a/cio.c b/cio.c index 6d4de96..bf96a6f 100644 --- a/cio.c +++ b/cio.c @@ -6,7 +6,7 @@ typedef struct { FILE *file; - uint32_t sect_cnt; + uint64_t sect_cnt; uint32_t sect_size; } vdisk_t; diff --git a/kofu.c b/kofu.c index e63bbfe..359647d 100644 --- a/kofu.c +++ b/kofu.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,38 +13,65 @@ #include "kolibri.h" #include "trace.h" -// http://home.thep.lu.se/~bjorn/crc/ -/* Simple public domain implementation of the standard CRC32 checksum. - * Outputs the checksum for each file given as a command line argument. - * Invalid file names and files that cause errors are silently skipped. - * The program reads from stdin if it is called with no arguments. */ - -uint32_t crc32_for_byte(uint32_t r) { - for(int j = 0; j < 8; ++j) - r = (r & 1? 0: (uint32_t)0xEDB88320L) ^ r >> 1; - return r ^ (uint32_t)0xFF000000L; -} - -void crc32(const void *data, size_t n_bytes, uint32_t* crc) { - static uint32_t table[0x100]; - if(!*table) - for(size_t i = 0; i < 0x100; ++i) - table[i] = crc32_for_byte(i); - for(size_t i = 0; i < n_bytes; ++i) - *crc = table[(uint8_t)*crc ^ ((uint8_t*)data)[i]] ^ *crc >> 8; -} - #define FGETS_BUF_LEN 4096 #define MAX_COMMAND_ARGS 42 #define PRINT_BYTES_PER_LINE 32 #define MAX_DIRENTS_TO_READ 100 -#define MAX_BYTES_TO_READ 1024 +#define MAX_BYTES_TO_READ (16*1024) char cmd_buf[FGETS_BUF_LEN]; bool is_tty; int cmd_num = 0; bool trace = false; +bool parse_uintmax(const char *str, uintmax_t *res) { + char *endptr; + *res = strtoumax(str, &endptr, 0); + bool ok = (str != endptr) && (*endptr == '\0'); + return ok; +} + +bool parse_uint32(const char *str, uint32_t *res) { + uintmax_t x; + if (parse_uintmax(str, &x) && x <= UINT32_MAX) { + *res = x; + return true; + } else { + perror("invalid number"); + return false; + } +} + +bool parse_uint64(const char *str, uint64_t *res) { + uintmax_t x; + if (parse_uintmax(str, &x) && x <= UINT64_MAX) { + *res = x; + return true; + } else { + perror("invalid number"); + return false; + } +} + +void print_bytes(uint8_t *x, size_t len) { + for (size_t i = 0; i < len; i++) { + if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) { + printf("\n"); + } + printf("%2.2x", x[i]); + } + putchar('\n'); +} + +void print_hash(uint8_t *x, size_t len) { + hash_context ctx; + hash_oneshot(&ctx, x, len); + for (size_t i = 0; i < HASH_SIZE; i++) { + printf("%2.2x", ctx.hash[i]); + } + putchar('\n'); +} + void prompt() { printf("#%d> ", cmd_num); fflush(stdout); @@ -81,8 +109,8 @@ void kofu_disk_del(int argc, const char **argv) { return; } -void ls_range(struct f70s1arg *f70) { - f70ret r; +void ls_range(f70s1arg_t *f70) { + f70ret_t r; uint32_t requested = f70->size; if (f70->size > MAX_DIRENTS_TO_READ) { f70->size = MAX_DIRENTS_TO_READ; @@ -94,7 +122,7 @@ void ls_range(struct f70s1arg *f70) { kos_fuse_lfn(f70, &r); f70->offset += f70->size; printf("status = %d, count = %d\n", r.status, r.count); - struct f70s1ret *dir = f70->buf; + f70s1info_t *dir = f70->buf; assert((r.status == F70_SUCCESS && r.count == f70->size) || (r.status == F70_END_OF_FILE && r.count < f70->size) ); @@ -114,15 +142,15 @@ void ls_range(struct f70s1arg *f70) { } } -void ls_all(struct f70s1arg *f70) { - f70ret r; +void ls_all(f70s1arg_t *f70) { + f70ret_t r; while (true) { kos_fuse_lfn(f70, &r); printf("status = %d, count = %d\n", r.status, r.count); if (r.status != F70_SUCCESS && r.status != F70_END_OF_FILE) { abort(); } - struct f70s1ret *dir = f70->buf; + f70s1info_t *dir = f70->buf; f70->offset += dir->cnt; assert((r.status == F70_SUCCESS && r.count == f70->size) || (r.status == F70_END_OF_FILE && r.count < f70->size) @@ -139,8 +167,8 @@ void ls_all(struct f70s1arg *f70) { void kofu_ls(int argc, const char **argv) { (void)argc; - struct f70s1ret *dir = (struct f70s1ret*)malloc(sizeof(struct f70s1ret) + sizeof(struct bdfe) * MAX_DIRENTS_TO_READ); - struct f70s1arg f70 = {1, 0, CP866, MAX_DIRENTS_TO_READ, dir, 0, argv[1]}; + f70s1info_t *dir = (f70s1info_t*)malloc(sizeof(f70s1info_t) + sizeof(bdfe_t) * MAX_DIRENTS_TO_READ); + f70s1arg_t f70 = {1, 0, CP866, MAX_DIRENTS_TO_READ, dir, 0, argv[1]}; if (argv[2]) { sscanf(argv[2], "%"SCNu32, &f70.size); if (argv[3]) { @@ -156,17 +184,21 @@ void kofu_ls(int argc, const char **argv) { void kofu_stat(int argc, const char **argv) { (void)argc; - f70ret r; - struct bdfe file; - struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, argv[1]}; + f70s5arg_t f70 = {.sf = 5, .flags = 0, .zero = 0}; + f70ret_t r; + bdfe_t file; + f70.buf = &file; + f70.path = argv[1]; kos_fuse_lfn(&f70, &r); printf("attr: 0x%2.2x\n", file.attr); printf("size: %llu\n", file.size); return; } +/* void read_range(struct f70s0arg *f70) { f70ret r; + hash_context ctx; uint32_t requested = f70->size; if (f70->size > MAX_BYTES_TO_READ) { f70->size = MAX_BYTES_TO_READ; @@ -181,13 +213,9 @@ void read_range(struct f70s0arg *f70) { assert((r.status == F70_SUCCESS && r.count == f70->size) || (r.status == F70_END_OF_FILE && r.count < f70->size) ); - for (size_t i = 0; i < r.count; i++) { - if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) { - printf("\n"); - } - printf("%2.2x", ((uint8_t*)f70->buf)[i]); - } - printf("\n"); + print_bytes(f70->buf, r.count); + hash_oneshot(&ctx, f70->buf, r.count); + print_hash(ctx.hash, HASH_SIZE); if (r.status == F70_END_OF_FILE) { break; } @@ -203,37 +231,58 @@ void read_all(struct f70s0arg *f70) { assert((r.status == F70_SUCCESS && r.count == f70->size) || (r.status == F70_END_OF_FILE && r.count < f70->size) ); - for (size_t i = 0; i < r.count; i++) { - if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) { - printf("\n"); - } - printf("%2.2x", ((uint8_t*)f70->buf)[i]); + if () { + print_bytes(f70->buf, r.count); + } + if () { + hash_context ctx; + hash_oneshot(&ctx, f70->buf, r.count); + print_hash(ctx.hash, HASH_SIZE); } - printf("\n"); if (r.status == F70_END_OF_FILE) { break; } } } +*/ void kofu_read(int argc, const char **argv) { (void)argc; - uint8_t *buf = (uint8_t*)malloc(MAX_BYTES_TO_READ); - struct f70s0arg f70 = {0, 0, 0, MAX_BYTES_TO_READ, buf, 0, argv[1]}; -// optind = 1; -// while ((opt = getopt(argc, argv, "fcshd:")) != -1) { -// switch (opt) { -// case - if (argv[2]) { - sscanf(argv[2], "%"SCNu32, &f70.size); - if (argv[3]) { - sscanf(argv[3], "%"SCNu32, &f70.offset_lo); - } - read_range(&f70); - } else { - read_all(&f70); + f70s0arg_t f70 = {.sf = 0, .zero = 0}; + f70ret_t r; + bool dump_bytes = false, dump_hash = false; + if (argc < 4) { + printf("usage: %s [-b] [-h]\n", argv[0]); + return; } - free(buf); + int opt = 1; + f70.path = argv[opt++]; + if ((opt >= argc) || !parse_uint64(argv[opt++], &f70.offset)) + return; + if ((opt >= argc) || !parse_uint32(argv[opt++], &f70.count)) + return; + for (; opt < argc; opt++) { + if (!strcmp(argv[opt], "-b")) { + dump_bytes = true; + } else if (!strcmp(argv[opt], "-h")) { + dump_hash = true; + } else { + printf("invalid option: '%s'\n", argv[opt]); + return; + } + } + f70.buf = (uint8_t*)malloc(f70.count); + + kos_fuse_lfn(&f70, &r); + assert((r.status == F70_SUCCESS && r.count == f70.count) || + (r.status == F70_END_OF_FILE && r.count < f70.count)); + + if (dump_bytes) + print_bytes(f70.buf, r.count); + if (dump_hash) + print_hash(f70.buf, r.count); + + free(f70.buf); return; } @@ -251,13 +300,6 @@ struct func_table funcs[] = { { NULL, NULL }, }; -void crc() { - uint8_t data[] = {1,2,3,4}; - uint32_t x = 0; - crc32(data, 4, &x); - printf("crc=%"PRIx32"\n", x); -} - int main(int argc, char **argv) { (void)argc; (void)argv; diff --git a/kofuse.c b/kofuse.c index 2f1979f..92f8231 100644 --- a/kofuse.c +++ b/kofuse.c @@ -35,7 +35,7 @@ #define DIRENTS_TO_READ 100 -static void bdfe_to_stat(struct bdfe *kf, struct stat *st) { +static void bdfe_to_stat(bdfe_t *kf, struct stat *st) { if (kf->attr & KF_FOLDER) { st->st_mode = S_IFDIR | 0755; st->st_nlink = 2; @@ -62,9 +62,9 @@ static int kofuse_getattr(const char *path, struct stat *stbuf, int res = 0; - struct bdfe file; - struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, path}; - f70ret r; + bdfe_t file; + f70s5arg_t f70 = {.sf = 5, .flags = 0, .buf = &file, .zero = 0, .path = path}; + f70ret_t r; kos_fuse_lfn(&f70, &r); bdfe_to_stat(&file, stbuf); @@ -79,9 +79,9 @@ static int kofuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, (void) fi; (void) flags; - struct f70s1ret *dir = (struct f70s1ret*)malloc(sizeof(struct f70s1ret) + sizeof(struct bdfe) * DIRENTS_TO_READ); - struct f70s1arg f70 = {1, 0, CP866, DIRENTS_TO_READ, dir, 0, path}; - f70ret r; + f70s1info_t *dir = (f70s1info_t*)malloc(sizeof(f70s1info_t) + sizeof(bdfe_t) * DIRENTS_TO_READ); + f70s1arg_t f70 = {1, 0, CP866, DIRENTS_TO_READ, dir, 0, path}; + f70ret_t r; kos_fuse_lfn(&f70, &r); for (size_t i = 0; i < dir->cnt; i++) { filler(buf, dir->bdfes[i].name, NULL, 0, 0); @@ -105,8 +105,8 @@ static int kofuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { (void) fi; - struct f70s5arg f70 = {0, offset, offset >> 32, size, buf, 0, path}; - f70ret r; + f70s0arg_t f70 = {.sf = 0, .offset = offset, .count = size, .buf = buf, .zero = 0, .path = path}; + f70ret_t r; kos_fuse_lfn(&f70, &r); return size; } diff --git a/kolibri.asm b/kolibri.asm index a06bcfa..978d5f1 100644 --- a/kolibri.asm +++ b/kolibri.asm @@ -30,12 +30,20 @@ include 'blkdev/disk_cache.inc' include 'fs/fs_lfn.inc' include 'crc.inc' +include 'sha3.asm' + struct VDISK File dd ? - SectCnt dd ? ; FIXME: dq + SectCnt DQ ? SectSize dd ? ; sector size ends +public sha3_256_oneshot as 'hash_oneshot' +proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len + stdcall sha3_256.oneshot, [_ctx], [_data], [_len] + ret +endp + ; TODO: move to trace_lbr public set_eflags_tf set_eflags_tf: @@ -206,9 +214,10 @@ proc vdisk_querymedia stdcall uses ebx esi edi ebp, vdisk, mediainfo mov [ecx + DISKMEDIAINFO.Flags], 0 mov eax, [edx + VDISK.SectSize] mov [ecx + DISKMEDIAINFO.SectorSize], eax - mov eax, [edx + VDISK.SectCnt] + mov eax, [edx + VDISK.SectCnt.lo] mov dword [ecx + DISKMEDIAINFO.Capacity + 0], eax - mov dword [ecx + DISKMEDIAINFO.Capacity + 4], 0 + mov eax, [edx + VDISK.SectCnt.hi] + mov dword [ecx + DISKMEDIAINFO.Capacity + 4], eax movi eax, DISK_STATUS_OK ret diff --git a/kolibri.h b/kolibri.h index 8ad6e47..031f19e 100644 --- a/kolibri.h +++ b/kolibri.h @@ -2,8 +2,9 @@ #define KOLIBRI_H_INCLUDED #include +#include -enum encoding { +enum { DEFAULT, CP866, UTF16, @@ -27,11 +28,6 @@ typedef enum { } f70status; typedef struct { - uint32_t status; - uint32_t count; -} f70ret; - -struct bdfe { uint32_t attr; uint32_t enc; uint32_t ctime; @@ -42,19 +38,23 @@ struct bdfe { uint32_t mdate; uint64_t size; char name[264]; -}; +} bdfe_t; -struct f70s0arg { +typedef struct { + uint32_t status; + uint32_t count; +} f70ret_t; + +typedef struct { uint32_t sf; - uint32_t offset_lo; - uint32_t offset_hi; - uint32_t size; + uint64_t offset; + uint32_t count; void *buf; uint8_t zero; const char *path; -} __attribute__((packed)); +} __attribute__((packed)) f70s0arg_t; -struct f70s1arg { +typedef struct { uint32_t sf; uint32_t offset; uint32_t encoding; @@ -62,17 +62,17 @@ struct f70s1arg { void *buf; uint8_t zero; const char *path; -} __attribute__((packed)); +} __attribute__((packed)) f70s1arg_t; -struct f70s1ret { +typedef struct { uint32_t version; uint32_t cnt; uint32_t total_cnt; uint32_t reserved[5]; - struct bdfe bdfes[0]; -}; + bdfe_t bdfes[0]; +} f70s1info_t; -struct f70s5arg { +typedef struct { uint32_t sf; uint32_t reserved1; uint32_t flags; @@ -80,7 +80,7 @@ struct f70s5arg { void *buf; uint8_t zero; const char *path; -} __attribute__((packed)); +} __attribute__((packed)) f70s5arg_t; #define KF_READONLY 0x01 #define KF_HIDDEN 0x02 @@ -88,14 +88,25 @@ struct f70s5arg { #define KF_LABEL 0x08 #define KF_FOLDER 0x10 +#define HASH_SIZE 32 +typedef struct { + uint8_t hash[HASH_SIZE]; + uint8_t opaque[1024-HASH_SIZE]; +} hash_context; + uint32_t kos_time_to_epoch(uint32_t *time); void *kos_fuse_init(int fd, uint32_t sect_cnt, uint32_t sect_sz); -void kos_fuse_lfn(void *f70arg, f70ret *r); +void kos_fuse_lfn(void *f70sXarg, f70ret_t *r); void kos_init(void); void *kos_disk_add(const char *file_name, const char *disk_name); int kos_disk_del(const char *name); +//void hash_init(void *ctx); +//void hash_update(void *ctx, void *data, size_t len); +//void hash_final(void *ctx); +void hash_oneshot(void *ctx, void *data, size_t len); + void set_eflags_tf(int x); void coverage_begin(void); void coverage_end(void); diff --git a/makefile b/makefile index cb0a534..25e38b8 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ FASM=fasm CC=gcc -CFLAGS=-Wall -Wextra -g -O0 -D_FILE_OFFSET_BITS=64 +CFLAGS=-Wall -Wextra -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member CFLAGS_32=-m32 LDFLAGS= LDFLAGS_32=-m32 @@ -14,7 +14,7 @@ kofuse: kofuse.o kolibri.o cio.o $(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs` kolibri.o kolibri.fas: kolibri.asm kolibri.h - INCLUDE="$(KOLIBRI_TRUNK)" $(FASM) $< $@ -s kolibri.fas + INCLUDE="$(KOLIBRI_TRUNK);$(LIBCRASH_X86)" $(FASM) $< $@ -s kolibri.fas kolibri.sym: kolibri.fas symbols kolibri.fas kolibri.sym