init commit of lab4_challenge3

lab4_challenge3_shell
liguo 11 months ago
parent 38183534a3
commit 735dbaa2e1

@ -14,6 +14,7 @@ SRC_DIR := .
OBJ_DIR := obj
SPROJS_INCLUDE := -I.
HOSTFS_ROOT := hostfs_root
ifneq (,)
march := -march=
is_32bit := $(findstring 32,$(march))
@ -63,12 +64,41 @@ SPIKE_INF_LIB := $(OBJ_DIR)/spike_interface.a
#--------------------- user -----------------------
USER_CPPS := user/*.c
USER_CPPS := user/app_shell.c user/user_lib.c
USER_CPPS := $(wildcard $(USER_CPPS))
USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS)))
USER_TARGET := $(OBJ_DIR)/app_hardlink
USER_TARGET := $(HOSTFS_ROOT)/bin/app_shell
USER_E_CPPS := user/app_ls.c user/user_lib.c
USER_E_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_E_CPPS)))
USER_E_TARGET := $(HOSTFS_ROOT)/bin/app_ls
USER_M_CPPS := user/app_mkdir.c user/user_lib.c
USER_M_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_M_CPPS)))
USER_M_TARGET := $(HOSTFS_ROOT)/bin/app_mkdir
USER_T_CPPS := user/app_touch.c user/user_lib.c
USER_T_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_T_CPPS)))
USER_T_TARGET := $(HOSTFS_ROOT)/bin/app_touch
USER_C_CPPS := user/app_cat.c user/user_lib.c
USER_C_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_C_CPPS)))
USER_C_TARGET := $(HOSTFS_ROOT)/bin/app_cat
USER_O_CPPS := user/app_echo.c user/user_lib.c
USER_O_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_O_CPPS)))
USER_O_TARGET := $(HOSTFS_ROOT)/bin/app_echo
#------------------------targets------------------------
$(OBJ_DIR):
@-mkdir -p $(OBJ_DIR)
@ -76,7 +106,12 @@ $(OBJ_DIR):
@-mkdir -p $(dir $(SPIKE_INF_OBJS))
@-mkdir -p $(dir $(KERNEL_OBJS))
@-mkdir -p $(dir $(USER_OBJS))
@-mkdir -p $(dir $(USER_E_OBJS))
@-mkdir -p $(dir $(USER_M_OBJS))
@-mkdir -p $(dir $(USER_T_OBJS))
@-mkdir -p $(dir $(USER_C_OBJS))
@-mkdir -p $(dir $(USER_O_OBJS))
$(OBJ_DIR)/%.o : %.c
@echo "compiling" $<
@$(COMPILE) -c $< -o $@
@ -102,20 +137,52 @@ $(KERNEL_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(SPIKE_INF_LIB) $(KERNEL_OBJS) $(KERNE
$(USER_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
@cp $@ $(OBJ_DIR)
$(USER_E_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_E_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_E_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
$(USER_M_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_M_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_M_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
$(USER_T_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_T_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_T_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
$(USER_C_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_C_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_C_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
$(USER_O_TARGET): $(OBJ_DIR) $(UTIL_LIB) $(USER_O_OBJS)
@echo "linking" $@ ...
-@mkdir -p $(HOSTFS_ROOT)/bin
@$(COMPILE) --entry=main $(USER_O_OBJS) $(UTIL_LIB) -o $@
@echo "User app has been built into" \"$@\"
-include $(wildcard $(OBJ_DIR)/*/*.d)
-include $(wildcard $(OBJ_DIR)/*/*/*.d)
.DEFAULT_GOAL := $(all)
all: $(KERNEL_TARGET) $(USER_TARGET)
all: $(KERNEL_TARGET) $(USER_TARGET) $(USER_E_TARGET) $(USER_M_TARGET) $(USER_T_TARGET) $(USER_C_TARGET) $(USER_O_TARGET)
.PHONY:all
run: $(KERNEL_TARGET) $(USER_TARGET)
run: $(KERNEL_TARGET) $(USER_TARGET) $(USER_E_TARGET) $(USER_M_TARGET) $(USER_T_TARGET) $(USER_C_TARGET) $(USER_O_TARGET)
@echo "********************HUST PKE********************"
spike $(KERNEL_TARGET) $(USER_TARGET)
spike $(KERNEL_TARGET) /bin/app_shell
# need openocd!
gdb:$(KERNEL_TARGET) $(USER_TARGET)
@ -146,4 +213,4 @@ format:
@python ./format.py ./
clean:
rm -fr ${OBJ_DIR}
rm -fr ${OBJ_DIR} ${HOSTFS_ROOT}/bin

