261 lines
5.6 KiB
C
261 lines
5.6 KiB
C
#include <stddef.h>
|
|
#include <logger.h>
|
|
#include <timer.h>
|
|
#include <errcode.h>
|
|
#include <kmalloc.h>
|
|
#include <utils.h>
|
|
#include <string.h>
|
|
#include <uart.h>
|
|
#include <mbox.h>
|
|
#include <shell.h>
|
|
#include <exec.h>
|
|
#include <mman.h>
|
|
|
|
#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 <size> : alloate memory and print" ENDL
|
|
"ls : list directory contents" ENDL
|
|
"cat <file> : concatenate files and print" ENDL
|
|
"exec <file> : execute file in usermode" ENDL
|
|
"settimeout <sec> <message...>: pring message after a few seconds" ENDL
|
|
"time : print current time tick" 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 _free(uint64_t ptr)
|
|
{
|
|
kfree((void *)ptr);
|
|
LOG(ptr);
|
|
INFOR("has been freed");
|
|
}
|
|
|
|
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_timer_task(task);
|
|
}
|
|
|
|
static inline
|
|
void _time()
|
|
{
|
|
uint64_t cntpct_el0, cntfrq_el0, cntp_cval_el0, cntp_tval_el0;
|
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
|
R_SYSREG(cntp_cval_el0, cntp_cval_el0);
|
|
R_SYSREG(cntp_tval_el0, cntp_tval_el0);
|
|
|
|
LOG(cntpct_el0);
|
|
LOG(cntfrq_el0);
|
|
LOG(cntp_cval_el0);
|
|
INFOR(cntp_tval_el0);
|
|
}
|
|
|
|
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, "free") && args->size >= 2) {
|
|
char *p1 = VEC_AT(char, args, 1);
|
|
_free((uint64_t)atoh32(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, "time")) {
|
|
_time();
|
|
} else if (!strcmp(cmd, "reboot")) {
|
|
_reboot();
|
|
}
|
|
|
|
return true;
|
|
}
|