diff --git a/doc/src/app/return-value.md b/doc/src/app/return-value.md
new file mode 100644
index 0000000..e04275b
--- /dev/null
+++ b/doc/src/app/return-value.md
@@ -0,0 +1,51 @@
+
+# 应用程序返回值
+
+应用程序返回值是一个 32 位整数(即使在 64 位系统上也是如此)。
+The application return value is a 32-bit integer (even on 64-bit systems).
+
+应用程序返回值的高 16 位不应当被应用程序设置,而只应被操作系统或系统库设置。
+The high 16 bits of the application return value should not be set by the application, but only by the operating system or system library.
+
+应用程序退出码应当是一个 8 位无符号整数,如果需要也可以是一个 16 位无符号整数。
+The application exit code should be an 8-bit unsigned integer, and can be a 16-bit unsigned integer if necessary.
+
+- `0-7`: 应用程序退出码 / Application exit code.
+- `8-15`: 可用 / Available.
+- `16-23`: 错误码 / Error code.
+- `24-28`: 保留 / Reserved.
+- `29`: 链接错误 / Link error.
+- `30`: 非应用程序主动退出 / Non-application initiated exit.
+- `31`: 保留 / Reserved.
+
+第 31 位永远不会被使用,第 24-28 位可能在未来被使用。
+The 31st bit will never be used, and the 16th-28th bits may be used in the future.
+
+第 30 位标记为非应用程序主动退出,可能是因为启动时链接错误、未处理信号、因某些原因被杀死等。
+The 30th bit is marked as a non-application initiated exit, which may be due to a link error at startup, unhandled signals, being killed for some reason, etc.
+
+第 29 位标记为链接错误,可能是因为未找到依赖库、文件数据错误等。
+The 29th bit is marked as a link error, which may be due to missing dependent libraries, file data errors, etc.
+
+第 16-23 位是错误码,用于标记应用程序的错误类型。
+The 16th-23rd bits are error codes used to mark the error type of the application.
+
+非应用程序主动退出时低 16 位将被填充为 0xffff。
+When a non-application initiated exit occurs, the low 16 bits will be filled with 0xffff.
+
+应用程序退出码的值应当在 0 到 255 之间,其中 0 表示成功,非 0 表示失败。
+The value of the application exit code should be between 0 and 255, where 0 indicates success and non-zero indicates failure.
+
+## 链接错误
+
+- `0` 未知错误 / Unknown error.
+- `1` 未定义入口点 / Entry point undefined.
+- `2` 无法找到文件 / Unable to find file.
+- `3` 无法读取文件 / Unable to read file.
+- `4` 无法解析文件 / Unable to parse file.
+- `5` 无法找到依赖库 / Unable to find dependent library.
+- `6` 无法读取依赖库 / Unable to read dependent library.
+- `7` 无法解析依赖库 / Unable to parse dependent library.
+- `8` 内存不足 / Out of memory.
+- `9` 架构不匹配 / Architecture mismatch.
+- `255` 传入参数错误 / Invalid input parameters.
diff --git a/include/libc-base/asm/asm.h b/include/libc-base/asm/asm.h
index f1943c3..1f5315e 100755
--- a/include/libc-base/asm/asm.h
+++ b/include/libc-base/asm/asm.h
@@ -21,7 +21,13 @@
#define asm_setreg(reg, value) ({ asm volatile("mov %0, %%" #reg "\n\t" ::"r"((size_t)(value))); })
-#define used_val(value) ({ asm volatile("" ::"r,m"(value) : "memory"); })
+#define used_val1(value) ({ asm volatile("" ::"r,m"(value)); })
+#define used_val2(value, ...) ({ used_val1(value), used_val1(__VA_ARGS__); })
+#define used_val3(value, ...) ({ used_val1(value), used_val2(__VA_ARGS__); })
+#define used_val4(value, ...) ({ used_val1(value), used_val3(__VA_ARGS__); })
+#define used_val5(value, ...) ({ used_val1(value), used_val4(__VA_ARGS__); })
+#define used_val6(value, ...) ({ used_val1(value), used_val5(__VA_ARGS__); })
+#define used_val(...) CONCAT(used_val, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
/**
*\brief 加载 GDT
diff --git a/src/kernel/cpu/gdtidt.c b/src/kernel/cpu/gdtidt.c
index edb04b9..81409ac 100755
--- a/src/kernel/cpu/gdtidt.c
+++ b/src/kernel/cpu/gdtidt.c
@@ -38,7 +38,7 @@ size_t syscall(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t esi, size_
FASTCALL void inthandler(i32 id, regs32 *regs) {
kassert(id < 256);
- if (id != 0x07 && id != 0x2d) asm_set_ts;
+ if (fpu_using_task != null && id != 0x07 && id != 0x2d) asm_set_ts;
if (id >= 0x20 && id < 0x30) send_eoi(id - 0x20);
if (acpi_inited) {
@@ -55,7 +55,7 @@ FASTCALL void inthandler(i32 id, regs32 *regs) {
klogw("Unknown interrupt %02x (%d)", id, id);
}
- if (id != 0x07 && id != 0x2d) {
+ if (fpu_using_task != null && id != 0x07 && id != 0x2d) {
val from_usermod = (regs->cs & 3) == 3;
(current_task == fpu_using_task && fpu_ctx_usermod == from_usermod) ? asm_clr_ts : asm_set_ts;
}
diff --git a/src/kernel/exec/exec.c b/src/kernel/exec/exec.c
index ecb7117..9ddd440 100755
--- a/src/kernel/exec/exec.c
+++ b/src/kernel/exec/exec.c
@@ -71,15 +71,13 @@ void task_to_user_mode_elf() {
struct args args = {.cmdline = current_task->command_line, .sp = (void *)TASK_ARGS_ADDR};
parse_args(&args);
+ used_val(*args.argv, *args.envp);
klogd("argc: %d", args.argc);
- klogd("argv: %p", args.argv);
- klogd("argv: %p", args.envp);
for (int i = 0; i < args.argc; i++) {
klogd("argv[%d]: %s", i, args.argv[i]);
}
vfs_node_t file = vfs_open("/fatfs0/ld-plos.bin");
- // vfs_node_t file = vfs_open(args.argv[0]);
if (file == null) {
if (mouse_use_task == current_task) mouse_sleep(&mdec);
kloge();
diff --git a/src/kernel/task/basetask.c b/src/kernel/task/basetask.c
index a6332fa..37e8b5e 100755
--- a/src/kernel/task/basetask.c
+++ b/src/kernel/task/basetask.c
@@ -39,23 +39,26 @@ static plff_t load_font(cstr path) {
}
void plty_set_default(plty_t plty);
+
void stdout_read() {}
void stdout_write(int drive, u8 *buffer, u32 number, u32 lba) {
for (int i = 0; i < number; i++) {
putchar(buffer[i]);
}
}
+
void random_read(int drive, u8 *buffer, u32 number, u32 lba) {
for (int i = 0; i < number; i++) {
buffer[i] = krandb();
}
}
-void random_write(int drive, u8 *buffer, u32 number, u32 lba) {}
+void random_write(int drive, u8 *buffer, u32 number, u32 lba) {}
+
char *GetSVGACharOEMString();
bool is_vbox = false;
static void check_device() {
- char *s = strdup(GetSVGACharOEMString());
+ char *s = GetSVGACharOEMString();
info("VIDEO CARD: %s", s);
if (strstr(s, "VirtualBox")) {
info("VirtualBox detected");
@@ -64,16 +67,6 @@ static void check_device() {
is_vbox = false;
info("VirtualBox not detected");
}
- free(s);
-}
-
-static void draw(int n) {
- u32 *buf = vbe_backbuffer;
- for (size_t y = 0; y < screen_h; y++) {
- for (size_t x = 0; x < screen_w; x++) {
- buf[y * screen_w + x] = (0xff8000 + x + n) & 0xffffff;
- }
- }
}
extern bool debug_enabled;
diff --git a/src/ld-plos/ld-plos.c b/src/ld-plos/ld-plos.c
index cd70dbf..f56988d 100644
--- a/src/ld-plos/ld-plos.c
+++ b/src/ld-plos/ld-plos.c
@@ -2,37 +2,36 @@
#include
#include
+#include "ld-plos.h"
+
// 一个在没有标准库的环境下加载动态链接 elf 文件的程序
-#define syscall(...) __syscall(__VA_ARGS__)
+static int argc;
+static char **argv;
+static char **envp;
-#ifdef __x86_64__
+// 加载完毕后运行应用程序
+static __attr(noreturn) void run(usize entry) {
+ asm("mov %0, %%edi\n\t" ::"r"(argc));
+ asm("mov %0, %%esi\n\t" ::"r"(argv));
+ asm("mov %0, %%edx\n\t" ::"r"(envp));
+ asm volatile("jmp *%0" ::"r"(entry));
+ __builtin_unreachable();
+}
-static void load_elf32(const Elf32Header *elf) {}
-static void load_elf64(const Elf64Header *elf) {}
+#ifdef __x86_64__
-#else
+static int load_elf32(const Elf32Header *elf) {
+ return 0;
+}
-void print_num(usize num) {
- static char buffer[32];
- char *buf = buffer + 32;
- *--buf = '\0';
- *--buf = '\n';
- while (num) {
- int digit = num % 16;
- *--buf = (digit < 10) ? digit + '0' : digit - 10 + 'a';
- num /= 16;
- }
- syscall(SYSCALL_PRINT, buf);
+static int load_elf64(const Elf64Header *elf) {
+ return 0;
}
+#else
+
int load_segment(const Elf32ProgramHeader *prog, const void *elf) {
- print_num(prog->type);
- print_num(prog->offset);
- print_num(prog->vaddr);
- print_num(prog->filesz);
- print_num(prog->memsz);
- print_num(prog->flags);
if (prog->type != ELF_PROGRAM_TYPE_LOAD) return 0;
usize hi = PADDING_UP(prog->vaddr + prog->memsz, PAGE_SIZE);
usize lo = PADDING_DOWN(prog->vaddr, PAGE_SIZE);
@@ -42,45 +41,51 @@ int load_segment(const Elf32ProgramHeader *prog, const void *elf) {
return 0;
}
-static void load_elf32(const Elf32Header *elf) {
+static int load_elf32(const Elf32Header *elf) {
var prog = (const Elf32ProgramHeader *)((usize)elf + elf->phoff);
for (usize i = 0; i < elf->phnum; i++) {
- if (load_segment(prog + i, elf) < 0) return;
+ if (load_segment(prog + i, elf) < 0) return LDE_FILE_UNPARSABLE;
}
- asm volatile("jmp *%0" : : "r"(elf->entry));
+ run(elf->entry);
}
-static void load_elf64(const void *elf) {
+
+static int load_elf64(const void *elf) {
// Can't load 64-bit ELF in 32-bit system.
+ return LDE_ARCH_MISSMATCH;
}
#endif
-void __linker_main(int argc, char **argv, char **envp) {
- if (argc <= 0 || argv == null || envp == null) return;
- if (argv[0] == null) return;
+int __linker_main(int argc, char **argv, char **envp) {
+ if (argc <= 0 || argv == null || envp == null || argv[0] == null) return LDE_INVALID_INPUT;
- usize size = syscall(SYSCALL_FILE_SIZE, argv[0]);
+ isize size = syscall(SYSCALL_FILE_SIZE, argv[0]);
+ if (size < 0) return LDE_FILE_NOT_FOUND;
void *file = (void *)syscall(SYSCALL_MMAP, null, size);
- syscall(SYSCALL_LOAD_FILE, argv[0], file, size);
+ if (file == null) return LDE_OUT_OF_MEMORY;
+ if (syscall(SYSCALL_LOAD_FILE, argv[0], file, size) < 0) return LDE_FILE_UNREADABLE;
+
+ const Elf32Header *elf = (Elf32Header *)file;
+ const ElfIdent *ident = (ElfIdent *)file;
+ if (ident->magic != ELF_MAGIC) return 1;
- const ElfIdent *ident = (ElfIdent *)file;
- if (ident->magic != ELF_MAGIC) return;
if (ident->class == ELF_CLASS_32) {
- load_elf32(file);
- } else if (ident->class == ELF_CLASS_64) {
- load_elf64(file);
+ if (elf->machine != ELF_MACHINE_IA32) return LDE_ARCH_MISSMATCH;
+ return load_elf32(file);
+ }
+ if (ident->class == ELF_CLASS_64) {
+ if (elf->machine != ELF_MACHINE_AMD64) return LDE_ARCH_MISSMATCH;
+ return load_elf64(file);
}
+ return LDE_FILE_UNPARSABLE;
}
void __linker_start() {
- int volatile argc;
- char **volatile argv;
- char **volatile envp;
asm("mov %%edi, %0\n\t" : "=r"(argc));
asm("mov %%esi, %0\n\t" : "=r"(argv));
asm("mov %%edx, %0\n\t" : "=r"(envp));
- __linker_main(argc, argv, envp);
+ int errcode = __linker_main(argc, argv, envp);
- syscall(SYSCALL_EXIT, INT_MAX);
+ syscall(SYSCALL_EXIT, MASK(30) | MASK(29) | (errcode << 16));
}
diff --git a/src/ld-plos/ld-plos.h b/src/ld-plos/ld-plos.h
new file mode 100644
index 0000000..4783a59
--- /dev/null
+++ b/src/ld-plos/ld-plos.h
@@ -0,0 +1,16 @@
+#pragma once
+
+// 动态链接器错误
+#define LDE_UNKNOWN 0 // 未知错误
+#define LDE_ENTRY_POINT 1 // 未定义入口点
+#define LDE_FILE_NOT_FOUND 2 // 无法找到文件
+#define LDE_FILE_UNREADABLE 3 // 无法读取文件
+#define LDE_FILE_UNPARSABLE 4 // 无法解析文件
+#define LDE_DEP_LIB_NOT_FOUND 5 // 无法找到依赖库
+#define LDE_DEP_LIB_UNREADABLE 6 // 无法读取依赖库
+#define LDE_DEP_LIB_UNPARSABLE 7 // 无法解析依赖库
+#define LDE_OUT_OF_MEMORY 8 // 内存不足
+#define LDE_ARCH_MISSMATCH 9 // 架构不匹配
+#define LDE_INVALID_INPUT 255 // 传入参数错误
+
+#define syscall(...) __syscall(__VA_ARGS__)