feat: unified block device manipulation using vfs.
chore: bug fix & code formatting.
#include <hal/pci.h>
#include <klibc/string.h>
+#include <lunaix/block.h>
#include <lunaix/mm/mmio.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/valloc.h>
if (!ahci_init_device(port)) {
kprintf(KERROR "fail to init device");
}
+
+ block_mount_disk(port->device);
}
}
#define LPT_SIG 0x414e554c
#define PARTITION_NAME_SIZE 48
+#define DEV_ID_SIZE 32
typedef uint64_t partition_t;
typedef uint32_t bdev_t;
struct block_dev
{
+ char bdev_id[DEV_ID_SIZE];
char name[PARTITION_NAME_SIZE];
struct hba_device* hd_dev;
uint64_t base_lba;
uint32_t table_len;
} __attribute__((packed));
+void
+block_init();
+
+int
+block_mount_disk(struct hba_device* hd_dev);
+
#endif /* __LUNAIX_BLOCK_H */
__LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent);
+__LXSYSCALL3(int, lseek, int, fd, int, offset, int, options);
+
+__LXSYSCALL3(int, read, int, fd, void*, buf, unsigned int, count);
+
+__LXSYSCALL3(int, write, int, fd, void*, buf, unsigned int, count);
+
#endif /* __LUNAIX_FCTRL_H */
#define FO_CREATE 0x1
#define FO_APPEND 0x2
+#define FSEEK_SET 0x1
+#define FSEEK_CUR 0x2
+#define FSEEK_END 0x3
+
#endif /* __LUNAIX_FOPTIONS_H */
{
struct v_inode* inode;
struct hstr name;
+ void* data;
uint32_t itype;
struct llist_header children;
struct llist_header siblings;
__LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options);
+__LXSYSCALL(int, geterrno);
+
#endif /* __LUNAIX_SYS_H */
#define EEXIST -12
#define EBADF -13
#define ENOTSUP -14
+#define ENXIO -15
#endif /* __LUNAIX_CODE_H */
#define __SYSCALL_write 22
#define __SYSCALL_readdir 23
#define __SYSCALL_mkdir 24
+#define __SYSCALL_lseek 25
+#define __SYSCALL_geterrno 26
#define __SYSCALL_MAX 0x100
.long __lxsys_sigpending
.long __lxsys_sigsuspend
.long __lxsys_open
- .long __lxsys_close
+ .long __lxsys_close /* 20 */
.long __lxsys_read
.long __lxsys_write
.long __lxsys_readdir
.long __lxsys_mkdir
+ .long __lxsys_lseek /* 25 */
+ .long __lxsys_geterrno
2:
.rept __SYSCALL_MAX - (2b - 1b)/4
.long 0
#include <hal/ahci/hba.h>
+#include <klibc/stdio.h>
#include <klibc/string.h>
#include <lib/crc.h>
#include <lunaix/block.h>
+#include <lunaix/fs/twifs.h>
#include <lunaix/mm/cake.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/syslog.h>
+#include <lunaix/spike.h>
+
#define BLOCK_EREAD 1
#define BLOCK_ESIG 2
#define BLOCK_ECRC 3
{
lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
+ free_slot = 0;
+}
+
+int
+__block_read(struct v_file* file, void* buffer, size_t len);
+
+int
+__block_write(struct v_file* file, void* buffer, size_t len);
+
+void
+block_twifs_create()
+{
+ struct twifs_node* dev = twifs_toplevel_node("dev", 3);
+ struct twifs_node* dev_block = twifs_dir_node(dev, "block", 5);
+
+ if (!dev_block) {
+ kprintf(KERROR "fail to create twifs node");
+ return;
+ }
+
+ struct block_dev* bdev;
+ struct twifs_node* bdev_node;
+ for (size_t i = 0; i < MAX_DEV; i++) {
+ if (!(bdev = dev_registry[i])) {
+ continue;
+ }
+
+ bdev_node =
+ twifs_dir_node(dev_block, bdev->bdev_id, strlen(bdev->bdev_id));
+ bdev_node->fops.read = __block_read;
+ bdev_node->fops.write = __block_write;
+ bdev_node->data = i;
+ bdev_node->inode->fsize = bdev->hd_dev->max_lba;
+ }
+}
+
+int
+__block_read(struct v_file* file, void* buffer, size_t len)
+{
+ int index = (int)((struct twifs_node*)file->inode->data)->data;
+ int errno;
+ struct block_dev* bdev;
+ if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
+ return ENXIO;
+ }
+ size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
+ rd_block = 0;
+ void* block = valloc(bsize);
+
+ while (acc_size < len) {
+ if (!bdev->hd_dev->ops.read_buffer(
+ bdev->hd_dev, file->f_pos + rd_block, block, bsize)) {
+ errno = ENXIO;
+ goto error;
+ }
+ rd_size = MIN(len - acc_size, bsize);
+ memcpy(buffer + acc_size, block, rd_size);
+ acc_size += rd_size;
+ rd_block++;
+ }
+
+ vfree(block);
+ return rd_block;
+
+error:
+ vfree(block);
+ return errno;
+}
+
+int
+__block_write(struct v_file* file, void* buffer, size_t len)
+{
+ int index = (int)((struct twifs_node*)file->inode->data)->data;
+ int errno;
+ struct block_dev* bdev;
+ if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
+ return ENXIO;
+ }
+ size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
+ wr_block = 0;
+ void* block = valloc(bsize);
+
+ while (acc_size < len) {
+ wr_size = MIN(len - acc_size, bsize);
+ memcpy(block, buffer + acc_size, wr_size);
+ if (!bdev->hd_dev->ops.write_buffer(
+ bdev->hd_dev, file->f_pos + wr_block, block, bsize)) {
+ errno = ENXIO;
+ break;
+ }
+ acc_size += wr_size;
+ wr_block++;
+ }
+
+ vfree(block);
+ return wr_block;
+
+error:
+ vfree(block);
+ return errno;
}
int
goto error;
}
- if ((errno = __block_mount_partitions(hd_dev))) {
- goto error;
- }
+ return errno;
error:
- kprintf(KERROR "Fail to mount hd: %s[%s] (%x)",
+ kprintf(KERROR "Fail to mount hd: %s[%s] (%x)\n",
hd_dev->model,
hd_dev->serial_num,
-errno);
}
+// FIXME make it more general, manipulate the device through vfs mapping
int
__block_mount_partitions(struct hba_device* hd_dev)
{
if (free_slot >= MAX_DEV) {
return 0;
}
-
+ snprintf(dev->bdev_id, DEV_ID_SIZE, "bd%x", free_slot);
dev_registry[free_slot++] = dev;
return 1;
}
\ No newline at end of file
void
_readdir_main()
{
- int fd = open("/bus/../..", 0);
+ int fd = open("/dev/block", 0);
if (fd == -1) {
kprintf(KERROR "fail to open\n");
return;
--- /dev/null
+#include <lunaix/fctrl.h>
+#include <lunaix/foptions.h>
+#include <lunaix/proc.h>
+#include <lunaix/syslog.h>
+
+LOG_MODULE("IOTEST")
+
+void
+_iotest_main()
+{
+ char test_sequence[] = "Once upon a time, in a magical land of Equestria. "
+ "There were two regal sisters who ruled together "
+ "and created harmony for all the land.";
+ int fd = open("/dev/block/bd0", 0);
+
+ if (fd < 0) {
+ kprintf(KERROR "fail to open (%d)\n", geterrno());
+ return;
+ }
+
+ lseek(fd, 1, FSEEK_SET);
+ write(fd, test_sequence, sizeof(test_sequence));
+
+ lseek(fd, -1, FSEEK_CUR);
+ char read_out[256];
+ read(fd, read_out, sizeof(read_out));
+
+ kprintf("%s", read_out);
+}
\ No newline at end of file
struct twifs_node*
__twifs_new_node(struct twifs_node* parent, const char* name, int name_len)
{
- struct hstr hname = HSTR(name, name_len);
- hstr_rehash(&hname, HSTR_FULL_HASH);
-
- struct twifs_node* node = __twifs_get_node(parent, &hname);
- if (node) {
- return node;
- }
-
- node = cake_grab(twi_pile);
+ struct twifs_node* node = cake_grab(twi_pile);
memset(node, 0, sizeof(*node));
- node->name = hname;
+ node->name = HSTR(name, name_len);
+ hstr_rehash(&node->name, HSTR_FULL_HASH);
llist_init_head(&node->children);
if (parent) {
struct twifs_node*
twifs_dir_node(struct twifs_node* parent, const char* name, int name_len)
{
+ struct hstr hname = HSTR(name, name_len);
+ hstr_rehash(&hname, HSTR_FULL_HASH);
+ struct twifs_node* node = __twifs_get_node(parent, &hname);
+ if (node) {
+ return node;
+ }
+
struct twifs_node* twi_node = __twifs_new_node(parent, name, name_len);
twi_node->itype = VFS_INODE_TYPE_DIR;
twi_node->fops.readdir = __twifs_iterate_dir;
error:
vfree(dnode->name.value);
vfs_d_free(dnode);
+ *dentry = NULL;
return errno;
}
if (!errno && !(errno = vfs_alloc_fdslot(&fd))) {
struct v_fd* fd_s = vzalloc(sizeof(*fd_s));
fd_s->file = opened_file;
- fd_s->pos = file->inode->fsize & -((options & FO_APPEND) == 0);
+ fd_s->pos = file->inode->fsize & -((options & FO_APPEND) != 0);
__current->fdtable->fds[fd] = fd_s;
}
return SYSCALL_ESTATUS(errno);
}
+#define GET_FD(fd, fd_s) \
+ (fd >= 0 && fd < VFS_MAX_FD && (fd_s = __current->fdtable->fds[fd]))
+
__DEFINE_LXSYSCALL1(int, close, int, fd)
{
struct v_fd* fd_s;
int errno;
- if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) {
+ if (!GET_FD(fd, fd_s)) {
errno = EBADF;
} else if (!(errno = vfs_close(fd_s->file))) {
vfree(fd_s);
{
struct v_fd* fd_s;
int errno;
- if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) {
+ if (!GET_FD(fd, fd_s)) {
errno = EBADF;
} else if (!(fd_s->file->inode->itype & VFS_INODE_TYPE_DIR)) {
errno = ENOTDIR;
return SYSCALL_ESTATUS(errno);
}
-__DEFINE_LXSYSCALL3(size_t, read, int, fd, void*, buf, size_t, count)
+__DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
{
- // TODO
+ int errno = 0;
+ struct v_fd* fd_s;
+ if (!GET_FD(fd, fd_s)) {
+ errno = EBADF;
+ } else {
+ struct v_file* file = fd_s->file;
+ file->f_pos = fd_s->pos;
+ if ((errno = file->ops.read(file, buf, count)) >= 0) {
+ fd_s->pos += errno;
+ }
+ }
+
+ __current->k_status = errno;
+ return SYSCALL_ESTATUS(errno);
}
-__DEFINE_LXSYSCALL3(size_t, write, int, fd, void*, buf, size_t, count)
+__DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
{
- // TODO
+ int errno = 0;
+ struct v_fd* fd_s;
+ if (!GET_FD(fd, fd_s)) {
+ errno = EBADF;
+ } else {
+ struct v_file* file = fd_s->file;
+ file->f_pos = fd_s->pos;
+ if ((errno = file->ops.write(file, buf, count)) >= 0) {
+ fd_s->pos += errno;
+ }
+ }
+
+ __current->k_status = errno;
+ return SYSCALL_ESTATUS(errno);
+}
+
+__DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options)
+{
+ int errno = 0;
+ struct v_fd* fd_s;
+ if (!GET_FD(fd, fd_s)) {
+ errno = EBADF;
+ } else {
+ size_t fpos = fd_s->file->f_pos;
+ switch (options) {
+ case FSEEK_CUR:
+ fpos = (size_t)((int)fd_s->file->f_pos + offset);
+ break;
+ case FSEEK_END:
+ fpos = (size_t)((int)fd_s->file->inode->fsize + offset);
+ break;
+ case FSEEK_SET:
+ fpos = offset;
+ break;
+
+ default:
+ break;
+ }
+ fd_s->pos = fpos;
+ }
+
+ __current->k_status = errno;
+ return SYSCALL_ESTATUS(errno);
}
\ No newline at end of file
#include <arch/x86/boot/multiboot.h>
+#include <lunaix/block.h>
#include <lunaix/common.h>
#include <lunaix/fs.h>
#include <lunaix/fs/twifs.h>
#define USE_DEMO
// #define DEMO_SIGNAL
-#define DEMO_READDIR
+// #define DEMO_READDIR
+#define DEMO_IOTEST
extern void
_pconsole_main();
extern void
_readdir_main();
+extern void
+_iotest_main();
+
void __USER__
__proc0_usr()
{
_signal_demo_main();
#elif defined DEMO_READDIR
_readdir_main();
+#elif defined DEMO_IOTEST
+ _iotest_main();
#else
_lxinit_main();
#endif
extern uint8_t __init_hhk_end; /* link/linker.ld */
extern multiboot_info_t* _k_init_mb_info; /* k_init.c */
-char test_sequence[] = "Once upon a time, in a magical land of Equestria. "
- "There were two regal sisters who ruled together "
- "and created harmony for all the land.";
-
-void
-__test_disk_io()
-{
- struct hba_port* port = ahci_get_port(0);
- struct hba_device* dev = port->device;
- char* buffer = vzalloc_dma(port->device->block_size);
- strcpy(buffer, test_sequence);
- kprintf("WRITE: %s\n", buffer);
- int result;
-
- // 写入第一扇区 (LBA=0)
- result = dev->ops.write_buffer(dev, 0, buffer, dev->block_size);
- if (!result) {
- kprintf(KWARN "fail to write: %x\n", dev->last_error);
- }
-
- memset(buffer, 0, dev->block_size);
-
- // 读出我们刚刚写的内容!
- result = dev->ops.read_buffer(dev, 0, buffer, dev->block_size);
- kprintf(KDEBUG "%x, %x\n", port->regs[HBA_RPxIS], port->regs[HBA_RPxTFD]);
- if (!result) {
- kprintf(KWARN "fail to read: %x\n", dev->last_error);
- } else {
- kprint_hex(buffer, 256);
- }
-
- vfree_dma(buffer);
-}
+extern void
+block_twifs_create();
void
init_platform()
clock_init();
ps2_kbd_init();
pci_init();
+ block_init();
ahci_init();
// ahci_list_device();
vfs_init();
twifs_init();
+ block_twifs_create();
+
vfs_mount("/", "twifs", -1);
//__test_disk_io();
return _wait(pid, status, options);
}
+__DEFINE_LXSYSCALL(int, geterrno)
+{
+ return __current->k_status;
+}
+
pid_t
_wait(pid_t wpid, int* status, int options)
{