#include #include #include #include #include #include #include #include #include #include #include #include #define INPUT_BUFLEN 1000 #define PM_PASSWORD 0x5a000000 #define PM_RSTC 0x3F10001c #define PM_WDOG 0x3F100024 static inline void _help (void) { uart_puts( "help : print this help menu" ENDL "hello : print Hello World!" ENDL "hwinfo : print hardware info" ENDL "memalloc : alloate memory and print" ENDL "ls : list directory contents" ENDL "cat : concatenate files and print" ENDL "exec : execute file in usermode" ENDL "settimeout : pring message after a few seconds" ENDL "reboot : reboot the device" ENDL ); } static inline void _hello (void) { uart_puts("hello, world" ENDL); } static inline void _hwinfo (void) { uart_puts( "hwinfo: " ENDL "board revision: " ); uart_hex(get_board_revision()); uart_puts( ENDL "memory base addr: " ); uart_hex(get_memory_base_addr()); uart_puts( ENDL "memory size: " ); uart_hex(get_memory_size()); uart_puts(ENDL); } static inline void _memalloc(size_t size) { void *addr = kmalloc(size); uart_puts("size: "); uart_hex(size); uart_puts(ENDL); uart_puts("addr: "); uart_hex((uint64_t)addr); uart_puts(ENDL); } static inline void _ls_initrd_callback(file_node_t *tr) { uart_puts(tr->filename); uart_puts(ENDL); } static inline void _ls(file_node_t *root) { initrd_traverse(root, _ls_initrd_callback); } static inline void _cat(file_node_t *root, const char *filename) { file_node_t *tr = initrd_get(root, filename); if (tr) { uart_puts((char *)tr->filecontent); } else { exit(ERR_NOT_EXIST); } } static inline void _exec(file_node_t *root, const char *filename) { file_node_t *tr = initrd_get(root, filename); if (tr) { void *userspace = allocate_page(1 << 6); memcpy(userspace, tr->filecontent, tr->filesize); user_exec(userspace, userspace + (1 << (12 + 6)) - 8); kfree(userspace); } else { exit(ERR_NOT_EXIST); } } static inline void _settimeout_cb_func(uint64_t args) { vector_t *v = (void *)args; for (int i = 2; i < (int)v->size; ++i) { uart_puts(VEC_AT(char, v, i)); uart_puts(" "); } uart_puts(ENDL); } static inline void _settimeout(int32_t sec, vector_t *args) { uint64_t cntpct_el0, cntfrq_el0; R_SYSREG(cntpct_el0, cntpct_el0); R_SYSREG(cntfrq_el0, cntfrq_el0); task_t task = (task_t){ .firing_tick = cntpct_el0 + sec * cntfrq_el0, .interval = sec * cntfrq_el0, .repeat = 1, .func = _settimeout_cb_func, .param = (uint64_t)args, }; add_task(task); } static inline void _set(long addr, unsigned int value) { volatile unsigned int* point = (unsigned int*)addr; *point = value; } static inline void _reset(int tick) { // reboot after watchdog timer expire _set(PM_RSTC, PM_PASSWORD | 0x20); // full reset _set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick } static inline void _reboot(void) { _reset(1 << 16); } char *_shell_buf = (char *)0x0; int _shell_sz = 0; static inline int _shell_operations(char ch) { switch (ch) { case 0x7f: if (_shell_sz > 0) { --_shell_sz; uart_puts("\b \b"); } return true; default: } return false; } int shell(file_node_t *initrd_root) { uart_puts("# "); char ch; _shell_buf = kmalloc(INPUT_BUFLEN * sizeof(char)); _shell_sz = 0; while ((ch = uart_getc()) != '\n') { if (_shell_operations(ch)) continue; _shell_buf[_shell_sz++] = ch; uart_putb((const uint8_t *)&ch, 1); } uart_puts(ENDL); _shell_buf[_shell_sz] = ' '; vector_t *args = make_vector(0); for (char *saveptr = 0x0, *tok = strtok_r(_shell_buf, " ", &saveptr); tok; tok = strtok_r((char *)0x0, " ", &saveptr)) { VEC_PUSH(args, tok); LOG(tok); } // DEBUG("ENDL"); CLEAN; char *cmd = args->size ? VEC_AT(char, args, 0) : (char *)0x0; if (!strcmp(cmd, "help")) { _help(); } else if (!strcmp(cmd, "hello")) { _hello(); } else if (!strcmp(cmd, "hwinfo")) { _hwinfo(); } else if (!strcmp(cmd, "memalloc") && args->size >= 2){ char *p1 = VEC_AT(char, args, 1); _memalloc((size_t)atoi32(p1)); } else if (!strcmp(cmd, "ls")) { _ls(initrd_root); } else if (!strcmp(cmd, "cat") && args->size >= 2) { char *p1 = VEC_AT(char, args, 1); _cat(initrd_root, p1); } else if (!strcmp(cmd, "exec") && args->size >= 2) { char *p1 = VEC_AT(char, args, 1); _exec(initrd_root, p1); } else if (!strcmp(cmd, "settimeout") && args->size >= 2) { char *p1 = VEC_AT(char, args, 1); _settimeout(atoi32(p1), args); } else if (!strcmp(cmd, "reboot")) { _reboot(); } return true; }