diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index 1cdcec22b0..5bbdbb6696 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -25,6 +26,8 @@ static rt_list_t blk_devices = RT_LIST_OBJECT_INIT(blk_devices); #define BLK_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define RT_DEVICE_CTRL_BLK_SSIZEGET 0x1268 /**< get number of bytes per sector */ +#define RT_DEVICE_CTRL_ALL_BLK_SSIZEGET 0x80081272 /**< get number of bytes per sector * sector counts*/ struct mmcsd_blk_device { @@ -267,6 +270,7 @@ static rt_err_t rt_mmcsd_close(rt_device_t dev) static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args) { struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; + switch (cmd) { case RT_DEVICE_CTRL_BLK_GETGEOME: @@ -274,6 +278,16 @@ static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args) break; case RT_DEVICE_CTRL_BLK_PARTITION: rt_memcpy(args, &blk_dev->part, sizeof(struct dfs_partition)); + break; + case RT_DEVICE_CTRL_BLK_SSIZEGET: + rt_memcpy(args, &blk_dev->geometry.bytes_per_sector, sizeof(rt_uint32_t)); + break; + case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET: + { + rt_uint64_t count_mul_per = blk_dev->geometry.bytes_per_sector * blk_dev->geometry.sector_count; + rt_memcpy(args, &count_mul_per, sizeof(rt_uint64_t)); + } + break; default: break; } @@ -414,6 +428,207 @@ const static struct rt_device_ops mmcsd_blk_ops = }; #endif +#ifdef RT_USING_DFS_V2 + +static ssize_t rt_mmcsd_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) +{ + int result = 0; + rt_device_t dev = (rt_device_t)file->vnode->data; + struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; + int bytes_per_sector = blk_dev->geometry.bytes_per_sector; + int blk_pos = *pos / bytes_per_sector; + int first_offs = *pos % bytes_per_sector; + char *rbuf; + int rsize = 0; + + rbuf = rt_malloc(bytes_per_sector); + if (!rbuf) + { + return 0; + } + + /* + ** #1: read first unalign block size. + */ + result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); + if (result != 1) + { + rt_free(rbuf); + return 0; + } + + if (count > bytes_per_sector - first_offs) + { + rsize = bytes_per_sector - first_offs; + } + else + { + rsize = count; + } + rt_memcpy(buf, rbuf + first_offs, rsize); + blk_pos++; + + /* + ** #2: read continuous block size. + */ + while (rsize < count) + { + result = rt_mmcsd_read(dev, blk_pos++, rbuf, 1); + if (result != 1) + { + break; + } + + if (count - rsize >= bytes_per_sector) + { + rt_memcpy(buf + rsize, rbuf, bytes_per_sector); + rsize += bytes_per_sector; + } + else + { + rt_memcpy(buf + rsize, rbuf, count - rsize); + rsize = count; + } + } + + rt_free(rbuf); + *pos += rsize; + + return rsize; +} + +static int rt_mmcsd_fops_ioctl(struct dfs_file *file, int cmd, void *arg) +{ + rt_device_t dev = (rt_device_t)file->vnode->data; + + return rt_mmcsd_control(dev,cmd,arg); +} + +static int rt_mmcsd_fops_open(struct dfs_file *file) +{ + rt_device_t dev = (rt_device_t)file->vnode->data; + rt_mmcsd_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size); + return RT_EOK; +} + +static int rt_mmcsd_fops_close(struct dfs_file *file) +{ + return RT_EOK; +} + +static ssize_t rt_mmcsd_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) +{ + int result = 0; + rt_device_t dev = (rt_device_t)file->vnode->data; + struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; + int bytes_per_sector = blk_dev->geometry.bytes_per_sector; + int blk_pos = *pos / bytes_per_sector; + int first_offs = *pos % bytes_per_sector; + char *rbuf = 0; + int wsize = 0; + + /* + ** #1: write first unalign block size. + */ + if (first_offs != 0) + { + if (count > bytes_per_sector - first_offs) + { + wsize = bytes_per_sector - first_offs; + } + else + { + wsize = count; + } + + rbuf = rt_malloc(bytes_per_sector); + if (!rbuf) + { + return 0; + } + + result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); + if (result != 1) + { + rt_free(rbuf); + return 0; + } + + rt_memcpy(rbuf + first_offs, buf, wsize); + result = rt_mmcsd_write(dev, blk_pos, rbuf, 1); + if (result != 1) + { + rt_free(rbuf); + return 0; + } + rt_free(rbuf); + blk_pos += 1; + } + + /* + ** #2: write continuous block size. + */ + if ((count - wsize) / bytes_per_sector != 0) + { + result = rt_mmcsd_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector); + wsize += result * bytes_per_sector; + blk_pos += result; + if (result != (count - wsize) / bytes_per_sector) + { + *pos += wsize; + return wsize; + } + } + + /* + ** # 3: write last unalign block size. + */ + if ((count - wsize) != 0) + { + rbuf = rt_malloc(bytes_per_sector); + if (rbuf != RT_NULL) + { + result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); + if (result == 1) + { + rt_memcpy(rbuf, buf + wsize, count - wsize); + result = rt_mmcsd_write(dev, blk_pos, rbuf, 1); + if (result == 1) + { + wsize += count - wsize; + } + } + + rt_free(rbuf); + } + } + + *pos += wsize; + return wsize; +} + +static int rt_mmcsd_fops_poll(struct dfs_file *file, struct rt_pollreq *req) +{ + int mask = 0; + + return mask; +} + +const static struct dfs_file_ops mmcsd_blk_fops = +{ + rt_mmcsd_fops_open, + rt_mmcsd_fops_close, + rt_mmcsd_fops_ioctl, + rt_mmcsd_fops_read, + rt_mmcsd_fops_write, + RT_NULL, + generic_dfs_lseek, + RT_NULL, + RT_NULL, + rt_mmcsd_fops_poll +}; +#endif + rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card) { rt_int32_t err = RT_EOK; @@ -460,6 +675,11 @@ rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card) rt_device_register(&(blk_dev->dev), card->host->name, RT_DEVICE_FLAG_RDWR); +#ifdef RT_USING_POSIX_DEVIO +#ifdef RT_USING_DFS_V2 + blk_dev->dev.fops = &mmcsd_blk_fops; +#endif +#endif rt_list_insert_after(&blk_devices, &blk_dev->list); for (i = 0; i < RT_GPT_PARTITION_MAX; i++) @@ -505,6 +725,11 @@ rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card) rt_device_register(&(blk_dev->dev), dname, RT_DEVICE_FLAG_RDWR); +#ifdef RT_USING_POSIX_DEVIO +#ifdef RT_USING_DFS_V2 + blk_dev->dev.fops = &mmcsd_blk_fops; +#endif +#endif rt_list_insert_after(&blk_devices, &blk_dev->list); } else diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index eba5a0c1d9..c3b0760f6a 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -159,18 +159,25 @@ long list_thread(void) rt_list_t *obj_list[LIST_FIND_OBJ_NR]; rt_list_t *next = (rt_list_t *)RT_NULL; const char *item_title = "thread"; + const size_t tcb_strlen = sizeof(void *) * 2 + 2; int maxlen; list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0])); maxlen = RT_NAME_MAX; + rt_kprintf("%-*.*s ", tcb_strlen, tcb_strlen, "rt_thread_t"); + #ifdef RT_USING_SMP rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title); + object_split(tcb_strlen); + rt_kprintf(" "); object_split(maxlen); rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- ---\n"); #else rt_kprintf("%-*.*s pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title); + object_split(tcb_strlen); + rt_kprintf(" "); object_split(maxlen); rt_kprintf(" --- ------- ---------- ---------- ------ ---------- ---\n"); #endif /*RT_USING_SMP*/ @@ -202,6 +209,7 @@ long list_thread(void) rt_uint8_t stat; rt_uint8_t *ptr; + rt_kprintf("%p ", thread); #ifdef RT_USING_SMP if (thread->oncpu != RT_CPU_DETACHED) rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->oncpu, thread->bind_cpu, thread->current_priority); diff --git a/components/finsh/msh_file.c b/components/finsh/msh_file.c index 5c38b579b1..a47ae73f05 100644 --- a/components/finsh/msh_file.c +++ b/components/finsh/msh_file.c @@ -618,6 +618,7 @@ MSH_CMD_EXPORT_ALIAS(cmd_mount, mount, mount ); /* unmount the filesystem from the specified mountpoint */ static int cmd_umount(int argc, char **argv) { +#ifndef RT_USING_DFS_V2 char *path = argv[1]; if (argc != 2) @@ -637,6 +638,34 @@ static int cmd_umount(int argc, char **argv) rt_kprintf("succeed!\n"); return 0; } +#else + int flags = 0; + char *path = argv[1]; + + if (argc < 2) + { + rt_kprintf("Usage: unmount [-f] .\n"); + return -1; + } + + if (argc > 2) + { + flags = strcmp(argv[1], "-f") == 0 ? MNT_FORCE : 0; + path = argv[2]; + } + + rt_kprintf("unmount %s ... ", path); + if (dfs_umount(path, flags) < 0) + { + rt_kprintf("failed!\n"); + return -1; + } + else + { + rt_kprintf("succeed!\n"); + return 0; + } +#endif } MSH_CMD_EXPORT_ALIAS(cmd_umount, umount, Unmount the mountpoint); diff --git a/components/libc/posix/io/stdio/libc.c b/components/libc/posix/io/stdio/libc.c index 9c7d28fefd..522ff36510 100644 --- a/components/libc/posix/io/stdio/libc.c +++ b/components/libc/posix/io/stdio/libc.c @@ -30,39 +30,20 @@ int libc_system_init(void) dev_console = rt_console_get_device(); if (dev_console) { - int fd, ret; - char name[STDIO_DEVICE_NAME_MAX]; - - rt_snprintf(name, sizeof(name) - 1, "/dev/%s", dev_console->parent.name); - name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; - - fd = open(name, O_RDWR); - if (fd >= 0) - { - /* set fd (0, 1, 2) */ - ret = sys_dup2(fd, 0); - if (ret != fd) - { - close(fd); - } - sys_dup2(ret, 1); - sys_dup2(ret, 2); - - ret = libc_stdio_set_console(dev_console->parent.name, O_RDWR); - if (ret < 0) - { - return -1; - } - } - else + int fd = libc_stdio_set_console(dev_console->parent.name, O_RDWR); + if (fd < 0) { return -1; } + /* set fd (0, 1, 2) */ + sys_dup2(fd, 0); + sys_dup2(fd, 1); + sys_dup2(fd, 2); } #endif /* RT_USING_POSIX_STDIO */ return 0; } -INIT_APP_EXPORT(libc_system_init); +INIT_ENV_EXPORT(libc_system_init); #if defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIBC) diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index c27f4ca172..96ebdd866c 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -1403,3 +1403,17 @@ void lwp_user_setting_restore(rt_thread_t thread) } } #endif /* ARCH_MM_MMU */ + +void lwp_uthread_ctx_save(void *ctx) +{ + rt_thread_t thread; + thread = rt_thread_self(); + thread->user_ctx.ctx = ctx; +} + +void lwp_uthread_ctx_restore(void) +{ + rt_thread_t thread; + thread = rt_thread_self(); + thread->user_ctx.ctx = RT_NULL; +} diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h index 2924a99c81..841ce7725e 100644 --- a/components/lwp/lwp.h +++ b/components/lwp/lwp.h @@ -164,6 +164,10 @@ void lwp_aspace_switch(struct rt_thread *thread); #endif void lwp_user_setting_save(rt_thread_t thread); void lwp_user_setting_restore(rt_thread_t thread); + +void lwp_uthread_ctx_save(void *ctx); +void lwp_uthread_ctx_restore(void); + int lwp_setaffinity(pid_t pid, int cpu); /* ctime lwp API */ diff --git a/components/lwp/lwp_ipc.c b/components/lwp/lwp_ipc.c index a4b560e264..60e216565c 100644 --- a/components/lwp/lwp_ipc.c +++ b/components/lwp/lwp_ipc.c @@ -980,6 +980,7 @@ int lwp_channel_open(int fdt_type, const char *name, int flags) { /* initialize vnode */ dfs_vnode_init(d->vnode, FT_USER, &channel_fops); + d->flags = O_RDWR; /* set flags as read and write */ /* set socket to the data of dfs_file */ d->vnode->data = (void *)ch; diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index 82185adf34..79f4e2ec0f 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -106,6 +106,11 @@ static void lwp_pid_put(pid_t pid) rt_base_t level; struct lwp_avl_struct *p; + if (pid == 0) + { + return; + } + level = rt_hw_interrupt_disable(); p = lwp_avl_find(pid, lwp_pid_root); if (p) diff --git a/components/lwp/lwp_sys_socket.h b/components/lwp/lwp_sys_socket.h index ea73082c31..527d5ebbe8 100644 --- a/components/lwp/lwp_sys_socket.h +++ b/components/lwp/lwp_sys_socket.h @@ -94,4 +94,43 @@ #define INTF_IPV6_V6ONLY 26 #define IMPL_IPV6_V6ONLY 27 +struct musl_sockaddr +{ + uint16_t sa_family; + char sa_data[14]; +}; + +struct musl_ifmap { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct musl_ifreq +{ + union + { +#define IFNAMSIZ 16 + char ifrn_name[IFNAMSIZ]; + } ifr_ifrn; + union + { + struct musl_sockaddr ifru_addr; + struct musl_sockaddr ifru_dstaddr; + struct musl_sockaddr ifru_broadaddr; + struct musl_sockaddr ifru_netmask; + struct musl_sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct musl_ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; + char ifru_newname[IFNAMSIZ]; + char *ifru_data; + } ifr_ifru; +}; + #endif /* __LWP_SYS_SOCKET_H__ */ diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index bffd951a56..547d333f48 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -103,12 +103,6 @@ #error "No definition RT_USING_POSIX_CLOCK" #endif /* RT_USING_POSIX_CLOCK */ -struct musl_sockaddr -{ - uint16_t sa_family; - char sa_data[14]; -}; - void lwp_cleanup(struct rt_thread *tid); #ifdef ARCH_MM_MMU @@ -551,7 +545,7 @@ sysret_t sys_open(const char *name, int flag, ...) #endif } -/* syscall: "open" ret: "int" args: "const char *" "mode_t" "mode" */ +/* syscall: "openat" ret: "int" args: "const char *" "mode_t" "mode" */ sysret_t sys_openat(int dirfd, const char *name, int flag, mode_t mode) { #ifdef ARCH_MM_MMU @@ -4684,6 +4678,12 @@ sysret_t sys_sched_setparam(pid_t pid, void *param) return ret; } +sysret_t sys_sched_yield(void) +{ + rt_thread_yield(); + return 0; +} + sysret_t sys_sched_getparam(pid_t pid, void *param) { struct sched_param *sched_param = (struct sched_param *)param; @@ -5378,7 +5378,154 @@ sysret_t sys_epoll_pwait(int fd, return (ret < 0 ? GET_ERRNO() : ret); } -static const struct rt_syscall_def func_table[] = +sysret_t sys_chmod(const char *fileName, mode_t mode) +{ + char *copy_fileName; + size_t len_fileName, copy_len_fileName; + int err_fileName; +#ifdef RT_USING_DFS_V2 + struct dfs_attr attr; + attr.st_mode = mode; +#endif + int ret = 0; + + len_fileName = lwp_user_strlen(fileName, &err_fileName); + if (err_fileName) + { + return -EFAULT; + } + + copy_fileName = (char*)rt_malloc(len_fileName + 1); + if (!copy_fileName) + { + return -ENOMEM; + } + + copy_len_fileName = lwp_get_from_user(copy_fileName, (void *)fileName, len_fileName); + copy_fileName[copy_len_fileName] = '\0'; +#ifdef RT_USING_DFS_V2 + ret = dfs_file_setattr(copy_fileName, &attr); +#else + SET_ERRNO(EFAULT); +#endif + rt_free(copy_fileName); + + return (ret < 0 ? GET_ERRNO() : ret); +} + +sysret_t sys_reboot(int magic) +{ + rt_hw_cpu_reset(); + + return 0; +} + +ssize_t sys_pread64(int fd, void *buf, int size, off_t offset) +#ifdef RT_USING_DFS_V2 +{ + ssize_t pread(int fd, void *buf, size_t len, off_t offset); +#ifdef ARCH_MM_MMU + ssize_t ret = -1; + void *kmem = RT_NULL; + + if (!size) + { + return -EINVAL; + } + + if (!lwp_user_accessable((void *)buf, size)) + { + return -EFAULT; + } + kmem = kmem_get(size); + if (!kmem) + { + return -ENOMEM; + } + + ret = pread(fd, kmem, size, offset); + if (ret > 0) + { + lwp_put_to_user(buf, kmem, ret); + } + + if (ret < 0) + { + ret = GET_ERRNO(); + } + + kmem_put(kmem); + + return ret; +#else + if (!lwp_user_accessable((void *)buf, size)) + { + return -EFAULT; + } + + ssize_t ret = pread(fd, kmem, size, offset); + return (ret < 0 ? GET_ERRNO() : ret); +#endif +} +#else +{ + ssize_t ret = -ENOSYS; + return (ret < 0 ? GET_ERRNO() : ret); +} +#endif + +ssize_t sys_pwrite64(int fd, void *buf, int size, off_t offset) +#ifdef RT_USING_DFS_V2 +{ + ssize_t pwrite(int fd, const void *buf, size_t len, off_t offset); +#ifdef ARCH_MM_MMU + ssize_t ret = -1; + void *kmem = RT_NULL; + + if (!size) + { + return -EINVAL; + } + + if (!lwp_user_accessable((void *)buf, size)) + { + return -EFAULT; + } + kmem = kmem_get(size); + if (!kmem) + { + return -ENOMEM; + } + + lwp_get_from_user(kmem, (void *)buf, size); + + ret = pwrite(fd, kmem, size, offset); + if (ret < 0) + { + ret = GET_ERRNO(); + } + + kmem_put(kmem); + + return ret; +#else + if (!lwp_user_accessable((void *)buf, size)) + { + return -EFAULT; + } + + ssize_t ret = pwrite(fd, kmem, size, offset); + return (ret < 0 ? GET_ERRNO() : ret); +#endif +} +#else +{ + ssize_t ret = -ENOSYS; + return (ret < 0 ? GET_ERRNO() : ret); +} +#endif + +const static struct rt_syscall_def func_table[] = { SYSCALL_SIGN(sys_exit), /* 01 */ SYSCALL_SIGN(sys_read), @@ -5600,11 +5747,11 @@ static const struct rt_syscall_def func_table[] = SYSCALL_SIGN(sys_symlink), SYSCALL_SIGN(sys_getaffinity), /* 180 */ SYSCALL_SIGN(sys_sysinfo), - SYSCALL_SIGN(sys_notimpl), - SYSCALL_SIGN(sys_notimpl), - SYSCALL_SIGN(sys_notimpl), - SYSCALL_SIGN(sys_notimpl), /* 185 */ - SYSCALL_SIGN(sys_notimpl), + SYSCALL_SIGN(sys_chmod), + SYSCALL_SIGN(sys_reboot), + SYSCALL_SIGN(sys_sched_yield), + SYSCALL_SIGN(sys_pread64), /* 185 */ + SYSCALL_SIGN(sys_pwrite64), SYSCALL_SIGN(sys_sigpending), SYSCALL_SIGN(sys_sigtimedwait), SYSCALL_SIGN(sys_notimpl), @@ -5632,7 +5779,10 @@ const void *lwp_get_sys_api(rt_uint32_t number) } else { - LOG_I("Unimplement syscall %d", number); + if (__sys_log_enable) + { + LOG_I("Unimplement syscall %d", number); + } } } @@ -5656,7 +5806,10 @@ const char *lwp_get_syscall_name(rt_uint32_t number) } else { - LOG_I("Unimplement syscall %d", number); + if (__sys_log_enable) + { + LOG_I("Unimplement syscall %d", number); + } } } diff --git a/components/net/lwip/lwip-2.1.2/src/core/netif.c b/components/net/lwip/lwip-2.1.2/src/core/netif.c index b2b4adf85b..a489c570de 100644 --- a/components/net/lwip/lwip-2.1.2/src/core/netif.c +++ b/components/net/lwip/lwip-2.1.2/src/core/netif.c @@ -1763,7 +1763,8 @@ netif_find(const char *name) return NULL; } - num = (u8_t)atoi(&name[2]); + /* Out netif's name is e0, e1... */ + num = (u8_t)atoi(&name[1]); NETIF_FOREACH(netif) { if (num == netif->num && diff --git a/components/net/sal/socket/net_sockets.c b/components/net/sal/socket/net_sockets.c index 8f53e744c7..211876c6c4 100644 --- a/components/net/sal/socket/net_sockets.c +++ b/components/net/sal/socket/net_sockets.c @@ -52,8 +52,9 @@ int accept(int s, struct sockaddr *addr, socklen_t *addrlen) rt_set_errno(-ENOMEM); return -1; } - rt_memset(d->vnode, 0, sizeof(struct dfs_vnode)); + dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops()); + d->flags = O_RDWR; /* set flags as read and write */ /* set socket to the data of dfs_file */ d->vnode->data = (void *)(size_t)new_socket; @@ -258,6 +259,7 @@ int socket(int domain, int type, int protocol) if (socket >= 0) { dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops()); + d->flags = O_RDWR; /* set flags as read and write */ /* set socket to the data of dfs_file */ d->vnode->data = (void *)(size_t)socket; diff --git a/components/net/sal/src/sal_socket.c b/components/net/sal/src/sal_socket.c index b73ad749b1..9d343b8c1f 100644 --- a/components/net/sal/src/sal_socket.c +++ b/components/net/sal/src/sal_socket.c @@ -26,6 +26,10 @@ #include #endif +#ifdef RT_USING_LWP +#include +#endif + /* check system workqueue stack size */ #if defined(SAL_INTERNET_CHECK) && RT_SYSTEM_WORKQUEUE_STACKSIZE < 1536 #error "The system workqueue stack size must more than 1536 bytes" @@ -51,6 +55,16 @@ struct sal_netdev_res_table struct netdev *netdev; }; +struct ifconf +{ + int ifc_len; /* Size of buffer. */ + union + { + char* ifcu_buf; + struct sal_ifreq *ifcu_req; + } ifc_ifcu; +}; + #ifdef SAL_USING_TLS /* The global TLS protocol options */ static struct sal_proto_tls *proto_tls; @@ -1028,8 +1042,17 @@ int sal_closesocket(int socket) return error; } +#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */ +#define ARPHRD_LOOPBACK 772 /* Loopback device. */ +#define IFF_UP 0x1 +#define IFF_RUNNING 0x40 +#define IFF_NOARP 0x80 + int sal_ioctlsocket(int socket, long cmd, void *arg) { + rt_slist_t *node = RT_NULL; + struct netdev *netdev = RT_NULL; + struct netdev *cur_netdev_list = netdev_list; struct sal_socket *sock; struct sal_proto_family *pf; struct sockaddr_in *addr_in = RT_NULL; @@ -1048,48 +1071,276 @@ int sal_ioctlsocket(int socket, long cmd, void *arg) switch (cmd) { case SIOCGIFADDR: - addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr); -#if NETDEV_IPV4 && NETDEV_IPV6 - addr_in->sin_addr.s_addr = sock->netdev->ip_addr.u_addr.ip4.addr; -#elif NETDEV_IPV4 - addr_in->sin_addr.s_addr = sock->netdev->ip_addr.addr; -#elif NETDEV_IPV6 -#error "not only support IPV6" -#endif /* NETDEV_IPV4 && NETDEV_IPV6*/ - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr); + #if NETDEV_IPV4 && NETDEV_IPV6 + addr_in->sin_addr.s_addr = sock->netdev->ip_addr.u_addr.ip4.addr; + #elif NETDEV_IPV4 + addr_in->sin_addr.s_addr = sock->netdev->ip_addr.addr; + #elif NETDEV_IPV6 + #error "not only support IPV6" + #endif /* NETDEV_IPV4 && NETDEV_IPV6*/ + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr); + addr_in->sin_addr.s_addr = netdev->ip_addr.addr; + return 0; + } + } + return -1; + } case SIOCSIFADDR: - addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr); - sal_sockaddr_to_ipaddr(addr,&input_ipaddr); - netdev_set_ipaddr(sock->netdev,&input_ipaddr); - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr); + sal_sockaddr_to_ipaddr(addr, &input_ipaddr); + netdev_set_ipaddr(sock->netdev, &input_ipaddr); + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr); + sal_sockaddr_to_ipaddr(addr, &input_ipaddr); + netdev_set_ipaddr(netdev, &input_ipaddr); + return 0; + } + } + return -1; + } case SIOCGIFNETMASK: - addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask); -#if NETDEV_IPV4 && NETDEV_IPV6 - addr_in->sin_addr.s_addr = sock->netdev->netmask.u_addr.ip4.addr; -#elif NETDEV_IPV4 - addr_in->sin_addr.s_addr = sock->netdev->netmask.addr; -#elif NETDEV_IPV6 -#error "not only support IPV6" -#endif /* NETDEV_IPV4 && NETDEV_IPV6*/ - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask); + #if NETDEV_IPV4 && NETDEV_IPV6 + addr_in->sin_addr.s_addr = sock->netdev->netmask.u_addr.ip4.addr; + #elif NETDEV_IPV4 + addr_in->sin_addr.s_addr = sock->netdev->netmask.addr; + #elif NETDEV_IPV6 + #error "not only support IPV6" + #endif /* NETDEV_IPV4 && NETDEV_IPV6*/ + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask); + #if NETDEV_IPV4 && NETDEV_IPV6 + addr_in->sin_addr.s_addr = netdev->netmask.u_addr.ip4.addr; + #elif NETDEV_IPV4 + addr_in->sin_addr.s_addr = netdev->netmask.addr; + #elif NETDEV_IPV6 + #error "not only support IPV6" + #endif /* NETDEV_IPV4 && NETDEV_IPV6*/ + return 0; + } + } + return -1; + } case SIOCSIFNETMASK: - addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask); - sal_sockaddr_to_ipaddr(addr,&input_ipaddr); - netdev_set_netmask(sock->netdev,&input_ipaddr); - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask); + sal_sockaddr_to_ipaddr(addr, &input_ipaddr); + netdev_set_netmask(sock->netdev, &input_ipaddr); + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask); + sal_sockaddr_to_ipaddr(addr, &input_ipaddr); + netdev_set_netmask(netdev, &input_ipaddr); + return 0; + } + } + return -1; + } case SIOCGIFHWADDR: - addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr); - rt_memcpy(addr->sa_data,sock->netdev->hwaddr,sock->netdev->hwaddr_len); - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name,sock->netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr); +#ifdef RT_USING_LWP + if (!strcmp("lo", sock->netdev->name)) + { + struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg; + musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_LOOPBACK; + } + else + { + struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg; + musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; + } +#endif + rt_memcpy(addr->sa_data, sock->netdev->hwaddr, sock->netdev->hwaddr_len); + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr); +#ifdef RT_USING_LWP + if (!strcmp("lo", netdev->name)) + { + struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg; + musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_LOOPBACK; + } + else + { + struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg; + musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; + } +#endif + rt_memcpy(addr->sa_data, netdev->hwaddr, netdev->hwaddr_len); + return 0; + } + } + return -1; + } case SIOCGIFMTU: - ifr->ifr_ifru.ifru_mtu = sock->netdev->mtu; - return 0; + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + ifr->ifr_ifru.ifru_mtu = sock->netdev->mtu; + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + ifr->ifr_ifru.ifru_mtu = netdev->mtu; + return 0; + } + } + return -1; + } + case SIOCGIFFLAGS: + if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name)) + { + uint16_t flags_tmp = 0; + if (sock->netdev->flags & NETDEV_FLAG_UP) + flags_tmp = flags_tmp | IFF_UP; + if (!(sock->netdev->flags & NETDEV_FLAG_ETHARP)) + flags_tmp = flags_tmp | IFF_NOARP; + flags_tmp = flags_tmp | IFF_RUNNING; + ifr->ifr_ifru.ifru_flags = flags_tmp; + return 0; + } + else + { + if (cur_netdev_list == RT_NULL) + { + LOG_E("ifconfig: network interface device list error.\n"); + return -1; + } + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + netdev = rt_list_entry(node, struct netdev, list); + if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name)) + { + uint16_t flags_tmp = 0; + if (sock->netdev->flags & NETDEV_FLAG_UP) + flags_tmp = flags_tmp | IFF_UP; + if (!(sock->netdev->flags & NETDEV_FLAG_ETHARP)) + flags_tmp = flags_tmp | IFF_NOARP; + ifr->ifr_ifru.ifru_flags = flags_tmp; + return 0; + } + } + return -1; + } + + + case SIOCSIFFLAGS: + sock->netdev->flags = ifr->ifr_ifru.ifru_flags; + return 0; + case SIOCGIFCONF: + { + struct ifconf *ifconf_tmp; + ifconf_tmp = (struct ifconf *)arg; + int count_size = 0; + + for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) + { + struct sal_ifreq sal_ifreq_temp; + count_size++; + netdev = rt_list_entry(node, struct netdev, list); + rt_strcpy(sal_ifreq_temp.ifr_ifrn.ifrn_name, netdev->name); + rt_memcpy(ifconf_tmp->ifc_ifcu.ifcu_buf, &sal_ifreq_temp, sizeof(struct sal_ifreq)); + ifconf_tmp->ifc_ifcu.ifcu_buf += sizeof(struct sal_ifreq); + } + ifconf_tmp->ifc_len = sizeof(struct sal_ifreq) * count_size; + ifconf_tmp->ifc_ifcu.ifcu_buf = ifconf_tmp->ifc_ifcu.ifcu_buf - sizeof(struct sal_ifreq) * count_size; + return 0; + } default: break; } diff --git a/include/rtdef.h b/include/rtdef.h index f0e975d725..1966595ced 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -807,6 +807,8 @@ struct rt_user_context void *sp; void *pc; void *flag; + + void *ctx; }; #endif diff --git a/libcpu/aarch64/common/backtrace.c b/libcpu/aarch64/common/backtrace.c index d8985d0c09..14ea18a97f 100644 --- a/libcpu/aarch64/common/backtrace.c +++ b/libcpu/aarch64/common/backtrace.c @@ -6,10 +6,15 @@ * Change Logs: * Date Author Notes * 2022-06-02 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for non-active thread */ +#include "mm_aspace.h" +#include "mmu.h" + #include #include +#include #define BT_NESTING_MAX 100 @@ -19,7 +24,7 @@ static int unwind_frame(struct bt_frame *frame) if ((fp & 0x7) #ifdef RT_USING_LWP - || fp < KERNEL_VADDR_START + || (rt_kmem_v2p((void *)fp) == ARCH_MAP_FAILED) #endif ) { @@ -27,16 +32,18 @@ static int unwind_frame(struct bt_frame *frame) } frame->fp = *(unsigned long *)fp; frame->pc = *(unsigned long *)(fp + 8); + + if ((rt_kmem_v2p((void *)frame->pc) == ARCH_MAP_FAILED)) + return 1; return 0; } static void walk_unwind(unsigned long pc, unsigned long fp) { - struct bt_frame frame; + struct bt_frame frame = {fp, 1}; unsigned long lr = pc; int nesting = 0; - frame.fp = fp; while (nesting < BT_NESTING_MAX) { rt_kprintf(" %p", (void *)lr); @@ -51,18 +58,128 @@ static void walk_unwind(unsigned long pc, unsigned long fp) void backtrace(unsigned long pc, unsigned long lr, unsigned long fp) { - rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc); - walk_unwind(lr, fp); + rt_kprintf("please use: addr2line -e rtthread.elf -a -f"); + if (pc) + rt_kprintf(" %p", (void *)pc); + + if (lr && fp) + walk_unwind(lr, fp); rt_kprintf("\n"); } int rt_backtrace(void) { - unsigned long pc = (unsigned long)backtrace; unsigned long ra = (unsigned long)__builtin_return_address(0U); unsigned long fr = (unsigned long)__builtin_frame_address(0U); - backtrace(pc, ra, fr); + backtrace(0, ra, fr); return 0; } MSH_CMD_EXPORT_ALIAS(rt_backtrace, bt_test, backtrace test); + +#define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id))) + +int rt_backtrace_thread(rt_thread_t thread) +{ + unsigned long lr; + unsigned long fp; + + if (thread == rt_thread_self()) + { + return -RT_EINVAL; + } + else + { + lr = ARCH_CONTEXT_FETCH(thread->sp, 3); + fp = ARCH_CONTEXT_FETCH(thread->sp, 7); + backtrace(0, lr, fp); + return 0; + } +} + +#ifdef RT_USING_SMART + +int rt_backtrace_user_thread(rt_thread_t thread) +{ + unsigned long pc; + unsigned long lr; + unsigned long fp; + unsigned long ctx = (unsigned long)thread->user_ctx.ctx; + + if (ctx > (unsigned long)thread->stack_addr + && ctx < (unsigned long)thread->stack_addr + thread->stack_size) + { + pc = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 0); + lr = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 3); + fp = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 7); + backtrace(pc, lr, fp); + return 0; + } + else + return -1; +} + +#endif /* RT_USING_SMART */ + +static long custom_hex_to_long(const char* hex) +{ + long result = 0; + int i = 0; + + // Skip the "0x" prefix + if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) + { + i = 2; + } + + // Convert each hex digit to its decimal value + for (; hex[i] != '\0'; i++) + { + char digit = hex[i]; + if (digit >= '0' && digit <= '9') + { + result = result * 16 + (digit - '0'); + } + else if (digit >= 'a' && digit <= 'f') + { + result = result * 16 + (digit - 'a' + 10); + } + else if (digit >= 'A' && digit <= 'F') + { + result = result * 16 + (digit - 'A' + 10); + } + else + { + // Invalid hex digit + return 0; + } + } + + return result; +} + +static void cmd_backtrace(int argc, char** argv) +{ + long pid; + + if (argc < 2) + { + rt_kprintf("please use: backtrace pid\n"); + return; + } + + if (strncmp(argv[1], "0x", 2) == 0) + { + pid = custom_hex_to_long(argv[1]); + } + else + { + pid = atol(argv[1]); + } + if (pid) + { + rt_kprintf("backtrace %s(0x%lx), from %s\n", ((rt_thread_t)pid)->parent.name, pid, argv[1]); + rt_backtrace_thread((rt_thread_t)pid); + } +} +MSH_CMD_EXPORT_ALIAS(cmd_backtrace, backtrace, print backtrace of a thread); diff --git a/libcpu/aarch64/common/backtrace.h b/libcpu/aarch64/common/backtrace.h index 8c8006690c..e5e281978c 100644 --- a/libcpu/aarch64/common/backtrace.h +++ b/libcpu/aarch64/common/backtrace.h @@ -6,11 +6,14 @@ * Change Logs: * Date Author Notes * 2022-06-02 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for non-active thread */ #ifndef __BACKTRACE_H__ #define __BACKTRACE_H__ +#include + struct bt_frame { unsigned long fp; @@ -20,4 +23,7 @@ struct bt_frame void backtrace(unsigned long pc, unsigned long lr, unsigned long fp); int rt_backtrace(void); +int rt_backtrace_user_thread(rt_thread_t thread); +int rt_backtrace_thread(rt_thread_t thread); + #endif /*__BACKTRACE_H__*/ diff --git a/libcpu/aarch64/common/context_gcc.S b/libcpu/aarch64/common/context_gcc.S index d9dc2d1c93..e3487c9135 100644 --- a/libcpu/aarch64/common/context_gcc.S +++ b/libcpu/aarch64/common/context_gcc.S @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2021-05-18 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for user thread */ #include "rtconfig.h" @@ -375,13 +376,31 @@ rt_hw_context_switch_interrupt: vector_fiq: B . +.macro SAVE_USER_CTX + MRS X1, SPSR_EL1 + AND X1, X1, 0xf + CMP X1, XZR + + BNE 1f + BL lwp_uthread_ctx_save + LDP X0, X1, [SP] +1: +.endm + .globl vector_irq vector_irq: SAVE_CONTEXT STP X0, X1, [SP, #-0x10]! /* X0 is thread sp */ BL rt_interrupt_enter + LDP X0, X1, [SP] +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif BL rt_hw_trap_irq +#ifdef RT_USING_LWP + BL lwp_uthread_ctx_restore +#endif BL rt_interrupt_leave LDP X0, X1, [SP], #0x10 @@ -515,7 +534,15 @@ vector_irq_exit: START_POINT(vector_exception) SAVE_CONTEXT STP X0, X1, [SP, #-0x10]! +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif + BL rt_hw_trap_exception +#ifdef RT_USING_LWP + BL lwp_uthread_ctx_restore +#endif + LDP X0, X1, [SP], #0x10 MOV SP, X0 RESTORE_CONTEXT_WITHOUT_MMU_SWITCH @@ -523,6 +550,9 @@ START_POINT_END(vector_exception) START_POINT(vector_serror) SAVE_CONTEXT +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif STP X0, X1, [SP, #-0x10]! BL rt_hw_trap_serror b . diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c index dd5468daf1..8e97a8b0aa 100644 --- a/libcpu/aarch64/common/trap.c +++ b/libcpu/aarch64/common/trap.c @@ -296,6 +296,19 @@ void rt_hw_trap_exception(struct rt_hw_exp_stack *regs) #ifdef RT_USING_FINSH list_thread(); #endif + +#ifdef RT_USING_LWP + { + rt_thread_t th; + + th = rt_thread_self(); + if (th && th->lwp) + { + rt_backtrace_user_thread(th); + } + } +#endif + backtrace((unsigned long)regs->pc, (unsigned long)regs->x30, (unsigned long)regs->x29); rt_hw_cpu_shutdown(); } diff --git a/src/kservice.c b/src/kservice.c index 9a8e89f4f2..b29497c765 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -75,6 +75,13 @@ rt_weak const char *rt_hw_cpu_arch(void) return "unknown"; } +rt_weak void rt_hw_cpu_reset(void) +{ + LOG_D("rt_hw_cpu_reset() doesn't support for this board." + "Please consider implementing rt_hw_cpu_reset() in another file."); + return ; +} + static const char* rt_errno_strs[] = { "OK",