@ -1,2 +0,0 @@
This is an apple.
Apples are good for our health.

@ -0,0 +1,8 @@
/bin/app_mkdir /RAMDISK0/sub_dir
/bin/app_touch /RAMDISK0/sub_dir/ramfile1
/bin/app_touch /RAMDISK0/sub_dir/ramfile2
/bin/app_echo /RAMDISK0/sub_dir/ramfile1
/bin/app_cat /RAMDISK0/sub_dir/ramfile1
/bin/app_ls /RAMDISK0/sub_dir
/bin/app_ls /RAMDISK0
END END

@ -8,10 +8,11 @@
#include "riscv.h"
#include "vmm.h"
#include "pmm.h"
#include "vfs.h"
#include "spike_interface/spike_utils.h"
typedef struct elf_info_t {
spike_file_t *f;
struct file *f;
process *p;
} elf_info;
@ -34,14 +35,12 @@ static void *elf_alloc_mb(elf_ctx *ctx, uint64 elf_pa, uint64 elf_va, uint64 siz
}
//
// actual file reading, using the spike file interface.
// actual file reading, using the vfs file interface.
//
static uint64 elf_fpread(elf_ctx *ctx, void *dest, uint64 nb, uint64 offset) {
elf_info *msg = (elf_info *)ctx->info;
// call spike file utility to load the content of elf file into memory.
// spike_file_pread will read the elf file (msg->f) from offset to memory (indicated by
// *dest) for nb bytes.
return spike_file_pread(msg->f, dest, nb, offset);
vfs_lseek(msg->f, offset, SEEK_SET);
return vfs_read(msg->f, dest, nb);
}
//
@ -107,50 +106,18 @@ elf_status elf_load(elf_ctx *ctx) {
return EL_OK;
}
typedef union {
uint64 buf[MAX_CMDLINE_ARGS];
char *argv[MAX_CMDLINE_ARGS];
} arg_buf;
//
// returns the number (should be 1) of string(s) after PKE kernel in command line.
// and store the string(s) in arg_bug_msg.
//
static size_t parse_args(arg_buf *arg_bug_msg) {
// HTIFSYS_getmainvars frontend call reads command arguments to (input) *arg_bug_msg
long r = frontend_syscall(HTIFSYS_getmainvars, (uint64)arg_bug_msg,
sizeof(*arg_bug_msg), 0, 0, 0, 0, 0);
kassert(r == 0);
size_t pk_argc = arg_bug_msg->buf[0];
uint64 *pk_argv = &arg_bug_msg->buf[1];
int arg = 1; // skip the PKE OS kernel string, leave behind only the application name
for (size_t i = 0; arg + i < pk_argc; i++)
arg_bug_msg->argv[i] = (char *)(uintptr_t)pk_argv[arg + i];
//returns the number of strings after PKE kernel in command line
return pk_argc - arg;
}
//
// load the elf of user application, by using the spike file interface.
//
void load_bincode_from_host_elf(process *p) {
arg_buf arg_bug_msg;
// retrieve command line arguements
size_t argc = parse_args(&arg_bug_msg);
if (!argc) panic("You need to specify the application program!\n");
sprint("Application: %s\n", arg_bug_msg.argv[0]);
void load_bincode_from_host_elf(process *p, char *filename) {
sprint("Application: %s\n", filename);
//elf loading. elf_ctx is defined in kernel/elf.h, used to track the loading process.
elf_ctx elfloader;
// elf_info is defined above, used to tie the elf file and its corresponding process.
elf_info info;
info.f = spike_file_open(arg_bug_msg.argv[0], O_RDONLY, 0);
info.f = vfs_open(filename, O_RDONLY);
info.p = p;
// IS_ERR_VALUE is a macro defined in spike_interface/spike_htif.h
if (IS_ERR_VALUE(info.f)) panic("Fail on openning the input application program.\n");
@ -165,8 +132,8 @@ void load_bincode_from_host_elf(process *p) {
// entry (virtual, also physical in lab1_x) address
p->trapframe->epc = elfloader.ehdr.entry;
// close the host spike file
spike_file_close( info.f );
// close the vfs file
vfs_close( info.f );
sprint("Application program entry point (virtual address): 0x%lx\n", p->trapframe->epc);
}

@ -63,6 +63,6 @@ typedef struct elf_ctx_t {
elf_status elf_init(elf_ctx *ctx, void *info);
elf_status elf_load(elf_ctx *ctx);
void load_bincode_from_host_elf(process *p);
void load_bincode_from_host_elf(process *p, char *filename);
#endif

@ -33,6 +33,32 @@ void enable_paging() {
flush_tlb();
}
typedef union {
uint64 buf[MAX_CMDLINE_ARGS];
char *argv[MAX_CMDLINE_ARGS];
} arg_buf;
//
// returns the number (should be 1) of string(s) after PKE kernel in command line.
// and store the string(s) in arg_bug_msg.
//
static size_t parse_args(arg_buf *arg_bug_msg) {
// HTIFSYS_getmainvars frontend call reads command arguments to (input) *arg_bug_msg
long r = frontend_syscall(HTIFSYS_getmainvars, (uint64)arg_bug_msg,
sizeof(*arg_bug_msg), 0, 0, 0, 0, 0);
kassert(r == 0);
size_t pk_argc = arg_bug_msg->buf[0];
uint64 *pk_argv = &arg_bug_msg->buf[1];
int arg = 1; // skip the PKE OS kernel string, leave behind only the application name
for (size_t i = 0; arg + i < pk_argc; i++)
arg_bug_msg->argv[i] = (char *)(uintptr_t)pk_argv[arg + i];
//returns the number of strings after PKE kernel in command line
return pk_argc - arg;
}
//
// load the elf, and construct a "process" (with only a trapframe).
// load_bincode_from_host_elf is defined in elf.c
@ -43,7 +69,13 @@ process* load_user_program() {
proc = alloc_process();
sprint("User application is loading.\n");
load_bincode_from_host_elf(proc);
arg_buf arg_bug_msg;
// retrieve command line arguements
size_t argc = parse_args(&arg_bug_msg);
if (!argc) panic("You need to specify the application program!\n");
load_bincode_from_host_elf(proc, arg_bug_msg.argv[0]);
return proc;
}

@ -0,0 +1,23 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
int fd;
int MAXBUF = 512;
char buf[MAXBUF];
char *filename = argv[0];
printu("\n======== cat command ========\n");
printu("cat: %s\n", filename);
fd = open(filename, O_RDWR);
printu("file descriptor fd: %d\n", fd);
read_u(fd, buf, MAXBUF);
printu("read content: \n%s\n", buf);
close(fd);
exit(0);
return 0;
}

@ -0,0 +1,20 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
int fd;
char str[] = "hello world";
char *filename = argv[0];
printu("\n======== echo command ========\n");
printu("echo: %s\n", filename);
fd = open(filename, O_RDWR | O_CREAT);
printu("file descriptor fd: %d\n", fd);
write_u(fd, str, strlen(str));
printu("write content: \n%s\n", str);
close(fd);
exit(0);
return 0;
}

@ -1,94 +0,0 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
void ls(char *path) {
int dir_fd = opendir_u(path);
printu("------------------------------\n");
printu("ls \"%s\":\n", path);
printu("[name] [inode_num]\n");
struct dir dir;
int width = 20;
while(readdir_u(dir_fd, &dir) == 0) {
// we do not have %ms :(
char name[width + 1];
memset(name, ' ', width + 1);
name[width] = '\0';
if (strlen(dir.name) < width) {
strcpy(name, dir.name);
name[strlen(dir.name)] = ' ';
printu("%s %d\n", name, dir.inum);
}
else
printu("%s %d\n", dir.name, dir.inum);
}
printu("------------------------------\n");
closedir_u(dir_fd);
}
int main(int argc, char *argv[]) {
int MAXBUF = 512;
char str[] = "hello world";
char buf[MAXBUF];
int fd1, fd2;
printu("\n======== establish the file ========\n");
fd1 = open("/RAMDISK0/ramfile", O_RDWR | O_CREAT);
printu("create file: /RAMDISK0/ramfile\n");
close(fd1);
printu("\n======== Test 1: hard link ========\n");
link_u("/RAMDISK0/ramfile", "/RAMDISK0/ramfile2");
printu("create hard link: /RAMDISK0/ramfile2 -> /RAMDISK0/ramfile\n");
fd1 = open("/RAMDISK0/ramfile", O_RDWR);
fd2 = open("/RAMDISK0/ramfile2", O_RDWR);
printu("file descriptor fd1 (ramfile): %d\n", fd1);
printu("file descriptor fd2 (ramfile2): %d\n", fd2);
// check the number of hard links to ramfile on disk
struct istat st;
disk_stat_u(fd1, &st);
printu("ramfile hard links: %d\n", st.st_nlinks);
if (st.st_nlinks != 2) {
printu("ERROR: the number of hard links to ramfile should be 2, but it is %d\n",
st.st_nlinks);
exit(-1);
}
write_u(fd1, str, strlen(str));
printu("/RAMDISK0/ramfile write content: \n%s\n", str);
read_u(fd2, buf, MAXBUF);
printu("/RAMDISK0/ramfile2 read content: \n%s\n", buf);
close(fd1);
close(fd2);
printu("\n======== Test 2: unlink ========\n");
ls("/RAMDISK0");
unlink_u("/RAMDISK0/ramfile");
printu("unlink: /RAMDISK0/ramfile\n");
ls("/RAMDISK0");
// check the number of hard links to ramfile2 on disk
fd2 = open("/RAMDISK0/ramfile2", O_RDWR);
disk_stat_u(fd2, &st);
printu("ramfile2 hard links: %d\n", st.st_nlinks);
if (st.st_nlinks != 1) {
printu("ERROR: the number of hard links to ramfile should be 1, but it is %d\n",
st.st_nlinks);
exit(-1);
}
close(fd2);
printu("\nAll tests passed!\n\n");
exit(0);
return 0;
}

@ -0,0 +1,31 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
char *path = argv[0];
int dir_fd = opendir_u(path);
printu("---------- ls command -----------\n");
printu("ls \"%s\":\n", path);
printu("[name] [inode_num]\n");
struct dir dir;
int width = 20;
while(readdir_u(dir_fd, &dir) == 0) {
// we do not have %ms :(
char name[width + 1];
memset(name, ' ', width + 1);
name[width] = '\0';
if (strlen(dir.name) < width) {
strcpy(name, dir.name);
name[strlen(dir.name)] = ' ';
printu("%s %d\n", name, dir.inum);
}
else
printu("%s %d\n", dir.name, dir.inum);
}
printu("------------------------------\n");
closedir_u(dir_fd);
exit(0);
return 0;
}

