From: Minep Date: Sat, 17 Sep 2022 11:30:46 +0000 (+0100) Subject: Merge branch 'device-sys' X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/ea77b9c3fc7fb9bf9d7f9604fc187c8049212a2a?hp=55ed1283281df8f98b48a80c0ca989ba6fda5b7b Merge branch 'device-sys' --- diff --git a/README.md b/README.md index 1a71e57..77920e7 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有 + 内存管理与按需分页(Demand Paging) + 键盘输入 + 多进程 -+ 44个常见的Linux/POSIX系统调用([附录1](#appendix1)) ++ 47个常见的Linux/POSIX系统调用([附录1](#appendix1)) + 用户模式 + 信号机制 + PCI 3.0 @@ -98,10 +98,6 @@ qemu-img create -f vdi machine/disk0.vdi 128M 正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。 -#### 问题#4:键盘的上下方向键(用于滚屏)在VirtualBox下有时不好使 - -可以试试`Shift+<方向键>`,这个问题的解决需要重写键盘驱动的状态机。我会找时间去做,毕竟这不是燃眉之急。 - ## 参考教程 **没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。 @@ -193,6 +189,9 @@ qemu-img create -f vdi machine/disk0.vdi 128M 2. `setxattr(2)`※ 2. `fgetxattr(2)`※ 2. `fsetxattr(2)`※ +2. `ioctl(2)`※ +2. `getpgid(2)` +2. `setpgid(2)` **LunaixOS自有** diff --git a/docs/img/lunaix-os-mem.png b/docs/img/lunaix-os-mem.png index 75c82a4..dd64890 100644 Binary files a/docs/img/lunaix-os-mem.png and b/docs/img/lunaix-os-mem.png differ diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 9a7073a..43b8f1e 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -78,9 +78,8 @@ ahci_init() struct pci_device* ahci_dev = pci_get_device_by_class(AHCI_HBA_CLASS); assert_msg(ahci_dev, "AHCI: Not found."); - uintptr_t bar6, size; - size = pci_bar_sizing(ahci_dev, &bar6, 6); - assert_msg(bar6 && PCI_BAR_MMIO(bar6), "AHCI: BAR#6 is not MMIO."); + struct pci_base_addr* bar6 = &ahci_dev->bar[5]; + assert_msg(bar6->type & BAR_TYPE_MMIO, "AHCI: BAR#6 is not MMIO."); pci_reg_t cmd = pci_read_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD); @@ -94,7 +93,7 @@ ahci_init() memset(&hba, 0, sizeof(hba)); - hba.base = (hba_reg_t*)ioremap(PCI_BAR_ADDR_MM(bar6), size); + hba.base = (hba_reg_t*)ioremap(bar6->start, bar6->size); #ifdef DO_HBA_FULL_RESET // 重置HBA @@ -194,7 +193,7 @@ __ahci_hba_isr(const isr_param* param) { // TODO: clear the interrupt status // TODO: I/O-operation scheduler should be here - kprintf(KDEBUG "HBA INTR\n"); + // kprintf(KDEBUG "HBA INTR\n"); } void diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c index 3d6accf..aa6acd1 100644 --- a/lunaix-os/hal/pci.c +++ b/lunaix-os/hal/pci.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -55,13 +56,14 @@ pci_probe_device(int bus, int dev, int funct) pci_reg_t intr = pci_read_cspace(base, 0x3c); pci_reg_t class = pci_read_cspace(base, 0x8); - struct pci_device* device = valloc(sizeof(struct pci_device)); + struct pci_device* device = vzalloc(sizeof(struct pci_device)); *device = (struct pci_device){ .cspace_base = base, .class_info = class, .device_info = reg1, .intr_info = intr }; pci_probe_msi_info(device); + pci_probe_bar_info(device); llist_append(&pci_devices, &device->dev_chain); } @@ -78,6 +80,24 @@ pci_probe() } } +void +pci_probe_bar_info(struct pci_device* device) +{ + uint32_t bar; + struct pci_base_addr* ba; + for (size_t i = 0; i < 6; i++) { + ba = &device->bar[i]; + ba->size = pci_bar_sizing(device, &bar, i + 1); + if (PCI_BAR_MMIO(bar)) { + ba->start = PCI_BAR_ADDR_MM(bar); + ba->type |= PCI_BAR_CACHEABLE(bar) ? BAR_TYPE_CACHABLE : 0; + ba->type |= BAR_TYPE_MMIO; + } else { + ba->start = PCI_BAR_ADDR_IO(bar); + } + } +} + void pci_probe_msi_info(struct pci_device* device) { @@ -106,47 +126,99 @@ pci_probe_msi_info(struct pci_device* device) } } -#define PCI_PRINT_BAR_LISTING +void +__pci_read_cspace(struct twimap* map) +{ + struct pci_device* pcidev = (struct pci_device*)(map->data); + + for (size_t i = 0; i < 256; i += sizeof(pci_reg_t)) { + *(pci_reg_t*)(map->buffer + i) = + pci_read_cspace(pcidev->cspace_base, i); + } + + map->size_acc = 256; +} + +void +__pci_read_revid(struct twimap* map) +{ + int class = twimap_data(map, struct pci_device*)->class_info; + twimap_printf(map, "0x%x", PCI_DEV_REV(class)); +} void -pci_print_device() +__pci_read_class(struct twimap* map) { + int class = twimap_data(map, struct pci_device*)->class_info; + twimap_printf(map, "0x%x", PCI_DEV_CLASS(class)); +} + +void +__pci_bar_read(struct twimap* map) +{ + struct pci_device* pcidev = twimap_data(map, struct pci_device*); + int bar_index = twimap_index(map, int); + + struct pci_base_addr* bar = &pcidev->bar[bar_index]; + + if (!bar->start && !bar->size) { + twimap_printf(map, "[%d] not present \n", bar_index); + return; + } + + twimap_printf( + map, "[%d] base=%.8p, size=%.8p, ", bar_index, bar->start, bar->size); + + if ((bar->type & BAR_TYPE_MMIO)) { + twimap_printf(map, "mmio"); + if ((bar->type & BAR_TYPE_CACHABLE)) { + twimap_printf(map, ", prefetchable"); + } + } else { + twimap_printf(map, "io"); + } + + twimap_printf(map, "\n"); +} + +int +__pci_bar_gonext(struct twimap* map) +{ + if (twimap_index(map, int) >= 5) { + return 0; + } + map->index += 1; + return 1; +} + +void +pci_build_fsmapping() +{ + struct twifs_node *pci_class = twifs_dir_node(NULL, "pci"), *pci_dev; struct pci_device *pos, *n; + struct twimap* map; llist_for_each(pos, n, &pci_devices, dev_chain) { - kprintf(KINFO "(B%xh:D%xh:F%xh) Dev %x:%x, Class 0x%x\n", - PCI_BUS_NUM(pos->cspace_base), - PCI_SLOT_NUM(pos->cspace_base), - PCI_FUNCT_NUM(pos->cspace_base), - PCI_DEV_VENDOR(pos->device_info), - PCI_DEV_DEVID(pos->device_info), - PCI_DEV_CLASS(pos->class_info)); - - kprintf(KINFO "\t IRQ: %d, INT#x: %d\n", - PCI_INTR_IRQ(pos->intr_info), - PCI_INTR_PIN(pos->intr_info)); -#ifdef PCI_PRINT_BAR_LISTING - uint32_t bar; - for (size_t i = 1; i <= 6; i++) { - size_t size = pci_bar_sizing(pos, &bar, i); - if (!bar) - continue; - if (PCI_BAR_MMIO(bar)) { - kprintf(KINFO "\t BAR#%d (MMIO) %p [%d]\n", - i, - PCI_BAR_ADDR_MM(bar), - size); - } else { - kprintf(KINFO "\t BAR#%d (I/O) %p [%d]\n", - i, - PCI_BAR_ADDR_IO(bar), - size); - } - } -#endif - if (pos->msi_loc) { - kprintf(KINFO "\t MSI supported (@%xh)\n", pos->msi_loc); - } + pci_dev = twifs_dir_node(pci_class, + "%.2d:%.2d:%.2d.%.4x:%.4x", + PCI_BUS_NUM(pos->cspace_base), + PCI_SLOT_NUM(pos->cspace_base), + PCI_FUNCT_NUM(pos->cspace_base), + PCI_DEV_VENDOR(pos->device_info), + PCI_DEV_DEVID(pos->device_info)); + + map = twifs_mapping(pci_dev, pos, "config"); + map->read = __pci_read_cspace; + + map = twifs_mapping(pci_dev, pos, "revision"); + map->read = __pci_read_revid; + + map = twifs_mapping(pci_dev, pos, "class"); + map->read = __pci_read_class; + + map = twifs_mapping(pci_dev, pos, "io_bases"); + map->read = __pci_bar_read; + map->go_next = __pci_bar_gonext; } } @@ -241,4 +313,6 @@ pci_init() } // Otherwise, fallback to use legacy PCI 3.0 method. pci_probe(); + + pci_build_fsmapping(); } \ No newline at end of file diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index 57c04ca..95d5fb8 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -56,6 +56,16 @@ typedef unsigned int pci_reg_t; // PCI device header format // Ref: "PCI Local Bus Specification, Rev.3, Section 6.1" +#define BAR_TYPE_MMIO 0x1 +#define BAR_TYPE_CACHABLE 0x2 + +struct pci_base_addr +{ + uint32_t start; + uint32_t size; + uint32_t type; +}; + struct pci_device { struct llist_header dev_chain; @@ -64,6 +74,7 @@ struct pci_device uint32_t cspace_base; uint32_t msi_loc; uint16_t intr_info; + struct pci_base_addr bar[6]; }; // PCI Configuration Space (C-Space) r/w: @@ -91,9 +102,6 @@ pci_write_cspace(uint32_t base, int offset, pci_reg_t data) void pci_init(); -void -pci_print_device(); - /** * @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备 * 类型代码请参阅: PCI LB Spec. Appendix D. diff --git a/lunaix-os/includes/klibc/stdio.h b/lunaix-os/includes/klibc/stdio.h index d97f028..9af99e9 100644 --- a/lunaix-os/includes/klibc/stdio.h +++ b/lunaix-os/includes/klibc/stdio.h @@ -4,10 +4,10 @@ #include size_t -__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs); +__ksprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs); size_t -sprintf(char* buffer, char* fmt, ...); +ksprintf(char* buffer, char* fmt, ...); size_t -snprintf(char* buffer, size_t n, char* fmt, ...); +ksnprintf(char* buffer, size_t n, char* fmt, ...); #endif /* __LUNAIX_STDIO_H */ diff --git a/lunaix-os/includes/klibc/string.h b/lunaix-os/includes/klibc/string.h index fcb0df5..dc4e6e1 100644 --- a/lunaix-os/includes/klibc/string.h +++ b/lunaix-os/includes/klibc/string.h @@ -36,7 +36,7 @@ streq(const char* a, const char* b); void strrtrim(char* str); -void* +char* strltrim_safe(char* str); #endif /* __LUNAIX_STRING_H */ diff --git a/lunaix-os/includes/lunaix/block.h b/lunaix-os/includes/lunaix/block.h index 40935f9..df481d8 100644 --- a/lunaix-os/includes/lunaix/block.h +++ b/lunaix-os/includes/lunaix/block.h @@ -44,4 +44,10 @@ block_init(); int block_mount_disk(struct hba_device* hd_dev); +void +blk_mapping_init(); + +void +blk_set_blkmapping(struct block_dev* bdev); + #endif /* __LUNAIX_BLOCK_H */ diff --git a/lunaix-os/includes/lunaix/common.h b/lunaix-os/includes/lunaix/common.h index 4c8c794..f5a24a7 100644 --- a/lunaix-os/includes/lunaix/common.h +++ b/lunaix-os/includes/lunaix/common.h @@ -1,24 +1,20 @@ #ifndef __LUNAIX_CONSTANTS_H #define __LUNAIX_CONSTANTS_H -#define KSTACK_SIZE (64 << 10) +#define MEM_1MB 0x100000 +#define MEM_4MB 0x400000 + +#define KSTACK_SIZE MEM_1MB #define KSTACK_START ((0x3FFFFFU - KSTACK_SIZE) + 1) #define KSTACK_TOP 0x3FFFF0U #define KERNEL_MM_BASE 0xC0000000 -#define MEM_1MB 0x100000 -#define MEM_4MB 0x400000 #define KCODE_MAX_SIZE MEM_4MB -#define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE) -#define KHEAP_SIZE_MB 256 - -#define PROC_TABLE_SIZE_MB 4 -#define PROC_START (KHEAP_START + (KHEAP_SIZE_MB * MEM_1MB)) +// #define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE) +// #define KHEAP_SIZE_MB 256 -#define VGA_BUFFER_VADDR (PROC_START + (PROC_TABLE_SIZE_MB * MEM_1MB)) -#define VGA_BUFFER_PADDR 0xB8000 -#define VGA_BUFFER_SIZE 4096 +#define VGA_FRAMEBUFFER 0xB8000 #define KCODE_SEG 0x08 #define KDATA_SEG 0x10 diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index 414809a..c456df4 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -5,24 +5,40 @@ #include #include +#include + +#define DEV_STRUCT_MAGIC 0x5645444c + +#define DEV_MSKIF 0x00000003 + +#define DEV_IFVOL 0x0 // volumetric (block) device +#define DEV_IFSEQ 0x1 // sequential (character) device +#define DEV_IFCAT 0x2 // a device category (as device groupping) typedef unsigned int dev_t; struct device { - struct llist_header dev_list; + uint32_t magic; + struct llist_header siblings; + struct llist_header children; struct device* parent; struct hstr name; dev_t dev_id; + int dev_type; char name_val[DEVICE_NAME_SIZE]; void* underlay; - void* fs_node; int (*read)(struct device* dev, void* buf, size_t offset, size_t len); int (*write)(struct device* dev, void* buf, size_t offset, size_t len); + int (*exec_cmd)(struct device* dev, uint32_t req, va_list args); }; -void -device_init(); +struct device* +device_add(struct device* parent, + void* underlay, + char* name_fmt, + uint32_t type, + va_list args); struct device* device_addseq(struct device* parent, void* underlay, char* name_fmt, ...); @@ -30,7 +46,22 @@ device_addseq(struct device* parent, void* underlay, char* name_fmt, ...); struct device* device_addvol(struct device* parent, void* underlay, char* name_fmt, ...); +struct device* +device_addcat(struct device* parent, char* name_fmt, ...); + void device_remove(struct device* dev); +struct device* +device_getbyid(struct llist_header* devlist, dev_t id); + +struct device* +device_getbyhname(struct device* root_dev, struct hstr* name); + +struct device* +device_getbyname(struct device* root_dev, const char* name, size_t len); + +struct device* +device_getbyoffset(struct device* root_dev, int pos); + #endif /* __LUNAIX_DEVICE_H */ diff --git a/lunaix-os/includes/lunaix/dirent.h b/lunaix-os/includes/lunaix/dirent.h index faa56a6..160365d 100644 --- a/lunaix-os/includes/lunaix/dirent.h +++ b/lunaix-os/includes/lunaix/dirent.h @@ -3,6 +3,11 @@ #define DIRENT_NAME_MAX_LEN 256 +#define DT_FILE 0x0 +#define DT_DIR 0x1 +#define DT_SYMLINK 0x2 +#define DT_PIPE 0x2 + struct dirent { unsigned int d_type; diff --git a/lunaix-os/includes/lunaix/ds/fifo.h b/lunaix-os/includes/lunaix/ds/fifo.h index 3a21824..b6c0dec 100644 --- a/lunaix-os/includes/lunaix/ds/fifo.h +++ b/lunaix-os/includes/lunaix/ds/fifo.h @@ -23,6 +23,15 @@ fifo_backone(struct fifo_buf* fbuf); size_t fifo_putone(struct fifo_buf* fbuf, uint8_t data); +size_t +fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data); + +void +fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr); + +void +fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr); + void fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags); @@ -32,4 +41,7 @@ fifo_write(struct fifo_buf* fbuf, void* data, size_t count); size_t fifo_read(struct fifo_buf* fbuf, void* buf, size_t count); +void +fifo_clear(struct fifo_buf* fbuf); + #endif /* __LUNAIX_FIFO_BUF_H */ diff --git a/lunaix-os/includes/lunaix/ds/llist.h b/lunaix-os/includes/lunaix/ds/llist.h index 22e0f93..a4797c3 100644 --- a/lunaix-os/includes/lunaix/ds/llist.h +++ b/lunaix-os/includes/lunaix/ds/llist.h @@ -67,6 +67,12 @@ llist_empty(struct llist_header* elem) return elem->next == elem && elem->prev == elem; } +#define DEFINE_LLIST(name) \ + struct llist_header name = (struct llist_header) \ + { \ + .prev = &name, .next = &name \ + } + /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. diff --git a/lunaix-os/includes/lunaix/ds/mutex.h b/lunaix-os/includes/lunaix/ds/mutex.h index 5e166e5..97101ef 100644 --- a/lunaix-os/includes/lunaix/ds/mutex.h +++ b/lunaix-os/includes/lunaix/ds/mutex.h @@ -2,25 +2,33 @@ #define __LUNAIX_MUTEX_H #include "semaphore.h" - -// TODO: implement mutex lock - -typedef struct sem_t mutex_t; - -static inline void mutex_init(mutex_t *mutex) { - sem_init(mutex, 1); +#include + +typedef struct mutex_s +{ + struct sem_t sem; + pid_t owner; +} mutex_t; + +static inline void +mutex_init(mutex_t* mutex) +{ + sem_init(&mutex->sem, 1); } -static inline unsigned int mutex_on_hold(mutex_t *mutex) { - return !atomic_load(&mutex->counter); +static inline int +mutex_on_hold(mutex_t* mutex) +{ + return !atomic_load(&mutex->sem.counter); } -static inline void mutex_lock(mutex_t *mutex) { - sem_wait(mutex); -} +void +mutex_lock(mutex_t* mutex); -static inline void mutex_unlock(mutex_t *mutex) { - sem_post(mutex); -} +void +mutex_unlock(mutex_t* mutex); + +void +mutex_unlock_for(mutex_t* mutex, pid_t pid); #endif /* __LUNAIX_MUTEX_H */ diff --git a/lunaix-os/includes/lunaix/ds/rwlock.h b/lunaix-os/includes/lunaix/ds/rwlock.h new file mode 100644 index 0000000..7dda9ad --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/rwlock.h @@ -0,0 +1,28 @@ +#ifndef __LUNAIX_RWLOCK_H +#define __LUNAIX_RWLOCK_H + +#include "mutex.h" +#include "waitq.h" +#include + +typedef struct rwlock_s +{ + atomic_uint readers; + atomic_flag writer; + waitq_t waiting_readers; + waitq_t waiting_writers; +} rwlock_t; + +void +rwlock_begin_read(rwlock_t* rwlock); + +void +rwlock_end_read(rwlock_t* rwlock); + +void +rwlock_begin_write(rwlock_t* rwlock); + +void +rwlock_end_write(rwlock_t* rwlock); + +#endif /* __LUNAIX_RWLOCK_H */ diff --git a/lunaix-os/includes/lunaix/ds/waitq.h b/lunaix-os/includes/lunaix/ds/waitq.h new file mode 100644 index 0000000..4014d05 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/waitq.h @@ -0,0 +1,32 @@ +#ifndef __LUNAIX_CODVAR_H +#define __LUNAIX_CODVAR_H + +#include + +typedef struct waitq +{ + struct llist_header waiters; +} waitq_t; + +static inline void +waitq_init(waitq_t* waitq) +{ + llist_init_head(&waitq->waiters); +} + +static inline int +waitq_empty(waitq_t* waitq) +{ + return llist_empty(&waitq->waiters); +} + +void +pwait(waitq_t* queue); + +void +pwake_one(waitq_t* queue); + +void +pwake_all(waitq_t* queue); + +#endif /* __LUNAIX_CODVAR_H */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 099d47e..539f0a8 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -44,7 +44,7 @@ #define VFS_VALID_CHAR(chr) \ (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') || \ ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' || \ - (chr) == '-') + (chr) == '-' || (chr) == ':') #define unlock_inode(inode) mutex_unlock(&inode->lock) #define lock_inode(inode) \ @@ -172,6 +172,18 @@ struct v_fd int flags; }; +// FIXME how do we invalidate corresponding v_dnodes given the v_inode? +/* + Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow + info of every process being accessible via file system. Each process's + creation will result a creation of a directory under the root of task fs + with it's pid as name. But that dir must delete when process is killed, and + such deletion does not mediated by vfs itself, so there is a need of cache + syncing. + And this is also the case of all ramfs where argumentation to file tree is + performed by third party. +*/ + struct v_inode { inode_t id; @@ -185,12 +197,13 @@ struct v_inode uint32_t link_count; uint32_t lb_usage; uint32_t fsize; + void* data; // 允许底层FS绑定他的一些专有数据 + struct llist_header aka_dnodes; struct llist_header xattrs; struct v_superblock* sb; struct hlist_node hash_list; struct lru_node lru; struct pcache* pg_cache; - void* data; // 允许底层FS绑定他的一些专有数据 struct v_inode_ops* ops; struct v_file_ops* default_fops; }; @@ -216,6 +229,7 @@ struct v_dnode struct v_inode* inode; struct v_dnode* parent; struct hlist_node hash_list; + struct llist_header aka_list; struct llist_header children; struct llist_header siblings; struct v_superblock* super_block; @@ -250,7 +264,7 @@ struct pcache_pg uint32_t flags; uint32_t fpos; }; -/* --- file system manager --- */ + void fsm_init(); @@ -269,6 +283,9 @@ fsm_get(const char* fs_name); void vfs_init(); +void +vfs_export_attributes(); + struct v_dnode* vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str); @@ -318,6 +335,9 @@ vfs_mkdir(const char* path, struct v_dnode** dentry); int vfs_open(struct v_dnode* dnode, struct v_file** file); +int +vfs_pclose(struct v_file* file, pid_t pid); + int vfs_close(struct v_file* file); @@ -357,6 +377,18 @@ vfs_dup_fd(struct v_fd* old, struct v_fd** new); int vfs_getfd(int fd, struct v_fd** fd_s); +int +vfs_get_dtype(int itype); + +void +vfs_ref_dnode(struct v_dnode* dnode); + +void +vfs_unref_dnode(struct v_dnode* dnode); + +int +vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth); + void pcache_init(struct pcache* pcache); @@ -369,7 +401,7 @@ pcache_new_page(struct pcache* pcache, uint32_t index); void pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg); -struct pcache_pg* +int pcache_get_page(struct pcache* pcache, uint32_t index, uint32_t* offset, diff --git a/lunaix-os/includes/lunaix/fs/devfs.h b/lunaix-os/includes/lunaix/fs/devfs.h new file mode 100644 index 0000000..324706c --- /dev/null +++ b/lunaix-os/includes/lunaix/fs/devfs.h @@ -0,0 +1,7 @@ +#ifndef __LUNAIX_DEVFS_H +#define __LUNAIX_DEVFS_H + +void +devfs_init(); + +#endif /* __LUNAIX_DEVFS_H */ diff --git a/lunaix-os/includes/lunaix/fs/taskfs.h b/lunaix-os/includes/lunaix/fs/taskfs.h new file mode 100644 index 0000000..0d50be3 --- /dev/null +++ b/lunaix-os/includes/lunaix/fs/taskfs.h @@ -0,0 +1,28 @@ +#ifndef __LUNAIX_TASKFS_H +#define __LUNAIX_TASKFS_H + +#include +#include + +struct task_attribute +{ + struct llist_header siblings; + struct hlist_node attrs; + struct hstr key; + struct twimap* map_file; + char key_val[32]; +}; + +void +taskfs_init(); + +void +taskfs_export_attr(const char* key, struct twimap* attr_map_file); + +struct task_attribute* +taskfs_get_attr(struct hstr* key); + +void +taskfs_invalidate(pid_t pid); + +#endif /* __LUNAIX_TASKFS_H */ diff --git a/lunaix-os/includes/lunaix/fs/twifs.h b/lunaix-os/includes/lunaix/fs/twifs.h index f4614d8..a8117ef 100644 --- a/lunaix-os/includes/lunaix/fs/twifs.h +++ b/lunaix-os/includes/lunaix/fs/twifs.h @@ -2,6 +2,8 @@ #define __LUNAIX_TWIFS_H #include +#include +#include struct twifs_node { @@ -9,6 +11,7 @@ struct twifs_node inode_t ino_id; void* data; uint32_t itype; + char name_val[VFS_NAME_MAXLEN]; struct llist_header children; struct llist_header siblings; struct @@ -24,25 +27,29 @@ struct twifs_node } ops; }; +#define twinode_getdata(inode, type) \ + ({ \ + struct twifs_node* twinode = (struct twifs_node*)(inode)->data; \ + assert(twinode); \ + (type) twinode->data; \ + }) + void twifs_init(); struct twifs_node* -twifs_file_node(struct twifs_node* parent, - const char* name, - int name_len, - uint32_t itype); +twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args); struct twifs_node* -twifs_dir_node(struct twifs_node* parent, - const char* name, - int name_len, - uint32_t itype); +twifs_file_node(struct twifs_node* parent, const char* fmt, ...); struct twifs_node* -twifs_toplevel_node(const char* name, int name_len, uint32_t itype); +twifs_dir_node(struct twifs_node* parent, const char* fmt, ...); int twifs_rm_node(struct twifs_node* node); +struct twimap* +twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...); + #endif /* __LUNAIX_TWIFS_H */ diff --git a/lunaix-os/includes/lunaix/fs/twimap.h b/lunaix-os/includes/lunaix/fs/twimap.h new file mode 100644 index 0000000..7adbc53 --- /dev/null +++ b/lunaix-os/includes/lunaix/fs/twimap.h @@ -0,0 +1,37 @@ +#ifndef __LUNAIX_TWIMAP_H +#define __LUNAIX_TWIMAP_H + +#include + +#define twimap_index(twimap, type) ((type)((twimap)->index)) +#define twimap_data(twimap, type) ((type)((twimap)->data)) + +extern struct v_file_ops twimap_file_ops; + +struct twimap +{ + void* index; + void* buffer; + void* data; + size_t size_acc; + void (*read)(struct twimap* mapping); + int (*go_next)(struct twimap* mapping); + void (*reset)(struct twimap* mapping); +}; + +int +twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos); + +void +twimap_printf(struct twimap* mapping, const char* fmt, ...); + +int +twimap_memcpy(struct twimap* mapping, const void* src, const size_t len); + +int +twimap_memappend(struct twimap* mapping, const void* src, const size_t len); + +struct twimap* +twimap_create(void* data); + +#endif /* __LUNAIX_TWIMAP_H */ diff --git a/lunaix-os/includes/lunaix/input.h b/lunaix-os/includes/lunaix/input.h new file mode 100644 index 0000000..872ea04 --- /dev/null +++ b/lunaix-os/includes/lunaix/input.h @@ -0,0 +1,57 @@ +#ifndef __LUNAIX_INPUT_H +#define __LUNAIX_INPUT_H + +#include +#include +#include +#include +#include + +// event should propagate further +#define INPUT_EVT_NEXT 0 +// event should be captured here +#define INPUT_EVT_CATCH 1 + +// key pressed (key-type device) +#define PKT_PRESS 0x1 +// key released (key-type device) +#define PKT_RELEASE 0x2 +// vector (e.g. mice wheel scroll, mice maneuver) +#define PKT_VECTOR 0x3 + +struct input_evt_pkt +{ + uint32_t pkt_type; // packet type + uint32_t scan_code; // hardware raw code + uint32_t sys_code; // driver translated code + time_t timestamp; // event timestamp +}; + +struct input_device +{ + struct device* dev_if; // device interface + struct input_evt_pkt current_pkt; // recieved event packet + waitq_t readers; // reader wait queue +}; + +typedef int (*input_evt_cb)(struct input_device* dev); + +struct input_evt_chain +{ + struct llist_header chain; + input_evt_cb evt_cb; +}; + +void +input_init(); + +void +input_fire_event(struct input_device* idev, struct input_evt_pkt* pkt); + +void +input_add_listener(input_evt_cb listener); + +struct input_device* +input_add_device(char* name_fmt, ...); + +#endif /* __LUNAIX_INPUT_H */ diff --git a/lunaix-os/includes/lunaix/ioctl.h b/lunaix-os/includes/lunaix/ioctl.h new file mode 100644 index 0000000..e074bba --- /dev/null +++ b/lunaix-os/includes/lunaix/ioctl.h @@ -0,0 +1,19 @@ +#ifndef __LUNAIX_IOCTL_H +#define __LUNAIX_IOCTL_H + +#include + +#define IOREQ(cmd, arg_num) ((((cmd)&0xffff) << 8) | ((arg_num)&0xff)) + +#define IOCMD(req) ((req) >> 8) + +#define IOARGNUM(req) ((req)&0xff) + +#define TIOCGPGRP IOREQ(1, 0) +#define TIOCSPGRP IOREQ(1, 1) +#define TIOCCLSBUF IOREQ(2, 0) +#define TIOCFLUSH IOREQ(3, 0) + +__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req); + +#endif /* __LUNAIX_IOCTL_H */ diff --git a/lunaix-os/includes/lunaix/keyboard.h b/lunaix-os/includes/lunaix/keyboard.h index 2dd40dd..aa4d658 100644 --- a/lunaix-os/includes/lunaix/keyboard.h +++ b/lunaix-os/includes/lunaix/keyboard.h @@ -17,33 +17,33 @@ typedef unsigned short kbd_keycode_t; typedef unsigned short kbd_kstate_t; -#define KEYPAD 0x0100 -#define FN_KEY 0x0200 -#define CURSOR 0x0300 -#define MODIFR 0x0400 -#define OTHERS 0xff00 +#define KEYPAD 0x0100 +#define FN_KEY 0x0200 +#define CURSOR 0x0300 +#define MODIFR 0x0400 +#define OTHERS 0xff00 -#define ON_KEYPAD(x) ((x & 0xff) | KEYPAD) +#define ON_KEYPAD(x) ((x & 0xff) | KEYPAD) // backspace key -#define KEY_BS (0x08) +#define KEY_BS (0x08) // enter/return key -#define KEY_LF (0x0a) +#define KEY_LF (0x0a) #define KEY_HTAB (0x9) #define KEY_SPACE (0x20) #define KEY_ESC (0x1b) -#define KEY_F1 (0x00 | FN_KEY) -#define KEY_F2 (0x01 | FN_KEY) -#define KEY_F3 (0x02 | FN_KEY) -#define KEY_F4 (0x03 | FN_KEY) -#define KEY_F5 (0x04 | FN_KEY) -#define KEY_F6 (0x05 | FN_KEY) -#define KEY_F7 (0x06 | FN_KEY) -#define KEY_F8 (0x07 | FN_KEY) -#define KEY_F9 (0x08 | FN_KEY) +#define KEY_F1 (0x00 | FN_KEY) +#define KEY_F2 (0x01 | FN_KEY) +#define KEY_F3 (0x02 | FN_KEY) +#define KEY_F4 (0x03 | FN_KEY) +#define KEY_F5 (0x04 | FN_KEY) +#define KEY_F6 (0x05 | FN_KEY) +#define KEY_F7 (0x06 | FN_KEY) +#define KEY_F8 (0x07 | FN_KEY) +#define KEY_F9 (0x08 | FN_KEY) #define KEY_F10 (0x09 | FN_KEY) #define KEY_F11 (0x0a | FN_KEY) #define KEY_F12 (0x0b | FN_KEY) @@ -51,25 +51,25 @@ typedef unsigned short kbd_kstate_t; #define KEY_NUMSLK (0x0d | FN_KEY) #define KEY_SCRLLK (0x0e | FN_KEY) -#define KEY_PG_UP (0x0 | OTHERS) -#define KEY_PG_DOWN (0x1 | OTHERS) -#define KEY_INSERT (0x2 | OTHERS) -#define KEY_DELETE (0x3 | OTHERS) -#define KEY_HOME (0x4 | OTHERS) -#define KEY_END (0x5 | OTHERS) -#define KEY_PAUSE (0x6 | OTHERS) - -#define KEY_LEFT (0x0 | CURSOR) -#define KEY_RIGHT (0x1 | CURSOR) -#define KEY_UP (0x2 | CURSOR) -#define KEY_DOWN (0x3 | CURSOR) - -#define KEY_LSHIFT (0x0 | MODIFR) -#define KEY_RSHIFT (0x1 | MODIFR) -#define KEY_LCTRL (0x2 | MODIFR) -#define KEY_RCTRL (0x3 | MODIFR) -#define KEY_LALT (0x4 | MODIFR) -#define KEY_RALT (0x5 | MODIFR) +#define KEY_PG_UP (0x0 | OTHERS) +#define KEY_PG_DOWN (0x1 | OTHERS) +#define KEY_INSERT (0x2 | OTHERS) +#define KEY_DELETE (0x3 | OTHERS) +#define KEY_HOME (0x4 | OTHERS) +#define KEY_END (0x5 | OTHERS) +#define KEY_PAUSE (0x6 | OTHERS) + +#define KEY_LEFT (0x0 | CURSOR) +#define KEY_RIGHT (0x1 | CURSOR) +#define KEY_UP (0x2 | CURSOR) +#define KEY_DOWN (0x3 | CURSOR) + +#define KEY_LSHIFT (0x0 | MODIFR) +#define KEY_RSHIFT (0x1 | MODIFR) +#define KEY_LCTRL (0x2 | MODIFR) +#define KEY_RCTRL (0x3 | MODIFR) +#define KEY_LALT (0x4 | MODIFR) +#define KEY_RALT (0x5 | MODIFR) #define KBD_KEY_FRELEASED 0x0 #define KBD_KEY_FPRESSED 0x1 @@ -84,15 +84,4 @@ typedef unsigned short kbd_kstate_t; #define KBD_KEY_FLALT_HELD 0x100 #define KBD_KEY_FRALT_HELD 0x200 -typedef unsigned char kbd_scancode_t; - -struct kdb_keyinfo_pkt { - kbd_scancode_t scancode; - kbd_keycode_t keycode; - kbd_kstate_t state; - time_t timestamp; -}; - -int kbd_recv_key(struct kdb_keyinfo_pkt* key_event); - #endif /* __LUNAIX_KEYBOARD_H */ diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h index d964428..9f2ef9e 100644 --- a/lunaix-os/includes/lunaix/lunistd.h +++ b/lunaix-os/includes/lunaix/lunistd.h @@ -15,6 +15,10 @@ __LXSYSCALL(pid_t, getpid) __LXSYSCALL(pid_t, getppid) +__LXSYSCALL(pid_t, getpgid) + +__LXSYSCALL2(pid_t, setpgid, pid_t, pid, pid_t, pgid) + __LXSYSCALL1(void, _exit, int, status) __LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h index 02e2198..fbf59a4 100644 --- a/lunaix-os/includes/lunaix/lxconsole.h +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -1,6 +1,13 @@ #ifndef __LUNAIX_LXCONSOLE_H #define __LUNAIX_LXCONSOLE_H +#define TCINTR 0x03 // ETX +#define TCEOF 0x04 // EOT +#define TCBS 0x08 // BS +#define TCLF 0x0A // LF +#define TCCR 0x0D // CR +#define TCSTOP 0x1A // SUB + void lxconsole_init(); diff --git a/lunaix-os/includes/lunaix/mm/cake.h b/lunaix-os/includes/lunaix/mm/cake.h index 0312c45..81321f8 100644 --- a/lunaix-os/includes/lunaix/mm/cake.h +++ b/lunaix-os/includes/lunaix/mm/cake.h @@ -7,6 +7,10 @@ #define PILE_CACHELINE 1 +struct cake_pile; + +typedef void (*pile_cb)(struct cake_pile*, void*); + struct cake_pile { struct llist_header piles; @@ -20,6 +24,8 @@ struct cake_pile unsigned int pieces_per_cake; unsigned int pg_per_cake; char pile_name[PILE_NAME_MAXLEN]; + + pile_cb ctor; }; typedef unsigned int piece_index_t; @@ -49,6 +55,9 @@ cake_new_pile(char* name, unsigned int pg_per_cake, int options); +void +cake_set_constructor(struct cake_pile* pile, pile_cb ctor); + /** * @brief 拿一块儿蛋糕 * @@ -70,11 +79,12 @@ cake_release(struct cake_pile* pile, void* area); void cake_init(); -/** - * @brief 统计蛋糕数量 - 问问Pinkie :D - * - */ void -cake_stats(); +cake_export(); + +/********** some handy constructor ***********/ + +void +cake_ctor_zeroing(struct cake_pile* pile, void* piece); #endif /* __LUNAIX_VALLOC_H */ diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index 8883a6b..9458277 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -99,7 +99,7 @@ extern void __pg_mount_point; /* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */ #define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703) -#define PD_MOUNT_1 (VGA_BUFFER_VADDR + MEM_4MB) +#define PD_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB) #define PG_MOUNT_BASE (PD_MOUNT_1 + MEM_4MB) #define PG_MOUNT_1 (PG_MOUNT_BASE) #define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000) diff --git a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h index 08a0d56..3ebaa98 100644 --- a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h +++ b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h @@ -44,7 +44,6 @@ #define PS2_DELAY 1000 #define PS2_CMD_QUEUE_SIZE 8 -#define PS2_KBD_RECV_BUFFER_SIZE 8 #define PS2_NO_ARG 0xff00 @@ -70,14 +69,6 @@ struct ps2_cmd_queue mutex_t mutex; }; -struct ps2_key_buffer -{ - struct kdb_keyinfo_pkt buffer[PS2_KBD_RECV_BUFFER_SIZE]; - int read_ptr; - int buffered_len; - mutex_t mutex; -}; - /** * @brief 向PS/2控制器的控制端口(0x64)发送指令并等待返回代码。 * 注意,对于没有返回代码的命令请使用`ps2_post_cmd`,否则会造成死锁。 diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 18cddb9..c7b925e 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -13,7 +14,7 @@ // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。 #define KERNEL_PID -1 -#define PS_STOPPED 0 +#define PS_READY 0 #define PS_RUNNING 1 #define PS_TERMNAT 2 #define PS_DESTROY 4 @@ -57,9 +58,11 @@ struct proc_info /* ---- critical section end ---- */ + struct llist_header tasks; struct llist_header siblings; struct llist_header children; struct llist_header grp_member; + waitq_t waitqueue; struct { diff --git a/lunaix-os/includes/lunaix/sched.h b/lunaix-os/includes/lunaix/sched.h index 021b55e..f31eab5 100644 --- a/lunaix-os/includes/lunaix/sched.h +++ b/lunaix-os/includes/lunaix/sched.h @@ -3,9 +3,12 @@ #define SCHED_TIME_SLICE 300 +#define PROC_TABLE_SIZE 8192 +#define MAX_PROCESS (PROC_TABLE_SIZE / sizeof(uintptr_t)) + struct scheduler { - struct proc_info* _procs; + struct proc_info** _procs; int procs_index; unsigned int ptable_len; }; diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index 0e381b4..cc105b4 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -17,7 +17,7 @@ #define EEXIST -12 #define EBADF -13 #define ENOTSUP -14 -#define ENXIO -15 +#define EIO -15 #define ELOOP -16 #define ENOTEMPTY -17 #define EROFS -18 diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 98f5585..8a523ad 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -54,6 +54,10 @@ #define __SYSCALL_fgetxattr 46 #define __SYSCALL_fsetxattr 47 +#define __SYSCALL_ioctl 48 +#define __SYSCALL_getpgid 49 +#define __SYSCALL_setpgid 50 + #define __SYSCALL_MAX 0x100 #ifndef __ASM__ @@ -130,5 +134,13 @@ syscall_install(); asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4)); \ ___DOINT33(__SYSCALL_##name, rettype) \ } + +#define __LXSYSCALL2_VARG(rettype, name, t1, p1, t2, p2) \ + static rettype name(__PARAM_MAP2(t1, p1, t2, p2), ...) \ + { \ + void* _last = (void*)&p2 + sizeof(void*); \ + asm("\n" ::"b"(p1), "c"(p2), "d"(_last)); \ + ___DOINT33(__SYSCALL_##name, rettype) \ + } #endif #endif /* __LUNAIX_SYSCALL_H */ diff --git a/lunaix-os/includes/lunaix/tty/console.h b/lunaix-os/includes/lunaix/tty/console.h index e5eaa34..24d088f 100644 --- a/lunaix-os/includes/lunaix/tty/console.h +++ b/lunaix-os/includes/lunaix/tty/console.h @@ -9,8 +9,8 @@ struct console struct lx_timer* flush_timer; struct fifo_buf output; struct fifo_buf input; - unsigned int erd_pos; - unsigned int lines; + size_t wnd_start; + size_t lines; }; #endif /* __LUNAIX_CONSOLE_H */ diff --git a/lunaix-os/includes/lunaix/tty/tty.h b/lunaix-os/includes/lunaix/tty/tty.h index 518d376..96fe485 100644 --- a/lunaix-os/includes/lunaix/tty/tty.h +++ b/lunaix-os/includes/lunaix/tty/tty.h @@ -1,5 +1,8 @@ #ifndef __LUNAIX_TTY_H #define __LUNAIX_TTY_H + +#include + typedef unsigned short vga_attribute; #define VGA_COLOR_BLACK 0 @@ -31,8 +34,8 @@ tty_set_theme(vga_attribute fg, vga_attribute bg); vga_attribute tty_get_theme(); -size_t -tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size); +void +tty_flush_buffer(struct fifo_buf* buf); void tty_clear_line(int line_num); diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index 3069a83..fbe7e1e 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -1,6 +1,7 @@ #ifndef __LUNAIX_TYPES_H #define __LUNAIX_TYPES_H +#include #include #include diff --git a/lunaix-os/includes/ulibc/stdio.h b/lunaix-os/includes/ulibc/stdio.h new file mode 100644 index 0000000..e9496a8 --- /dev/null +++ b/lunaix-os/includes/ulibc/stdio.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_USTDIO_H +#define __LUNAIX_USTDIO_H + +#define stdout 0 +#define stdin 1 + +void +printf(const char* fmt, ...); + +#endif /* __LUNAIX_USTDIO_H */ diff --git a/lunaix-os/kernel/asm/x86/intr_routines.c b/lunaix-os/kernel/asm/x86/intr_routines.c index 813490c..402ceea 100644 --- a/lunaix-os/kernel/asm/x86/intr_routines.c +++ b/lunaix-os/kernel/asm/x86/intr_routines.c @@ -79,7 +79,7 @@ intr_routine_apic_error(const isr_param* param) { uint32_t error_reg = apic_read_reg(APIC_ESR); char buf[32]; - sprintf(buf, "APIC error, ESR=0x%x", error_reg); + ksprintf(buf, "APIC error, ESR=0x%x", error_reg); console_flush(); __print_panic_msg(buf, param); spin(); diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c index 6df3182..fcd52cc 100644 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@ -108,14 +108,8 @@ int do_kernel(v_mapping* mapping) { uintptr_t addr = mapping->va; - if (addr >= KHEAP_START && addr < PROC_START) { - // This is kernel heap page - uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0); - *mapping->pte = (*mapping->pte & 0xfff) | pa | PG_PRESENT; - cpu_invplg(mapping->pte); - cpu_invplg(addr); - goto done; - } + + // TODO return 0; done: diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index b8d0219..34b4330 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -55,6 +55,9 @@ .long __lxsys_setxattr /* 45 */ .long __lxsys_fgetxattr .long __lxsys_fsetxattr + .long __lxsys_ioctl + .long __lxsys_getpgid + .long __lxsys_setpgid /* 50 */ 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/block/blk_mapping.c b/lunaix-os/kernel/block/blk_mapping.c new file mode 100644 index 0000000..f6d1346 --- /dev/null +++ b/lunaix-os/kernel/block/blk_mapping.c @@ -0,0 +1,111 @@ +#include +#include + +static struct twifs_node* blk_root; + +void +blk_mapping_init() +{ + blk_root = twifs_dir_node(NULL, "block"); +} + +void +__blk_rd_size(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + size_t secsize = bdev->hd_dev->block_size; + twimap_printf(map, "%u", (bdev->end_lba - bdev->base_lba) * secsize); +} + +void +__blk_rd_secsize(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + size_t secsize = bdev->hd_dev->block_size; + twimap_printf(map, "%u", secsize); +} + +void +__blk_rd_range(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf( + map, "%u,%u", (uint32_t)bdev->base_lba, (uint32_t)bdev->end_lba); +} + +void +__blk_rd_model(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf(map, "%s", bdev->hd_dev->model); +} + +void +__blk_rd_serial(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf(map, "%s", bdev->hd_dev->serial_num); +} + +void +__blk_rd_status(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf(map, "%p", bdev->hd_dev->last_result.status); +} + +void +__blk_rd_error(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf(map, "%p", bdev->hd_dev->last_result.error); +} + +void +__blk_rd_sense_key(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + twimap_printf(map, "%p", bdev->hd_dev->last_result.sense_key); +} + +void +__blk_rd_wwid(struct twimap* map) +{ + struct block_dev* bdev = twimap_data(map, struct block_dev*); + uint32_t h = bdev->hd_dev->wwn >> 32; + uint32_t l = (uint32_t)bdev->hd_dev->wwn; + twimap_printf(map, "%x%x", h, l); +} + +void +blk_set_blkmapping(struct block_dev* bdev) +{ + struct twifs_node* dev_root = twifs_dir_node(blk_root, bdev->bdev_id); + + struct twimap* map = twifs_mapping(dev_root, bdev, "size"); + map->read = __blk_rd_size; + + map = twifs_mapping(dev_root, bdev, "secsize"); + map->read = __blk_rd_secsize; + + map = twifs_mapping(dev_root, bdev, "range"); + map->read = __blk_rd_range; + + map = twifs_mapping(dev_root, bdev, "model"); + map->read = __blk_rd_model; + + map = twifs_mapping(dev_root, bdev, "serial"); + map->read = __blk_rd_serial; + + map = twifs_mapping(dev_root, bdev, "status"); + map->read = __blk_rd_status; + + map = twifs_mapping(dev_root, bdev, "error"); + map->read = __blk_rd_error; + + map = twifs_mapping(dev_root, bdev, "sense-key"); + map->read = __blk_rd_sense_key; + + map = twifs_mapping(dev_root, bdev, "wwid"); + map->read = __blk_rd_wwid; +} \ No newline at end of file diff --git a/lunaix-os/kernel/block.c b/lunaix-os/kernel/block/block.c similarity index 89% rename from lunaix-os/kernel/block.c rename to lunaix-os/kernel/block/block.c index b855910..936ce2a 100644 --- a/lunaix-os/kernel/block.c +++ b/lunaix-os/kernel/block/block.c @@ -36,6 +36,8 @@ block_init() 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; + + blk_mapping_init(); } int @@ -44,13 +46,14 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len) int errno; struct block_dev* bdev = (struct block_dev*)dev->underlay; size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size, - rd_block = offset / bsize, r = offset % bsize; + rd_block = offset / bsize, r = offset % bsize, + max_blk = (size_t)bdev->hd_dev->max_lba; void* block = vzalloc(bsize); - while (acc_size < len) { + while (acc_size < len && rd_block < max_blk) { if (!bdev->hd_dev->ops.read_buffer( bdev->hd_dev, rd_block, block, bsize)) { - errno = ENXIO; + errno = EIO; goto error; } rd_size = MIN(len - acc_size, bsize - r); @@ -61,7 +64,7 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len) } vfree(block); - return rd_block; + return acc_size; error: vfree(block); @@ -82,7 +85,7 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len) memcpy(block + r, buf + acc_size, wr_size); if (!bdev->hd_dev->ops.write_buffer( bdev->hd_dev, wr_block, block, bsize)) { - errno = ENXIO; + errno = EIO; break; } acc_size += wr_size; @@ -112,6 +115,7 @@ block_mount_disk(struct hba_device* hd_dev) goto error; } + blk_set_blkmapping(bdev); return errno; error: @@ -119,6 +123,7 @@ error: hd_dev->model, hd_dev->serial_num, -errno); + return errno; } int @@ -133,6 +138,7 @@ __block_register(struct block_dev* bdev) dev->read = __block_read; bdev->dev = dev; + strcpy(bdev->bdev_id, dev->name_val); dev_registry[free_slot++] = bdev; return 1; } \ No newline at end of file diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c index 0d62a79..54ffd97 100644 --- a/lunaix-os/kernel/demos/dir_read.c +++ b/lunaix-os/kernel/demos/dir_read.c @@ -2,32 +2,29 @@ #include #include #include -#include - -LOG_MODULE("RDDIR") void _readdir_main() { int fd = open("/dev/./../dev/.", 0); if (fd == -1) { - kprintf(KERROR "fail to open (%d)\n", geterrno()); + printf("fail to open (%d)\n", geterrno()); return; } char path[129]; int len = realpathat(fd, path, 128); if (len < 0) { - kprintf(KERROR "fail to read (%d)\n", geterrno()); + printf("fail to read (%d)\n", geterrno()); } else { path[len] = 0; - kprintf("%s\n", path); + printf("%s\n", path); } struct dirent ent = { .d_offset = 0 }; while (readdir(fd, &ent) == 1) { - kprintf(KINFO "%s\n", ent.d_name); + printf("%s\n", ent.d_name); } close(fd); diff --git a/lunaix-os/kernel/demos/input_test.c b/lunaix-os/kernel/demos/input_test.c new file mode 100644 index 0000000..5f2a904 --- /dev/null +++ b/lunaix-os/kernel/demos/input_test.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +#define STDIN 1 +#define STDOUT 0 + +void +input_test() +{ + int fd = open("/dev/input/i8042-kbd", 0); + + if (fd < 0) { + printf("fail to open (%d)", geterrno()); + return; + } + + struct input_evt_pkt event; + + while (read(fd, &event, sizeof(event)) > 0) { + char* action; + if (event.pkt_type == PKT_PRESS) { + action = "pressed"; + } else { + action = "release"; + } + + printf("%u: %s '%c', class=0x%x, scan=%x\n", + event.timestamp, + action, + event.sys_code & 0xff, + (event.sys_code & 0xff00) >> 8, + event.scan_code); + } + return; +} \ No newline at end of file diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c index 0ebe696..643452c 100644 --- a/lunaix-os/kernel/demos/iotest.c +++ b/lunaix-os/kernel/demos/iotest.c @@ -2,12 +2,7 @@ #include #include #include -#include - -LOG_MODULE("IOTEST") - -#define STDIN 1 -#define STDOUT 0 +#include void _iotest_main() @@ -20,14 +15,12 @@ _iotest_main() // 切换工作目录至 /dev int errno = chdir("/dev"); if (errno) { - write(STDOUT, "fail to chdir", 15); + write(stdout, "fail to chdir", 15); return; } if (getcwd(read_out, sizeof(read_out))) { - write(STDOUT, "current working dir: ", 22); - write(STDOUT, read_out, 256); - write(STDOUT, "\n", 2); + printf("current working dir: %s\n", read_out); } // sda 设备 - 硬盘 @@ -36,7 +29,7 @@ _iotest_main() int fd = open("./sda", 0); if (fd < 0) { - kprintf(KERROR "fail to open (%d)\n", geterrno()); + printf("fail to open (%d)\n", geterrno()); return; } @@ -52,24 +45,21 @@ _iotest_main() lseek(fd, 4 * 4096, FSEEK_SET); write(fd, test_sequence, sizeof(test_sequence)); - write(STDOUT, "input: ", 8); - int size = read(STDIN, read_out, 256); + printf("input: "); + int size = read(stdin, read_out, 256); + + printf("your said: %s\n", read_out); - write(STDOUT, "your input: ", 13); - write(STDOUT, read_out, size); write(fd, read_out, size); - write(STDOUT, "\n", 1); // 读出我们写的内容 lseek(fd, 512, FSEEK_SET); read(fd, read_out, sizeof(read_out)); // 将读出的内容直接写入tty设备 - write(STDOUT, read_out, sizeof(read_out)); - write(STDOUT, "\n", 1); + write(stdout, read_out, sizeof(read_out)); + write(stdout, "\n", 1); // 关闭文件,这同时会将页缓存中的数据下发到底层驱动 close(fd); - - kprint_hex(read_out, sizeof(read_out)); } \ No newline at end of file diff --git a/lunaix-os/kernel/demos/signal_demo.c b/lunaix-os/kernel/demos/signal_demo.c index 616a38e..27d7814 100644 --- a/lunaix-os/kernel/demos/signal_demo.c +++ b/lunaix-os/kernel/demos/signal_demo.c @@ -2,22 +2,20 @@ #include #include #include -#include #include - -LOG_MODULE("SIGDEMO") +#include void __USER__ sigchild_handler(int signum) { - kprintf(KINFO "SIGCHLD received\n"); + printf("SIGCHLD received\n"); } void __USER__ sigsegv_handler(int signum) { pid_t pid = getpid(); - kprintf(KWARN "SIGSEGV received on process %d\n", pid); + printf("SIGSEGV received on process %d\n", pid); _exit(signum); } @@ -25,7 +23,7 @@ void __USER__ sigalrm_handler(int signum) { pid_t pid = getpid(); - kprintf(KWARN "I, pid %d, have received an alarm!\n", pid); + printf("I, pid %d, have received an alarm!\n", pid); } void __USER__ @@ -40,7 +38,7 @@ _signal_demo_main() int status; pid_t p = 0; - kprintf(KINFO "Child sleep 3s, parent pause.\n"); + printf("Child sleep 3s, parent pause.\n"); if (!fork()) { sleep(3); _exit(0); @@ -48,7 +46,7 @@ _signal_demo_main() pause(); - kprintf("Parent resumed on SIGCHILD\n"); + printf("Parent resumed on SIGCHILD\n"); for (int i = 0; i < 5; i++) { pid_t pid = 0; @@ -58,26 +56,22 @@ _signal_demo_main() if (i == 3) { i = *(int*)0xdeadc0de; // seg fault! } - kprintf(KINFO "%d\n", i); + printf("%d\n", i); _exit(0); } - kprintf(KINFO "Forked %d\n", pid); + printf("Forked %d\n", pid); } while ((p = wait(&status)) >= 0) { short code = WEXITSTATUS(status); if (WIFSIGNALED(status)) { - kprintf(KINFO "Process %d terminated by signal, exit_code: %d\n", - p, - code); + printf("Process %d terminated by signal, exit_code: %d\n", p, code); } else if (WIFEXITED(status)) { - kprintf(KINFO "Process %d exited with code %d\n", p, code); + printf("Process %d exited with code %d\n", p, code); } else { - kprintf(KWARN "Process %d aborted with code %d\n", p, code); + printf("Process %d aborted with code %d\n", p, code); } } - kprintf("done\n"); - - _exit(0); + printf("done\n"); } \ No newline at end of file diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c new file mode 100644 index 0000000..3a1e1bb --- /dev/null +++ b/lunaix-os/kernel/demos/simple_sh.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +char pwd[512]; +char cat_buf[1024]; + +/* + Simple shell - (actually this is not even a shell) + It just to make the testing more easy. +*/ + +void +parse_cmdline(char* line, char** cmd, char** arg_part) +{ + strrtrim(line); + line = strltrim_safe(line); + int l = 0; + char c = 0; + while ((c = line[l])) { + if (c == ' ') { + line[l++] = 0; + break; + } + l++; + } + *cmd = line; + *arg_part = strltrim_safe(line + l); +} + +void +sh_printerr() +{ + int errno = geterrno(); + switch (errno) { + case ENOTDIR: + printf("Error: Not a directory\n"); + break; + case ENOENT: + printf("Error: No such file or directory\n"); + break; + case EINVAL: + printf("Error: Invalid parameter or operation\n"); + break; + case ENOTSUP: + printf("Error: Not supported\n"); + break; + case EROFS: + printf("Error: File system is read only\n"); + break; + case ENOMEM: + printf("Error: Out of memory\n"); + break; + case EISDIR: + printf("Error: This is a directory\n"); + break; + default: + printf("Error: (%d)\n", errno); + break; + } +} + +void +sigint_handle(int signum) +{ + return; +} + +void +do_cat(const char* file) +{ + int fd = open(file, 0); + if (fd < 0) { + sh_printerr(); + } else { + int sz; + while ((sz = read(fd, cat_buf, 1024)) > 0) { + write(stdout, cat_buf, sz); + } + if (sz < 0) { + sh_printerr(); + } + close(fd); + printf("\n"); + } +} + +void +do_ls(const char* path) +{ + int fd = open(path, 0); + if (fd < 0) { + sh_printerr(); + } else { + struct dirent ent = { .d_offset = 0 }; + int status; + while ((status = readdir(fd, &ent)) == 1) { + if (ent.d_type == DT_DIR) { + printf(" \033[3m%s\033[39;49m\n", ent.d_name); + } else { + printf(" %s\n", ent.d_name); + } + } + + if (status < 0) + sh_printerr(); + + close(fd); + } +} + +void +sh_loop() +{ + char buf[512]; + char *cmd, *argpart; + pid_t p; + signal(_SIGINT, sigint_handle); + + // set our shell as foreground process + // (unistd.h:tcsetpgrp is essentially a wrapper of this) + // stdout (by default, unless user did smth) is the tty we are currently at + ioctl(stdout, TIOCSPGRP, getpgid()); + + while (1) { + getcwd(pwd, 512); + printf("[\033[2m%s\033[39;49m]$ ", pwd); + size_t sz = read(stdin, buf, 511); + if (sz < 0) { + printf("fail to read user input (%d)\n", geterrno()); + return; + } + buf[sz] = '\0'; + parse_cmdline(buf, &cmd, &argpart); + if (cmd[0] == 0) { + printf("\n"); + goto cont; + } + if (streq(cmd, "cd")) { + if (chdir(argpart) < 0) { + sh_printerr(); + } + goto cont; + } else if (streq(cmd, "clear")) { + ioctl(stdout, TIOCCLSBUF); + goto cont; + } else if (streq(cmd, "ls")) { + if (!(p = fork())) { + do_ls(argpart); + _exit(0); + } + } else if (streq(cmd, "cat")) { + if (!(p = fork())) { + do_cat(argpart); + _exit(0); + } + } else { + printf("unknow command\n"); + goto cont; + } + setpgid(p, getpgid()); + waitpid(p, NULL, 0); + cont: + printf("\n"); + } +} + +void +sh_main() +{ + printf("\n Simple shell. Use or to scroll.\n\n"); + if (!fork()) { + sh_loop(); + _exit(0); + } + wait(NULL); +} \ No newline at end of file diff --git a/lunaix-os/kernel/device.c b/lunaix-os/kernel/device.c deleted file mode 100644 index 017f3b3..0000000 --- a/lunaix-os/kernel/device.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include - -struct llist_header dev_list; - -static struct twifs_node* dev_root; - -int -__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos); - -int -__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos); - -void -device_init() -{ - dev_root = twifs_toplevel_node("dev", 3, 0); - - llist_init_head(&dev_list); -} - -struct device* -__device_add(struct device* parent, - void* underlay, - char* name_fmt, - uint32_t type, - va_list args) -{ - struct device* dev = vzalloc(sizeof(struct device)); - - size_t strlen = - __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args); - - dev->name = HSTR(dev->name_val, strlen); - dev->parent = parent; - dev->underlay = underlay; - - hstr_rehash(&dev->name, HSTR_FULL_HASH); - llist_append(&dev_list, &dev->dev_list); - - struct twifs_node* dev_node = - twifs_file_node(dev_root, dev->name_val, strlen, type); - dev_node->data = dev; - dev_node->ops.read = __dev_read; - dev_node->ops.write = __dev_write; - - dev->fs_node = dev_node; - - return dev; -} - -struct device* -device_addseq(struct device* parent, void* underlay, char* name_fmt, ...) -{ - va_list args; - va_start(args, name_fmt); - - struct device* dev = - __device_add(parent, underlay, name_fmt, VFS_IFSEQDEV, args); - - va_end(args); - return dev; -} - -struct device* -device_addvol(struct device* parent, void* underlay, char* name_fmt, ...) -{ - va_list args; - va_start(args, name_fmt); - - struct device* dev = - __device_add(parent, underlay, name_fmt, VFS_IFVOLDEV, args); - - va_end(args); - return dev; -} - -int -__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos) -{ - struct twifs_node* dev_node = (struct twifs_node*)inode->data; - struct device* dev = (struct device*)dev_node->data; - - if (!dev->read) { - return ENOTSUP; - } - return dev->read(dev, buffer, fpos, len); -} - -int -__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos) -{ - struct twifs_node* dev_node = (struct twifs_node*)inode->data; - struct device* dev = (struct device*)dev_node->data; - - if (!dev->write) { - return ENOTSUP; - } - return dev->write(dev, buffer, fpos, len); -} - -void -device_remove(struct device* dev) -{ - llist_delete(&dev->dev_list); - twifs_rm_node((struct twifs_node*)dev->fs_node); - vfree(dev); -} \ No newline at end of file diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c new file mode 100644 index 0000000..012f919 --- /dev/null +++ b/lunaix-os/kernel/device/devfs.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include + +extern struct v_inode_ops devfs_inode_ops; +extern struct v_file_ops devfs_file_ops; + +int +devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + assert(inode->data); + + struct device* dev = (struct device*)inode->data; + + if (!dev->read) { + return ENOTSUP; + } + + return dev->read(dev, buffer, fpos, len); +} + +int +devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + assert(inode->data); + + struct device* dev = (struct device*)inode->data; + + if (!dev->write) { + return ENOTSUP; + } + + return dev->write(dev, buffer, fpos, len); +} + +int +devfs_get_itype(struct device* dev) +{ + int itype = VFS_IFFILE; + int dev_if = dev->dev_type & DEV_MSKIF; + if (dev_if == DEV_IFCAT) { + itype = VFS_IFDIR; + } else if (dev_if == DEV_IFVOL) { + itype |= VFS_IFVOLDEV; + } else { + itype |= VFS_IFSEQDEV; + } + return itype; +} + +int +devfs_get_dtype(struct device* dev) +{ + switch (dev->dev_type & DEV_MSKIF) { + case DEV_IFCAT: + return DT_DIR; + + default: + return DT_FILE; + } +} + +int +devfs_mknod(struct v_dnode* dnode, struct device* dev) +{ + assert(dev); + + struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id); + if (!devnod) { + if ((devnod = vfs_i_alloc(dnode->super_block))) { + devnod->id = dev->dev_id; + devnod->data = dev; + devnod->itype = devfs_get_itype(dev); + + vfs_i_addhash(devnod); + } else { + return ENOMEM; + } + } + + vfs_assign_inode(dnode, devnod); + return 0; +} + +int +devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) +{ + struct device* dev = + device_getbyhname((struct device*)this->data, &dnode->name); + if (!dev) { + return ENOENT; + } + return devfs_mknod(dnode, dev); +} + +int +devfs_readdir(struct v_file* file, struct dir_context* dctx) +{ + struct device* dev = + device_getbyoffset((struct device*)(file->inode->data), dctx->index); + if (!dev) { + return 0; + } + dctx->read_complete_callback( + dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev)); + return 1; +} + +void +devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) +{ + inode->ops = &devfs_inode_ops; + inode->default_fops = &devfs_file_ops; +} + +int +devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) +{ + vsb->ops.init_inode = devfs_init_inode; + + struct v_inode* rootnod = vfs_i_alloc(vsb); + + if (!rootnod) { + return ENOMEM; + } + + rootnod->id = -1; + rootnod->itype = VFS_IFDIR; + + vfs_i_addhash(rootnod); + vfs_assign_inode(mount_point, rootnod); + + return 0; +} + +int +devfs_unmount(struct v_superblock* vsb) +{ + return 0; +} + +void +devfs_init() +{ + struct filesystem* fs = fsm_new_fs("devfs", 5); + fsm_register(fs); + fs->mount = devfs_mount; + fs->unmount = devfs_unmount; +} + +struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup, + .open = default_inode_open, + .mkdir = default_inode_mkdir, + .rmdir = default_inode_rmdir }; + +struct v_file_ops devfs_file_ops = { .close = default_file_close, + .read = devfs_read, + .write = devfs_write, + .seek = default_file_seek, + .readdir = devfs_readdir }; \ No newline at end of file diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c new file mode 100644 index 0000000..6b901a6 --- /dev/null +++ b/lunaix-os/kernel/device/device.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_LLIST(root_list); + +static volatile dev_t devid = 0; + +struct device* +device_add(struct device* parent, + void* underlay, + char* name_fmt, + uint32_t type, + va_list args) +{ + struct device* dev = vzalloc(sizeof(struct device)); + + if (parent) { + assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); + llist_append(&parent->children, &dev->siblings); + } else { + llist_append(&root_list, &dev->siblings); + } + + size_t strlen = + __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args); + + dev->magic = DEV_STRUCT_MAGIC; + dev->dev_id = devid++; + dev->name = HSTR(dev->name_val, strlen); + dev->parent = parent; + dev->underlay = underlay; + dev->dev_type = type; + + hstr_rehash(&dev->name, HSTR_FULL_HASH); + llist_init_head(&dev->children); + + return dev; +} + +struct device* +device_addseq(struct device* parent, void* underlay, char* name_fmt, ...) +{ + va_list args; + va_start(args, name_fmt); + + struct device* dev = + device_add(parent, underlay, name_fmt, DEV_IFSEQ, args); + + va_end(args); + return dev; +} + +struct device* +device_addvol(struct device* parent, void* underlay, char* name_fmt, ...) +{ + va_list args; + va_start(args, name_fmt); + + struct device* dev = + device_add(parent, underlay, name_fmt, DEV_IFVOL, args); + + va_end(args); + return dev; +} + +struct device* +device_addcat(struct device* parent, char* name_fmt, ...) +{ + va_list args; + va_start(args, name_fmt); + + struct device* dev = device_add(parent, NULL, name_fmt, DEV_IFCAT, args); + + va_end(args); + return dev; +} + +struct device* +device_getbyid(struct llist_header* devlist, dev_t id) +{ + devlist = devlist ? devlist : &root_list; + struct device *pos, *n; + llist_for_each(pos, n, devlist, siblings) + { + if (pos->dev_id == id) { + return pos; + } + } + + return NULL; +} + +struct device* +device_getbyhname(struct device* root_dev, struct hstr* name) +{ + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; + struct device *pos, *n; + llist_for_each(pos, n, devlist, siblings) + { + if (HSTR_EQ(&pos->name, name)) { + return pos; + } + } + + return NULL; +} + +struct device* +device_getbyname(struct device* root_dev, const char* name, size_t len) +{ + struct hstr hname = HSTR(name, len); + hstr_rehash(&hname, HSTR_FULL_HASH); + + return device_getbyhname(root_dev, &hname); +} + +void +device_remove(struct device* dev) +{ + llist_delete(&dev->siblings); + vfree(dev); +} + +struct device* +device_getbyoffset(struct device* root_dev, int offset) +{ + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; + struct device *pos, *n; + int off = 0; + llist_for_each(pos, n, devlist, siblings) + { + if (off++ >= offset) { + return pos; + } + } + return NULL; +} + +__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) +{ + int errno; + struct v_fd* fd_s; + if ((errno = vfs_getfd(fd, &fd_s))) { + goto done; + } + + struct device* dev = (struct device*)fd_s->file->inode->data; + if (dev->magic != DEV_STRUCT_MAGIC) { + errno = ENODEV; + goto done; + } + + if (!dev->exec_cmd) { + errno = EINVAL; + goto done; + } + + errno = dev->exec_cmd(dev, req, args); + +done: + return DO_STATUS_OR_RETURN(errno); +} \ No newline at end of file diff --git a/lunaix-os/kernel/device/input.c b/lunaix-os/kernel/device/input.c new file mode 100644 index 0000000..5ddf6a4 --- /dev/null +++ b/lunaix-os/kernel/device/input.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +#include + +static DEFINE_LLIST(listener_chain); + +static struct device* input_devcat = NULL; + +void +input_init() +{ + input_devcat = device_addcat(NULL, "input"); +} + +void +input_fire_event(struct input_device* idev, struct input_evt_pkt* pkt) +{ + pkt->timestamp = clock_systime(); + idev->current_pkt = *pkt; + + struct input_evt_chain *pos, *n; + llist_for_each(pos, n, &listener_chain, chain) + { + if (pos->evt_cb(idev) == INPUT_EVT_CATCH) { + break; + } + } + + // wake up all pending readers + pwake_all(&idev->readers); +} + +void +input_add_listener(input_evt_cb listener) +{ + assert(listener); + + struct input_evt_chain* chain = vzalloc(sizeof(*chain)); + llist_append(&listener_chain, &chain->chain); + + chain->evt_cb = listener; +} + +int +__input_dev_read(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct input_device* idev = dev->underlay; + + if (len < sizeof(struct input_evt_pkt)) { + return ERANGE; + } + + // wait for new event + pwait(&idev->readers); + + memcpy(buf, &idev->current_pkt, sizeof(struct input_evt_pkt)); + + return sizeof(struct input_evt_pkt); +} + +struct input_device* +input_add_device(char* name_fmt, ...) +{ + assert(input_devcat); + + struct input_device* idev = vzalloc(sizeof(*idev)); + waitq_init(&idev->readers); + + va_list args; + va_start(args, name_fmt); + + struct device* dev = + device_add(input_devcat, idev, name_fmt, DEV_IFSEQ, args); + + idev->dev_if = dev; + dev->read = __input_dev_read; + + va_end(args); + + return idev; +} diff --git a/lunaix-os/kernel/ds/fifo.c b/lunaix-os/kernel/ds/fifo.c index 1e72e8d..252cd2d 100644 --- a/lunaix-os/kernel/ds/fifo.c +++ b/lunaix-os/kernel/ds/fifo.c @@ -15,6 +15,16 @@ fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags) mutex_init(&buf->lock); } +void +fifo_clear(struct fifo_buf* fbuf) +{ + mutex_lock(&fbuf->lock); + fbuf->rd_pos = 0; + fbuf->wr_pos = 0; + fbuf->free_len = fbuf->size; + mutex_unlock(&fbuf->lock); +} + int fifo_backone(struct fifo_buf* fbuf) { @@ -53,6 +63,43 @@ fifo_putone(struct fifo_buf* fbuf, uint8_t data) return 1; } +size_t +fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data) +{ + if (fbuf->free_len == fbuf->size) { + return 0; + } + + uint8_t* dest = fbuf->data; + *data = dest[fbuf->rd_pos]; + fbuf->rd_pos = (fbuf->rd_pos + 1) % fbuf->size; + fbuf->free_len++; + + return 1; +} + +void +fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr) +{ + fbuf->rd_pos = rdptr; + if (rdptr <= fbuf->wr_pos) { + fbuf->free_len = fbuf->size - fbuf->wr_pos + rdptr; + } else { + fbuf->free_len = rdptr - fbuf->wr_pos; + } +} + +void +fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr) +{ + fbuf->wr_pos = wrptr; + if (wrptr <= fbuf->rd_pos) { + fbuf->free_len = fbuf->size - fbuf->rd_pos + wrptr; + } else { + fbuf->free_len = wrptr - fbuf->rd_pos; + } +} + size_t fifo_write(struct fifo_buf* fbuf, void* data, size_t count) { diff --git a/lunaix-os/kernel/ds/mutex.c b/lunaix-os/kernel/ds/mutex.c new file mode 100644 index 0000000..7bfbf10 --- /dev/null +++ b/lunaix-os/kernel/ds/mutex.c @@ -0,0 +1,24 @@ +#include +#include + +void +mutex_lock(mutex_t* mutex) +{ + sem_wait(&mutex->sem); + mutex->owner = __current->pid; +} + +void +mutex_unlock(mutex_t* mutex) +{ + mutex_unlock_for(mutex, __current->pid); +} + +void +mutex_unlock_for(mutex_t* mutex, pid_t pid) +{ + if (mutex->owner != pid) { + return; + } + sem_post(&mutex->sem); +} \ No newline at end of file diff --git a/lunaix-os/kernel/ds/rwlock.c b/lunaix-os/kernel/ds/rwlock.c new file mode 100644 index 0000000..383e4c4 --- /dev/null +++ b/lunaix-os/kernel/ds/rwlock.c @@ -0,0 +1,58 @@ +#include +#include + +void +rwlock_init(rwlock_t* rwlock) +{ + waitq_init(&rwlock->waiting_readers); + waitq_init(&rwlock->waiting_writers); + atomic_init(&rwlock->readers, 0); + atomic_flag_clear(&rwlock->writer); +} + +void +rwlock_begin_read(rwlock_t* rwlock) +{ + while (atomic_flag_test_and_set(&rwlock->writer)) { + pwait(&rwlock->waiting_readers); + } + atomic_fetch_add(&rwlock->readers, 1); + atomic_flag_clear(&rwlock->writer); + pwake_all(&rwlock->waiting_readers); +} + +void +rwlock_end_read(rwlock_t* rwlock) +{ + assert(atomic_load(&rwlock->readers) > 0); + atomic_fetch_sub(&rwlock->readers, 1); + + if (!atomic_load(&rwlock->readers)) { + pwake_one(&rwlock->waiting_writers); + } +} + +void +rwlock_begin_write(rwlock_t* rwlock) +{ + // first, acquire writer lock, prevent any incoming readers + while (atomic_flag_test_and_set(&rwlock->writer)) { + pwait(&rwlock->waiting_writers); + } + + // then, wait for reader finish the read. + while (atomic_load(&rwlock->readers)) { + pwait(&rwlock->waiting_writers); + } +} + +void +rwlock_end_write(rwlock_t* rwlock) +{ + atomic_flag_clear(&rwlock->writer); + if (waitq_empty(&rwlock->waiting_writers)) { + pwake_all(&rwlock->waiting_readers); + } else { + pwake_one(&rwlock->waiting_writers); + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/ds/waitq.c b/lunaix-os/kernel/ds/waitq.c new file mode 100644 index 0000000..5241a4e --- /dev/null +++ b/lunaix-os/kernel/ds/waitq.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +void +pwait(waitq_t* queue) +{ + waitq_t* current_wq = &__current->waitqueue; + assert(llist_empty(¤t_wq->waiters)); + + llist_append(&queue->waiters, ¤t_wq->waiters); + + // FIXME centralize the state change. + __current->state = PS_BLOCKED; + sched_yieldk(); +} + +void +pwake_one(waitq_t* queue) +{ + if (llist_empty(&queue->waiters)) { + return; + } + + waitq_t* wq = list_entry(queue->waiters.next, waitq_t, waiters); + struct proc_info* proc = container_of(wq, struct proc_info, waitqueue); + + assert(proc->state == PS_BLOCKED); + proc->state = PS_READY; + llist_delete(&wq->waiters); +} + +void +pwake_all(waitq_t* queue) +{ + if (llist_empty(&queue->waiters)) { + return; + } + + struct proc_info* proc; + waitq_t *pos, *n; + llist_for_each(pos, n, &queue->waiters, waiters) + { + proc = container_of(pos, struct proc_info, waitqueue); + + proc->state = PS_READY; + llist_delete(&pos->waiters); + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/fs_export.c b/lunaix-os/kernel/fs/fs_export.c new file mode 100644 index 0000000..13d6557 --- /dev/null +++ b/lunaix-os/kernel/fs/fs_export.c @@ -0,0 +1,47 @@ +#include +#include +#include + +extern struct llist_header all_mnts; + +void +__mount_read(struct twimap* map) +{ + char path[512]; + struct v_mount* mnt = twimap_index(map, struct v_mount*); + size_t len = vfs_get_path(mnt->mnt_point, path, 511, 0); + path[len] = '\0'; + twimap_printf(map, "%s at %s", mnt->super_block->fs->fs_name.value, path); + if ((mnt->flags & MNT_RO)) { + twimap_printf(map, ", ro"); + } else { + twimap_printf(map, ", rw"); + } + twimap_printf(map, "\n"); +} + +int +__mount_next(struct twimap* map) +{ + struct v_mount* mnt = twimap_index(map, struct v_mount*); + if (mnt->list.next == &all_mnts) { + return 0; + } + map->index = container_of(mnt->list.next, struct v_mount, list); + return 1; +} + +void +__mount_reset(struct twimap* map) +{ + map->index = container_of(all_mnts.next, struct v_mount, list); +} + +void +vfs_export_attributes() +{ + struct twimap* map = twifs_mapping(NULL, NULL, "mounts"); + map->read = __mount_read; + map->go_next = __mount_next; + map->reset = __mount_reset; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/fs_setup.c b/lunaix-os/kernel/fs/fs_setup.c index 74fdef7..5b3a35d 100644 --- a/lunaix-os/kernel/fs/fs_setup.c +++ b/lunaix-os/kernel/fs/fs_setup.c @@ -1,5 +1,7 @@ #include +#include #include +#include #include void @@ -7,5 +9,8 @@ fsm_register_all() { ramfs_init(); twifs_init(); - // Add more fs implementation + devfs_init(); + taskfs_init(); + + // ... more fs implementation } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index 7b83757..ff8d46b 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -4,7 +4,7 @@ #include #include -static struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts }; +struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts }; struct v_mount* vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point) @@ -145,12 +145,12 @@ vfs_mount_at(const char* fs_name, } struct v_mount* parent_mnt = mnt_point->mnt; - struct v_superblock* sb = vfs_sb_alloc(); + struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block; sb->dev = device; + mnt_point->super_block = sb; int errno = 0; if (!(errno = fs->mount(sb, mnt_point))) { - mnt_point->super_block = sb; sb->fs = fs; sb->root = mnt_point; @@ -167,6 +167,7 @@ vfs_mount_at(const char* fs_name, return errno; cleanup: + mnt_point->super_block = old_sb; vfs_sb_free(sb); return errno; } @@ -233,7 +234,7 @@ __DEFINE_LXSYSCALL4(int, // By our convention. // XXX could we do better? - struct device* device = (struct device*)dev->data; + struct device* device = (struct device*)dev->inode->data; if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) { errno = ENOTDEV; diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index ea5b1c5..c80d713 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -33,7 +33,10 @@ __vfs_walk(struct v_dnode* start, panick("vfs: no root"); } } - i++; + + if (path[0] == VFS_PATH_DELIM) { + i++; + } } assert(start); @@ -71,9 +74,7 @@ __vfs_walk(struct v_dnode* start, if (!lookahead && (walk_options & VFS_WALK_PARENT)) { if (component) { - component->hash = name.hash; - component->len = j; - strcpy(component->value, fname_buffer); + hstrcpy(component, &name); } break; } diff --git a/lunaix-os/kernel/fs/pcache.c b/lunaix-os/kernel/fs/pcache.c index 0094ec4..c27f78b 100644 --- a/lunaix-os/kernel/fs/pcache.c +++ b/lunaix-os/kernel/fs/pcache.c @@ -76,7 +76,7 @@ pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg) } } -struct pcache_pg* +int pcache_get_page(struct pcache* pcache, uint32_t index, uint32_t* offset, @@ -140,7 +140,7 @@ pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos) errno = inode->default_fops->read(inode, pg->pg, PG_SIZE, pg->fpos); if (errno >= 0 && errno < PG_SIZE) { // EOF - len = buf_off + errno; + len = MIN(len, buf_off + errno); } else if (errno < 0) { break; } diff --git a/lunaix-os/kernel/fs/ramfs/ramfs.c b/lunaix-os/kernel/fs/ramfs/ramfs.c index 3dcbd59..a1018da 100644 --- a/lunaix-os/kernel/fs/ramfs/ramfs.c +++ b/lunaix-os/kernel/fs/ramfs/ramfs.c @@ -42,6 +42,7 @@ volatile static inode_t ino = 0; extern const struct v_inode_ops ramfs_inode_ops; +extern const struct v_file_ops ramfs_file_ops; int ramfs_readdir(struct v_file* file, struct dir_context* dctx) @@ -51,8 +52,10 @@ ramfs_readdir(struct v_file* file, struct dir_context* dctx) llist_for_each(pos, n, &file->dnode->children, siblings) { if (i++ >= dctx->index) { - dctx->read_complete_callback( - dctx, pos->name.value, pos->name.len, 0); + dctx->read_complete_callback(dctx, + pos->name.value, + pos->name.len, + vfs_get_dtype(pos->inode->itype)); return 1; } } @@ -88,7 +91,7 @@ ramfs_inode_init(struct v_superblock* vsb, struct v_inode* inode) { inode->id = ino++; inode->ops = &ramfs_inode_ops; - inode->default_fops = &default_file_ops; + inode->default_fops = &ramfs_file_ops; } int @@ -127,4 +130,10 @@ const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir, default_inode_dirlookup, .create = ramfs_create, .open = default_inode_open, - .rename = default_inode_rename }; \ No newline at end of file + .rename = default_inode_rename }; + +const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir, + .close = default_file_close, + .read = default_file_read, + .write = default_file_write, + .seek = default_file_seek }; \ No newline at end of file diff --git a/lunaix-os/kernel/fs/twifs/twifs.c b/lunaix-os/kernel/fs/twifs/twifs.c index d452d0b..437ab0b 100644 --- a/lunaix-os/kernel/fs/twifs/twifs.c +++ b/lunaix-os/kernel/fs/twifs/twifs.c @@ -8,12 +8,15 @@ * @copyright Copyright (c) 2022 * */ +#include #include #include #include #include +#include #include #include +#include static struct twifs_node* fs_root; @@ -33,7 +36,9 @@ __twifs_new_node(struct twifs_node* parent, struct twifs_node* node = cake_grab(twi_pile); memset(node, 0, sizeof(*node)); - node->name = HSTR(name, name_len); + strncpy(node->name_val, name, VFS_NAME_MAXLEN); + + node->name = HSTR(node->name_val, MIN(name_len, VFS_NAME_MAXLEN)); node->itype = itype; node->ino_id = inode_id++; hstr_rehash(&node->name, HSTR_FULL_HASH); @@ -120,24 +125,24 @@ __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode) struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name); if (child_node) { - struct v_inode* inode = vfs_i_find(inode->sb, child_node->ino_id); - if (inode) { + struct v_inode* child_inode = vfs_i_find(inode->sb, child_node->ino_id); + if (child_inode) { goto done; } - if (!(inode = vfs_i_alloc(inode->sb))) { + if (!(child_inode = vfs_i_alloc(inode->sb))) { return ENOENT; } - inode->id = child_node->ino_id; - inode->itype = child_node->itype; - inode->data = child_node; + child_inode->id = child_node->ino_id; + child_inode->itype = child_node->itype; + child_inode->data = child_node; - vfs_i_addhash(inode); + vfs_i_addhash(child_inode); done: dnode->data = child_node->data; - vfs_assign_inode(dnode, inode); + vfs_assign_inode(dnode, child_inode); return 0; } return ENOENT; @@ -155,7 +160,7 @@ __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx) if (counter++ >= dctx->index) { dctx->index = counter; dctx->read_complete_callback( - dctx, pos->name.value, pos->name.len, pos->itype); + dctx, pos->name.value, pos->name.len, vfs_get_dtype(pos->itype)); return 1; } } @@ -185,40 +190,41 @@ twifs_rm_node(struct twifs_node* node) } struct twifs_node* -twifs_file_node(struct twifs_node* parent, - const char* name, - int name_len, - uint32_t itype) +twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args) { - struct twifs_node* twi_node = - __twifs_new_node(parent, name, name_len, VFS_IFFILE | itype); + char buf[VFS_NAME_MAXLEN]; + size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args); - return twi_node; + return __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFSEQDEV); } struct twifs_node* -twifs_dir_node(struct twifs_node* parent, - const char* name, - int name_len, - uint32_t itype) -{ - 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; - } +twifs_file_node(struct twifs_node* parent, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); - struct twifs_node* twi_node = - __twifs_new_node(parent, name, name_len, VFS_IFDIR | itype); + struct twifs_node* twi_node = twifs_file_node_vargs(parent, fmt, args); + + va_end(args); return twi_node; } struct twifs_node* -twifs_toplevel_node(const char* name, int name_len, uint32_t itype) +twifs_dir_node(struct twifs_node* parent, const char* fmt, ...) { - return twifs_dir_node(fs_root, name, name_len, itype); + va_list args; + va_start(args, fmt); + + char buf[VFS_NAME_MAXLEN]; + size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args); + struct twifs_node* twi_node = + __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFDIR); + + va_end(args); + + return twi_node; } void @@ -237,6 +243,30 @@ twifs_init() fs_root = twifs_dir_node(NULL, NULL, 0, 0); } +int +__twifs_twimap_file_read(struct v_inode* inode, + void* buf, + size_t len, + size_t fpos) +{ + struct twimap* map = twinode_getdata(inode, struct twimap*); + return twimap_read(map, buf, len, fpos); +} + +struct twimap* +twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + struct twimap* map = twimap_create(data); + struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args); + node->ops.read = __twifs_twimap_file_read; + node->data = map; + + return map; +} + const struct v_file_ops twifs_file_ops = { .close = default_file_close, .read = __twifs_fread, .write = __twifs_fwrite, diff --git a/lunaix-os/kernel/fs/twimap.c b/lunaix-os/kernel/fs/twimap.c new file mode 100644 index 0000000..009cdf3 --- /dev/null +++ b/lunaix-os/kernel/fs/twimap.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +#include +#include + +#define TWIMAP_BUFFER_SIZE 1024 + +void +__twimap_default_reset(struct twimap* map) +{ + map->index = NULL; +} + +int +__twimap_default_gonext(struct twimap* map) +{ + return 0; +} + +int +__twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos) +{ + struct twimap* map = (struct twimap*)(inode->data); + return twimap_read(map, buf, len, fpos); +} + +int +twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos) +{ + map->buffer = valloc(TWIMAP_BUFFER_SIZE); + map->reset(map); + + // FIXME what if TWIMAP_BUFFER_SIZE is not big enough? + + size_t pos = 0; + do { + map->size_acc = 0; + map->read(map); + pos += map->size_acc; + } while (pos <= fpos && map->go_next(map)); + + if (pos <= fpos) { + vfree(map->buffer); + return 0; + } + + if (!fpos) { + pos = 0; + } + + size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size; + memcpy(buffer, map->buffer + (pos - fpos), acc_size); + + while (acc_size < len && map->go_next(map)) { + map->size_acc = 0; + map->read(map); + rdlen = MIN(len - acc_size, map->size_acc); + memcpy(buffer + acc_size, map->buffer, rdlen); + acc_size += rdlen; + } + + vfree(map->buffer); + return acc_size; +} + +void +twimap_printf(struct twimap* mapping, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + char* buf = mapping->buffer + mapping->size_acc; + + mapping->size_acc += + __ksprintf_internal(buf, fmt, TWIMAP_BUFFER_SIZE, args); + + va_end(args); +} + +int +twimap_memcpy(struct twimap* mapping, const void* src, const size_t len) +{ + mapping->size_acc = MIN(TWIMAP_BUFFER_SIZE, len); + memcpy(mapping->buffer, src, mapping->size_acc); + + return mapping->size_acc; +} + +int +twimap_memappend(struct twimap* mapping, const void* src, const size_t len) +{ + size_t cpy_len = MIN(TWIMAP_BUFFER_SIZE - mapping->size_acc, len); + memcpy(mapping->buffer + mapping->size_acc, src, cpy_len); + mapping->size_acc += cpy_len; + + return cpy_len; +} + +struct twimap* +twimap_create(void* data) +{ + struct twimap* map = vzalloc(sizeof(struct twimap)); + map->reset = __twimap_default_reset; + map->go_next = __twimap_default_gonext; + map->data = data; + + return map; +} + +struct v_file_ops twimap_file_ops = { .close = default_file_close, + .read = __twimap_file_read, + .readdir = default_file_readdir, + .seek = default_file_seek, + .write = default_file_write }; \ No newline at end of file diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 83bd0bd..df374cd 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -163,6 +163,7 @@ vfs_dcache_remove(struct v_dnode* dnode) assert(dnode->ref_count == 1); llist_delete(&dnode->siblings); + llist_delete(&dnode->aka_list); hlist_delete(&dnode->hash_list); dnode->parent = NULL; @@ -225,8 +226,10 @@ void vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode) { if (assign_to->inode) { + llist_delete(&assign_to->aka_list); assign_to->inode->link_count--; } + llist_append(&inode->aka_dnodes, &assign_to->aka_list); assign_to->inode = inode; inode->link_count++; } @@ -254,12 +257,35 @@ vfs_link(struct v_dnode* to_link, struct v_dnode* name) } int -vfs_close(struct v_file* file) +vfs_pclose(struct v_file* file, pid_t pid) { int errno = 0; - if (!(errno = file->ops->close(file))) { + if (file->ref_count > 1) { + atomic_fetch_sub(&file->ref_count, 1); + } else if (!(errno = file->ops->close(file))) { atomic_fetch_sub(&file->dnode->ref_count, 1); file->inode->open_count--; + + // Prevent dead lock. + // This happened when process is terminated while blocking on read. + // In that case, the process is still holding the inode lock and it will + // never get released. + /* + * The unlocking should also include ownership check. + * + * To see why, consider two process both open the same file both with + * fd=x. + * Process A: busy on reading x + * Process B: do nothing with x + * Assuming that, after a very short time, process B get terminated + * while process A is still busy in it's reading business. By this + * design, the inode lock of this file x is get released by B rather + * than A. And this will cause a probable race condition on A if other + * process is writing to this file later after B exit. + */ + if (mutex_on_hold(&file->inode->lock)) { + mutex_unlock_for(&file->inode->lock, pid); + } mnt_chillax(file->dnode->mnt); pcache_commit_all(file->inode); @@ -268,6 +294,12 @@ vfs_close(struct v_file* file) return errno; } +int +vfs_close(struct v_file* file) +{ + return vfs_pclose(file, __current->pid); +} + int vfs_fsync(struct v_file* file) { @@ -358,6 +390,7 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name) memset(dnode, 0, sizeof(*dnode)); llist_init_head(&dnode->children); llist_init_head(&dnode->siblings); + llist_init_head(&dnode->aka_list); mutex_init(&dnode->lock); dnode->ref_count = ATOMIC_VAR_INIT(0); @@ -367,6 +400,7 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name) if (parent) { dnode->super_block = parent->super_block; + dnode->mnt = parent->mnt; } lru_use_one(dnode_lru, &dnode->lru); @@ -439,6 +473,7 @@ vfs_i_alloc(struct v_superblock* sb) memset(inode, 0, sizeof(*inode)); mutex_init(&inode->lock); llist_init_head(&inode->xattrs); + llist_init_head(&inode->aka_dnodes); sb->ops.init_inode(sb, inode); @@ -486,6 +521,8 @@ __vfs_try_locate_file(const char* path, char name_str[VFS_NAME_MAXLEN]; struct hstr name = HSTR(name_str, 0); int errno; + + name_str[0] = 0; if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) { return errno; } @@ -558,9 +595,7 @@ __DEFINE_LXSYSCALL1(int, close, int, fd) goto done_err; } - if (fd_s->file->ref_count > 1) { - fd_s->file->ref_count--; - } else if ((errno = vfs_close(fd_s->file))) { + if ((errno = vfs_close(fd_s->file))) { goto done_err; } @@ -606,9 +641,9 @@ __DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent) __vfs_readdir_callback }; errno = 1; if (dent->d_offset == 0) { - __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, 0); + __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, DT_DIR); } else if (dent->d_offset == 1) { - __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, 0); + __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, DT_DIR); } else { dctx.index -= 2; if ((errno = fd_s->file->ops->readdir(fd_s->file, &dctx)) != 1) { @@ -643,13 +678,11 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) file->inode->atime = clock_unixtime(); - __SYSCALL_INTERRUPTIBLE({ - if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) { - errno = file->ops->read(file->inode, buf, count, file->f_pos); - } else { - errno = pcache_read(file->inode, buf, count, file->f_pos); - } - }) + if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) { + errno = file->ops->read(file->inode, buf, count, file->f_pos); + } else { + errno = pcache_read(file->inode, buf, count, file->f_pos); + } if (errno > 0) { file->f_pos += errno; @@ -686,13 +719,11 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) file->inode->mtime = clock_unixtime(); - __SYSCALL_INTERRUPTIBLE({ - if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) { - errno = file->ops->write(file->inode, buf, count, file->f_pos); - } else { - errno = pcache_write(file->inode, buf, count, file->f_pos); - } - }) + if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) { + errno = file->ops->write(file->inode, buf, count, file->f_pos); + } else { + errno = pcache_write(file->inode, buf, count, file->f_pos); + } if (errno > 0) { file->f_pos += errno; @@ -752,7 +783,7 @@ done: int vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) { - if (!dnode || dnode->parent == dnode) { + if (!dnode) { return 0; } @@ -760,13 +791,19 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) return ENAMETOOLONG; } - size_t len = vfs_get_path(dnode->parent, buf, size, depth + 1); + size_t len = 0; + + if (dnode->parent != dnode) { + len = vfs_get_path(dnode->parent, buf, size, depth + 1); + } if (len >= size) { return len; } - buf[len++] = VFS_PATH_DELIM; + if (!len || buf[len - 1] != VFS_PATH_DELIM) { + buf[len++] = VFS_PATH_DELIM; + } size_t cpy_size = MIN(dnode->name.len, size - len); strncpy(buf + len, dnode->name.value, cpy_size); @@ -792,6 +829,19 @@ vfs_readlink(struct v_dnode* dnode, char* buf, size_t size) return 0; } +int +vfs_get_dtype(int itype) +{ + switch (itype) { + case VFS_IFDIR: + return DT_DIR; + case VFS_IFSYMLINK: + return DT_SYMLINK; + default: + return DT_PIPE; + } +} + __DEFINE_LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size) { int errno; @@ -1161,8 +1211,22 @@ done: return DO_STATUS(errno); } +void +vfs_ref_dnode(struct v_dnode* dnode) +{ + atomic_fetch_add(&dnode->ref_count, 1); + mnt_mkbusy(dnode->mnt); +} + +void +vfs_unref_dnode(struct v_dnode* dnode) +{ + atomic_fetch_sub(&dnode->ref_count, 1); + mnt_chillax(dnode->mnt); +} + int -__vfs_do_chdir(struct v_dnode* dnode) +vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) { int errno = 0; @@ -1173,14 +1237,12 @@ __vfs_do_chdir(struct v_dnode* dnode) goto done; } - if (__current->cwd) { - atomic_fetch_sub(&__current->cwd->ref_count, 1); - mnt_chillax(__current->cwd->mnt); + if (proc->cwd) { + vfs_unref_dnode(proc->cwd); } - atomic_fetch_add(&dnode->ref_count, 1); - mnt_mkbusy(dnode->mnt); - __current->cwd = dnode; + vfs_ref_dnode(dnode); + proc->cwd = dnode; unlock_dnode(dnode); @@ -1197,7 +1259,7 @@ __DEFINE_LXSYSCALL1(int, chdir, const char*, path) goto done; } - errno = __vfs_do_chdir(dnode); + errno = vfs_do_chdir(__current, dnode); done: return DO_STATUS(errno); @@ -1212,7 +1274,7 @@ __DEFINE_LXSYSCALL1(int, fchdir, int, fd) goto done; } - errno = __vfs_do_chdir(fd_s->file->dnode); + errno = vfs_do_chdir(__current, fd_s->file->dnode); done: return DO_STATUS(errno); diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 30e06ca..fe9cf90 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -3,7 +3,9 @@ #include #include +#include #include +#include #include #include #include @@ -55,9 +57,6 @@ _kernel_pre_init() setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size); - tty_init((void*)VGA_BUFFER_VADDR); - tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); - __kernel_ptd = cpu_rcr3(); tmp = (struct proc_info){ .page_table = __kernel_ptd }; @@ -72,17 +71,22 @@ _kernel_init() cake_init(); valloc_init(); + tty_init(ioremap(VGA_FRAMEBUFFER, PG_SIZE)); + tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); + vfs_init(); fsm_init(); + input_init(); - device_init(); + vfs_export_attributes(); if ((errno = vfs_mount_root("ramfs", NULL))) { panickf("Fail to mount root. (errno=%d)", errno); } - // FIXME replace with more specific fs for device. - vfs_mount("/dev", "twifs", NULL, MNT_RO); + vfs_mount("/dev", "devfs", NULL, 0); + vfs_mount("/sys", "twifs", NULL, MNT_RO); + vfs_mount("/task", "taskfs", NULL, MNT_RO); lxconsole_init(); @@ -193,22 +197,7 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) // 将内核占据的页,包括前1MB,hhk_init 设为已占用 size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS; - pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0); - - size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS; - - // 首先,标记VGA部分为已占用,并且锁定 - pmm_mark_chunk_occupied( - KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, PP_FGLOCKED); - - // 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer) - for (size_t i = 0; i < vga_buf_pgs; i++) { - vmm_set_mapping(PD_REFERENCED, - VGA_BUFFER_VADDR + (i << PG_SIZE_BITS), - VGA_BUFFER_PADDR + (i << PG_SIZE_BITS), - PG_PREM_URW, - VMAP_NULL); - } + pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED); for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) { vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL); diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index d18691a..fd005c0 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -22,51 +22,51 @@ __kprintf(const char* component, const char* fmt, va_list args) switch (log_level) { case '0': - snprintf(expanded_fmt, - MAX_XFMT_SIZE, - "[%s] (%s) %s", - "INFO", - component, - fmt); + ksnprintf(expanded_fmt, + MAX_XFMT_SIZE, + "[%s] (%s) %s", + "INFO", + component, + fmt); break; case '1': // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12); - snprintf(expanded_fmt, - MAX_XFMT_SIZE, - "\033[6;0m[%s] (%s) %s\033[39;49m", - "WARN", - component, - fmt); + ksnprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\033[6;0m[%s] (%s) %s\033[39;49m", + "WARN", + component, + fmt); break; case '2': // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12); - snprintf(expanded_fmt, - MAX_XFMT_SIZE, - "\033[12;0m[%s] (%s) %s\033[39;49m", - "EROR", - component, - fmt); + ksnprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\033[12;0m[%s] (%s) %s\033[39;49m", + "EROR", + component, + fmt); break; case '3': // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12); - snprintf(expanded_fmt, - MAX_XFMT_SIZE, - "\033[9;0m[%s] (%s) %s\033[39;49m", - "DEBG", - component, - fmt); + ksnprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\033[9;0m[%s] (%s) %s\033[39;49m", + "DEBG", + component, + fmt); break; default: - snprintf(expanded_fmt, - MAX_XFMT_SIZE, - "[%s] (%s) %s", - "LOG", - component, - fmt); + ksnprintf(expanded_fmt, + MAX_XFMT_SIZE, + "[%s] (%s) %s", + "LOG", + component, + fmt); break; } - __sprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args); + __ksprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args); console_write_str(buf); } @@ -80,7 +80,7 @@ kprint_panic(const char* fmt, ...) tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED); tty_clear_line(24); - __sprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args); + __ksprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args); tty_put_str_at(buf, 0, 24); va_end(args); @@ -98,12 +98,12 @@ kprint_hex(const void* buffer, unsigned int size) ch_cache[0] = '|'; ch_cache[1] = ' '; while (size) { - snprintf(buf, 64, " %.4p: ", ptr); + ksnprintf(buf, 64, " %.4p: ", ptr); console_write_str(buf); for (i = 0; i < 8 && size; i++, size--, ptr++) { unsigned char c = *(data + ptr) & 0xff; ch_cache[2 + i] = (32 <= c && c < 127) ? c : '.'; - snprintf(buf, 64, "%.2x ", c); + ksnprintf(buf, 64, "%.2x ", c); console_write_str(buf); } ch_cache[2 + i] = '\0'; diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c deleted file mode 100644 index 785330a..0000000 --- a/lunaix-os/kernel/lxconsole.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct console lx_console; - -int -__tty_write(struct device* dev, void* buf, size_t offset, size_t len); - -int -__tty_read(struct device* dev, void* buf, size_t offset, size_t len); - -void -lxconsole_init() -{ - memset(&lx_console, 0, sizeof(lx_console)); - fifo_init(&lx_console.output, VGA_BUFFER_VADDR + 0x1000, 8192, 0); - fifo_init(&lx_console.input, valloc(4096), 4096, 0); - - // FIXME use valloc to allocate console buffer. - // In doing this, the console buffer can only be accessed from kernel mode - // any direct write to this buffer from user land should be purged! - - // 分配控制台缓存 - for (size_t i = 0; i < PG_ALIGN(lx_console.output.size); i += PG_SIZE) { - uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0); - vmm_set_mapping(PD_REFERENCED, - (uintptr_t)lx_console.output.data + i, - pa, - PG_PREM_URW, - 0); - } - - lx_console.flush_timer = NULL; - - struct device* tty_dev = device_addseq(NULL, &lx_console, "tty"); - tty_dev->write = __tty_write; - tty_dev->read = __tty_read; -} - -int -__tty_write(struct device* dev, void* buf, size_t offset, size_t len) -{ - struct console* console = (struct console*)dev->underlay; - console_write(console, buf, len); -} - -int -__tty_read(struct device* dev, void* buf, size_t offset, size_t len) -{ - struct kdb_keyinfo_pkt keyevent; - struct console* console = (struct console*)dev->underlay; - - size_t count = fifo_read(&console->input, buf, len); - if (count > 0 && ((char*)buf)[count - 1] == '\n') { - return count; - } - - while (count < len) { - // FIXME RACE! - // Consider two process that is polling the input key simultaneously. - // When a key is arrived, one of the processes will win the race and - // swallow it (advancing the key buffer pointer) - if (!kbd_recv_key(&keyevent)) { - sched_yieldk(); - continue; - } - if (!(keyevent.state & KBD_KEY_FPRESSED)) { - continue; - } - if ((keyevent.keycode & 0xff00) > KEYPAD) { - continue; - } - - char c = (char)(keyevent.keycode & 0x00ff); - if (c == 0x08) { - if (fifo_backone(&console->input)) { - console_write_char(c); - } - continue; - } - console_write_char(c); - if (!fifo_putone(&console->input, c) || c == '\n') { - break; - } - } - return count + fifo_read(&console->input, buf + count, len - count); -} - -void -console_schedule_flush() -{ - // TODO make the flush on-demand rather than periodic -} - -void -console_view_up() -{ - struct fifo_buf* buffer = &lx_console.output; - mutex_lock(&buffer->lock); - size_t p = lx_console.erd_pos - 2; - while (p < lx_console.erd_pos && p != buffer->wr_pos && - ((char*)buffer->data)[p] != '\n') { - p--; - } - p++; - - if (p > lx_console.erd_pos) { - p = 0; - } - - buffer->flags |= FIFO_DIRTY; - lx_console.erd_pos = p; - mutex_unlock(&buffer->lock); -} - -size_t -__find_next_line(size_t start) -{ - size_t p = start; - while (p != lx_console.output.wr_pos && - ((char*)lx_console.output.data)[p] != '\n') { - p = (p + 1) % lx_console.output.size; - } - return p + 1; -} - -void -console_view_down() -{ - struct fifo_buf* buffer = &lx_console.output; - mutex_lock(&buffer->lock); - - lx_console.erd_pos = __find_next_line(lx_console.erd_pos); - buffer->flags |= FIFO_DIRTY; - mutex_unlock(&buffer->lock); -} - -void -console_flush() -{ - if (mutex_on_hold(&lx_console.output.lock)) { - return; - } - if (!(lx_console.output.flags & FIFO_DIRTY)) { - return; - } - - tty_flush_buffer(lx_console.output.data, - lx_console.erd_pos, - lx_console.output.wr_pos, - lx_console.output.size); - lx_console.output.flags &= ~FIFO_DIRTY; -} - -void -console_write(struct console* console, uint8_t* data, size_t size) -{ - mutex_lock(&console->output.lock); - uint8_t* buffer = console->output.data; - uintptr_t ptr = console->output.wr_pos; - uintptr_t rd_ptr = console->output.rd_pos; - - char c; - int lines = 0; - int j = 0; - for (size_t i = 0; i < size; i++) { - c = data[i]; - if (!c) { - continue; - } - buffer[(ptr + j) % console->output.size] = c; - lines += (c == '\n'); - j++; - } - - size = j; - - uintptr_t new_ptr = (ptr + size) % console->output.size; - console->output.wr_pos = new_ptr; - - if (console->lines > TTY_HEIGHT && lines > 0) { - console->output.rd_pos = - __find_next_line((size + rd_ptr) % console->output.size); - } - - if (new_ptr < ptr + size && new_ptr > rd_ptr) { - console->output.rd_pos = new_ptr; - } - - console->lines += lines; - console->erd_pos = console->output.rd_pos; - console->output.flags |= FIFO_DIRTY; - mutex_unlock(&console->output.lock); -} - -void -console_write_str(char* str) -{ - console_write(&lx_console, str, strlen(str)); -} - -void -console_write_char(char str) -{ - console_write(&lx_console, &str, 1); -} - -void -console_start_flushing() -{ - struct lx_timer* timer = - timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC); - lx_console.flush_timer = timer; -} \ No newline at end of file diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index c3cee83..5e03d34 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -48,6 +48,7 @@ __new_cake(struct cake_pile* pile) cake->first_piece = (void*)((uintptr_t)cake + pile->offset); cake->next_free = 0; + pile->cakes_count++; piece_index_t* free_list = cake->free_list; for (size_t i = 0; i < max_piece - 1; i++) { @@ -119,6 +120,12 @@ cake_new_pile(char* name, return pile; } +void +cake_set_constructor(struct cake_pile* pile, pile_cb ctor) +{ + pile->ctor = ctor; +} + void* cake_grab(struct cake_pile* pile) { @@ -146,8 +153,14 @@ cake_grab(struct cake_pile* pile) llist_append(&pile->partial, &pos->cakes); } - return (void*)((uintptr_t)pos->first_piece + - found_index * pile->piece_size); + void* ptr = + (void*)((uintptr_t)pos->first_piece + found_index * pile->piece_size); + + if (pile->ctor) { + pile->ctor(pile, ptr); + } + + return ptr; } int @@ -190,18 +203,7 @@ found: } void -cake_stats() +cake_ctor_zeroing(struct cake_pile* pile, void* piece) { - kprintf(KDEBUG "

\n"); - - struct cake_pile *pos, *n; - llist_for_each(pos, n, &piles, piles) - { - kprintf("%s %d %d %d %d\n", - pos->pile_name, - pos->cakes_count, - pos->pg_per_cake, - pos->pieces_per_cake, - pos->alloced_pieces); - } + memset(piece, 0, pile->piece_size); } \ No newline at end of file diff --git a/lunaix-os/kernel/mm/cake_export.c b/lunaix-os/kernel/mm/cake_export.c new file mode 100644 index 0000000..276e823 --- /dev/null +++ b/lunaix-os/kernel/mm/cake_export.c @@ -0,0 +1,108 @@ +#include +#include + +extern struct llist_header piles; + +int +__cake_stat_gonext(struct twimap* map) +{ + struct cake_pile* pile = twimap_index(map, struct cake_pile*); + if (pile->piles.next == &piles) { + return 0; + } + map->index = list_entry(pile->piles.next, struct cake_pile, piles); + return 1; +} + +void +__cake_stat_reset(struct twimap* map) +{ + map->index = container_of(piles.next, struct cake_pile, piles); +} + +void +__cake_rd_stat(struct twimap* map) +{ + struct cake_pile* pos = twimap_index(map, struct cake_pile*); + twimap_printf(map, + "%s %d %d %d %d\n", + pos->pile_name, + pos->cakes_count, + pos->pg_per_cake, + pos->pieces_per_cake, + pos->alloced_pieces); +} + +void +__cake_rd_psize(struct twimap* map) +{ + struct cake_pile* pile = twimap_data(map, struct cake_pile*); + twimap_printf(map, "%u", pile->piece_size); +} + +void +__cake_rd_ccount(struct twimap* map) +{ + struct cake_pile* pile = twimap_data(map, struct cake_pile*); + twimap_printf(map, "%u", pile->cakes_count); +} + +void +__cake_rd_alloced(struct twimap* map) +{ + struct cake_pile* pile = twimap_data(map, struct cake_pile*); + twimap_printf(map, "%u", pile->alloced_pieces); +} + +void +__cake_rd_ppc(struct twimap* map) +{ + struct cake_pile* pile = twimap_data(map, struct cake_pile*); + twimap_printf(map, "%u", pile->pieces_per_cake); +} + +void +__cake_rd_ppg(struct twimap* map) +{ + struct cake_pile* pile = twimap_data(map, struct cake_pile*); + twimap_printf(map, "%u", pile->pg_per_cake); +} + +void +cake_export_pile(struct twifs_node* root, struct cake_pile* pile) +{ + struct twifs_node* pile_rt = twifs_dir_node(root, pile->pile_name); + + struct twimap* map = twifs_mapping(pile_rt, pile, "piece_size"); + map->read = __cake_rd_psize; + + map = twifs_mapping(pile_rt, pile, "cake_count"); + map->read = __cake_rd_ccount; + + map = twifs_mapping(pile_rt, pile, "grabbed"); + map->read = __cake_rd_alloced; + + map = twifs_mapping(pile_rt, pile, "pieces_per_cake"); + map->read = __cake_rd_ppc; + + map = twifs_mapping(pile_rt, pile, "page_per_cake"); + map->read = __cake_rd_ppg; +} + +void +cake_export() +{ + struct twifs_node* cake_root = twifs_dir_node(NULL, "cake"); + + struct twimap* map = twifs_mapping(cake_root, NULL, "pinkiepie"); + map->reset = __cake_stat_reset; + map->go_next = __cake_stat_gonext; + map->read = __cake_rd_stat; + __cake_stat_reset(map); + + struct cake_pile *pos, *n; + llist_for_each(pos, n, &piles, piles) + { + cake_export_pile(cake_root, pos); + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/mm/dmm.c b/lunaix-os/kernel/mm/dmm.c index 651c6fc..edc28ef 100644 --- a/lunaix-os/kernel/mm/dmm.c +++ b/lunaix-os/kernel/mm/dmm.c @@ -50,13 +50,11 @@ dmm_init(heap_context_t* heap) heap->brk = heap->start; mutex_init(&heap->lock); - int perm = PG_ALLOW_USER; - if (heap->brk >= KHEAP_START) { - perm = 0; - } - - return vmm_set_mapping( - PD_REFERENCED, heap->brk, 0, PG_WRITE | perm, VMAP_NULL) != NULL; + return vmm_set_mapping(PD_REFERENCED, + heap->brk, + 0, + PG_WRITE | PG_ALLOW_USER, + VMAP_NULL) != NULL; } int diff --git a/lunaix-os/kernel/mm/kalloc.c b/lunaix-os/kernel/mm/kalloc.c index 6b5b878..aec1001 100644 --- a/lunaix-os/kernel/mm/kalloc.c +++ b/lunaix-os/kernel/mm/kalloc.c @@ -1,3 +1,6 @@ + +/**** DO NOT USE ****/ + /** * @file kalloc.c * @author Lunaixsky @@ -11,269 +14,271 @@ * @copyright Copyright (c) 2022 * */ -#include -#include -#include - -#include -#include - -#include +// #include +// #include +// #include -#include +// #include +// #include -extern uint8_t __kernel_heap_start; +// #include -void* -lx_malloc_internal(heap_context_t* heap, size_t size); - -void -place_chunk(uint8_t* ptr, size_t size); +// #include -void -lx_free_internal(void* ptr); +// extern uint8_t __kernel_heap_start; + +// void* +// lx_malloc_internal(heap_context_t* heap, size_t size); + +// void +// place_chunk(uint8_t* ptr, size_t size); -void* -coalesce(uint8_t* chunk_ptr); +// void +// lx_free_internal(void* ptr); -void* -lx_grow_heap(heap_context_t* heap, size_t sz); +// void* +// coalesce(uint8_t* chunk_ptr); + +// void* +// lx_grow_heap(heap_context_t* heap, size_t sz); -/* - At the beginning, we allocate an empty page and put our initial marker +// /* +// At the beginning, we allocate an empty page and put our initial marker - | 4/1 | 0/1 | - ^ ^ brk - start +// | 4/1 | 0/1 | +// ^ ^ brk +// start - Then, expand the heap further, with HEAP_INIT_SIZE (evaluated to 4096, i.e., - 1 pg size) This will allocate as much pages and override old epilogue marker - with a free region hdr and put new epilogue marker. These are handled by - lx_grow_heap which is internally used by alloc to expand the heap at many - moment when needed. +// Then, expand the heap further, with HEAP_INIT_SIZE (evaluated to 4096, +// i.e., +// 1 pg size) This will allocate as much pages and override old epilogue +// marker with a free region hdr and put new epilogue marker. These are +// handled by lx_grow_heap which is internally used by alloc to expand the +// heap at many moment when needed. - | 4/1 | 4096/0 | ....... | 4096/0 | 0/1 | - ^ ^ brk_old ^ - start brk +// | 4/1 | 4096/0 | ....... | 4096/0 | 0/1 | +// ^ ^ brk_old ^ +// start brk - Note: the brk always point to the beginning of epilogue. -*/ +// Note: the brk always point to the beginning of epilogue. +// */ -static heap_context_t kheap; +// static heap_context_t kheap; -int -kalloc_init() -{ - kheap.start = KHEAP_START; - kheap.brk = NULL; - kheap.max_addr = - (void*)PROC_START; // 在新的布局中,堆结束的地方即为进程表开始的地方 - - for (size_t i = 0; i < KHEAP_SIZE_MB >> 2; i++) { - vmm_set_mapping(PD_REFERENCED, - (uintptr_t)kheap.start + (i << 22), - 0, - PG_PREM_RW, - VMAP_NOMAP); - } - - if (!dmm_init(&kheap)) { - return 0; - } - - SW(kheap.start, PACK(4, M_ALLOCATED)); - SW(kheap.start + WSIZE, PACK(0, M_ALLOCATED)); - kheap.brk += WSIZE; - - return lx_grow_heap(&kheap, HEAP_INIT_SIZE) != NULL; -} - -void* -lxmalloc(size_t size) -{ - mutex_lock(&kheap.lock); - void* r = lx_malloc_internal(&kheap, size); - mutex_unlock(&kheap.lock); - - return r; -} - -void* -lxcalloc(size_t n, size_t elem) -{ - size_t pd = n * elem; - - // overflow detection - if (pd < elem || pd < n) { - return NULL; - } - - void* ptr = lxmalloc(pd); - if (!ptr) { - return NULL; - } - - return memset(ptr, 0, pd); -} - -void -lxfree(void* ptr) -{ - if (!ptr) { - return; - } - mutex_lock(&kheap.lock); - - uint8_t* chunk_ptr = (uint8_t*)ptr - WSIZE; - uint32_t hdr = LW(chunk_ptr); - size_t sz = CHUNK_S(hdr); - uint8_t* next_hdr = chunk_ptr + sz; - - // make sure the ptr we are 'bout to free makes sense - // the size trick is stolen from glibc's malloc/malloc.c:4437 ;P - - assert_msg(((uintptr_t)ptr < (uintptr_t)(-sz)) && !((uintptr_t)ptr & 0x3), - "free(): invalid pointer"); - - assert_msg(sz > WSIZE, "free(): invalid size"); - - SW(chunk_ptr, hdr & ~M_ALLOCATED); - SW(FPTR(chunk_ptr, sz), hdr & ~M_ALLOCATED); - SW(next_hdr, LW(next_hdr) | M_PREV_FREE); - - coalesce(chunk_ptr); - - mutex_unlock(&kheap.lock); -} - -void* -lx_malloc_internal(heap_context_t* heap, size_t size) -{ - // Simplest first fit approach. - - if (!size) { - return NULL; - } - - uint8_t* ptr = heap->start; - // round to largest 4B aligned value - // and space for header - size = ROUNDUP(size + WSIZE, BOUNDARY); - while (ptr < (uint8_t*)heap->brk) { - uint32_t header = *((uint32_t*)ptr); - size_t chunk_size = CHUNK_S(header); - if (!chunk_size && CHUNK_A(header)) { - break; - } - if (chunk_size >= size && !CHUNK_A(header)) { - // found! - place_chunk(ptr, size); - return BPTR(ptr); - } - ptr += chunk_size; - } - - // if heap is full (seems to be!), then allocate more space (if it's - // okay...) - if ((ptr = lx_grow_heap(heap, size))) { - place_chunk(ptr, size); - return BPTR(ptr); - } - - // Well, we are officially OOM! - return NULL; -} - -void -place_chunk(uint8_t* ptr, size_t size) -{ - uint32_t header = *((uint32_t*)ptr); - size_t chunk_size = CHUNK_S(header); - *((uint32_t*)ptr) = PACK(size, CHUNK_PF(header) | M_ALLOCATED); - uint8_t* n_hdrptr = (uint8_t*)(ptr + size); - uint32_t diff = chunk_size - size; - - if (!diff) { - // if the current free block is fully occupied - uint32_t n_hdr = LW(n_hdrptr); - // notify the next block about our avaliability - SW(n_hdrptr, n_hdr & ~0x2); - } else { - // if there is remaining free space left - uint32_t remainder_hdr = PACK(diff, M_NOT_ALLOCATED | M_PREV_ALLOCATED); - SW(n_hdrptr, remainder_hdr); - SW(FPTR(n_hdrptr, diff), remainder_hdr); - - /* - | xxxx | | | - - | - v - - | xxxx | | - */ - coalesce(n_hdrptr); - } -} - -void* -coalesce(uint8_t* chunk_ptr) -{ - uint32_t hdr = LW(chunk_ptr); - uint32_t pf = CHUNK_PF(hdr); - uint32_t sz = CHUNK_S(hdr); - - uint32_t n_hdr = LW(chunk_ptr + sz); - - if (CHUNK_A(n_hdr) && pf) { - // case 1: prev is free - uint32_t prev_ftr = LW(chunk_ptr - WSIZE); - size_t prev_chunk_sz = CHUNK_S(prev_ftr); - uint32_t new_hdr = PACK(prev_chunk_sz + sz, CHUNK_PF(prev_ftr)); - SW(chunk_ptr - prev_chunk_sz, new_hdr); - SW(FPTR(chunk_ptr, sz), new_hdr); - chunk_ptr -= prev_chunk_sz; - } else if (!CHUNK_A(n_hdr) && !pf) { - // case 2: next is free - size_t next_chunk_sz = CHUNK_S(n_hdr); - uint32_t new_hdr = PACK(next_chunk_sz + sz, pf); - SW(chunk_ptr, new_hdr); - SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr); - } else if (!CHUNK_A(n_hdr) && pf) { - // case 3: both free - uint32_t prev_ftr = LW(chunk_ptr - WSIZE); - size_t next_chunk_sz = CHUNK_S(n_hdr); - size_t prev_chunk_sz = CHUNK_S(prev_ftr); - uint32_t new_hdr = - PACK(next_chunk_sz + prev_chunk_sz + sz, CHUNK_PF(prev_ftr)); - SW(chunk_ptr - prev_chunk_sz, new_hdr); - SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr); - chunk_ptr -= prev_chunk_sz; - } - - // (fall through) case 4: prev and next are not free - return chunk_ptr; -} - -void* -lx_grow_heap(heap_context_t* heap, size_t sz) -{ - void* start; - - // The "+ WSIZE" capture the overhead for epilogue marker - if (!(start = lxsbrk(heap, sz + WSIZE, 0))) { - return NULL; - } - sz = ROUNDUP(sz, BOUNDARY); - - // minus the overhead for epilogue, keep the invariant. - heap->brk -= WSIZE; - - uint32_t old_marker = *((uint32_t*)start); - uint32_t free_hdr = PACK(sz, CHUNK_PF(old_marker)); - SW(start, free_hdr); - SW(FPTR(start, sz), free_hdr); - SW(NEXT_CHK(start), PACK(0, M_ALLOCATED | M_PREV_FREE)); - - return coalesce(start); -} \ No newline at end of file +// int +// kalloc_init() +// { +// kheap.start = KHEAP_START; +// kheap.brk = NULL; +// kheap.max_addr = +// (void*)PROC_START; // 在新的布局中,堆结束的地方即为进程表开始的地方 + +// for (size_t i = 0; i < KHEAP_SIZE_MB >> 2; i++) { +// vmm_set_mapping(PD_REFERENCED, +// (uintptr_t)kheap.start + (i << 22), +// 0, +// PG_PREM_RW, +// VMAP_NOMAP); +// } + +// if (!dmm_init(&kheap)) { +// return 0; +// } + +// SW(kheap.start, PACK(4, M_ALLOCATED)); +// SW(kheap.start + WSIZE, PACK(0, M_ALLOCATED)); +// kheap.brk += WSIZE; + +// return lx_grow_heap(&kheap, HEAP_INIT_SIZE) != NULL; +// } + +// void* +// lxmalloc(size_t size) +// { +// mutex_lock(&kheap.lock); +// void* r = lx_malloc_internal(&kheap, size); +// mutex_unlock(&kheap.lock); + +// return r; +// } + +// void* +// lxcalloc(size_t n, size_t elem) +// { +// size_t pd = n * elem; + +// // overflow detection +// if (pd < elem || pd < n) { +// return NULL; +// } + +// void* ptr = lxmalloc(pd); +// if (!ptr) { +// return NULL; +// } + +// return memset(ptr, 0, pd); +// } + +// void +// lxfree(void* ptr) +// { +// if (!ptr) { +// return; +// } +// mutex_lock(&kheap.lock); + +// uint8_t* chunk_ptr = (uint8_t*)ptr - WSIZE; +// uint32_t hdr = LW(chunk_ptr); +// size_t sz = CHUNK_S(hdr); +// uint8_t* next_hdr = chunk_ptr + sz; + +// // make sure the ptr we are 'bout to free makes sense +// // the size trick is stolen from glibc's malloc/malloc.c:4437 ;P + +// assert_msg(((uintptr_t)ptr < (uintptr_t)(-sz)) && !((uintptr_t)ptr & +// 0x3), +// "free(): invalid pointer"); + +// assert_msg(sz > WSIZE, "free(): invalid size"); + +// SW(chunk_ptr, hdr & ~M_ALLOCATED); +// SW(FPTR(chunk_ptr, sz), hdr & ~M_ALLOCATED); +// SW(next_hdr, LW(next_hdr) | M_PREV_FREE); + +// coalesce(chunk_ptr); + +// mutex_unlock(&kheap.lock); +// } + +// void* +// lx_malloc_internal(heap_context_t* heap, size_t size) +// { +// // Simplest first fit approach. + +// if (!size) { +// return NULL; +// } + +// uint8_t* ptr = heap->start; +// // round to largest 4B aligned value +// // and space for header +// size = ROUNDUP(size + WSIZE, BOUNDARY); +// while (ptr < (uint8_t*)heap->brk) { +// uint32_t header = *((uint32_t*)ptr); +// size_t chunk_size = CHUNK_S(header); +// if (!chunk_size && CHUNK_A(header)) { +// break; +// } +// if (chunk_size >= size && !CHUNK_A(header)) { +// // found! +// place_chunk(ptr, size); +// return BPTR(ptr); +// } +// ptr += chunk_size; +// } + +// // if heap is full (seems to be!), then allocate more space (if it's +// // okay...) +// if ((ptr = lx_grow_heap(heap, size))) { +// place_chunk(ptr, size); +// return BPTR(ptr); +// } + +// // Well, we are officially OOM! +// return NULL; +// } + +// void +// place_chunk(uint8_t* ptr, size_t size) +// { +// uint32_t header = *((uint32_t*)ptr); +// size_t chunk_size = CHUNK_S(header); +// *((uint32_t*)ptr) = PACK(size, CHUNK_PF(header) | M_ALLOCATED); +// uint8_t* n_hdrptr = (uint8_t*)(ptr + size); +// uint32_t diff = chunk_size - size; + +// if (!diff) { +// // if the current free block is fully occupied +// uint32_t n_hdr = LW(n_hdrptr); +// // notify the next block about our avaliability +// SW(n_hdrptr, n_hdr & ~0x2); +// } else { +// // if there is remaining free space left +// uint32_t remainder_hdr = PACK(diff, M_NOT_ALLOCATED | +// M_PREV_ALLOCATED); SW(n_hdrptr, remainder_hdr); SW(FPTR(n_hdrptr, +// diff), remainder_hdr); + +// /* +// | xxxx | | | + +// | +// v + +// | xxxx | | +// */ +// coalesce(n_hdrptr); +// } +// } + +// void* +// coalesce(uint8_t* chunk_ptr) +// { +// uint32_t hdr = LW(chunk_ptr); +// uint32_t pf = CHUNK_PF(hdr); +// uint32_t sz = CHUNK_S(hdr); + +// uint32_t n_hdr = LW(chunk_ptr + sz); + +// if (CHUNK_A(n_hdr) && pf) { +// // case 1: prev is free +// uint32_t prev_ftr = LW(chunk_ptr - WSIZE); +// size_t prev_chunk_sz = CHUNK_S(prev_ftr); +// uint32_t new_hdr = PACK(prev_chunk_sz + sz, CHUNK_PF(prev_ftr)); +// SW(chunk_ptr - prev_chunk_sz, new_hdr); +// SW(FPTR(chunk_ptr, sz), new_hdr); +// chunk_ptr -= prev_chunk_sz; +// } else if (!CHUNK_A(n_hdr) && !pf) { +// // case 2: next is free +// size_t next_chunk_sz = CHUNK_S(n_hdr); +// uint32_t new_hdr = PACK(next_chunk_sz + sz, pf); +// SW(chunk_ptr, new_hdr); +// SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr); +// } else if (!CHUNK_A(n_hdr) && pf) { +// // case 3: both free +// uint32_t prev_ftr = LW(chunk_ptr - WSIZE); +// size_t next_chunk_sz = CHUNK_S(n_hdr); +// size_t prev_chunk_sz = CHUNK_S(prev_ftr); +// uint32_t new_hdr = +// PACK(next_chunk_sz + prev_chunk_sz + sz, CHUNK_PF(prev_ftr)); +// SW(chunk_ptr - prev_chunk_sz, new_hdr); +// SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr); +// chunk_ptr -= prev_chunk_sz; +// } + +// // (fall through) case 4: prev and next are not free +// return chunk_ptr; +// } + +// void* +// lx_grow_heap(heap_context_t* heap, size_t sz) +// { +// void* start; + +// // The "+ WSIZE" capture the overhead for epilogue marker +// if (!(start = lxsbrk(heap, sz + WSIZE, 0))) { +// return NULL; +// } +// sz = ROUNDUP(sz, BOUNDARY); + +// // minus the overhead for epilogue, keep the invariant. +// heap->brk -= WSIZE; + +// uint32_t old_marker = *((uint32_t*)start); +// uint32_t free_hdr = PACK(sz, CHUNK_PF(old_marker)); +// SW(start, free_hdr); +// SW(FPTR(start, sz), free_hdr); +// SW(NEXT_CHK(start), PACK(0, M_ALLOCATED | M_PREV_FREE)); + +// return coalesce(start); +// } \ No newline at end of file diff --git a/lunaix-os/kernel/mm/mmio.c b/lunaix-os/kernel/mm/mmio.c index 5e0d01e..a52dc1b 100644 --- a/lunaix-os/kernel/mm/mmio.c +++ b/lunaix-os/kernel/mm/mmio.c @@ -1,11 +1,19 @@ #include #include #include +#include void* ioremap(uintptr_t paddr, uint32_t size) { - return vmm_vmap(paddr, size, PG_PREM_RW | PG_DISABLE_CACHE); + void* ptr = vmm_vmap(paddr, size, PG_PREM_RW | PG_DISABLE_CACHE); + if (ptr) { + pmm_mark_chunk_occupied(KERNEL_PID, + paddr >> PG_SIZE_BITS, + CEIL(size, PG_SIZE_BITS), + PP_FGLOCKED); + } + return ptr; } void* diff --git a/lunaix-os/kernel/mm/region.c b/lunaix-os/kernel/mm/region.c index 920c35b..bd3b26e 100644 --- a/lunaix-os/kernel/mm/region.c +++ b/lunaix-os/kernel/mm/region.c @@ -21,7 +21,7 @@ region_release_all(struct mm_region* regions) llist_for_each(pos, n, ®ions->head, head) { - lxfree(pos); + vfree(pos); } } diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c index 2fc1298..7507b1a 100644 --- a/lunaix-os/kernel/mm/vmap.c +++ b/lunaix-os/kernel/mm/vmap.c @@ -26,18 +26,18 @@ vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr) current_addr = (current_addr & 0xffc00000) + MEM_4MB; } else { x86_page_table* ptd = (x86_page_table*)(L2_VADDR(l1inx)); - size_t i = L2_INDEX(current_addr); - for (; i < PG_MAX_ENTRIES && examed_size < size; i++) { + size_t i = L2_INDEX(current_addr), j = 0; + for (; i < PG_MAX_ENTRIES && examed_size < size; i++, j++) { if (!ptd->entry[i]) { examed_size += PG_SIZE; } else if (examed_size) { // found a discontinuity, start from beginning examed_size = 0; - i++; + j++; break; } } - current_addr += i << 12; + current_addr += j << 12; } if (examed_size >= size) { @@ -46,6 +46,7 @@ vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr) if (current_addr >= VMAP_END) { wrapped = 1; + examed_size = 0; current_addr = VMAP_START; } } diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index 6905b1e..6f17176 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,6 @@ LOG_MODULE("PS2KBD"); static struct ps2_cmd_queue cmd_q; -static struct ps2_key_buffer key_buf; static struct ps2_kbd_state kbd_state; #define KEY_NUM(x) (x + 0x30) @@ -69,18 +69,21 @@ static kbd_keycode_t scancode_set2_shift[] = { // clang-format on +static struct input_device* kbd_idev; + #define KBD_STATE_KWAIT 0x00 #define KBD_STATE_KSPECIAL 0x01 #define KBD_STATE_KRELEASED 0x02 +#define KBD_STATE_E012 0x03 +#define KBD_STATE_KRELEASED_E0 0x04 #define KBD_STATE_CMDPROCS 0x40 -#define KBD_ENABLE_SPIRQ_FIX +// #define KBD_ENABLE_SPIRQ_FIX +#define KBD_ENABLE_SPIRQ_FIX2 // #define KBD_DBGLOG void intr_ps2_kbd_handler(const isr_param* param); -static struct kdb_keyinfo_pkt* -ps2_keybuffer_next_write(); void ps2_device_post_cmd(char cmd, char arg) @@ -107,15 +110,15 @@ ps2_kbd_init() { memset(&cmd_q, 0, sizeof(cmd_q)); - memset(&key_buf, 0, sizeof(key_buf)); memset(&kbd_state, 0, sizeof(kbd_state)); mutex_init(&cmd_q.mutex); - mutex_init(&key_buf.mutex); kbd_state.translation_table = scancode_set2; kbd_state.state = KBD_STATE_KWAIT; + kbd_idev = input_add_device("i8042-kbd"); + acpi_context* acpi_ctx = acpi_get_context(); if (acpi_ctx->fadt.header.rev > 1) { /* @@ -132,13 +135,13 @@ ps2_kbd_init() * https://bochs.sourceforge.io/cgi-bin/lxr/source/bios/rombios32.c#L1314 */ if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) { - kprintf(KERROR "No PS/2 controller detected.\n"); + kprintf(KERROR "i8042: not found\n"); // FUTURE: Some alternative fallback on this? Check PCI bus for USB // controller instead? return; } } else { - kprintf(KWARN "Outdated FADT used, assuming 8042 always exist.\n"); + kprintf(KWARN "i8042: outdated FADT used, assuming exists.\n"); } char result; @@ -271,14 +274,13 @@ kbd_buffer_key_event(kbd_keycode_t key, uint8_t scancode, kbd_kstate_t state) key = key & (0xffdf | -('a' > key || key > 'z' || !(state & KBD_KEY_FCAPSLKED))); - if (!mutex_on_hold(&key_buf.mutex)) { - struct kdb_keyinfo_pkt* keyevent_pkt = ps2_keybuffer_next_write(); - *keyevent_pkt = - (struct kdb_keyinfo_pkt){ .keycode = key, - .scancode = scancode, - .state = state, - .timestamp = clock_systime() }; - } + struct input_evt_pkt ipkt = { .pkt_type = (state & KBD_KEY_FPRESSED) + ? PKT_PRESS + : PKT_RELEASE, + .scan_code = scancode, + .sys_code = (state << 16) | key }; + + input_fire_event(kbd_idev, &ipkt); return; } @@ -337,6 +339,12 @@ intr_ps2_kbd_handler(const isr_param* param) } #endif +#ifdef KBD_ENABLE_SPIRQ_FIX2 + if (scancode == PS2_RESULT_ACK || scancode == PS2_RESULT_NAK) { + return; + } +#endif + #ifdef KBD_DBGLOG kprintf(KDEBUG "%x\n", scancode & 0xff); #endif @@ -354,8 +362,10 @@ intr_ps2_kbd_handler(const isr_param* param) } break; case KBD_STATE_KSPECIAL: - if (scancode == 0xf0) { // release code - kbd_state.state = KBD_STATE_KRELEASED; + if (scancode == 0x12) { + kbd_state.state = KBD_STATE_E012; + } else if (scancode == 0xf0) { // release code + kbd_state.state = KBD_STATE_KRELEASED_E0; } else { key = kbd_state.translation_table[scancode]; kbd_buffer_key_event(key, scancode, KBD_KEY_FPRESSED); @@ -364,10 +374,23 @@ intr_ps2_kbd_handler(const isr_param* param) kbd_state.translation_table = scancode_set2; } break; + // handle the '0xE0, 0x12, 0xE0, xx' sequence + case KBD_STATE_E012: + if (scancode == 0xe0) { + kbd_state.state = KBD_STATE_KSPECIAL; + kbd_state.translation_table = scancode_set2_ex; + } + break; + case KBD_STATE_KRELEASED_E0: + if (scancode == 0x12) { + goto escape_release; + } + // fall through case KBD_STATE_KRELEASED: key = kbd_state.translation_table[scancode]; kbd_buffer_key_event(key, scancode, KBD_KEY_FRELEASED); + escape_release: // reset the translation table to scancode_set2 kbd_state.state = KBD_STATE_KWAIT; kbd_state.translation_table = scancode_set2; @@ -419,37 +442,4 @@ ps2_issue_dev_cmd(char cmd, uint16_t arg) ; return io_inb(PS2_PORT_ENC_CMDREG); -} - -int -kbd_recv_key(struct kdb_keyinfo_pkt* key_event) -{ - if (!key_buf.buffered_len) { - return 0; - } - - mutex_lock(&key_buf.mutex); - *key_event = key_buf.buffer[key_buf.read_ptr]; - key_buf.buffered_len--; - key_buf.read_ptr = (key_buf.read_ptr + 1) % PS2_KBD_RECV_BUFFER_SIZE; - - mutex_unlock(&key_buf.mutex); - return 1; -} - -static struct kdb_keyinfo_pkt* -ps2_keybuffer_next_write() -{ - int index = - (key_buf.read_ptr + key_buf.buffered_len) % PS2_KBD_RECV_BUFFER_SIZE; - if (index == key_buf.read_ptr && key_buf.buffered_len) { - // the reader is lagged so much such that the buffer is full. - // It is suggested to read from beginning for nearly up-to-date - // readings. - key_buf.read_ptr = 0; - key_buf.buffered_len = index; - } else { - key_buf.buffered_len++; - } - return &key_buf.buffer[index]; } \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index e137b8e..e242196 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -27,6 +27,8 @@ #include +#include + LOG_MODULE("PROC0") extern void @@ -46,8 +48,10 @@ __do_reserved_memory(int unlock); #define USE_DEMO // #define DEMO_SIGNAL -#define DEMO_READDIR -//#define DEMO_IOTEST +// #define DEMO_READDIR +// #define DEMO_IOTEST +// #define DEMO_INPUT_TEST +#define DEMO_SIMPLE_SH extern void _pconsole_main(); @@ -64,19 +68,25 @@ _readdir_main(); extern void _iotest_main(); +extern void +input_test(); + +extern void +sh_main(); + void __USER__ __proc0_usr() { // 打开tty设备(控制台),作为标准输入输出。 // tty设备属于序列设备(Sequential Device),该类型设备的上层读写 // 无须经过Lunaix的缓存层,而是直接下发到底层驱动。(不受FO_DIRECT的影响) - int stdout = open("/dev/tty", 0); - int stdin = dup2(stdout, 1); + int fdstdout = open("/dev/tty", 0); + int fdstdin = dup2(stdout, 1); pid_t p; - if (!fork()) { - _pconsole_main(); - } + // if (!fork()) { + // _pconsole_main(); + // } if (!(p = fork())) { #ifndef USE_DEMO @@ -87,9 +97,15 @@ __proc0_usr() _readdir_main(); #elif defined DEMO_IOTEST _iotest_main(); +#elif defined DEMO_INPUT_TEST + input_test(); +#elif defined DEMO_SIMPLE_SH + sh_main(); #else _lxinit_main(); #endif + printf("==== test end ====\n"); + _exit(0); } waitpid(p, 0, 0); @@ -141,9 +157,6 @@ init_platform() // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 lock_reserved_memory(); - // we are using no kalloc! - // assert_msg(kalloc_init(), "Fail to initialize heap"); - rtc_init(); acpi_init(_k_init_mb_info); apic_init(); @@ -154,20 +167,23 @@ init_platform() pci_init(); block_init(); ahci_init(); - // ahci_list_device(); - // cake_stats(); syscall_install(); console_start_flushing(); console_flush(); + cake_export(); unlock_reserved_memory(); for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) { vmm_del_mapping(PD_REFERENCED, (void*)i); pmm_free_page(KERNEL_PID, (void*)i); } + + for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) { + vmm_set_mapping(PD_REFERENCED, i << 22, 0, 0, VMAP_NOMAP); + } } void diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process/process.c similarity index 97% rename from lunaix-os/kernel/process.c rename to lunaix-os/kernel/process/process.c index 086a5e3..82f1ffa 100644 --- a/lunaix-os/kernel/process.c +++ b/lunaix-os/kernel/process/process.c @@ -123,7 +123,7 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid) struct proc_info* gruppenfuhrer = get_process(pgid); - if (!gruppenfuhrer || proc->pgid == proc->pid) { + if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) { __current->k_status = EINVAL; return -1; } @@ -151,7 +151,7 @@ init_proc_user_space(struct proc_info* pcb) vmm_set_mapping(PD_MOUNT_1, i, 0, PG_ALLOW_USER | PG_WRITE, VMAP_NULL); } - // todo: other uspace initialization stuff + // TODO other uspace initialization stuff vmm_unmount_pd(PD_MOUNT_1); } @@ -196,6 +196,11 @@ dup_proc() pcb->intr_ctx = __current->intr_ctx; pcb->parent = __current; + if (__current->cwd) { + pcb->cwd = __current->cwd; + vfs_ref_dnode(pcb->cwd); + } + __copy_fdtable(pcb); region_copy(&__current->mm.regions, &pcb->mm.regions); diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/process/sched.c similarity index 79% rename from lunaix-os/kernel/sched.c rename to lunaix-os/kernel/process/sched.c index f8f00d4..3ee0e76 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include #include @@ -16,28 +18,31 @@ #include #include -#define MAX_PROCESS 512 - volatile struct proc_info* __current; struct proc_info dummy; struct scheduler sched_ctx; +struct cake_pile* proc_pile; + LOG_MODULE("SCHED") void sched_init() { - size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000); + // size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000); - for (size_t i = 0; i <= pg_size; i += 4096) { - uintptr_t pa = pmm_alloc_page(KERNEL_PID, PP_FGPERSIST); - vmm_set_mapping( - PD_REFERENCED, PROC_START + i, pa, PG_PREM_RW, VMAP_NULL); - } + // for (size_t i = 0; i <= pg_size; i += 4096) { + // uintptr_t pa = pmm_alloc_page(KERNEL_PID, PP_FGPERSIST); + // vmm_set_mapping( + // PD_REFERENCED, PROC_START + i, pa, PG_PREM_RW, VMAP_NULL); + // } - sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)PROC_START, + proc_pile = cake_new_pile("proc", sizeof(struct proc_info), 1, 0); + cake_set_constructor(proc_pile, cake_ctor_zeroing); + + sched_ctx = (struct scheduler){ ._procs = vzalloc(PROC_TABLE_SIZE), .ptable_len = 0, .procs_index = 0 }; } @@ -80,7 +85,7 @@ can_schedule(struct proc_info* proc) void check_sleepers() { - struct proc_info* leader = &sched_ctx._procs[0]; + struct proc_info* leader = sched_ctx._procs[0]; struct proc_info *pos, *n; time_t now = clock_systime(); llist_for_each(pos, n, &leader->sleep.sleepers, sleep.sleepers) @@ -94,7 +99,7 @@ check_sleepers() if (wtime && now >= wtime) { pos->sleep.wakeup_time = 0; - pos->state = PS_STOPPED; + pos->state = PS_READY; } if (atime && now >= atime) { @@ -123,7 +128,7 @@ schedule() int ptr = prev_ptr; if (!(__current->state & ~PS_RUNNING)) { - __current->state = PS_STOPPED; + __current->state = PS_READY; } check_sleepers(); @@ -132,8 +137,8 @@ schedule() redo: do { ptr = (ptr + 1) % sched_ctx.ptable_len; - next = &sched_ctx._procs[ptr]; - } while (next->state != PS_STOPPED && ptr != prev_ptr); + next = sched_ctx._procs[ptr]; + } while (!next || (next->state != PS_READY && ptr != prev_ptr)); sched_ctx.procs_index = ptr; @@ -148,6 +153,7 @@ redo: void sched_yieldk() { + cpu_enable_interrupt(); cpu_int(LUNAIX_SCHED); } @@ -161,9 +167,9 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) return (__current->sleep.wakeup_time - clock_systime()) / 1000U; } + struct proc_info* root_proc = sched_ctx._procs[0]; __current->sleep.wakeup_time = clock_systime() + seconds * 1000; - llist_append(&sched_ctx._procs[0].sleep.sleepers, - &__current->sleep.sleepers); + llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers); __current->intr_ctx.registers.eax = seconds; __current->state = PS_BLOCKED; @@ -177,9 +183,9 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds) __current->sleep.alarm_time = seconds ? now + seconds * 1000 : 0; + struct proc_info* root_proc = sched_ctx._procs[0]; if (llist_empty(&__current->sleep.sleepers)) { - llist_append(&sched_ctx._procs[0].sleep.sleepers, - &__current->sleep.sleepers); + llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers); } return prev_ddl ? (prev_ddl - now) / 1000 : 0; @@ -233,7 +239,7 @@ repeat: status_flags |= PEXITTERM; goto done; } - if (proc->state == PS_STOPPED && (options & WUNTRACED)) { + if (proc->state == PS_READY && (options & WUNTRACED)) { status_flags |= PEXITSTOP; goto done; } @@ -258,8 +264,7 @@ struct proc_info* alloc_process() { pid_t i = 0; - for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PS_DESTROY; - i++) + for (; i < sched_ctx.ptable_len && sched_ctx._procs[i]; i++) ; if (i == MAX_PROCESS) { @@ -270,8 +275,7 @@ alloc_process() sched_ctx.ptable_len++; } - struct proc_info* proc = &sched_ctx._procs[i]; - memset(proc, 0, sizeof(*proc)); + struct proc_info* proc = cake_grab(proc_pile); proc->state = PS_CREATED; proc->pid = i; @@ -280,9 +284,13 @@ alloc_process() proc->fdtable = vzalloc(sizeof(struct v_fdtable)); llist_init_head(&proc->mm.regions.head); + llist_init_head(&proc->tasks); llist_init_head(&proc->children); llist_init_head(&proc->grp_member); llist_init_head(&proc->sleep.sleepers); + waitq_init(&proc->waitqueue); + + sched_ctx._procs[i] = proc; return proc; } @@ -290,7 +298,7 @@ alloc_process() void commit_process(struct proc_info* process) { - assert(process == &sched_ctx._procs[process->pid]); + assert(process == sched_ctx._procs[process->pid]); if (process->state != PS_CREATED) { __current->k_status = EINVAL; @@ -299,12 +307,13 @@ commit_process(struct proc_info* process) // every process is the child of first process (pid=1) if (!process->parent) { - process->parent = &sched_ctx._procs[1]; + process->parent = sched_ctx._procs[1]; } llist_append(&process->parent->children, &process->siblings); + llist_append(&sched_ctx._procs[0]->tasks, &process->tasks); - process->state = PS_STOPPED; + process->state = PS_READY; } // from @@ -319,14 +328,24 @@ destroy_process(pid_t pid) __current->k_status = EINVAL; return; } - struct proc_info* proc = &sched_ctx._procs[index]; - proc->state = PS_DESTROY; + struct proc_info* proc = sched_ctx._procs[index]; + sched_ctx._procs[index] = 0; + llist_delete(&proc->siblings); + llist_delete(&proc->grp_member); + llist_delete(&proc->tasks); + llist_delete(&proc->sleep.sleepers); + + taskfs_invalidate(pid); + + if (proc->cwd) { + vfs_unref_dnode(proc->cwd); + } for (size_t i = 0; i < VFS_MAX_FD; i++) { struct v_fd* fd = proc->fdtable->fds[i]; if (fd) - vfs_close(fd->file); + vfs_pclose(fd->file, pid); } vfree(proc->fdtable); @@ -343,6 +362,8 @@ destroy_process(pid_t pid) vmm_unmount_pd(PD_MOUNT_1); + cake_release(proc_pile, proc); + return pid; } @@ -362,7 +383,7 @@ get_process(pid_t pid) if (index < 0 || index > sched_ctx.ptable_len) { return NULL; } - return &sched_ctx._procs[index]; + return sched_ctx._procs[index]; } int @@ -372,7 +393,7 @@ orphaned_proc(pid_t pid) return 0; if (pid >= sched_ctx.ptable_len) return 0; - struct proc_info* proc = &sched_ctx._procs[pid]; + struct proc_info* proc = sched_ctx._procs[pid]; struct proc_info* parent = proc->parent; // 如果其父进程的状态是terminated 或 destroy中的一种 diff --git a/lunaix-os/kernel/signal.c b/lunaix-os/kernel/process/signal.c similarity index 99% rename from lunaix-os/kernel/signal.c rename to lunaix-os/kernel/process/signal.c index 5f0c868..5d09d9b 100644 --- a/lunaix-os/kernel/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -126,7 +126,6 @@ send_grp: { __SIGSET(pos->sig_pending, signum); } - return 0; send_single: if (PROC_TERMINATED(proc->state)) { diff --git a/lunaix-os/kernel/process/task_attr.c b/lunaix-os/kernel/process/task_attr.c new file mode 100644 index 0000000..4610acf --- /dev/null +++ b/lunaix-os/kernel/process/task_attr.c @@ -0,0 +1,103 @@ +#include + +void +__read_pending_sig(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + twimap_printf(map, "%bb", proc->sig_pending); +} + +void +__read_masked_sig(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + twimap_printf(map, "%bb", proc->sig_mask); +} + +void +__read_parent(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + twimap_printf(map, "%d", proc->parent->pid); +} + +void +__read_ctimestamp(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + twimap_printf(map, "%d", proc->created); +} + +void +__read_pgid(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + twimap_printf(map, "%d", proc->pgid); +} + +void +__read_children(struct twimap* map) +{ + struct llist_header* proc_list = twimap_index(map, struct llist_header*); + struct proc_info* proc = + container_of(proc_list, struct proc_info, siblings); + if (!proc) + return; + twimap_printf(map, "%d ", proc->pid); +} + +int +__next_children(struct twimap* map) +{ + struct llist_header* proc = twimap_index(map, struct llist_header*); + struct proc_info* current = twimap_data(map, struct proc_info*); + if (!proc) + return 0; + map->index = proc->next; + if (map->index == ¤t->children) { + return 0; + } + return 1; +} + +void +__reset_children(struct twimap* map) +{ + struct proc_info* proc = twimap_data(map, struct proc_info*); + if (llist_empty(&proc->children)) { + map->index = 0; + return; + } + map->index = proc->children.next; +} + +void +export_task_attr() +{ + struct twimap* map; + map = twimap_create(NULL); + map->read = __read_pending_sig; + taskfs_export_attr("sig_pending", map); + + map = twimap_create(NULL); + map->read = __read_masked_sig; + taskfs_export_attr("sig_masked", map); + + map = twimap_create(NULL); + map->read = __read_parent; + taskfs_export_attr("parent", map); + + map = twimap_create(NULL); + map->read = __read_ctimestamp; + taskfs_export_attr("created", map); + + map = twimap_create(NULL); + map->read = __read_pgid; + taskfs_export_attr("pgid", map); + + map = twimap_create(NULL); + map->read = __read_children; + map->go_next = __next_children; + map->reset = __reset_children; + taskfs_export_attr("children", map); +} \ No newline at end of file diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c new file mode 100644 index 0000000..28c3713 --- /dev/null +++ b/lunaix-os/kernel/process/taskfs.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define COUNTER_MASK ((1 << 16) - 1) + +static struct hbucket* attr_export_table; +static DEFINE_LLIST(attributes); +static volatile int ino_cnt = 1; + +int +taskfs_next_counter() +{ + return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1); +} + +inode_t +taskfs_inode_id(pid_t pid, int sub_counter) +{ + return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK); +} + +int +taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype) +{ + inode_t ino = taskfs_inode_id(pid, sub_counter); + + struct v_superblock* vsb = dnode->super_block; + struct v_inode* inode = vfs_i_find(vsb, ino); + if (!inode) { + if (!(inode = vfs_i_alloc(vsb))) { + return ENOMEM; + } + inode->id = ino; + inode->itype = itype; + vfs_i_addhash(inode); + } + + vfs_assign_inode(dnode, inode); + return 0; +} + +int +taskfs_readdir(struct v_file* file, struct dir_context* dctx) +{ + struct v_inode* inode = file->inode; + pid_t pid = inode->id >> 16; + int counter = 0; + + if ((inode->id & COUNTER_MASK)) { + return ENOTDIR; + } + + if (pid) { + struct task_attribute *pos, *n; + llist_for_each(pos, n, &attributes, siblings) + { + if (counter == dctx->index) { + dctx->read_complete_callback( + dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE); + return 1; + } + counter++; + } + return 0; + } + + char name[VFS_NAME_MAXLEN]; + struct proc_info *root = get_process(pid), *pos, *n; + llist_for_each(pos, n, &root->tasks, tasks) + { + if (counter == dctx->index) { + ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid); + dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR); + return 1; + } + counter++; + } + return 0; +} + +// ascii to pid +pid_t +taskfs_atop(const char* str) +{ + pid_t t = 0; + int i = 0; + char c; + while ((c = str[i++])) { + if ('0' > c || c > '9') { + return -1; + } + t = t * 10 + (c - '0'); + } + return t; +} + +int +taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) +{ + pid_t pid = this->id >> 16; + struct proc_info* proc; + + if (pid) { + struct task_attribute* tattr = taskfs_get_attr(&dnode->name); + if (!tattr || !(proc = get_process(pid))) + return ENOENT; + + int errno = + taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFSEQDEV); + if (!errno) { + tattr->map_file->data = proc; + dnode->inode->data = tattr->map_file; + dnode->inode->default_fops = &twimap_file_ops; + } + return errno; + } + + pid = taskfs_atop(dnode->name.value); + + if (pid <= 0 || !(proc = get_process(pid))) { + return ENOENT; + } + + return taskfs_mknod(dnode, pid, 0, VFS_IFDIR); +} + +static struct v_file_ops taskfs_file_ops = { .close = default_file_close, + .read = default_file_read, + .write = default_file_write, + .readdir = taskfs_readdir, + .seek = default_file_seek }; +static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup, + .open = default_inode_open, + .mkdir = default_inode_mkdir, + .rmdir = default_inode_rmdir, + .rename = default_inode_rename }; + +void +taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) +{ + inode->default_fops = &taskfs_file_ops; + inode->ops = &taskfs_inode_ops; +} + +static volatile struct v_superblock* taskfs_sb; + +int +taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) +{ + taskfs_sb = vsb; + vsb->ops.init_inode = taskfs_init_inode; + + return taskfs_mknod(mount_point, 0, 0, VFS_IFDIR); +} + +void +taskfs_invalidate(pid_t pid) +{ + struct v_dnode *pos, *n; + struct v_inode* inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0)); + + if (!inode) + return; + + llist_for_each(pos, n, &inode->aka_dnodes, aka_list) + { + if (pos->ref_count > 1) { + continue; + } + vfs_d_free(pos); + } +} + +#define ATTR_TABLE_LEN 16 + +void +taskfs_export_attr(const char* key, struct twimap* attr_map_file) +{ + struct task_attribute* tattr = valloc(sizeof(*tattr)); + + tattr->map_file = attr_map_file; + tattr->key = HSTR(tattr->key_val, 0); + strncpy(tattr->key_val, key, 32); + hstr_rehash(&tattr->key, HSTR_FULL_HASH); + + struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN]; + hlist_add(&slot->head, &tattr->attrs); + llist_append(&attributes, &tattr->siblings); +} + +struct task_attribute* +taskfs_get_attr(struct hstr* key) +{ + struct hbucket* slot = &attr_export_table[key->hash % ATTR_TABLE_LEN]; + struct task_attribute *pos, *n; + hashtable_bucket_foreach(slot, pos, n, attrs) + { + if (HSTR_EQ(&pos->key, key)) { + return pos; + } + } + return NULL; +} + +extern void +export_task_attr(); + +void +taskfs_init() +{ + struct filesystem* taskfs = fsm_new_fs("taskfs", 5); + taskfs->mount = taskfs_mount; + + fsm_register(taskfs); + + attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket)); + + export_task_attr(); +} \ No newline at end of file diff --git a/lunaix-os/kernel/service/pconsole.c b/lunaix-os/kernel/service/pconsole.c deleted file mode 100644 index 200303d..0000000 --- a/lunaix-os/kernel/service/pconsole.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include - -void -_pconsole_main() -{ - struct kdb_keyinfo_pkt keyevent; - while (1) { - if (!kbd_recv_key(&keyevent)) { - yield(); - continue; - } - if ((keyevent.state & KBD_KEY_FPRESSED)) { - if (keyevent.keycode == KEY_UP) { - console_view_up(); - } else if (keyevent.keycode == KEY_DOWN) { - console_view_down(); - } - } - } -} \ No newline at end of file diff --git a/lunaix-os/kernel/spike.c b/lunaix-os/kernel/spike.c index 87726b0..860b201 100644 --- a/lunaix-os/kernel/spike.c +++ b/lunaix-os/kernel/spike.c @@ -7,7 +7,7 @@ static char buffer[1024]; void __assert_fail(const char* expr, const char* file, unsigned int line) { - sprintf(buffer, "%s (%s:%u)", expr, file, line); + ksprintf(buffer, "%s (%s:%u)", expr, file, line); // Here we load the buffer's address into %edi ("D" constraint) // This is a convention we made that the LUNAIX_SYS_PANIC syscall will @@ -30,7 +30,7 @@ panickf(const char* fmt, ...) { va_list args; va_start(args, fmt); - __sprintf_internal(buffer, fmt, 1024, args); + __ksprintf_internal(buffer, fmt, 1024, args); va_end(args); asm("int %0" ::"i"(LUNAIX_SYS_PANIC), "D"(buffer)); diff --git a/lunaix-os/kernel/time/clock.c b/lunaix-os/kernel/time/clock.c index 15a6a32..0f04575 100644 --- a/lunaix-os/kernel/time/clock.c +++ b/lunaix-os/kernel/time/clock.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -8,6 +9,52 @@ static volatile time_t sys_time; void clock_systime_counter(void* arg); +void +__clock_read_systime(struct twimap* map) +{ + time_t save = sys_time; + twimap_printf(map, "%u", save); +} + +void +__clock_read_datetime(struct twimap* map) +{ + datetime_t dt; + clock_walltime(&dt); + twimap_printf(map, + "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", + dt.year, + dt.month, + dt.day, + dt.hour, + dt.minute, + dt.second); +} + +void +__clock_read_unix(struct twimap* map) +{ + datetime_t dt; + clock_walltime(&dt); + twimap_printf(map, "%u", clock_tounixtime(&dt)); +} + +void +clock_build_mapping() +{ + struct twifs_node* root = twifs_dir_node(NULL, "clock"); + struct twimap* map; + + map = twifs_mapping(root, NULL, "systime"); + map->read = __clock_read_systime; + + map = twifs_mapping(root, NULL, "unix"); + map->read = __clock_read_unix; + + map = twifs_mapping(root, NULL, "datetime"); + map->read = __clock_read_datetime; +} + void clock_init() { @@ -17,6 +64,8 @@ clock_init() // 系统计时器每毫秒累加。 timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC); + + clock_build_mapping(); } void diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c new file mode 100644 index 0000000..ad3fc42 --- /dev/null +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct console lx_console; + +int +__tty_write(struct device* dev, void* buf, size_t offset, size_t len); + +int +__tty_read(struct device* dev, void* buf, size_t offset, size_t len); + +void +console_flush(); + +static waitq_t lx_reader; +static volatile char ttychr; + +static pid_t fg_pgid = 0; + +inline void +print_control_code(const char cntrl) +{ + console_write_char('^'); + console_write_char(cntrl + 64); +} + +int +__lxconsole_listener(struct input_device* dev) +{ + uint32_t key = dev->current_pkt.sys_code; + uint32_t type = dev->current_pkt.pkt_type; + kbd_kstate_t state = key >> 16; + ttychr = key & 0xff; + key = key & 0xffff; + + if (type == PKT_RELEASE) { + goto done; + } + + if ((state & KBD_KEY_FLCTRL_HELD)) { + char cntrl = (char)(ttychr | 0x20); + if ('a' > cntrl || cntrl > 'z') { + goto done; + } + ttychr = cntrl - 'a' + 1; + switch (ttychr) { + case TCINTR: + signal_send(-fg_pgid, _SIGINT); + print_control_code(ttychr); + break; + case TCSTOP: + signal_send(-fg_pgid, _SIGSTOP); + print_control_code(ttychr); + break; + default: + break; + } + } else if (key == KEY_PG_UP) { + console_view_up(); + goto done; + } else if (key == KEY_PG_DOWN) { + console_view_down(); + goto done; + } else if ((key & 0xff00) <= KEYPAD) { + ttychr = key; + } else { + goto done; + } + + pwake_all(&lx_reader); + +done: + return INPUT_EVT_NEXT; +} + +int +__tty_exec_cmd(struct device* dev, uint32_t req, va_list args) +{ + switch (req) { + case TIOCGPGRP: + return fg_pgid; + case TIOCSPGRP: + fg_pgid = va_arg(args, pid_t); + break; + case TIOCCLSBUF: + fifo_clear(&lx_console.output); + fifo_clear(&lx_console.input); + lx_console.wnd_start = 0; + lx_console.lines = 0; + lx_console.output.flags |= FIFO_DIRTY; + break; + case TIOCFLUSH: + lx_console.output.flags |= FIFO_DIRTY; + console_flush(); + break; + default: + return EINVAL; + } + return 0; +} + +void +lxconsole_init() +{ + memset(&lx_console, 0, sizeof(lx_console)); + fifo_init(&lx_console.output, valloc(8192), 8192, 0); + fifo_init(&lx_console.input, valloc(4096), 4096, 0); + + lx_console.flush_timer = NULL; + + struct device* tty_dev = device_addseq(NULL, &lx_console, "tty"); + tty_dev->write = __tty_write; + tty_dev->read = __tty_read; + tty_dev->exec_cmd = __tty_exec_cmd; + + waitq_init(&lx_reader); + input_add_listener(__lxconsole_listener); +} + +int +__tty_write(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct console* console = (struct console*)dev->underlay; + console_write(console, buf, len); +} + +int +__tty_read(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct console* console = (struct console*)dev->underlay; + + size_t count = fifo_read(&console->input, buf, len); + if (count > 0 && ((char*)buf)[count - 1] == '\n') { + return count; + } + + while (count < len) { + pwait(&lx_reader); + + if (ttychr < 0x1B) { + // ASCII control codes + switch (ttychr) { + case TCINTR: + fifo_clear(&console->input); + return 0; + case TCBS: + if (fifo_backone(&console->input)) { + console_write_char(ttychr); + } + continue; + case TCLF: + case TCCR: + goto proceed; + default: + break; + } + print_control_code(ttychr); + continue; + } + + proceed: + console_write_char(ttychr); + if (!fifo_putone(&console->input, ttychr) || ttychr == '\n') { + break; + } + } + return count + fifo_read(&console->input, buf + count, len - count); +} + +void +console_schedule_flush() +{ + // TODO make the flush on-demand rather than periodic +} + +size_t +__find_next_line(size_t start) +{ + size_t p = start - 1; + struct fifo_buf* buffer = &lx_console.output; + do { + p = (p + 1) % buffer->size; + } while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n'); + return p + (((char*)buffer->data)[p] == '\n'); +} + +size_t +__find_prev_line(size_t start) +{ + size_t p = start - 1; + struct fifo_buf* buffer = &lx_console.output; + do { + p--; + } while (p < lx_console.wnd_start && p != buffer->wr_pos && + ((char*)buffer->data)[p] != '\n'); + + if (p > lx_console.wnd_start) { + return 0; + } + return p + 1; +} + +void +console_view_up() +{ + struct fifo_buf* buffer = &lx_console.output; + mutex_lock(&buffer->lock); + fifo_set_rdptr(buffer, __find_prev_line(buffer->rd_pos)); + buffer->flags |= FIFO_DIRTY; + mutex_unlock(&buffer->lock); + + console_flush(); +} + +void +console_view_down() +{ + struct fifo_buf* buffer = &lx_console.output; + mutex_lock(&buffer->lock); + + size_t wnd = lx_console.wnd_start; + size_t p = __find_next_line(buffer->rd_pos); + fifo_set_rdptr(buffer, p > wnd ? wnd : p); + buffer->flags |= FIFO_DIRTY; + mutex_unlock(&buffer->lock); + + console_flush(); +} + +void +console_flush() +{ + if (mutex_on_hold(&lx_console.output.lock)) { + return; + } + if (!(lx_console.output.flags & FIFO_DIRTY)) { + return; + } + + size_t rdpos_save = lx_console.output.rd_pos; + tty_flush_buffer(&lx_console.output); + fifo_set_rdptr(&lx_console.output, rdpos_save); + + lx_console.output.flags &= ~FIFO_DIRTY; +} + +void +console_write(struct console* console, uint8_t* data, size_t size) +{ + struct fifo_buf* fbuf = &console->output; + mutex_lock(&console->output.lock); + fifo_set_rdptr(fbuf, console->wnd_start); + + uint8_t* buffer = fbuf->data; + uintptr_t ptr = fbuf->wr_pos; + uintptr_t rd_ptr = fbuf->rd_pos; + + char c; + for (size_t i = 0; i < size; i++) { + c = data[i]; + if (!c) { + continue; + } + if (c == '\n') { + console->lines++; + } else if (c == '\x08') { + ptr = ptr ? ptr - 1 : fbuf->size - 1; + continue; + } + buffer[ptr] = c; + ptr = (ptr + 1) % fbuf->size; + } + + fifo_set_wrptr(fbuf, ptr); + + while (console->lines >= TTY_HEIGHT) { + rd_ptr = __find_next_line(rd_ptr); + console->lines--; + } + + fifo_set_rdptr(&lx_console.output, rd_ptr); + console->wnd_start = rd_ptr; + fbuf->flags |= FIFO_DIRTY; + mutex_unlock(&fbuf->lock); +} + +void +console_write_str(char* str) +{ + console_write(&lx_console, str, strlen(str)); +} + +void +console_write_char(char str) +{ + console_write(&lx_console, &str, 1); +} + +void +console_start_flushing() +{ + struct lx_timer* timer = + timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC); + lx_console.flush_timer = timer; +} \ No newline at end of file diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index d4ac8d0..b8631b6 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -6,22 +6,25 @@ #include #include -vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; +vga_attribute* tty_vga_buffer; vga_attribute tty_theme_color = VGA_COLOR_BLACK; -#define TTY_CLEAR \ - asm volatile("rep stosw" ::"D"(tty_vga_buffer), \ - "c"(TTY_HEIGHT * TTY_WIDTH), \ - "a"(tty_theme_color) \ +inline void +tty_clear() +{ + asm volatile("rep stosw" ::"D"(tty_vga_buffer), + "c"(TTY_HEIGHT * TTY_WIDTH), + "a"(tty_theme_color) : "memory"); +} void tty_init(void* vga_buf) { tty_vga_buffer = (vga_attribute*)vga_buf; - TTY_CLEAR + tty_clear(); io_outb(0x3D4, 0x0A); io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); @@ -36,23 +39,19 @@ tty_set_theme(vga_attribute fg, vga_attribute bg) tty_theme_color = (bg << 4 | fg) << 8; } -size_t -tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) +void +tty_flush_buffer(struct fifo_buf* buf) { int x = 0, y = 0; // Clear screen - TTY_CLEAR + tty_clear(); + char chr; int state = 0; int g[2] = { 0, 0 }; vga_attribute current_theme = tty_theme_color; - while (1) { - size_t ptr = pos % buf_size; - if (pos == limit) { - break; - } - char chr = data[pos]; + while (fifo_readone_async(buf, &chr)) { if (state == 0 && chr == '\033') { state = 1; } else if (state == 1 && chr == '[') { @@ -84,11 +83,10 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) case '\r': x = 0; break; - case '\x08': - x = x ? x - 1 : 0; - *(tty_vga_buffer + x + y * TTY_WIDTH) = - (current_theme | 0x20); - break; + // case '\x08': + // *(tty_vga_buffer + x + y * TTY_WIDTH) = + // (current_theme | 0x20); + // break; default: *(tty_vga_buffer + x + y * TTY_WIDTH) = (current_theme | chr); @@ -105,10 +103,8 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) break; } } - pos++; } tty_set_cursor(x, y); - return pos; } void diff --git a/lunaix-os/libs/klibc/stdio/sprintf.c b/lunaix-os/libs/klibc/stdio/ksprintf.c similarity index 94% rename from lunaix-os/libs/klibc/stdio/sprintf.c rename to lunaix-os/libs/klibc/stdio/ksprintf.c index ade37bb..2497e10 100644 --- a/lunaix-os/libs/klibc/stdio/sprintf.c +++ b/lunaix-os/libs/klibc/stdio/ksprintf.c @@ -20,7 +20,7 @@ static const char flag_chars[] = "#0- +"; #define FLAG_CAPS (1 << 9) size_t -__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs) +__ksprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs) { // This sprintf just a random implementation I found it on Internet . lol. // Of course, with some modifications for porting to LunaixOS :) @@ -102,6 +102,9 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs) : va_arg(vargs, unsigned); flags |= FLAG_NUMERIC; break; + case 'b': + base = 2; + goto format_unsigned; case 'x': base = 16; goto format_unsigned; @@ -196,21 +199,21 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs) } size_t -sprintf(char* buffer, char* fmt, ...) +ksprintf(char* buffer, char* fmt, ...) { va_list args; va_start(args, fmt); - size_t len = __sprintf_internal(buffer, fmt, 0, args); + size_t len = __ksprintf_internal(buffer, fmt, 0, args); va_end(args); return len; } size_t -snprintf(char* buffer, size_t n, char* fmt, ...) +ksnprintf(char* buffer, size_t n, char* fmt, ...) { va_list args; va_start(args, fmt); - size_t len = __sprintf_internal(buffer, fmt, n, args); + size_t len = __ksprintf_internal(buffer, fmt, n, args); va_end(args); return len; } \ No newline at end of file diff --git a/lunaix-os/libs/klibc/string/strcpy.c b/lunaix-os/libs/klibc/string/strcpy.c index 1258606..1f7a06d 100644 --- a/lunaix-os/libs/klibc/string/strcpy.c +++ b/lunaix-os/libs/klibc/string/strcpy.c @@ -1,11 +1,11 @@ #include char* -strcpy(char* dest, const char* src) { +strcpy(char* dest, const char* src) +{ char c; unsigned int i = 0; - while ((c = src[i])) - { + while ((c = src[i])) { dest[i] = c; i++; } @@ -14,10 +14,13 @@ strcpy(char* dest, const char* src) { } char* -strncpy(char* dest, const char* src, size_t n) { +strncpy(char* dest, const char* src, size_t n) +{ char c; unsigned int i = 0; - while ((c = src[i]) && i < n) dest[i++] = c; - while (i < n) dest[i++] = 0; + while ((c = src[i]) && i <= n) + dest[i++] = c; + while (i <= n) + dest[i++] = 0; return dest; } \ No newline at end of file diff --git a/lunaix-os/libs/klibc/string/trim.c b/lunaix-os/libs/klibc/string/trim.c index 82f29bd..fb907fa 100644 --- a/lunaix-os/libs/klibc/string/trim.c +++ b/lunaix-os/libs/klibc/string/trim.c @@ -18,12 +18,16 @@ strrtrim(char* str) str[l + 1] = '\0'; } -void* +char* strltrim_safe(char* str) { size_t l = 0; char c = 0; - while ((c = str[l++]) && WS_CHAR(c)) - ; + while ((c = str[l]) && WS_CHAR(c)) { + l++; + } + + if (!l) + return str; return strcpy(str, str + l); } \ No newline at end of file diff --git a/lunaix-os/libs/ulibc/printf.c b/lunaix-os/libs/ulibc/printf.c new file mode 100644 index 0000000..18e2387 --- /dev/null +++ b/lunaix-os/libs/ulibc/printf.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +// This is VERY bad implementation as it mixes both kernel and user space +// code together. It is here however, just for the convenience of our testing +// program. +// FIXME Eliminate this when we're able to load program. + +void __USER__ +printf(const char* fmt, ...) +{ + const char buf[512]; + va_list args; + va_start(args, fmt); + + size_t sz = __ksprintf_internal(buf, fmt, 512, args); + + write(stdout, buf, sz); + + va_end(args); +} \ No newline at end of file