Implement volume unmounting, collecting VFS volume info, usb Add eject command
This commit is contained in:
@@ -39,5 +39,7 @@
|
||||
#define SYS_STREAM_READ 36
|
||||
#define SYS_GET_PROC_INFO 37
|
||||
#define SYS_GET_DEVICE_INFO 38
|
||||
#define SYS_GET_VOLUME_INFO 39
|
||||
#define SYS_VOLUME_DELETE 40
|
||||
|
||||
#endif // _M_SYSCALL_DEFS_H
|
||||
|
||||
11
include/volume_info.h
Normal file
11
include/volume_info.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef _VOLUME_INFO_H
|
||||
#define _VOLUME_INFO_H
|
||||
|
||||
#include <path_defs.h>
|
||||
|
||||
struct volume_info {
|
||||
char volume_name[VOLUME_MAX];
|
||||
char device_key[0x100];
|
||||
};
|
||||
|
||||
#endif // _VOLUME_INFO_H
|
||||
@@ -7,6 +7,8 @@
|
||||
int name (struct vfs_volume* UNUSED volume, struct proc* UNUSED proc, \
|
||||
struct reschedule_ctx* UNUSED rctx, bool UNUSED format)
|
||||
|
||||
#define DEFINE_VFS_UNMOUNT(name) int name (struct vfs_volume* UNUSED volume)
|
||||
|
||||
#define DEFINE_VFS_FORMAT(name) \
|
||||
int name (struct vfs_volume* UNUSED volume, struct proc* UNUSED proc, \
|
||||
struct reschedule_ctx* UNUSED rctx)
|
||||
|
||||
@@ -122,6 +122,14 @@ DEFINE_VFS_MOUNT (fatfs_mount) {
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_VFS_UNMOUNT (fatfs_unmount) {
|
||||
struct fatfs_ctx* fatfs_ctx = volume->udata;
|
||||
|
||||
free (fatfs_ctx);
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_VFS_FORMAT (fatfs16_format) {
|
||||
uint64_t fd;
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ struct vfs_volume;
|
||||
|
||||
DEFINE_VFS_MOUNT (fatfs_mount);
|
||||
|
||||
DEFINE_VFS_UNMOUNT (fatfs_unmount);
|
||||
|
||||
DEFINE_VFS_FORMAT (fatfs16_format);
|
||||
|
||||
DEFINE_VFS_FORMAT (fatfs32_format);
|
||||
|
||||
@@ -145,6 +145,14 @@ DEFINE_VFS_MOUNT (iso9660fs_mount) {
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_VFS_UNMOUNT (iso9660fs_unmount) {
|
||||
l9660_fs* fs_ctx = volume->udata;
|
||||
|
||||
free (fs_ctx);
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_VFS_FORMAT (iso9660fs_format) { return -ST_FORMAT_ERROR; }
|
||||
|
||||
DEFINE_VFS_DESCRIBE (iso9660fs_describe) {
|
||||
|
||||
@@ -13,6 +13,8 @@ struct vfs_volume;
|
||||
|
||||
DEFINE_VFS_MOUNT (iso9660fs_mount);
|
||||
|
||||
DEFINE_VFS_UNMOUNT (iso9660fs_unmount);
|
||||
|
||||
DEFINE_VFS_FORMAT (iso9660fs_format);
|
||||
|
||||
DEFINE_VFS_DESCRIBE (iso9660fs_describe);
|
||||
|
||||
@@ -128,6 +128,14 @@ DEFINE_VFS_MOUNT (tarfs_mount) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_VFS_UNMOUNT (tarfs_unmount) {
|
||||
struct tarfs* tarfs = volume->udata;
|
||||
|
||||
free (tarfs);
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_VFS_FORMAT (tarfs_format) { return ST_OK; }
|
||||
|
||||
DEFINE_VFS_DESCRIBE (tarfs_describe) {
|
||||
|
||||
@@ -37,6 +37,8 @@ struct vfs_volume;
|
||||
|
||||
DEFINE_VFS_MOUNT (tarfs_mount);
|
||||
|
||||
DEFINE_VFS_UNMOUNT (tarfs_unmount);
|
||||
|
||||
DEFINE_VFS_FORMAT (tarfs_format);
|
||||
|
||||
DEFINE_VFS_DESCRIBE (tarfs_describe);
|
||||
|
||||
@@ -19,9 +19,46 @@
|
||||
#include <status.h>
|
||||
#include <sync/spin_lock.h>
|
||||
#include <sys/debug.h>
|
||||
#include <volume_info.h>
|
||||
|
||||
static struct vfs_volume_table volume_table;
|
||||
|
||||
size_t volume_populate_volume_infos (struct volume_info* infos, size_t count) {
|
||||
uint64_t fvt, fv, fd;
|
||||
|
||||
if (count >= lengthof (volume_table.volume_buckets))
|
||||
count = lengthof (volume_table.volume_buckets);
|
||||
|
||||
spin_lock (&volume_table.lock, &fvt);
|
||||
|
||||
size_t j = 0;
|
||||
|
||||
for (size_t i = 0; i < lengthof (volume_table.volume_buckets); i++) {
|
||||
struct hash_node_link* hash_link = volume_table.volume_buckets[i];
|
||||
|
||||
while (hash_link != NULL && j < count) {
|
||||
struct vfs_volume* volume = hash_entry (hash_link, struct vfs_volume, volume_table_link);
|
||||
struct volume_info* info = &infos[j];
|
||||
|
||||
spin_lock (&volume->lock, &fv);
|
||||
spin_lock (&volume->back_device->lock, &fd);
|
||||
|
||||
memcpy (info->volume_name, volume->key, sizeof (info->volume_name));
|
||||
memcpy (info->device_key, volume->back_device->key, sizeof (info->device_key));
|
||||
|
||||
spin_unlock (&volume->back_device->lock, fd);
|
||||
spin_unlock (&volume->lock, fv);
|
||||
|
||||
hash_link = hash_link->next;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock (&volume_table.lock, fvt);
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static struct vfs_volume* vfs_find_volume (const char* volume) {
|
||||
uint64_t fvt;
|
||||
|
||||
@@ -62,6 +99,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
|
||||
switch (volume->fs_type) {
|
||||
case FS_TARFS:
|
||||
volume->driver_ops.mount = &tarfs_mount;
|
||||
volume->driver_ops.unmount = &tarfs_unmount;
|
||||
volume->driver_ops.format = &tarfs_format;
|
||||
volume->driver_ops.describe = &tarfs_describe;
|
||||
volume->driver_ops.read_file = &tarfs_read_file;
|
||||
@@ -73,6 +111,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
|
||||
break;
|
||||
case FS_FAT16:
|
||||
volume->driver_ops.mount = &fatfs_mount;
|
||||
volume->driver_ops.unmount = &fatfs_unmount;
|
||||
volume->driver_ops.format = &fatfs16_format;
|
||||
volume->driver_ops.describe = &fatfs_describe;
|
||||
volume->driver_ops.read_file = &fatfs_read_file;
|
||||
@@ -84,6 +123,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
|
||||
break;
|
||||
case FS_FAT32:
|
||||
volume->driver_ops.mount = &fatfs_mount;
|
||||
volume->driver_ops.unmount = &fatfs_unmount;
|
||||
volume->driver_ops.format = &fatfs32_format;
|
||||
volume->driver_ops.describe = &fatfs_describe;
|
||||
volume->driver_ops.read_file = &fatfs_read_file;
|
||||
@@ -95,6 +135,7 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
|
||||
break;
|
||||
case FS_ISO9660:
|
||||
volume->driver_ops.mount = &iso9660fs_mount;
|
||||
volume->driver_ops.unmount = &iso9660fs_unmount;
|
||||
volume->driver_ops.format = &iso9660fs_format;
|
||||
volume->driver_ops.describe = &iso9660fs_describe;
|
||||
volume->driver_ops.read_file = &iso9660fs_read_file;
|
||||
@@ -128,6 +169,52 @@ int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const cha
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
int vfs_volume_delete (const char* key) {
|
||||
uint64_t fv, fvt;
|
||||
|
||||
struct hash_node_link* found_link = NULL;
|
||||
size_t key_len = strlen_null (key);
|
||||
uint32_t hash = hash_fnv32 (key, key_len);
|
||||
|
||||
spin_lock (&volume_table.lock, &fvt);
|
||||
|
||||
hash_find (&volume_table, key, key_len, hash, lengthof (volume_table.volume_buckets),
|
||||
volume_buckets, struct vfs_volume, volume_table_link, key, found_link);
|
||||
|
||||
if (found_link == NULL) {
|
||||
spin_unlock (&volume_table.lock, fvt);
|
||||
return -ST_NOT_FOUND;
|
||||
}
|
||||
|
||||
struct vfs_volume* volume = hash_entry (found_link, struct vfs_volume, volume_table_link);
|
||||
|
||||
if (volume == NULL) {
|
||||
spin_unlock (&volume_table.lock, fvt);
|
||||
return -ST_NOT_FOUND;
|
||||
}
|
||||
|
||||
spin_lock (&volume->lock, &fv);
|
||||
|
||||
if (volume->locked) {
|
||||
spin_unlock (&volume->lock, fv);
|
||||
spin_unlock (&volume_table.lock, fvt);
|
||||
return -ST_TRY_AGAIN;
|
||||
}
|
||||
|
||||
hash_delete (&volume_table, key, strlen_null (key), hash, lengthof (volume_table.volume_buckets),
|
||||
volume_buckets, struct vfs_volume, volume_table_link, key, found_link);
|
||||
|
||||
int ret = volume->driver_ops.unmount (volume);
|
||||
|
||||
spin_unlock (&volume->lock, fv);
|
||||
|
||||
free (volume);
|
||||
|
||||
spin_unlock (&volume_table.lock, fvt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_volume_open (struct proc* proc, const char* volume_name, struct reschedule_ctx* rctx) {
|
||||
uint64_t fv;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <proc/reschedule.h>
|
||||
#include <proc/suspension_q.h>
|
||||
#include <sync/spin_lock.h>
|
||||
#include <volume_info.h>
|
||||
|
||||
struct vfs_volume;
|
||||
|
||||
@@ -30,6 +31,8 @@ struct vfs_volume {
|
||||
int (*mount) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx,
|
||||
bool format);
|
||||
|
||||
int (*unmount) (struct vfs_volume* volume);
|
||||
|
||||
int (*format) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx);
|
||||
|
||||
int (*describe) (struct vfs_volume* volume, struct proc* proc, struct reschedule_ctx* rctx,
|
||||
@@ -66,6 +69,8 @@ struct vfs_volume_table {
|
||||
int vfs_create_volume (struct proc* proc, struct reschedule_ctx* rctx, const char* key, int fs_type,
|
||||
struct device* back_device, bool format);
|
||||
|
||||
int vfs_volume_delete (const char* key);
|
||||
|
||||
int vfs_volume_open (struct proc* proc, const char* volume, struct reschedule_ctx* rctx);
|
||||
|
||||
int vfs_volume_close (struct proc* proc, const char* volume, struct reschedule_ctx* rctx);
|
||||
@@ -98,4 +103,6 @@ void vfs_init (void);
|
||||
void vfs_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 volume_populate_volume_infos (struct volume_info* infos, size_t count);
|
||||
|
||||
#endif // _KERNEL_FS_VFS_H
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <sys/proc.h>
|
||||
#include <syscall/syscall.h>
|
||||
#include <syscall_defs.h>
|
||||
#include <volume_info.h>
|
||||
#include <write_file.h>
|
||||
|
||||
#define DEFINE_SYSCALL(name) \
|
||||
@@ -1097,6 +1098,57 @@ DEFINE_SYSCALL (sys_get_device_info) {
|
||||
return SYSRESULT (device_populate_device_infos (infos, infos_count));
|
||||
}
|
||||
|
||||
/* int get_volume_info (struct volume_info* infos, size_t count) */
|
||||
DEFINE_SYSCALL (sys_get_volume_info) {
|
||||
uint64_t fp;
|
||||
|
||||
uintptr_t uvaddr_infos = a1;
|
||||
size_t infos_count = (size_t)a2;
|
||||
|
||||
spin_lock (&proc->lock, &fp);
|
||||
struct procgroup* procgroup = proc->procgroup;
|
||||
spin_unlock (&proc->lock, fp);
|
||||
|
||||
struct volume_info* infos =
|
||||
sys_get_user_buffer (procgroup, uvaddr_infos, infos_count * sizeof (struct volume_info));
|
||||
|
||||
if (infos == NULL)
|
||||
return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
|
||||
|
||||
return SYSRESULT (volume_populate_volume_infos (infos, infos_count));
|
||||
}
|
||||
|
||||
/* int volume_delete (const char* volume) */
|
||||
DEFINE_SYSCALL (sys_volume_delete) {
|
||||
uint64_t fpg, fp;
|
||||
|
||||
uintptr_t uvaddr_volume = a1;
|
||||
|
||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||
|
||||
uintptr_t out_paddr;
|
||||
|
||||
spin_lock (&proc->lock, &fp);
|
||||
struct procgroup* procgroup = proc->procgroup;
|
||||
spin_unlock (&proc->lock, fp);
|
||||
|
||||
spin_lock (&procgroup->lock, &fpg);
|
||||
out_paddr = mm_v2p (&procgroup->pd, uvaddr_volume);
|
||||
spin_unlock (&procgroup->lock, fpg);
|
||||
|
||||
if (out_paddr == 0)
|
||||
return SYSRESULT (-ST_BAD_ADDRESS_SPACE);
|
||||
|
||||
const char* volume = (const char*)((uintptr_t)hhdm->offset + out_paddr);
|
||||
|
||||
int ret = vfs_volume_delete (volume);
|
||||
|
||||
if (ret < 0)
|
||||
return SYSRESULT (ret);
|
||||
|
||||
return SYSRESULT (ST_OK);
|
||||
}
|
||||
|
||||
static syscall_handler_func_t handler_table[] = {
|
||||
[SYS_QUIT] = &sys_quit,
|
||||
[SYS_TEST] = &sys_test,
|
||||
@@ -1136,6 +1188,8 @@ static syscall_handler_func_t handler_table[] = {
|
||||
[SYS_STREAM_READ] = &sys_stream_read,
|
||||
[SYS_GET_PROC_INFO] = &sys_get_proc_info,
|
||||
[SYS_GET_DEVICE_INFO] = &sys_get_device_info,
|
||||
[SYS_GET_VOLUME_INFO] = &sys_get_volume_info,
|
||||
[SYS_VOLUME_DELETE] = &sys_volume_delete,
|
||||
};
|
||||
|
||||
syscall_handler_func_t syscall_find_handler (int syscall_num) {
|
||||
|
||||
@@ -118,3 +118,9 @@ int get_proc_info (struct proc_info* infos, size_t count) {
|
||||
int get_device_info (struct device_info* infos, size_t count) {
|
||||
return (int)do_syscall (SYS_GET_DEVICE_INFO, infos, count);
|
||||
}
|
||||
|
||||
int get_volume_info (struct volume_info* infos, size_t count) {
|
||||
return (int)do_syscall (SYS_GET_VOLUME_INFO, infos, count);
|
||||
}
|
||||
|
||||
int volume_delete (const char* key) { return (int)do_syscall (SYS_VOLUME_DELETE, key); }
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <proc_info.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <volume_info.h>
|
||||
|
||||
/* Quit the current running process */
|
||||
int quit (void);
|
||||
@@ -122,4 +123,10 @@ int get_proc_info (struct proc_info* infos, size_t count);
|
||||
/* get device information */
|
||||
int get_device_info (struct device_info* infos, size_t count);
|
||||
|
||||
/* get volume information */
|
||||
int get_volume_info (struct volume_info* infos, size_t count);
|
||||
|
||||
/* delete a volume */
|
||||
int volume_delete (const char* key);
|
||||
|
||||
#endif // _LIBMSL_M_SYSTEM_H
|
||||
|
||||
81
usb/usb.c
81
usb/usb.c
@@ -5,14 +5,68 @@
|
||||
#include <process.h>
|
||||
#include <process_self.h>
|
||||
#include <status.h>
|
||||
#include <str_status.h>
|
||||
#include <string.h>
|
||||
#include <system.h>
|
||||
#include <volume_info.h>
|
||||
|
||||
static void usb_poll (void) {
|
||||
struct device_info* infos = malloc (sizeof (struct device_info) * 1024);
|
||||
memset (infos, 0, sizeof (struct device_info) * 1024);
|
||||
|
||||
int device_count = get_device_info (infos, 1024);
|
||||
struct device_info info;
|
||||
bool found = false;
|
||||
|
||||
for (int dev = 0; dev < device_count; dev++) {
|
||||
info = infos[dev];
|
||||
|
||||
if (info.type == DEVICE_TYPE_USB_CTRL) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
mprintf ("Polling device %s\n", info.key);
|
||||
|
||||
for (;;) {
|
||||
device_do (info.key, XUSBCTRL_POLL_DRIVER, NULL, NULL, NULL, NULL);
|
||||
|
||||
for (volatile int i = 0; i < 500; i++)
|
||||
sched ();
|
||||
}
|
||||
}
|
||||
|
||||
free (infos);
|
||||
}
|
||||
|
||||
static void usb_eject (const char* dev_key) {
|
||||
struct volume_info* volume_infos = malloc (sizeof (*volume_infos) * 100);
|
||||
memset (volume_infos, 0, sizeof (*volume_infos) * 100);
|
||||
|
||||
size_t count = get_volume_info (volume_infos, 100);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
struct volume_info* info = &volume_infos[i];
|
||||
|
||||
if (strcmp (info->device_key, dev_key) == 0) {
|
||||
int ret = volume_delete (info->volume_name);
|
||||
mprintf ("Deleted volume %s: %s", info->volume_name, str_status[ret < 0 ? -ret : ret]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (volume_infos);
|
||||
}
|
||||
|
||||
void app_main (void) {
|
||||
libprocess_self_init ();
|
||||
|
||||
char commandbuf[32];
|
||||
memset (commandbuf, 0, sizeof (commandbuf));
|
||||
char devnamebuf[32];
|
||||
memset (devnamebuf, 0, sizeof (devnamebuf));
|
||||
|
||||
if (env_get (process_get_pgid (), "C", (void*)commandbuf, sizeof (commandbuf)) != ST_OK) {
|
||||
mprintf ("ERROR C=???. No command provided\n");
|
||||
@@ -20,29 +74,14 @@ void app_main (void) {
|
||||
}
|
||||
|
||||
if (strcmp (commandbuf, "poll") == 0) {
|
||||
struct device_info* infos = malloc (sizeof (struct device_info) * 1024);
|
||||
memset (infos, 0, sizeof (struct device_info) * 1024);
|
||||
|
||||
int device_count = get_device_info (infos, 1024);
|
||||
|
||||
for (int dev = 0; dev < device_count; dev++) {
|
||||
struct device_info* info = &infos[dev];
|
||||
|
||||
if (info->type != DEVICE_TYPE_USB_CTRL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mprintf ("Polling device %s\n", info->key);
|
||||
|
||||
for (;;) {
|
||||
device_do (info->key, XUSBCTRL_POLL_DRIVER, NULL, NULL, NULL, NULL);
|
||||
|
||||
for (volatile int i = 0; i < 500; i++)
|
||||
sched ();
|
||||
}
|
||||
usb_poll ();
|
||||
} else if (strcmp (commandbuf, "eject") == 0) {
|
||||
if (env_get (process_get_pgid (), "dev", (void*)devnamebuf, sizeof (devnamebuf)) != ST_OK) {
|
||||
mprintf ("ERROR No device provided\n");
|
||||
return;
|
||||
}
|
||||
|
||||
free (infos);
|
||||
usb_eject (devnamebuf);
|
||||
} else {
|
||||
mprintf ("ERROR unknown command %s\n", commandbuf);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user