@ -0,0 +1,15 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
char *new_dir = argv[0];
printu("\n======== mkdir command ========\n");
mkdir_u(new_dir);
printu("mkdir: %s\n", new_dir);
exit(0);
return 0;
}

@ -0,0 +1,53 @@
/*
* This app starts a very simple shell and executes some simple commands.
* The commands are stored in the hostfs_root/shellrc
* The shell loads the file and executes the command line by line.
*/
#include "user_lib.h"
#include "string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
printu("\n======== Shell Start ========\n\n");
int fd;
int MAXBUF = 1024;
char buf[MAXBUF];
char *token;
char delim[3] = " \n";
fd = open("/shellrc", O_RDONLY);
read_u(fd, buf, MAXBUF);
close(fd);
char *command = naive_malloc();
char *para = naive_malloc();
int start = 0;
while (1)
{
if(!start) {
token = strtok(buf, delim);
start = 1;
}
else
token = strtok(NULL, delim);
strcpy(command, token);
token = strtok(NULL, delim);
strcpy(para, token);
if(strcmp(command, "END") == 0 && strcmp(para, "END") == 0)
break;
printu("Next command: %s %s\n\n", command, para);
printu("==========Command Start============\n\n");
int pid = fork();
if(pid == 0) {
int ret = exec(command, para);
if (ret == -1)
printu("exec failed!\n");
}
else
{
wait(pid);
printu("==========Command End============\n\n");
}
}
exit(0);
return 0;
}

@ -0,0 +1,17 @@
#include "user_lib.h"
#include "util/string.h"
#include "util/types.h"
int main(int argc, char *argv[]) {
int fd;
char *filename = argv[0];
printu("\n======== touch command ========\n");
printu("touch: %s\n", filename);
fd = open(filename, O_CREAT);
printu("file descriptor fd: %d\n", fd);
close(fd);
exit(0);
return 0;
}
Loading…
Cancel
Save