From c6de44b989e9d7286337e4cbf4d82d919f9120e6 Mon Sep 17 00:00:00 2001 From: Minep Date: Fri, 11 Nov 2022 19:50:54 +0000 Subject: [PATCH 1/1] feat: (iso9660) directory read support feat: (syslog) syslog syscall for kernel-level logging in userspace feat: (blkio) block io feature in sector level granularity refactor: (vfs) simplify some interfaces refactor: (vfs) verbose logging on mount refactor: (lunaix) rename proc.h to lunaix.h fix: regression chore: code clean up and add verbose logging message --- lunaix-os/includes/lunaix/block.h | 11 ++ lunaix-os/includes/lunaix/clock.h | 9 +- lunaix-os/includes/lunaix/fs.h | 1 + lunaix-os/includes/lunaix/fs/iso9660.h | 143 ++++++++++++++--- .../includes/lunaix/{proc.h => lunaix.h} | 8 +- lunaix-os/includes/lunaix/lxconsole.h | 3 + lunaix-os/includes/lunaix/status.h | 1 + lunaix-os/includes/lunaix/syscall.h | 3 + lunaix-os/kernel/asm/x86/syscall.S | 1 + lunaix-os/kernel/block/block.c | 69 +++++++- lunaix-os/kernel/demos/dir_read.c | 2 +- lunaix-os/kernel/demos/input_test.c | 2 +- lunaix-os/kernel/demos/iotest.c | 2 +- lunaix-os/kernel/demos/signal_demo.c | 2 +- lunaix-os/kernel/demos/simple_sh.c | 2 +- lunaix-os/kernel/fs/fs_setup.c | 2 + lunaix-os/kernel/fs/fsm.c | 3 + lunaix-os/kernel/fs/iso9660/directory.c | 148 ++++++++++++++++++ lunaix-os/kernel/fs/iso9660/file.c | 37 +++++ lunaix-os/kernel/fs/iso9660/inode.c | 72 +++++++++ lunaix-os/kernel/fs/iso9660/mount.c | 108 +++++++++++++ lunaix-os/kernel/fs/iso9660/utils.c | 24 +++ lunaix-os/kernel/fs/mount.c | 23 +++ lunaix-os/kernel/fs/ramfs/ramfs.c | 2 +- lunaix-os/kernel/fs/twifs/twifs.c | 1 - lunaix-os/kernel/k_init.c | 4 +- lunaix-os/kernel/kprintf.c | 41 +++-- lunaix-os/kernel/lxinit.c | 2 +- lunaix-os/kernel/proc0.c | 22 ++- lunaix-os/kernel/tty/lxconsole.c | 4 + 30 files changed, 698 insertions(+), 54 deletions(-) rename lunaix-os/includes/lunaix/{proc.h => lunaix.h} (60%) create mode 100644 lunaix-os/kernel/fs/iso9660/directory.c create mode 100644 lunaix-os/kernel/fs/iso9660/file.c create mode 100644 lunaix-os/kernel/fs/iso9660/inode.c create mode 100644 lunaix-os/kernel/fs/iso9660/mount.c create mode 100644 lunaix-os/kernel/fs/iso9660/utils.c diff --git a/lunaix-os/includes/lunaix/block.h b/lunaix-os/includes/lunaix/block.h index 551bc22..c574dd3 100644 --- a/lunaix-os/includes/lunaix/block.h +++ b/lunaix-os/includes/lunaix/block.h @@ -9,6 +9,16 @@ #define PARTITION_NAME_SIZE 48 #define DEV_ID_SIZE 32 +struct block_dev; + +struct block_dev_ops +{ + int (*block_read)(struct block_dev*, void*, u64_t, size_t); + int (*block_write)(struct block_dev*, void*, u64_t, size_t); + void* (*block_alloc)(struct block_dev*); + void (*block_free)(struct block_dev*, void*); +}; + struct block_dev { struct llist_header parts; @@ -20,6 +30,7 @@ struct block_dev u64_t start_lba; u64_t end_lba; u32_t blk_size; + struct block_dev_ops ops; }; // Lunaix Partition Table diff --git a/lunaix-os/includes/lunaix/clock.h b/lunaix-os/includes/lunaix/clock.h index 44dfa04..8c9ab15 100644 --- a/lunaix-os/includes/lunaix/clock.h +++ b/lunaix-os/includes/lunaix/clock.h @@ -1,7 +1,7 @@ #ifndef __LUNAIX_CLOCK_H #define __LUNAIX_CLOCK_H -#include +#include typedef uint32_t time_t; @@ -44,4 +44,11 @@ clock_tounixtime(datetime_t* dt) (dt->minute - 1) * 60u + dt->second; } +static inline time_t +time_tounix(u32_t yyyy, u32_t mm, u32_t dd, u32_t hh, u32_t MM, u32_t ss) +{ + return (yyyy - 1970) * 31556926u + (mm - 1) * 2629743u + (dd - 1) * 86400u + + (hh - 1) * 3600u + (MM - 1) * 60u + ss; +} + #endif /* __LUNAIX_CLOCK_H */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 4f57e08..cc850ad 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -97,6 +97,7 @@ struct v_superblock struct filesystem* fs; uint32_t iobuf_size; struct hbucket* i_cache; + void* data; struct { uint32_t (*read_capacity)(struct v_superblock* vsb); diff --git a/lunaix-os/includes/lunaix/fs/iso9660.h b/lunaix-os/includes/lunaix/fs/iso9660.h index edccadc..de433d4 100644 --- a/lunaix-os/includes/lunaix/fs/iso9660.h +++ b/lunaix-os/includes/lunaix/fs/iso9660.h @@ -12,8 +12,13 @@ #ifndef __LUNAIX_ISO9660_H #define __LUNAIX_ISO9660_H +#include +#include #include +#define ISO_SIGNATURE_LO 0x30304443UL +#define ISO_SIGNATURE_HI 0x31 + // Volume Types #define ISO_VOLBOOT 0 // Boot Record #define ISO_VOLPRIM 1 // Primary @@ -28,6 +33,9 @@ #define ISO_FPROTECT 0x10 // file being protected by access control #define ISO_FEXTENTS 0x80 // the extent by this record is a file partial +#define ISO9660_BLKSZ 2048 +#define ISO9660_IDLEN 256 + // NOTES: // Each Descriptor sized 1 logical block (2048 bytes in common cases) // ISO9660 store number in both-byte order. That is, for a d-bits number, it @@ -61,6 +69,20 @@ struct iso_datetime u8_t gmt; } PACKED; +// 32bits both-byte-order integer +typedef struct iso_bbo32 +{ + u32_t le; // little-endian + u32_t be; // big-endian +} PACKED iso_bbo32_t; + +// 16bits both-byte-order integer +typedef struct iso_bbo16 +{ + u16_t le; // little-endian + u16_t be; // big-endian +} PACKED iso_bbo16_t; + // (8.4) Describe a primary volume space struct iso_vol_primary { @@ -68,17 +90,15 @@ struct iso_vol_primary u8_t reserved_1; u8_t sys_id[32]; u8_t vol_id[32]; - u8_t reserved_2; - u32_t sz_lo; // (8.4.8) only lower portion is valid. - u32_t sz_hi; - u8_t reserved_2; - u32_t set_size; - u32_t seq_num; - u32_t lb_size; - u32_t path_tbl_sz_lo; // lower partition - LE. - u32_t path_tbl_sz_hi; + u8_t reserved_2[8]; + iso_bbo32_t vol_size; + u8_t reserved_3[32]; + iso_bbo16_t set_size; + iso_bbo16_t seq_num; + iso_bbo16_t lb_size; + iso_bbo32_t ptable_size; u32_t lpath_tbl_ptr; // Type L Path table location (LBA) - u32_t reserved_3[3]; // use type M if big endian machine. + u32_t reserved_4[3]; // use type M if big endian machine. u8_t root_record[34]; u8_t set_id[128]; u8_t publisher_id[128]; @@ -104,10 +124,8 @@ struct iso_partition u8_t reserved; u8_t sys_id[32]; u8_t part_id[32]; - u32_t part_addr_lo; // (8.6.7) only lower portion is valid. - u32_t part_addr_hi; - u32_t part_sz_lo; // (8.6.8) only lower portion is valid. - u32_t part_sz_hi; + iso_bbo32_t part_addr; + iso_bbo32_t part_size; } PACKED; // (6.10.4) MDU with variable record @@ -121,14 +139,13 @@ struct iso_var_mdu struct iso_drecord { u8_t xattr_len; - u32_t extent_lo; // location of extent, lower 32 bits is valid. - u32_t extent_hi; - u32_t data_sz_lo; // size of extent, lower 32 bits is valid. - u32_t data_sz_hi; + iso_bbo32_t extent_addr; + iso_bbo32_t data_size; struct { u8_t year; u8_t month; + u8_t day; u8_t hour; u8_t min; u8_t sec; @@ -137,11 +154,11 @@ struct iso_drecord u8_t flags; u8_t fu_sz; // size of file unit (FU) u8_t gap_sz; // size of gap if FU is interleaved. - u32_t vol_seq; + iso_bbo16_t vol_seq; struct iso_var_mdu name; } PACKED; -// (9.4) Path Table Record. [Embedded into Variable MDU] +// (9.4) L-Path Table Record. [Embedded into Variable MDU] struct iso_precord { u8_t xattr_len; @@ -152,8 +169,8 @@ struct iso_precord struct iso_xattr { - u32_t owner; - u32_t group; + iso_bbo16_t owner; + iso_bbo16_t group; u16_t perm; struct iso_datetime ctime; struct iso_datetime mtime; @@ -161,16 +178,94 @@ struct iso_xattr struct iso_datetime ef_time; u8_t record_fmt; u8_t record_attr; - u8_t record_len; + iso_bbo16_t record_len; u32_t sys_id; u8_t reserved1[64]; u8_t version; u8_t len_esc; u8_t reserved2[64]; - u32_t payload_sz; + iso_bbo16_t payload_sz; u8_t payload[0]; // There is also a escape sequence after payload, // It however marked as optional, hence we ignore it. } PACKED; +struct iso_ptable +{ + u32_t start_lba; + u32_t current_lba; + u32_t size; + u32_t range_lower; + u32_t range_upper; + void* ptable_part; +}; + +struct iso_inode +{ + time_t ctime; + time_t mtime; + u32_t record_fmt; + u32_t fu_size; + u32_t gap_size; + struct llist_header* drecaches; +}; + +struct iso_drecache +{ + struct llist_header caches; + u32_t extent_addr; + u32_t data_size; + u32_t xattr_len; + u32_t fu_size; + u32_t gap_size; + u32_t flags; + struct hstr name; + char name_val[ISO9660_IDLEN]; +}; + +struct iso_superblock +{ + u32_t volume_size; + u32_t lb_size; +}; + +struct iso_drecord* +iso9660_get_drecord(struct iso_var_mdu* drecord_mdu); + +int +iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino); + +time_t +iso9660_dt2unix(struct iso_datetime* isodt); + +void +iso9660_init(); + +int +iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode); + +void +iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec); + +int +iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode); + +int +iso9660_readdir(struct v_file* file, struct dir_context* dctx); + +int +iso9660_open(struct v_inode* this, struct v_file* file); + +int +iso9660_close(struct v_file* file); + +int +iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos); + +int +iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos); + +int +iso9660_seek(struct v_inode* inode, size_t offset); + #endif /* __LUNAIX_ISO9660_H */ diff --git a/lunaix-os/includes/lunaix/proc.h b/lunaix-os/includes/lunaix/lunaix.h similarity index 60% rename from lunaix-os/includes/lunaix/proc.h rename to lunaix-os/includes/lunaix/lunaix.h index f4de8cf..adbde1d 100644 --- a/lunaix-os/includes/lunaix/proc.h +++ b/lunaix-os/includes/lunaix/lunaix.h @@ -1,5 +1,5 @@ -#ifndef __LUNAIX_SYS_H -#define __LUNAIX_SYS_H +#ifndef __LUNAIX_LUNAIX_H +#define __LUNAIX_LUNAIX_H #include #include @@ -12,4 +12,6 @@ __LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options); __LXSYSCALL(int, geterrno); -#endif /* __LUNAIX_SYS_H */ +__LXSYSCALL2_VARG(void, syslog, int, level, const char*, fmt); + +#endif /* __LUNAIX_LUNAIX_H */ diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h index fbf59a4..197bc9e 100644 --- a/lunaix-os/includes/lunaix/lxconsole.h +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -11,6 +11,9 @@ void lxconsole_init(); +void +lxconsole_spawn_ttydev(); + void console_write_str(char* str); diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index cc105b4..f9b947d 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -29,5 +29,6 @@ #define ENOMEM LXOUTOFMEM #define ENOTDEV -24 #define EOVERFLOW -25 +#define ENOTBLK -26 #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 6169781..82fc4b9 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -58,6 +58,8 @@ #define __SYSCALL_getpgid 49 #define __SYSCALL_setpgid 50 +#define __SYSCALL_syslog 51 + #define __SYSCALL_MAX 0x100 #ifndef __ASM__ @@ -145,4 +147,5 @@ syscall_install(); ___DOINT33(__SYSCALL_##name, rettype) \ } #endif + #endif /* __LUNAIX_SYSCALL_H */ diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index 34b4330..93ea1c7 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -58,6 +58,7 @@ .long __lxsys_ioctl .long __lxsys_getpgid .long __lxsys_setpgid /* 50 */ + .long __lxsys_syslog 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/block/block.c b/lunaix-os/kernel/block/block.c index bcbc60f..494a977 100644 --- a/lunaix-os/kernel/block/block.c +++ b/lunaix-os/kernel/block/block.c @@ -98,10 +98,10 @@ int __block_write(struct device* dev, void* buf, size_t offset, size_t len) { struct block_dev* bdev = (struct block_dev*)dev->underlay; - size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba, + size_t bsize = bdev->blk_size, wr_block = offset / bsize + bdev->start_lba, r = offset % bsize, wr_size = 0; - if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) { + if (!(len = MIN(len, ((size_t)bdev->end_lba - wr_block + 1) * bsize))) { return 0; } @@ -123,7 +123,10 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len) vbuf_alloc(&vbuf, buf + wr_size, llen); } - req = blkio_vwr(vbuf, rd_block, NULL, NULL, 0); + // FIXME race condition between blkio_commit and pwait. + // Consider: what if scheduler complete the request before process enter + // wait state? + req = blkio_vwr(vbuf, wr_block, NULL, NULL, 0); blkio_commit(bdev->blkio, req); pwait(&req->wait); @@ -144,6 +147,64 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len) return errno; } +int +__block_rd_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count) +{ + struct vecbuf* vbuf = NULL; + vbuf_alloc(&vbuf, buf, bdev->blk_size * count); + + struct blkio_req* req = blkio_vrd(vbuf, start, NULL, NULL, 0); + blkio_commit(bdev->blkio, req); + pwait(&req->wait); + + int errno = req->errcode; + if (!errno) { + errno = count; + } else { + errno = -errno; + } + + blkio_free_req(req); + vbuf_free(vbuf); + + return errno; +} + +int +__block_wr_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count) +{ + struct vecbuf* vbuf = NULL; + vbuf_alloc(&vbuf, buf, bdev->blk_size * count); + + struct blkio_req* req = blkio_vwr(vbuf, start, NULL, NULL, 0); + blkio_commit(bdev->blkio, req); + pwait(&req->wait); + + int errno = req->errcode; + if (!errno) { + errno = count; + } else { + errno = -errno; + } + + blkio_free_req(req); + vbuf_free(vbuf); + + return errno; +} + +void* +block_alloc_buf(struct block_dev* bdev) +{ + return valloc(bdev->blk_size); +} + +void +block_free_buf(struct block_dev* bdev, void* buf) +{ + return vfree(buf); +} + struct block_dev* block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler) { @@ -155,6 +216,8 @@ block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler) bdev->blkio = blkio_newctx(ioreq_handler); bdev->driver = driver; bdev->blkio->driver = driver; + bdev->ops = (struct block_dev_ops){ .block_read = __block_rd_lb, + .block_write = __block_wr_lb }; return bdev; } diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c index 54ffd97..e1ef7a2 100644 --- a/lunaix-os/kernel/demos/dir_read.c +++ b/lunaix-os/kernel/demos/dir_read.c @@ -1,7 +1,7 @@ #include #include +#include #include -#include void _readdir_main() diff --git a/lunaix-os/kernel/demos/input_test.c b/lunaix-os/kernel/demos/input_test.c index 5f2a904..47e0081 100644 --- a/lunaix-os/kernel/demos/input_test.c +++ b/lunaix-os/kernel/demos/input_test.c @@ -1,8 +1,8 @@ #include #include #include +#include #include -#include #include #define STDIN 1 diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c index 643452c..cba8962 100644 --- a/lunaix-os/kernel/demos/iotest.c +++ b/lunaix-os/kernel/demos/iotest.c @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include void diff --git a/lunaix-os/kernel/demos/signal_demo.c b/lunaix-os/kernel/demos/signal_demo.c index 27d7814..3878a18 100644 --- a/lunaix-os/kernel/demos/signal_demo.c +++ b/lunaix-os/kernel/demos/signal_demo.c @@ -1,5 +1,5 @@ +#include #include -#include #include #include #include diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c index 3a1e1bb..acebe21 100644 --- a/lunaix-os/kernel/demos/simple_sh.c +++ b/lunaix-os/kernel/demos/simple_sh.c @@ -1,8 +1,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/lunaix-os/kernel/fs/fs_setup.c b/lunaix-os/kernel/fs/fs_setup.c index 5b3a35d..0966222 100644 --- a/lunaix-os/kernel/fs/fs_setup.c +++ b/lunaix-os/kernel/fs/fs_setup.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -11,6 +12,7 @@ fsm_register_all() twifs_init(); devfs_init(); taskfs_init(); + iso9660_init(); // ... more fs implementation } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/fsm.c b/lunaix-os/kernel/fs/fsm.c index bce983a..a6a2be6 100644 --- a/lunaix-os/kernel/fs/fsm.c +++ b/lunaix-os/kernel/fs/fsm.c @@ -54,6 +54,9 @@ struct filesystem* fsm_new_fs(char* name, size_t name_len) { struct filesystem* fs = vzalloc(sizeof(*fs)); + if (name_len == (size_t)-1) { + name_len = strlen(name); + } fs->fs_name = HHSTR(name, name_len, 0); return fs; } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/directory.c b/lunaix-os/kernel/fs/iso9660/directory.c new file mode 100644 index 0000000..d240e1f --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/directory.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include + +#include + +extern struct cake_pile* drec_cache_pile; + +void +iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec) +{ + *cache = (struct iso_drecache){ .data_size = drec->data_size.le, + .extent_addr = drec->extent_addr.le, + .flags = drec->flags, + .fu_size = drec->fu_sz ? drec->fu_sz : 1, + .gap_size = drec->gap_sz, + .xattr_len = drec->xattr_len }; + u32_t l = drec->name.len; + while (l < (u32_t)-1 && drec->name.content[l--] != ';') + ; + l = (l + 1) ? l : drec->name.len; + l = MIN(l, ISO9660_IDLEN); + strncpy(cache->name_val, drec->name.content, l); + cache->name = HSTR(cache->name_val, l); + hstr_rehash(&cache->name, HSTR_FULL_HASH); +} + +int +iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode) +{ + if (!(inode->itype & VFS_IFDIR)) { + return; + } + + int errno = 0; + struct device* dev = dnode->super_block->dev; + struct iso_inode* isoino = inode->data; + struct llist_header* lead = valloc(sizeof(*lead)); + void* records = valloc(ISO9660_BLKSZ); + u32_t current_pos = -ISO9660_BLKSZ, max_pos = inode->fsize, + blk = inode->lb_addr * ISO9660_BLKSZ, blk_offset = (u32_t)-1; + + llist_init_head(lead); + + // As per 6.8.1, Directory structure shall NOT recorded in interleave mode. + do { + if (blk_offset >= ISO9660_BLKSZ - sizeof(struct iso_drecord)) { + current_pos += ISO9660_BLKSZ; + errno = dev->read(dev, records, blk + current_pos, ISO9660_BLKSZ); + if (errno < 0) { + errno = EIO; + goto done; + } + blk_offset = 0; + } + + struct iso_drecord* drec; + struct iso_var_mdu* mdu = (struct iso_var_mdu*)(records + blk_offset); + + if (!(drec = iso9660_get_drecord(mdu))) { + break; + } + + // ignore the '.', '..' as we have built-in support + if (drec->name.len == 1) { + goto cont; + } + + struct iso_drecache* cache = cake_grab(drec_cache_pile); + + iso9660_fill_drecache(cache, drec); + llist_append(lead, &cache->caches); + cont: + blk_offset += mdu->len; + } while (current_pos + blk_offset < max_pos); + + dnode->data = lead; + isoino->drecaches = lead; + + vfs_assign_inode(dnode, inode); + + errno = 0; + +done: + vfree(records); + return errno; +} + +int +iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode) +{ + struct iso_inode* isoino = this->data; + struct llist_header* lead = isoino->drecaches; + struct iso_drecache *pos, *n; + + llist_for_each(pos, n, lead, caches) + { + if (HSTR_EQ(&dnode->name, &pos->name)) { + goto found; + } + } + + return ENOENT; +found: + struct v_inode* inode = vfs_i_find(dnode->super_block, pos->extent_addr); + + if (!inode) { + inode = vfs_i_alloc(dnode->super_block); + iso9660_fill_inode(inode, pos, pos->extent_addr); + vfs_i_addhash(inode); + } + + iso9660_setup_dnode(dnode, inode); + + return 0; +} + +static int +__get_dtype(struct iso_drecache* pos) +{ + if ((pos->flags & ISO_FDIR)) { + return DT_DIR; + } else { + return DT_FILE; + } +} + +int +iso9660_readdir(struct v_file* file, struct dir_context* dctx) +{ + struct llist_header* lead = file->dnode->data; + struct iso_drecache *pos, *n; + u32_t counter = dctx->index - 1; + + llist_for_each(pos, n, lead, caches) + { + if (counter == (u32_t)-1 && !(pos->flags & ISO_FHIDDEN)) { + dctx->read_complete_callback( + dctx, pos->name_val, pos->name.len, __get_dtype(pos)); + return 1; + } + counter--; + } + return 0; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/file.c b/lunaix-os/kernel/fs/iso9660/file.c new file mode 100644 index 0000000..6813c22 --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/file.c @@ -0,0 +1,37 @@ +#include +#include + +int +iso9660_open(struct v_inode* this, struct v_file* file) +{ + // TODO + return 0; +} + +int +iso9660_close(struct v_file* file) +{ + // TODO + return 0; +} + +int +iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + // TODO + return 0; +} + +int +iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + // TODO + return EROFS; +} + +int +iso9660_seek(struct v_inode* inode, size_t offset) +{ + // TODO + return 0; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/inode.c b/lunaix-os/kernel/fs/iso9660/inode.c new file mode 100644 index 0000000..31f85ce --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/inode.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include + +static struct v_inode_ops iso_inode_ops = { + .dir_lookup = iso9660_dir_lookup, + .open = iso9660_open, +}; + +static struct v_file_ops iso_file_ops = { .close = iso9660_close, + .read = iso9660_read, + .write = iso9660_write, + .seek = iso9660_seek, + .readdir = iso9660_readdir }; + +void +iso9660_init_inode(struct v_superblock* vsb, struct v_inode* inode) +{ + inode->data = vzalloc(sizeof(struct iso_inode)); +} + +int +iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino) +{ + int errno = 0; + struct device* dev = inode->sb->dev; + struct iso_inode* isoino = (struct iso_inode*)inode->data; + + // In the spec, there is a differentiation in how file section organized + // between interleaving and non-interleaving mode. To simplify this, we + // treat the non-interleaving as an interleaving with gap size = 0 and fu + // size = 1 + isoino->fu_size = dir->fu_size; + isoino->gap_size = dir->gap_size; + + u32_t fu_len = isoino->fu_size * ISO9660_BLKSZ; + + inode->id = ino; + inode->lb_addr = dir->extent_addr; + inode->ops = &iso_inode_ops; + inode->default_fops = &iso_file_ops; + + // xattr_len is in unit of FU. Each FU comprise block(s). + inode->fsize = dir->data_size - dir->xattr_len * fu_len; + + if ((dir->flags & ISO_FDIR)) { + inode->itype = VFS_IFDIR; + } else { + inode->itype = VFS_IFFILE; + } + + if (dir->xattr_len) { + struct iso_xattr* xattr = (struct iso_xattr*)valloc(ISO9660_BLKSZ); + // Only bring in single FU, as we only care about the attributes. + errno = + dev->read(dev, xattr, ISO9660_BLKSZ * inode->lb_addr, ISO9660_BLKSZ); + if (errno < 0) { + return EIO; + } + isoino->record_fmt = xattr->record_fmt; + isoino->ctime = iso9660_dt2unix(&xattr->ctime); + isoino->mtime = iso9660_dt2unix(&xattr->mtime); + + inode->lb_addr += dir->xattr_len * dir->fu_size; + + vfree(xattr); + } + + return 0; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/mount.c b/lunaix-os/kernel/fs/iso9660/mount.c new file mode 100644 index 0000000..f6bb2fc --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/mount.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include + +#include + +struct cake_pile* drec_cache_pile; + +extern void +iso9660_init_inode(struct v_superblock* vsb, struct v_inode* inode); + +uint32_t +iso9660_rd_capacity(struct v_superblock* vsb) +{ + struct iso_superblock* isovsb = (struct iso_superblock*)vsb->data; + return isovsb->volume_size; +} + +int +iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point) +{ + struct device* dev = vsb->dev; + struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ); + struct iso_vol_primary* vprim = NULL; + int errno = 0; + do { + errno = dev->read(dev, vdesc, ISO9660_BLKSZ * 16, ISO9660_BLKSZ); + if (errno < 0) { + errno = EIO; + goto done; + } + if (*(u32_t*)vdesc->std_id != ISO_SIGNATURE_LO) { + errno = ENODEV; + goto done; + } + if (vdesc->type == ISO_VOLPRIM) { + vprim = (struct iso_vol_primary*)vdesc; + break; + } + + } while (vdesc->type != ISO_VOLTERM); + + if (!vprim) { + errno = EINVAL; + goto done; + } + + struct iso_superblock* isovsb = valloc(sizeof(*isovsb)); + isovsb->lb_size = vprim->lb_size.le; + isovsb->volume_size = vprim->vol_size.le * isovsb->lb_size; + + vsb->data = isovsb; + vsb->ops.init_inode = iso9660_init_inode; + vsb->ops.read_capacity = iso9660_rd_capacity; + + struct v_inode* rootino = vfs_i_alloc(vsb); + struct iso_drecord* dir = + iso9660_get_drecord((struct iso_var_mdu*)vprim->root_record); + + if (!dir) { + vfree(isovsb); + errno = EINVAL; + goto done; + } + + struct iso_drecache drecache; + iso9660_fill_drecache(&drecache, dir); + + if ((errno = iso9660_fill_inode(rootino, &drecache, 0)) < 0) { + vfree(isovsb); + errno = EINVAL; + goto done; + } + + if ((errno = iso9660_setup_dnode(mount_point, rootino)) < 0) { + vfree(isovsb); + errno = EINVAL; + goto done; + } + + vfs_i_addhash(rootino); + +done: + vfree(vdesc); + return 0; +} + +int +iso9660_unmount(struct v_superblock* vsb) +{ + // TODO clean up +} + +void +iso9660_init() +{ + drec_cache_pile = + cake_new_pile("iso_drec", sizeof(struct iso_drecache), 1, 0); + + struct filesystem* fs = fsm_new_fs("iso9660", -1); + fs->types |= FSTYPE_ROFS; + fs->mount = iso9660_mount; + fs->unmount = iso9660_unmount; + + fsm_register(fs); +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/utils.c b/lunaix-os/kernel/fs/iso9660/utils.c new file mode 100644 index 0000000..748077d --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/utils.c @@ -0,0 +1,24 @@ +#include + +struct iso_drecord* +iso9660_get_drecord(struct iso_var_mdu* drecord_mdu) +{ + if (drecord_mdu->len <= sizeof(struct iso_drecord)) { + return NULL; + } + return (struct iso_drecord*)drecord_mdu->content; +} + +#define FOUR_DIGIT(x) (x[0] + x[1] * 10 + x[2] * 100 + x[3] * 1000) +#define TWO_DIGIT(x) (x[0] + x[1] * 10) + +time_t +iso9660_dt2unix(struct iso_datetime* isodt) +{ + return time_tounix(FOUR_DIGIT(isodt->year), + TWO_DIGIT(isodt->month), + TWO_DIGIT(isodt->day), + TWO_DIGIT(isodt->hour), + TWO_DIGIT(isodt->min), + TWO_DIGIT(isodt->sec)); +} diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index ca80238..7db9513 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -3,8 +3,11 @@ #include #include #include +#include #include +LOG_MODULE("fs") + struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts }; struct v_mount* @@ -129,6 +132,10 @@ vfs_mount_at(const char* fs_name, struct v_dnode* mnt_point, int options) { + if (device && device->dev_type != DEV_IFVOL) { + return ENOTBLK; + } + if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) { return ENOTDIR; } @@ -138,11 +145,20 @@ vfs_mount_at(const char* fs_name, return ENODEV; } + if (fs->types == FSTYPE_ROFS) { + options |= MNT_RO; + } + + char* dev_name = "sys"; struct v_mount* parent_mnt = mnt_point->mnt; struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block; sb->dev = device; mnt_point->super_block = sb; + if (device) { + dev_name = device->name_val; + } + int errno = 0; if (!(errno = fs->mount(sb, mnt_point))) { sb->fs = fs; @@ -153,6 +169,8 @@ vfs_mount_at(const char* fs_name, goto cleanup; } + kprintf("mount: dev=%s, fs=%s, mode=%d\n", dev_name, fs_name, options); + mnt_point->mnt->flags = options; } else { goto cleanup; @@ -161,6 +179,11 @@ vfs_mount_at(const char* fs_name, return errno; cleanup: + kprintf(KERROR "mount: dev=%s, fs=%s, mode=%d, err=%d\n", + dev_name, + fs_name, + options, + errno); mnt_point->super_block = old_sb; vfs_sb_free(sb); return errno; diff --git a/lunaix-os/kernel/fs/ramfs/ramfs.c b/lunaix-os/kernel/fs/ramfs/ramfs.c index a1018da..f33d330 100644 --- a/lunaix-os/kernel/fs/ramfs/ramfs.c +++ b/lunaix-os/kernel/fs/ramfs/ramfs.c @@ -117,7 +117,7 @@ ramfs_unmount(struct v_superblock* vsb) void ramfs_init() { - struct filesystem* ramfs = fsm_new_fs("ramfs", 5); + struct filesystem* ramfs = fsm_new_fs("ramfs", -1); ramfs->mount = ramfs_mount; ramfs->unmount = ramfs_unmount; diff --git a/lunaix-os/kernel/fs/twifs/twifs.c b/lunaix-os/kernel/fs/twifs/twifs.c index 437ab0b..312c0a4 100644 --- a/lunaix-os/kernel/fs/twifs/twifs.c +++ b/lunaix-os/kernel/fs/twifs/twifs.c @@ -61,7 +61,6 @@ __twifs_init_inode(struct v_superblock* vsb, struct v_inode* inode) int __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) { - vsb->dev = 1; vsb->ops.init_inode = __twifs_init_inode; struct v_inode* inode = vfs_i_alloc(vsb); diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 53027c9..6274dd8 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -82,6 +82,8 @@ _kernel_init() vfs_export_attributes(); + lxconsole_init(); + if ((errno = vfs_mount_root("ramfs", NULL))) { panickf("Fail to mount root. (errno=%d)", errno); } @@ -90,7 +92,7 @@ _kernel_init() vfs_mount("/sys", "twifs", NULL, MNT_RO); vfs_mount("/task", "taskfs", NULL, MNT_RO); - lxconsole_init(); + lxconsole_spawn_ttydev(); syscall_install(); diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index a9a256d..91646e9 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -7,21 +9,16 @@ #define MAX_XFMT_SIZE 512 void -__kprintf(const char* component, const char* fmt, va_list args) +__kprintf_internal(const char* component, + int log_level, + const char* fmt, + va_list args) { char buf[MAX_KPRINTF_BUF_SIZE]; - if (!fmt) - return; - char log_level = '0'; char expanded_fmt[MAX_XFMT_SIZE]; - if (*fmt == '\x1b') { - log_level = *(++fmt); - fmt++; - } - switch (log_level) { - case '1': + case 1: // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12); ksnprintf(expanded_fmt, MAX_XFMT_SIZE, @@ -29,7 +26,7 @@ __kprintf(const char* component, const char* fmt, va_list args) component, fmt); break; - case '2': + case 2: // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12); ksnprintf(expanded_fmt, MAX_XFMT_SIZE, @@ -37,7 +34,7 @@ __kprintf(const char* component, const char* fmt, va_list args) component, fmt); break; - case '3': + case 3: // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12); ksnprintf(expanded_fmt, MAX_XFMT_SIZE, @@ -54,6 +51,21 @@ __kprintf(const char* component, const char* fmt, va_list args) console_write_str(buf); } +void +__kprintf(const char* component, const char* fmt, va_list args) +{ + if (!fmt) + return; + char log_level = '0'; + + if (*fmt == '\x1b') { + log_level = *(++fmt); + fmt++; + } + + __kprintf_internal(component, log_level - '0', fmt, args); +} + void kprint_panic(const char* fmt, ...) { @@ -112,4 +124,9 @@ kprint_hex(const void* buffer, unsigned int size) console_write_str(ch_cache); console_write_char('\n'); } +} + +__DEFINE_LXSYSCALL3(void, syslog, int, level, const char*, fmt, va_list, args) +{ + __kprintf_internal("syslog", level, fmt, args); } \ No newline at end of file diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c index 4744cc1..f53405a 100644 --- a/lunaix-os/kernel/lxinit.c +++ b/lunaix-os/kernel/lxinit.c @@ -1,10 +1,10 @@ #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 1e54e59..19f04dc 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,8 +1,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -11,11 +13,11 @@ #include #include #include -#include #include #include #include #include + #include #include @@ -76,6 +78,18 @@ input_test(); extern void sh_main(); +void __USER__ +__setup_dir() +{ + int errno; + mkdir("/mnt"); + mkdir("/mnt/lunaix-os"); + + if ((errno = mount("/dev/sdb", "/mnt/lunaix-os", "iso9660", 0))) { + syslog(2, "fail mounting boot medium. (%d)\n", errno); + } +} + void __USER__ __proc0_usr() { @@ -85,6 +99,8 @@ __proc0_usr() int fdstdout = open("/dev/tty", 0); int fdstdin = dup2(stdout, 1); + __setup_dir(); + pid_t p; if (!(p = fork())) { @@ -154,7 +170,9 @@ extern multiboot_info_t* _k_init_mb_info; /* k_init.c */ void init_platform() { - kprintf(KINFO "\033[11;0mLunaixOS \033[39;49m\n"); + kprintf(KINFO "\033[11;0mLunaixOS (gcc v%s, %s)\033[39;49m\n", + __VERSION__, + __TIME__); // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 lock_reserved_memory(); diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c index 31afa64..d555175 100644 --- a/lunaix-os/kernel/tty/lxconsole.c +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -119,7 +119,11 @@ lxconsole_init() fifo_init(&lx_console.input, valloc(4096), 4096, 0); lx_console.flush_timer = NULL; +} +void +lxconsole_spawn_ttydev() +{ struct device* tty_dev = device_addseq(NULL, &lx_console, "tty"); tty_dev->write = __tty_write; tty_dev->read = __tty_read; -- 2.27.0