diff --git a/include/m/fs_desc_buffer.h b/include/m/fs_desc_buffer.h index ac67406..67a8983 100644 --- a/include/m/fs_desc_buffer.h +++ b/include/m/fs_desc_buffer.h @@ -1,6 +1,8 @@ #ifndef _M_FS_DESC_BUFFER_H #define _M_FS_DESC_BUFFER_H +#include + #define FS_FILE 0 #define FS_DIR 1 diff --git a/include/m/ramdisk_device.h b/include/m/ramdisk_device.h new file mode 100644 index 0000000..8c29667 --- /dev/null +++ b/include/m/ramdisk_device.h @@ -0,0 +1,6 @@ +#ifndef _M_RAMDISK_DEVICE_H +#define _M_RAMDISK_DEVICE_H + +#define RAMDISK_DEVICE 100 + +#endif // _M_RAMDISK_DEVICE_H diff --git a/include/m/status.h b/include/m/status.h index f31d84b..b03b997 100644 --- a/include/m/status.h +++ b/include/m/status.h @@ -14,5 +14,6 @@ #define ST_OOB_ERROR 10 #define ST_BAD_PATH 11 #define ST_EXEC_ERROR 12 +#define ST_MOUNT_ERROR 13 #endif // _M_STATUS_H diff --git a/include/m/xdrv_device.h b/include/m/xdrv_device.h new file mode 100644 index 0000000..a5ad967 --- /dev/null +++ b/include/m/xdrv_device.h @@ -0,0 +1,11 @@ +#ifndef _M_XDRV_DEVICE_H +#define _M_XDRV_DEVICE_H + +#define XDRV_TYPE_RAMDRV 0 + +#define XDRV_GET_SIZE 0 +#define XDRV_GET_SECTOR_SIZE 1 +#define XDRV_GET_DEVICE_TYPE 2 +#define XDRV_READ 3 + +#endif // _M_XDRV_DEVICE_H diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index a78bdbd..e4fbe64 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -12,12 +12,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -49,7 +51,19 @@ void bootmain (void) { devices_init (); vfs_init (); - vfs_create_mountpoint ("ramdisk", VFS_RAMDISKFS); + bool reschedule = false; + struct device* ramdisk_device = device_find (RAMDISK_DEVICE); + struct device_op_ctx op_ctx = { + .proc = NULL, + .reschedule_cpu = NULL, + .reschedule = &reschedule, + }; + int ret = vfs_create_mountpoint ("ramdisk", VFS_TARFS, ramdisk_device, &op_ctx); + + if (ret < 0) { + DEBUG ("could not mount ramdisk! (%d)\n", ret); + spin (); + } smp_init (); diff --git a/kernel/device/device.c b/kernel/device/device.c index 5336b24..7fefbbf 100644 --- a/kernel/device/device.c +++ b/kernel/device/device.c @@ -1,11 +1,15 @@ #include +#include #include #include #include #include #include +#include #include +#include #include +#include #include #include #include @@ -18,7 +22,7 @@ static struct rb_node_link* device_tree = NULL; static spin_lock_t device_tree_lock; struct device* device_create (int id, device_op_func_t* ops, size_t ops_len, - bool (*init) (void* arg), void (*fini) (void), void* arg) { + device_init_func_t init, device_fini_func_t fini, void* arg) { if (ops_len >= fieldlengthof (struct device, ops)) return NULL; @@ -36,7 +40,7 @@ struct device* device_create (int id, device_op_func_t* ops, size_t ops_len, if (ops != NULL) memcpy (device->ops, ops, ops_len * sizeof (device_op_func_t)); - if (!device->init (arg)) { + if (!device->init (device, arg)) { free (device); return NULL; } @@ -57,7 +61,8 @@ void device_delete (struct device* device) { spin_unlock (&device->lock); spin_unlock (&device_tree_lock); - device->fini (); + device->fini (device); + free (device); } struct device* device_find (int id) { @@ -70,19 +75,55 @@ struct device* device_find (int id) { return device; } -void devices_init (void) { - { - device_op_func_t ops[] = { - [TERMINAL_PUTSTR] = &terminal_putstr, - }; - device_create (TERMINAL_DEVICE, ops, lengthof (ops), &terminal_init, &terminal_fini, NULL); +void terminal_device_init (void) { + device_op_func_t ops[] = { + [TERMINAL_PUTSTR] = &terminal_putstr, + }; + device_create (TERMINAL_DEVICE, ops, lengthof (ops), &terminal_init, &terminal_fini, NULL); +} + +void ramdisk_device_init (void) { + device_op_func_t ops[] = { + [XDRV_GET_SIZE] = &ramdrv_get_size, + [XDRV_GET_SECTOR_SIZE] = &ramdrv_get_sector_size, + [XDRV_GET_DEVICE_TYPE] = &ramdrv_get_device_type, + [XDRV_READ] = &ramdrv_read, + }; + + struct limine_module_response* module = limine_module_request.response; + + const char* ramdisk_path = "/boot/mop3dist.tar"; + struct limine_file* file = NULL; + + for (size_t i = 0; i < module->module_count; i++) { + file = module->modules[i]; + + if (strncmp (file->path, ramdisk_path, strlen (ramdisk_path)) == 0) + break; } + + struct ramdrv_init init = { + .total_size = file->size, + .sector_size = 1024, + .buffer = file->address, + }; + device_create (RAMDISK_DEVICE, ops, lengthof (ops), &ramdrv_init, &ramdrv_fini, &init); +} + #if defined(__x86_64__) - { - device_op_func_t ops[] = { - [KB_READ_KEY] = &ps2kb_read_key, - }; - device_create (KB_DEVICE, ops, lengthof (ops), &ps2kb_init, &ps2kb_fini, NULL); - } +void ps2kb_device_init (void) { + device_op_func_t ops[] = { + [KB_READ_KEY] = &ps2kb_read_key, + }; + device_create (KB_DEVICE, ops, lengthof (ops), &ps2kb_init, &ps2kb_fini, NULL); +} +#endif + +void devices_init (void) { + terminal_device_init (); + ramdisk_device_init (); + +#if defined(__x86_64__) + ps2kb_device_init (); #endif } diff --git a/kernel/device/device.h b/kernel/device/device.h index 307662f..a4ab2dc 100644 --- a/kernel/device/device.h +++ b/kernel/device/device.h @@ -7,20 +7,32 @@ #include #include -typedef bool (*device_op_func_t) (struct proc* proc, struct cpu** reschedule_cpu, int* ret, - void* a1, void* a2, void* a3, void* a4); +struct device; + +struct device_op_ctx { + struct proc* proc; + struct cpu** reschedule_cpu; + bool* reschedule; +}; + +typedef int (*device_op_func_t) (struct device* device, struct device_op_ctx* op_ctx, void* a1, + void* a2, void* a3, void* a4); + +typedef bool (*device_init_func_t) (struct device* device, void* arg); +typedef void (*device_fini_func_t) (struct device* device); struct device { int id; device_op_func_t ops[32]; spin_lock_t lock; struct rb_node_link device_tree_link; - bool (*init) (void* arg); - void (*fini) (void); + device_init_func_t init; + device_fini_func_t fini; + void* udata; }; struct device* device_create (int id, device_op_func_t* ops, size_t ops_len, - bool (*init) (void* arg), void (*fini) (void), void* arg); + device_init_func_t init, device_fini_func_t fini, void* arg); struct device* device_find (int id); void device_delete (struct device* device); void devices_init (void); diff --git a/kernel/device/ps2_kb.c b/kernel/device/ps2_kb.c index 274cb9f..4d31332 100644 --- a/kernel/device/ps2_kb.c +++ b/kernel/device/ps2_kb.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -126,7 +128,7 @@ static uint8_t ctlmap[256] = { /* clang-format on */ }; -int32_t ps2kb_keycode (void) { +static int32_t ps2kb_keycode (void) { static uint8_t shift; static uint8_t* charcode[4] = {normalmap, shiftmap, ctlmap, ctlmap}; uint32_t st, data, c; @@ -163,7 +165,7 @@ int32_t ps2kb_keycode (void) { return c; } -bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { +static bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { int32_t keycode = ps2kb_keycode (); if (keycode <= 0) @@ -192,12 +194,12 @@ bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { return PROC_NO_RESCHEDULE; } -bool ps2kb_read_key (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, - void* a3, void* a4) { - if (!(proc->procgroup->capabilities & PROC_CAP_KB)) { - *ret = -ST_PERMISSION_ERROR; - return PROC_NO_RESCHEDULE; - } +int ps2kb_read_key (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4) { + (void)device; + + if ((op_ctx->proc != NULL) && !(op_ctx->proc->procgroup->capabilities & PROC_CAP_KB)) + return -ST_PERMISSION_ERROR; uint8_t* chbuf = (uint8_t*)a1; @@ -209,18 +211,21 @@ bool ps2kb_read_key (struct proc* proc, struct cpu** reschedule_cpu, int* ret, v size_t new_count = ps2kb_ringbuffer.count; - *ret = ST_OK; - /* didn't pop anything */ - if (prev_count == new_count) - return proc_sq_suspend (proc, &ps2kb_sq, &ps2kb_ringbuffer_lock, reschedule_cpu); + if (prev_count == new_count) { + *op_ctx->reschedule = + proc_sq_suspend (op_ctx->proc, &ps2kb_sq, &ps2kb_ringbuffer_lock, op_ctx->reschedule_cpu); + return ST_OK; + } spin_unlock (&ps2kb_ringbuffer_lock); - return PROC_NO_RESCHEDULE; + return ST_OK; } -bool ps2kb_init (void* arg) { +bool ps2kb_init (struct device* device, void* arg) { + (void)device; + amd64_ioapic_route_irq (PS2KB, 1, 0, thiscpu->lapic_id); irq_attach (&ps2kb_irq, NULL, PS2KB); @@ -241,7 +246,9 @@ bool ps2kb_init (void* arg) { return true; } -void ps2kb_fini (void) { +void ps2kb_fini (struct device* device) { + (void)device; + irq_detach (PS2KB); ringbuffer_fini (&ps2kb_ringbuffer); } diff --git a/kernel/device/ps2_kb.h b/kernel/device/ps2_kb.h index 402cb12..97397c8 100644 --- a/kernel/device/ps2_kb.h +++ b/kernel/device/ps2_kb.h @@ -2,12 +2,13 @@ #define _KERNEL_DEVICE_PS2_KB_H #include -#include -#include -bool ps2kb_read_key (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, - void* a3, void* a4); -bool ps2kb_init (void* arg); -void ps2kb_fini (void); +struct device; +struct device_op_ctx; + +int ps2kb_read_key (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4); +bool ps2kb_init (struct device* device, void* arg); +void ps2kb_fini (struct device* device); #endif // _KERNEL_DEVICE_PS2_KB_H diff --git a/kernel/device/ramdrv.c b/kernel/device/ramdrv.c new file mode 100644 index 0000000..f30a0e8 --- /dev/null +++ b/kernel/device/ramdrv.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include + +bool ramdrv_init (struct device* device, void* arg) { + struct ramdrv_init* init = arg; + + struct ramdrv* ramdrv = malloc (sizeof (*ramdrv)); + + if (ramdrv == NULL) + return false; + + ramdrv->total_size = init->total_size; + ramdrv->sector_size = init->sector_size; + + if (init->buffer == NULL) { + ramdrv->buffer = malloc (init->total_size); + + if (ramdrv->buffer == NULL) { + free (ramdrv); + return false; + } + + ramdrv->managed = false; + } else { + ramdrv->buffer = init->buffer; + ramdrv->managed = true; + } + + device->udata = ramdrv; + + return true; +} + +void ramdrv_fini (struct device* device) { + struct ramdrv* ramdrv = device->udata; + + if (!ramdrv->managed) + free (ramdrv); +} + +int ramdrv_get_device_type (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4) { + (void)device, (void)a2, (void)a3, (void)a4, (void)op_ctx; + + if (a1 == NULL) + return -ST_BAD_ADDRESS_SPACE; + + int* device_type = (int*)a1; + + *device_type = XDRV_TYPE_RAMDRV; + + return ST_OK; +} + +int ramdrv_get_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4) { + (void)a2, (void)a3, (void)a4, (void)op_ctx; + + if (a1 == NULL) + return -ST_BAD_ADDRESS_SPACE; + + size_t* size = (size_t*)a1; + + struct ramdrv* ramdrv = device->udata; + + *size = ramdrv->total_size; + + return ST_OK; +} + +int ramdrv_get_sector_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4) { + (void)a2, (void)a3, (void)a4, (void)op_ctx; + + if (a1 == NULL) + return -ST_BAD_ADDRESS_SPACE; + + size_t* secsize = (size_t*)a1; + + struct ramdrv* ramdrv = device->udata; + + *secsize = ramdrv->sector_size; + + return ST_OK; +} + +int ramdrv_read (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, void* a3, + void* a4) { + if (a1 == NULL || a2 == NULL || a3 == NULL) + return -ST_BAD_ADDRESS_SPACE; + + size_t pos = *(size_t*)a1; + size_t size = *(size_t*)a2; + uint8_t* buffer = a3; + + struct ramdrv* ramdrv = device->udata; + + if (pos + size > ramdrv->total_size) + return -ST_OOB_ERROR; + + memcpy (buffer, (void*)(((uintptr_t)ramdrv->buffer) + pos), size); + + return ST_OK; +} diff --git a/kernel/device/ramdrv.h b/kernel/device/ramdrv.h new file mode 100644 index 0000000..8bbf692 --- /dev/null +++ b/kernel/device/ramdrv.h @@ -0,0 +1,38 @@ +#ifndef _KERNEL_DEVICE_RAMDRV_H +#define _KERNEL_DEVICE_RAMDRV_H + +#include + +struct device; +struct device_op_ctx; + +struct ramdrv_init { + size_t total_size; + size_t sector_size; + uint8_t* buffer; +}; + +struct ramdrv { + size_t total_size; + size_t sector_size; + uint8_t* buffer; + bool managed; +}; + +bool ramdrv_init (struct device* device, void* arg); + +void ramdrv_fini (struct device* device); + +int ramdrv_read (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, void* a3, + void* a4); + +int ramdrv_get_device_type (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4); + +int ramdrv_get_sector_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4); + +int ramdrv_get_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4); + +#endif // _KERNEL_DEVICE_RAMDRV_H diff --git a/kernel/device/src.mk b/kernel/device/src.mk index 9c61a1d..25143f0 100644 --- a/kernel/device/src.mk +++ b/kernel/device/src.mk @@ -1,8 +1,10 @@ c += device/device.c \ - device/terminal.c + device/terminal.c \ + device/ramdrv.c o += device/device.o \ - device/terminal.o + device/terminal.o \ + device/ramdrv.o ifeq ($(platform),amd64) c += device/ps2_kb.c diff --git a/kernel/device/terminal.c b/kernel/device/terminal.c index 4b1c447..1855b07 100644 --- a/kernel/device/terminal.c +++ b/kernel/device/terminal.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -8,7 +9,6 @@ #include #include #include -#include struct flanterm_context* ft_ctx; @@ -19,8 +19,8 @@ void ft_free (void* ptr, size_t size) { free (ptr); } -bool terminal_init (void* arg) { - (void)arg; +bool terminal_init (struct device* device, void* arg) { + (void)arg, (void)device; struct limine_framebuffer_response* fb_r = limine_framebuffer_request.response; struct limine_framebuffer* fb = fb_r->framebuffers[0]; @@ -33,27 +33,22 @@ bool terminal_init (void* arg) { return true; } -void terminal_fini (void) {} +void terminal_fini (struct device* device) { (void)device; } -bool terminal_putstr (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, - void* a3, void* a4) { - (void)reschedule_cpu, (void)a2, (void)a3, (void)a4; +int terminal_putstr (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4) { + (void)a2, (void)a3, (void)a4, (void)device; - if (!(proc->procgroup->capabilities & PROC_CAP_TERMINAL)) { - *ret = -ST_PERMISSION_ERROR; - return PROC_NO_RESCHEDULE; - } + if ((op_ctx->proc != NULL) && !(op_ctx->proc->procgroup->capabilities & PROC_CAP_TERMINAL)) + return -ST_PERMISSION_ERROR; char* string = (char*)a1; size_t* len = (size_t*)a2; - if (string == NULL || len == NULL) { - *ret = -ST_BAD_ADDRESS_SPACE; - return PROC_NO_RESCHEDULE; - } + if (string == NULL || len == NULL) + return -ST_BAD_ADDRESS_SPACE; flanterm_write (ft_ctx, string, *len); - *ret = ST_OK; - return PROC_NO_RESCHEDULE; + return ST_OK; } diff --git a/kernel/device/terminal.h b/kernel/device/terminal.h index 1042088..b756e00 100644 --- a/kernel/device/terminal.h +++ b/kernel/device/terminal.h @@ -2,12 +2,13 @@ #define _KERNEL_DEVICE_TERMINAL_H #include -#include -#include -bool terminal_init (void* arg); -void terminal_fini (void); -bool terminal_putstr (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, - void* a3, void* a4); +struct device; +struct device_op_ctx; + +bool terminal_init (struct device* device, void* arg); +void terminal_fini (struct device* device); +int terminal_putstr (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, + void* a3, void* a4); #endif // _KERNEL_DEVICE_TERMINAL_H diff --git a/kernel/fs/ramdiskfs.c b/kernel/fs/ramdiskfs.c deleted file mode 100644 index 3ef47b1..0000000 --- a/kernel/fs/ramdiskfs.c +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct ramdisk_tar_header { - char filename[100]; - uint8_t mode[8]; - uint8_t uid[8]; - uint8_t gid[8]; - uint8_t size[12]; - uint8_t mtime[12]; - uint8_t checksum[8]; - uint8_t type_flag; -} PACKED; - -struct ramdisk_tar_file { - struct ramdisk_tar_header* header; - uint8_t* content; - size_t size; -}; - -#define RAMDISK_FILES_MAX 128 -#define RAMDISK_FILENAME_MAX 128 -#define RAMDISK_PATH "/boot/mop3dist.tar" - -static struct ramdisk_tar_file ramdisk_files[RAMDISK_FILES_MAX]; - -static struct ramdisk_tar_file* ramdisk_get_file (const char* filename) { - for (size_t i = 0; i < RAMDISK_FILES_MAX; i++) { - if ((ramdisk_files[i].header != NULL) && - (strncmp (ramdisk_files[i].header->filename, filename, RAMDISK_FILENAME_MAX) == 0)) - return &ramdisk_files[i]; - } - return NULL; -} - -static size_t ramdisk_tar_get_size (uint8_t* in) { - size_t size = 0; - size_t j; - size_t count = 1; - - for (j = 11; j > 0; j--, count *= 8) - size += ((in[j - 1] - '0') * count); - - return size; -} - -static size_t ramdisk_tar_parse (uint8_t* addr) { - size_t i; - - for (i = 0; i < RAMDISK_FILES_MAX; i++) { - struct ramdisk_tar_header* hdr = (struct ramdisk_tar_header*)addr; - - if (hdr->filename[0] == '\0') - break; - - size_t size = ramdisk_tar_get_size (hdr->size); - - ramdisk_files[i].header = hdr; - ramdisk_files[i].content = (uint8_t*)((uintptr_t)hdr + 512); - ramdisk_files[i].size = ramdisk_tar_get_size ((uint8_t*)hdr->size); - - addr += 512 + ((size + 511) & ~511); - } - - return i; -} - -bool ramdiskfs_mount (struct vfs_mountpoint* mountpoint) { - (void)mountpoint; - - struct limine_module_response* module = limine_module_request.response; - - uint8_t* rd_addr = NULL; - - for (size_t i = 0; i < module->module_count; i++) { - struct limine_file* file = module->modules[i]; - - if (strncmp (file->path, RAMDISK_PATH, strlen (RAMDISK_PATH)) == 0) { - rd_addr = file->address; - } - } - - if (rd_addr == NULL) - return false; - - ramdisk_tar_parse (rd_addr); - - return true; -} - -int ramdiskfs_describe (struct vfs_mountpoint* mountpoint, const char* path, - struct fs_desc_buffer* desc) { - (void)mountpoint; - - const char* filename = path_basename (path); - - if (filename == NULL) - return -ST_BAD_PATH; - - struct ramdisk_tar_file* file = ramdisk_get_file (filename); - - if (file == NULL) - return -ST_NOT_FOUND; - - desc->size = file->size; - desc->type = FS_FILE; - - return ST_OK; -} - -int ramdiskfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, - size_t off, size_t size) { - (void)mountpoint; - - const char* filename = path_basename (path); - - if (filename == NULL) - return -ST_BAD_PATH; - - struct ramdisk_tar_file* file = ramdisk_get_file (filename); - - if (file == NULL) - return -ST_NOT_FOUND; - - memcpy (buffer, (void*)((uintptr_t)file->content + off), min (size, file->size)); - - return ST_OK; -} diff --git a/kernel/fs/ramdiskfs.h b/kernel/fs/ramdiskfs.h deleted file mode 100644 index cfeeccb..0000000 --- a/kernel/fs/ramdiskfs.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _KERNEL_FS_RAMDISKFS_H -#define _KERNEL_FS_RAMDISKFS_H - -#include -#include - -struct vfs_mountpoint; - -bool ramdiskfs_mount (struct vfs_mountpoint* mountpoint); -int ramdiskfs_describe (struct vfs_mountpoint* mountpoint, const char* path, - struct fs_desc_buffer* desc); -int ramdiskfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, - size_t off, size_t size); - -#endif // _KERNEL_FS_RAMDISKFS_H diff --git a/kernel/fs/src.mk b/kernel/fs/src.mk index 8a9933a..42b386c 100644 --- a/kernel/fs/src.mk +++ b/kernel/fs/src.mk @@ -1,7 +1,7 @@ c += fs/vfs.c \ - fs/ramdiskfs.c \ + fs/tarfs.c \ fs/path.c o += fs/vfs.o \ - fs/ramdiskfs.o \ + fs/tarfs.o \ fs/path.o diff --git a/kernel/fs/tarfs.c b/kernel/fs/tarfs.c new file mode 100644 index 0000000..6a52ec8 --- /dev/null +++ b/kernel/fs/tarfs.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct tar_file* tar_get_file (struct tarfs* tarfs, const char* filename) { + for (size_t i = 0; i < TARFS_FILES_MAX; i++) { + if ((tarfs->tarfs_files[i].header != NULL) && + (strncmp (tarfs->tarfs_files[i].header->filename, filename, MAX_PATH) == 0)) + return &tarfs->tarfs_files[i]; + } + return NULL; +} + +static size_t tar_get_size (uint8_t* in) { + size_t size = 0; + size_t j; + size_t count = 1; + + for (j = 11; j > 0; j--, count *= 8) + size += ((in[j - 1] - '0') * count); + + return size; +} + +static size_t tar_parse (struct tarfs* tarfs, uint8_t* addr) { + size_t i; + + for (i = 0; i < TARFS_FILES_MAX; i++) { + struct tar_header* hdr = (struct tar_header*)addr; + + if (hdr->filename[0] == '\0') + break; + + size_t size = tar_get_size (hdr->size); + + tarfs->tarfs_files[i].header = hdr; + tarfs->tarfs_files[i].content = (uint8_t*)((uintptr_t)hdr + 512); + tarfs->tarfs_files[i].size = tar_get_size ((uint8_t*)hdr->size); + + addr += 512 + ((size + 511) & ~511); + } + + return i; +} + +int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx) { + struct tarfs* tarfs = malloc (sizeof (*tarfs)); + + if (tarfs == NULL) + return -ST_OOM_ERROR; + + memset (tarfs, 0, sizeof (*tarfs)); + + mountpoint->udata = tarfs; + + struct device* back_device = mountpoint->back_device; + size_t total_size; + int ret; + + spin_lock (&back_device->lock); + + ret = back_device->ops[XDRV_GET_SIZE](back_device, op_ctx, &total_size, NULL, NULL, NULL); + if (ret < 0) { + spin_unlock (&back_device->lock); + free (mountpoint->udata); + return ret; + } + + uint8_t* buffer = malloc (total_size); + + if (buffer == NULL) { + spin_unlock (&back_device->lock); + free (mountpoint->udata); + return ret; + } + + size_t pos = 0; + ret = back_device->ops[XDRV_READ](back_device, op_ctx, &pos, &total_size, buffer, NULL); + + spin_unlock (&back_device->lock); + + if (ret < 0) { + free (buffer); + return ret; + } + + tarfs->buffer = buffer; + + tar_parse (tarfs, tarfs->buffer); + + return ret; +} + +int tarfs_describe (struct vfs_mountpoint* mountpoint, const char* path, + struct fs_desc_buffer* desc) { + (void)mountpoint; + + const char* filename = path_basename (path); + + if (filename == NULL) + return -ST_BAD_PATH; + + struct tar_file* file = tar_get_file ((struct tarfs*)mountpoint->udata, filename); + + if (file == NULL) + return -ST_NOT_FOUND; + + desc->size = file->size; + desc->type = FS_FILE; + + return ST_OK; +} + +int tarfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, size_t off, + size_t size) { + (void)mountpoint; + + const char* filename = path_basename (path); + + if (filename == NULL) + return -ST_BAD_PATH; + + struct tar_file* file = tar_get_file ((struct tarfs*)mountpoint->udata, filename); + + if (file == NULL) + return -ST_NOT_FOUND; + + memcpy (buffer, (void*)((uintptr_t)file->content + off), min (size, file->size)); + + return ST_OK; +} diff --git a/kernel/fs/tarfs.h b/kernel/fs/tarfs.h new file mode 100644 index 0000000..bf66e86 --- /dev/null +++ b/kernel/fs/tarfs.h @@ -0,0 +1,42 @@ +#ifndef _KERNEL_FS_TARFS_H +#define _KERNEL_FS_TARFS_H + +#include +#include +#include + +struct tar_header { + char filename[100]; + uint8_t mode[8]; + uint8_t uid[8]; + uint8_t gid[8]; + uint8_t size[12]; + uint8_t mtime[12]; + uint8_t checksum[8]; + uint8_t type_flag; +} PACKED; + +struct tar_file { + struct tar_header* header; + uint8_t* content; + size_t size; +}; + +#define TARFS_FILES_MAX 128 + +struct tarfs { + struct tar_file tarfs_files[TARFS_FILES_MAX]; + uint8_t* buffer; +}; + +struct vfs_mountpoint; + +int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx); + +int tarfs_describe (struct vfs_mountpoint* mountpoint, const char* path, + struct fs_desc_buffer* desc); + +int tarfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, size_t off, + size_t size); + +#endif // _KERNEL_FS_TARFS_H diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 426f71a..14d73a1 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -1,4 +1,5 @@ -#include +#include +#include #include #include #include @@ -30,38 +31,40 @@ static struct vfs_mountpoint* vfs_find_mountpoint (const char* mountpoint) { return hash_entry (found_link, struct vfs_mountpoint, mount_table_link); } -struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type) { +int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, + struct device_op_ctx* op_ctx) { if (strlen_null (key) > fieldsizeof (struct vfs_mountpoint, key)) - return NULL; + return -ST_OOB_ERROR; struct vfs_mountpoint* mountpoint = malloc (sizeof (*mountpoint)); if (mountpoint == NULL) - return NULL; + return -ST_OOM_ERROR; memset (mountpoint, 0, sizeof (*mountpoint)); memcpy (mountpoint->key, key, strlen_null (key)); mountpoint->fs_type = fs_type; mountpoint->lock = SPIN_LOCK_INIT; + mountpoint->back_device = back_device; switch (mountpoint->fs_type) { - case VFS_RAMDISKFS: { - mountpoint->driver_ops.mount = &ramdiskfs_mount; - mountpoint->driver_ops.describe = &ramdiskfs_describe; - mountpoint->driver_ops.read = &ramdiskfs_read; + case VFS_TARFS: { + mountpoint->driver_ops.mount = &tarfs_mount; + mountpoint->driver_ops.describe = &tarfs_describe; + mountpoint->driver_ops.read = &tarfs_read; } break; default: { free (mountpoint); - return NULL; + return -ST_MOUNT_ERROR; } break; } - bool ok = mountpoint->driver_ops.mount (mountpoint); + int ret = mountpoint->driver_ops.mount (mountpoint, op_ctx); - if (!ok) { + if (ret < 0) { free (mountpoint); - return NULL; + return ret; } uint32_t mp_hash = hash_fnv32 (mountpoint->key, strlen (mountpoint->key)); @@ -73,7 +76,7 @@ struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type) { spin_unlock (&mount_table.lock); - return mountpoint; + return ST_OK; } int vfs_open (struct procgroup* procgroup, const char* mountpoint, const char* path) { diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index b37aeea..ae49a39 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -1,6 +1,7 @@ #ifndef _KERNEL_FS_VFS_H #define _KERNEL_FS_VFS_H +#include #include #include #include @@ -8,7 +9,7 @@ #include #include -#define VFS_RAMDISKFS 0 +#define VFS_TARFS 0 struct vfs_mountpoint { char key[0x100]; @@ -18,12 +19,14 @@ struct vfs_mountpoint { bool locked; struct procgroup* ownerpg; struct { - bool (*mount) (struct vfs_mountpoint* mountpoint); + int (*mount) (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx); int (*describe) (struct vfs_mountpoint* mountpoint, const char* path, struct fs_desc_buffer* desc); int (*read) (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size); } driver_ops; + struct device* back_device; + void* udata }; struct vfs_mount_table { @@ -31,14 +34,21 @@ struct vfs_mount_table { spin_lock_t lock; }; -struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type); +int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, + struct device_op_ctx* op_ctx); + int vfs_describe (struct procgroup* procgroup, const char* mountpoint, const char* path, struct fs_desc_buffer* desc); + int vfs_read (struct procgroup* procgroup, const char* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size); + int vfs_close (struct procgroup* procgroup, const char* mountpoint, const char* path); + int vfs_open (struct procgroup* procgroup, const char* mountpoint, const char* path); + void vfs_procgroup_cleanup (struct procgroup* procgroup); + void vfs_init (void); #endif // _KERNEL_FS_VFS_H diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index ae901ba..809d774 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -211,14 +211,15 @@ DEFINE_SYSCALL (sys_device_do) { if (device == NULL) return SYSRESULT (-ST_NOT_FOUND); - int ret; + struct device_op_ctx op_ctx = { + .proc = proc, + .reschedule = reschedule, + .reschedule_cpu = reschedule_cpu, + }; spin_lock (&device->lock); - if (device->ops[cmd](proc, reschedule_cpu, &ret, (void*)ka1, (void*)ka2, (void*)ka3, - (void*)ka4) == PROC_NEED_RESCHEDULE) { - *reschedule = true; - } + int ret = device->ops[cmd](device, &op_ctx, (void*)ka1, (void*)ka2, (void*)ka3, (void*)ka4); spin_unlock (&device->lock);