diff --git a/kolibri.h b/kolibri.h index 17e6d7c..3dff79f 100644 --- a/kolibri.h +++ b/kolibri.h @@ -51,7 +51,7 @@ typedef enum { F80 = 80, } f70or80_t; -typedef enum { +enum { ERROR_SUCCESS, ERROR_DISK_BASE, ERROR_UNSUPPORTED_FS, @@ -65,7 +65,19 @@ typedef enum { ERROR_ACCESS_DENIED, ERROR_DEVICE, ERROR_OUT_OF_MEMORY, -} f70status_t; +}; + +typedef struct lhead lhead_t; + +struct lhead { + lhead_t *next; + lhead_t *prev; +}; + +typedef struct { + lhead_t wait_list; + uint32_t count; +} mutex_t; typedef struct { uint32_t flags; @@ -73,6 +85,24 @@ typedef struct { uint64_t capacity; // in sectors } diskmediainfo_t; +typedef struct { + uintptr_t pointer; + uint32_t data_size; + uintptr_t data; + uint32_t sad_size; + uint32_t search_start; + uint32_t sector_size_log; +} disk_cache_t; + +typedef struct { + uint64_t first_sector; + uint64_t length; // in sectors + void *disk; + void *fs_user_functions; +} partition_t; + +typedef struct disk_t disk_t; + typedef struct { uint32_t strucsize; void (*close)(void *userdata) __attribute__((__stdcall__)); @@ -84,6 +114,28 @@ typedef struct { unsigned int (*adjust_cache_size)(uint32_t suggested_size) __attribute__((__stdcall__)); } diskfunc_t; +struct disk_t { + disk_t *next; + disk_t *prev; + diskfunc_t *functions; + const char *name; + void *userdata; + uint32_t driver_flags; + uint32_t ref_count; + mutex_t media_lock; + uint8_t media_inserted; + uint8_t media_used; + uint16_t padding; + uint32_t media_ref_count; + diskmediainfo_t media_info; + uint32_t num_partitions; + partition_t **partitions; + uint32_t cache_size; + mutex_t cache_lock; + disk_cache_t sys_cache; + disk_cache_t app_cache; +}; + typedef struct { uint32_t attr; uint32_t enc; @@ -176,19 +228,26 @@ typedef struct { uint8_t opaque[1024-HASH_SIZE]; } hash_context; -uint32_t kos_time_to_epoch(uint32_t *time); void kos_init(void); void i40(void); -void *kos_disk_add(const char *file_name, const char *disk_name); -int kos_disk_del(const char *name); +uint32_t kos_time_to_epoch(uint32_t *time); +void set_eflags_tf(int x); + +void *disk_add(diskfunc_t *disk, const char *name, void *userdata, uint32_t flags) __attribute__((__stdcall__)); +void *disk_media_changed(diskfunc_t *disk, int inserted) __attribute__((__stdcall__)); +void disk_del(disk_t *disk) __attribute__((__stdcall__)); void hash_oneshot(void *ctx, void *data, size_t len); -void set_eflags_tf(int x); +void xfs_user_functions(void); +void ext_user_functions(void); +void fat_user_functions(void); +void ntfs_user_functions(void); void coverage_begin(void); void coverage_end(void); extern uint32_t *kos_lfb_base; extern uint16_t *kos_win_stack; extern uint16_t *kos_win_pos; +extern disk_t disk_list; #endif diff --git a/umka.asm b/umka.asm index 2b7842a..afe883e 100644 --- a/umka.asm +++ b/umka.asm @@ -5,7 +5,30 @@ __DEBUG_LEVEL__ = 1 extrn 'malloc' as libc_malloc extrn 'free' as libc_free -extrn vdisk_functions + +public disk_add +public disk_del +public disk_list +public disk_media_changed + +public xfs._.user_functions as 'xfs_user_functions' +public ext_user_functions +public fat_user_functions +public ntfs_user_functions + +public i40 + +public coverage_begin +public coverage_end + +public sha3_256_oneshot as 'hash_oneshot' +public set_eflags_tf +public kos_time_to_epoch +public kos_init + +public win_stack_addr as 'kos_win_stack' +public win_pos_addr as 'kos_win_pos' +public lfb_base_addr as 'kos_lfb_base' cli equ nop iretd equ retd @@ -30,10 +53,7 @@ purge mov,add,sub purge mov,add,sub section '.text' executable align 32 -public i40 - coverage_begin: -public coverage_begin include 'macros.inc' macro diff16 msg,blah2,blah3 { @@ -123,14 +143,12 @@ struct VDISK 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: pushfd pop eax @@ -143,7 +161,6 @@ set_eflags_tf: popfd ret -public kos_time_to_epoch proc kos_time_to_epoch c uses ebx esi edi ebp, _time mov esi, [_time] call fsCalculateTime @@ -151,7 +168,6 @@ proc kos_time_to_epoch c uses ebx esi edi ebp, _time ret endp -public kos_init proc kos_init c uses ebx esi edi ebp mov edi, endofcode mov ecx, uglobals_size @@ -255,79 +271,6 @@ proc kos_init c uses ebx esi edi ebp ret endp -public kos_disk_add -proc kos_disk_add c uses ebx esi edi ebp, _file_name, _disk_name - extrn vdisk_init - ccall vdisk_init, [_file_name] - stdcall disk_add, vdisk_functions, [_disk_name], eax, DISK_NO_INSERT_NOTIFICATION - push eax - stdcall disk_media_changed, eax, 1 - pop edx - movi ecx, 1 - mov esi, [edx+DISK.Partitions] -.next_part: - cmp ecx, [edx+DISK.NumPartitions] - ja .part_done - DEBUGF 1, "/%s/%d: ", [edx+DISK.Name], ecx - lodsd - inc ecx - cmp [eax+PARTITION.FSUserFunctions], xfs._.user_functions - jnz @f - DEBUGF 1, "xfs\n" - jmp .next_part -@@: - cmp [eax+PARTITION.FSUserFunctions], ext_user_functions - jnz @f - DEBUGF 1, "ext\n" - jmp .next_part -@@: - cmp [eax+PARTITION.FSUserFunctions], fat_user_functions - jnz @f - DEBUGF 1, "fat\n" - jmp .next_part -@@: - cmp [eax+PARTITION.FSUserFunctions], ntfs_user_functions - jnz @f - DEBUGF 1, "ntfs\n" - jmp .next_part -@@: - DEBUGF 1, "???\n" - jmp .next_part -.part_done: - xor eax, eax - ret -.error: - movi eax, 1 - ret -endp - - -public kos_disk_del -proc kos_disk_del c uses ebx esi edi ebp, _name - mov eax, [disk_list+LHEAD.next] -.next_disk: - cmp eax, disk_list - jz .not_found - mov esi, [eax+DISK.Name] - mov edi, [_name] -@@: - movzx ecx, byte[esi] - cmpsb - jnz .skip - jecxz .found - jmp @b -.skip: - mov eax, [eax+LHEAD.next] - jmp .next_disk -.found: - stdcall disk_del, eax - xor eax, eax - ret -.not_found: - movi eax, 1 - ret -endp - proc alloc_page ret push ecx edx @@ -462,7 +405,6 @@ macro pew x, y { end if } -1FFFFFFFh fix 0 include fix pew HEAP_BASE equ macro org x {} @@ -497,7 +439,6 @@ purge HEAP_BASE restore pew coverage_end: -public coverage_end section '.data' writeable align 64 @@ -506,11 +447,8 @@ section '.data' writeable align 64 timer_ticks dd 0 fpu_owner dd ? -public win_stack_addr as 'kos_win_stack' win_stack_addr dd WIN_STACK -public win_pos_addr as 'kos_win_pos' win_pos_addr dd WIN_POS -public lfb_base_addr as 'kos_lfb_base' lfb_base_addr dd lfb_base uglobal @@ -539,7 +477,6 @@ window_data: rb 0x2000 CURRENT_TASK: rb 4 TASK_COUNT: rb 12 rb 0x1000000 -;os_base rb 0x1000000 BOOT_LO boot_data BOOT boot_data lfb_base rd MAX_SCREEN_WIDTH*MAX_SCREEN_HEIGHT diff --git a/umka_fuse.c b/umka_fuse.c index 0879e55..f628da1 100644 --- a/umka_fuse.c +++ b/umka_fuse.c @@ -31,6 +31,7 @@ #include #include #include +#include "vdisk.h" #include "kolibri.h" #include "syscalls.h" @@ -122,12 +123,25 @@ static struct fuse_operations umka_oper = { .read = umka_read, }; +diskfunc_t vdisk_functions = { + .strucsize = sizeof(diskfunc_t), + .close = vdisk_close, + .closemedia = NULL, + .querymedia = vdisk_querymedia, + .read = vdisk_read, + .write = vdisk_write, + .flush = NULL, + .adjust_cache_size = NULL, + }; + int main(int argc, char *argv[]) { if (argc != 3) { printf("usage: umka_fuse dir img\n"); exit(1); } kos_init(); - kos_disk_add(argv[2], "hd0"); + void *userdata = vdisk_init(argv[2]); + void *vdisk = disk_add(&vdisk_functions, "hd0", userdata, 0); + disk_media_changed(vdisk, 1); return fuse_main(argc-1, argv, &umka_oper, NULL); } diff --git a/umka_shell.c b/umka_shell.c index 701d4d8..b279c5b 100644 --- a/umka_shell.c +++ b/umka_shell.c @@ -30,6 +30,7 @@ #include #include #include +#include "vdisk.h" #include "kolibri.h" #include "syscalls.h" #include "trace.h" @@ -53,6 +54,16 @@ } \ } while (0) +diskfunc_t vdisk_functions = { + .strucsize = sizeof(diskfunc_t), + .close = vdisk_close, + .closemedia = NULL, + .querymedia = vdisk_querymedia, + .read = vdisk_read, + .write = vdisk_write, + .flush = NULL, + .adjust_cache_size = NULL, + }; char cur_dir[PATH_MAX] = "/"; const char *last_dir = cur_dir; bool cur_dir_changed = true; @@ -76,7 +87,7 @@ const char *f70_status_name[] = { "out_of_memory" }; -const char *get_f70_status_name(f70status_t s) { +const char *get_f70_status_name(int s) { switch (s) { case ERROR_SUCCESS: // return ""; @@ -195,22 +206,55 @@ int split_args(char *s, char **argv) { return argc; } +void umka_disk_list_partitions(disk_t *d) { + for (size_t i = 0; i < d->num_partitions; i++) { + printf("/%s/%d: ", d->name, i+1); + if (d->partitions[i]->fs_user_functions == xfs_user_functions) { + printf("xfs\n"); + } else if (d->partitions[i]->fs_user_functions == ext_user_functions) { + printf("ext\n"); + } else if (d->partitions[i]->fs_user_functions == fat_user_functions) { + printf("fat\n"); + } else if (d->partitions[i]->fs_user_functions == ntfs_user_functions) { + printf("ntfs\n"); + } else { + printf("???\n"); + } + } +} + void umka_disk_add(int argc, char **argv) { (void)argc; const char *file_name = argv[1]; const char *disk_name = argv[2]; - if (kos_disk_add(file_name, disk_name)) { - printf("[!!] can't add file '%s' as disk '%s'\n", file_name, disk_name); + + void *userdata = vdisk_init(file_name); + if (userdata) { + void *vdisk = disk_add(&vdisk_functions, disk_name, userdata, 0); + if (vdisk) { + disk_media_changed(vdisk, 1); + umka_disk_list_partitions(vdisk); + return; + } } + printf("umka: can't add file '%s' as disk '%s'\n", file_name, disk_name); return; } +void umka_disk_del_by_name(const char *name) { + for(disk_t *d = disk_list.next; d != &disk_list; d = d->next) { + if (!strcmp(d->name, name)) { + disk_del(d); + return; + } + } + printf("umka: can't find disk '%s'\n", name); +} + void umka_disk_del(int argc, char **argv) { (void)argc; const char *name = argv[1]; - if (kos_disk_del(name)) { - printf("[!!] can't find or delete disk '%s'\n", name); - } + umka_disk_del_by_name(name); return; } diff --git a/vdisk.c b/vdisk.c index 5d990a3..7ce0782 100644 --- a/vdisk.c +++ b/vdisk.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "kolibri.h" typedef struct { @@ -12,6 +13,10 @@ typedef struct { void *vdisk_init(const char *fname) { FILE *f = fopen(fname, "r+"); + if (!f) { + printf("vdisk: can't open file '%s': %s\n", fname, strerror(errno)); + return NULL; + } fseeko(f, 0, SEEK_END); off_t fsize = ftello(f); fseeko(f, 0, SEEK_SET); @@ -55,14 +60,3 @@ int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo) { minfo->capacity = vdisk->sect_cnt; return ERROR_SUCCESS; } - -diskfunc_t vdisk_functions = { - .strucsize = sizeof(diskfunc_t), - .close = vdisk_close, - .closemedia = NULL, - .querymedia = vdisk_querymedia, - .read = vdisk_read, - .write = vdisk_write, - .flush = NULL, - .adjust_cache_size = NULL, - }; diff --git a/vdisk.h b/vdisk.h new file mode 100644 index 0000000..54a54fb --- /dev/null +++ b/vdisk.h @@ -0,0 +1,22 @@ +#ifndef VDISK_H_INCLUDED +#define VDISK_H_INCLUDED + +#include +#include +#include "kolibri.h" + +void *vdisk_init(const char *fname); + +__attribute__((__stdcall__)) +void vdisk_close(void *userdata); + +__attribute__((__stdcall__)) +int vdisk_read(void *userdata, void *buffer, off_t startsector, size_t *numsectors); + +__attribute__((__stdcall__)) +int vdisk_write(void *userdata, void *buffer, off_t startsector, size_t *numsectors); + +__attribute__((__stdcall__)) +int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo); + +#endif // VDISK_H_INCLUDED