From de20d7430df08731d9108acb83e1234ba7f1fe16 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 19 Sep 2020 14:53:29 -0400 Subject: file manager --- src/user/dirinfo/dirinfo.c | 2 +- src/user/elf.ld | 8 -- src/user/fileman/fileman.c | 130 ++++++++++++++++++++++++++++ src/user/highway/line.c | 6 +- src/user/highway/main.c | 2 +- src/user/include/knob/block.h | 3 + src/user/include/knob/file.h | 5 +- src/user/include/knob/quit.h | 7 -- src/user/include/knob/user.h | 3 + src/user/include/pland/pcrt.h | 16 ++++ src/user/include/pland/syscall.h | 182 +++++++++++++++++++++++++++++++-------- src/user/knob/block.c | 9 ++ src/user/knob/entry.asm | 23 ----- src/user/knob/file.c | 21 ++++- src/user/knob/quit.c | 8 -- src/user/knob/user.c | 13 ++- src/user/runtimes/asm/elf.ld | 8 ++ src/user/runtimes/c/elf.ld | 22 +++++ src/user/runtimes/c/entry.asm | 42 +++++++++ 19 files changed, 416 insertions(+), 94 deletions(-) delete mode 100644 src/user/elf.ld create mode 100644 src/user/fileman/fileman.c delete mode 100644 src/user/include/knob/quit.h create mode 100644 src/user/include/pland/pcrt.h delete mode 100644 src/user/knob/entry.asm delete mode 100644 src/user/knob/quit.c create mode 100644 src/user/runtimes/asm/elf.ld create mode 100644 src/user/runtimes/c/elf.ld create mode 100644 src/user/runtimes/c/entry.asm (limited to 'src/user') diff --git a/src/user/dirinfo/dirinfo.c b/src/user/dirinfo/dirinfo.c index 7484eb8..21afcc7 100644 --- a/src/user/dirinfo/dirinfo.c +++ b/src/user/dirinfo/dirinfo.c @@ -13,7 +13,7 @@ void main(const char *arg) { tell_user_sz(*arg ? arg : "drive root"); tell_user_sz("\n"); - _dir_info_entry infos[MAX_DIR_ENTRIES]; + _dir_info_entry_t infos[MAX_DIR_ENTRIES]; uint8_t count = _enumerate_dir(dn, path, infos, MAX_DIR_ENTRIES); tell_user_sz( count == MAX_DIR_ENTRIES diff --git a/src/user/elf.ld b/src/user/elf.ld deleted file mode 100644 index aaef517..0000000 --- a/src/user/elf.ld +++ /dev/null @@ -1,8 +0,0 @@ -OUTPUT_FORMAT(elf32-i386) -OUTPUT_ARCH(i386) -ENTRY(_entry) - -MEMORY { - kernel (!a) : ORIGIN = 0x00000000, LENGTH = 0x08000000 - user (awx) : ORIGIN = 0x08000000, LENGTH = 0xf8000000 -} \ No newline at end of file diff --git a/src/user/fileman/fileman.c b/src/user/fileman/fileman.c new file mode 100644 index 0000000..0b28d1d --- /dev/null +++ b/src/user/fileman/fileman.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include + +char path_sz[1024] = ""; +uint32_t path_len = 0; + +_dir_info_entry_t *dir_info; +uint32_t dir_info_len; + +uint32_t scroll; +uint32_t selected; +#define MAX_PER_SCREEN 18 + +void paint_screen() { + _clear_screen(); + + _set_color(0x70); + _print_at(0, 0, path_sz); + _log_string("/"); + _set_color(0x07); + + for (uint32_t i = scroll, row = 2; (i < dir_info_len) && (row < MAX_PER_SCREEN + 2); ++i, ++row) { + if (i == selected) + _set_color(0x17); + _print_at(row, 0, dir_info[i].name); + if (dir_info[i].is_dir) + _log_string("/"); + if (i == selected) + _set_color(0x07); + } + + _print_at(21, 0, "keybindings:\n" + "UP, DOWN, PAGE UP, PAGE DOWN, HOME, END: move selection\n" + "ENTER: enter selected directory, run selected program\n" + "ESC: go up a directory Q: quit"); +} + +void load_dir() { + free_block(dir_info); + dir_info = get_directory_info(path_sz, &dir_info_len); + scroll = 0; + selected = 0; +} + +void main(const char *sz) { + path_len = strcpy(path_sz, sz); + dir_info = get_directory_info(sz, &dir_info_len); + + paint_screen(); + + while (true) { + _key_code_t key; + switch (key = _get_key()) { + case 0: + _yield_task(); + continue; + case '\n': + { + uint32_t old_len = path_len; + if (path_len) + path_sz[path_len++] = '/'; + path_len += strcpy(path_sz + path_len, dir_info[selected].name); + if (dir_info[selected].is_dir) + load_dir(); + else { + try_run_command_blocking(path_sz); + //TODO: handle error + path_sz[old_len] = '\0'; + path_len = old_len; + } + } + break; + case _KEY_ESC: + { + char *cutoff = path_sz; + for (char *i = path_sz + path_len - 1; i >= path_sz; --i) + if (*i == '/') { + cutoff = i; + break; + } + *cutoff = '\0'; + path_len = cutoff - path_sz; + load_dir(); + } + break; + case _KEY_HOME: + scroll = 0; + selected = 0; + break; + case _KEY_END: + selected = dir_info_len - 1; + scroll = dir_info_len >= MAX_PER_SCREEN + ? dir_info_len - MAX_PER_SCREEN : 0; + break; + case _KEY_UP: + if (!selected) + continue; + if (--selected < scroll) + scroll = selected; + break; + case _KEY_DOWN: + if (selected == dir_info_len - 1) + continue; + if (++selected >= scroll + MAX_PER_SCREEN) + ++scroll; + break; + case _KEY_PUP: + selected = selected >= MAX_PER_SCREEN + ? selected - MAX_PER_SCREEN : 0; + scroll = scroll >= MAX_PER_SCREEN + ? scroll - MAX_PER_SCREEN : 0; + break; + case _KEY_PDOWN: + if ((selected += MAX_PER_SCREEN) >= dir_info_len) + selected = dir_info_len - 1; + if ((scroll += MAX_PER_SCREEN) > selected) + scroll = selected; + break; + case 'q': + _clear_screen(); + return; + default: + continue; + } + paint_screen(); + } +} \ No newline at end of file diff --git a/src/user/highway/line.c b/src/user/highway/line.c index ca38c9b..40dccfa 100644 --- a/src/user/highway/line.c +++ b/src/user/highway/line.c @@ -1,5 +1,5 @@ +#include #include -#include #include #include #include "cmds.h" @@ -68,7 +68,7 @@ void run_line(const char *original_line) { else if (blockequ(line, "vars", space - line)) dump_vars(); else if (blockequ(line, "quit", space - line)) - quit(space + 1); + __pcrt_quit(); else if (blockequ(line, "help", space - line)) tell_user_sz("Highway is a command shell for Portland OS. It includes variables and a couple\n" "of pseudo-commands. Variables are addressed by surrounding with \"$\". The\n" @@ -78,7 +78,7 @@ void run_line(const char *original_line) { " echo STRING print STRING\n" " vars dump variables\n" " quit exit highway\n" - " help show this\n\n"); + " help show this\n"); else if (!try_run_command_blocking(line)) { struct no_null_sn arg = { .data = "_path", diff --git a/src/user/highway/main.c b/src/user/highway/main.c index 1934920..61f736e 100644 --- a/src/user/highway/main.c +++ b/src/user/highway/main.c @@ -9,7 +9,7 @@ void main(const char *arg) { yield_task(); tell_user_sz("Portland Highway\nType \"help\" for help.\n"); while (1) { - tell_user_sz("> "); + tell_user_sz("\n> "); ask_user_line_sz(cmd_buf, 127); run_line(cmd_buf); } diff --git a/src/user/include/knob/block.h b/src/user/include/knob/block.h index 4625577..43137e1 100644 --- a/src/user/include/knob/block.h +++ b/src/user/include/knob/block.h @@ -7,4 +7,7 @@ void blockcpy(void *to, const void *from, uint32_t size); bool blockequ(const void *a, const void *b, uint32_t size) __attribute__ ((__pure__)); +//returns length without null-terminator +uint32_t strcpy(char *to, const char *from); + #endif \ No newline at end of file diff --git a/src/user/include/knob/file.h b/src/user/include/knob/file.h index a0d084f..8862098 100644 --- a/src/user/include/knob/file.h +++ b/src/user/include/knob/file.h @@ -2,6 +2,7 @@ #define KNOB_FILE_H #include +#include struct file; @@ -9,7 +10,6 @@ const char *remove_prefix(const char *path, uint8_t *dn_out); struct file *open_file(const char *path); void close_file(struct file *f); -void _close_all_files(); uint32_t read_from_file(struct file *f, uint32_t max, void *buf); //return value and max_length don't include null terminator @@ -19,4 +19,7 @@ int32_t seek_file_by(struct file *f, int32_t by); uint32_t file_size(struct file *f) __attribute__ ((pure)); +//return value must be manually freed, unless it is a null pointer +_dir_info_entry_t *get_directory_info(const char *path, uint32_t *count_out); + #endif \ No newline at end of file diff --git a/src/user/include/knob/quit.h b/src/user/include/knob/quit.h deleted file mode 100644 index 7b10d09..0000000 --- a/src/user/include/knob/quit.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef KNOB_QUIT_H -#define KNOB_QUIT_H - -void on_quit(void (*run_f)()); -void quit() __attribute__ ((noreturn)); - -#endif \ No newline at end of file diff --git a/src/user/include/knob/user.h b/src/user/include/knob/user.h index 479a731..cd7676c 100644 --- a/src/user/include/knob/user.h +++ b/src/user/include/knob/user.h @@ -2,6 +2,9 @@ #define KNOB_USER_H #include +#include + +char key_to_char(_key_code_t key) __attribute__ ((const)); void tell_user_sz(const char *sz); diff --git a/src/user/include/pland/pcrt.h b/src/user/include/pland/pcrt.h new file mode 100644 index 0000000..07ad453 --- /dev/null +++ b/src/user/include/pland/pcrt.h @@ -0,0 +1,16 @@ +#ifndef PLAND_PCRT_H +#define PLAND_PCRT_H + +#define BEFORE_MAIN(f) \ + __attribute__ ((section (".__pcrt_before_main"))) \ + __attribute__ ((unused)) \ + void (*const __pcrt_bm_##f)() = &f; + +#define BEFORE_QUIT(f) \ + __attribute__ ((section (".__pcrt_before_quit"))) \ + __attribute__ ((unused)) \ + void (*const __pcrt_bq_##f)() = &f; + +void __pcrt_quit() __attribute__ ((noreturn)); + +#endif \ No newline at end of file diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index e16a7fb..331002e 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -7,14 +7,9 @@ typedef uint32_t _file_handle_t; typedef uint32_t _task_handle_t; typedef uint32_t _drive_number_t; -typedef uint32_t _pages_t; typedef uint32_t _process_handle_t; typedef enum { - _KEY_BACKSPACE = '\b', - _KEY_RETURN = '\n', - //etc. - _KEY_LSHIFT = 0x00000100, _KEY_RSHIFT = 0x00000200, _KEY_CAPS = 0x00000400, @@ -33,8 +28,103 @@ typedef enum { _KEY_ALT = 0x0000c000, _KEY_CTRL = 0x00030000, _KEY_META = 0x000c0000, + + _KEY_BEGIN_CAPS = 0x80, + _KEY_BEGIN_INSERT, + _KEY_BEGIN_NUM, + _KEY_BEGIN_SCROLL, + _KEY_BEGIN_LSHIFT, + _KEY_BEGIN_RSHIFT, + _KEY_BEGIN_LALT, + _KEY_BEGIN_RALT, + _KEY_BEGIN_LCTRL, + _KEY_BEGIN_RCTRL, + _KEY_BEGIN_LMETA, + _KEY_BEGIN_RMETA, + /* 0x8c - 0x97 reserved */ + /* 0x98 - 0x9f unassigned */ + _KEY_F1 = 0xa0, + _KEY_F2, + _KEY_F3, + _KEY_F4, + _KEY_F5, + _KEY_F6, + _KEY_F7, + _KEY_F8, + _KEY_F9, + _KEY_F10, + _KEY_F11, + _KEY_F12, + /* 0xac - 0xaf unassigned */ + _KEY_NUM0 = 0xb0, + _KEY_NUM1, + _KEY_NUM2, + _KEY_NUM3, + _KEY_NUM4, + _KEY_NUM5, + _KEY_NUM6, + _KEY_NUM7, + _KEY_NUM8, + _KEY_NUM9, + _KEY_NTIMES, + _KEY_NPLUS, + _KEY_NENTER, + _KEY_NMINUS, + _KEY_NDOT, + _KEY_NSLASH, + /* 0xc0 unassigned */ + _KEY_DELETE, + _KEY_HOME, + _KEY_END, + _KEY_PUP, + _KEY_PDOWN, + _KEY_UP, + _KEY_DOWN, + _KEY_LEFT, + _KEY_RIGHT, + _KEY_ESC, + _KEY_MENU, + _KEY_PAUSE, + _KEY_PRSCR, + /* 0xce - 0xef unassigned */ } _key_code_t; +typedef enum { + _COLOR_FG_BLACK = 0x00, + _COLOR_FG_BLUE = 0x01, + _COLOR_FG_GREEN = 0x02, + _COLOR_FG_CYAN = 0x03, + _COLOR_FG_RED = 0x04, + _COLOR_FG_MAGENTA = 0x05, + _COLOR_FG_BROWN = 0x06, + _COLOR_FG_LGRAY = 0x07, + + _COLOR_FG_DGRAY = 0x08, + _COLOR_FG_LBLUE = 0x09, + _COLOR_FG_LGREEN = 0x0a, + _COLOR_FG_LCYAN = 0x0b, + _COLOR_FG_LRED = 0x0c, + _COLOR_FG_PINK = 0x0d, + _COLOR_FG_YELLOW = 0x0e, + _COLOR_FG_WHITE = 0x0f, + + _COLOR_BG_BLACK = 0x00, + _COLOR_BG_BLUE = 0x10, + _COLOR_BG_GREEN = 0x20, + _COLOR_BG_CYAN = 0x30, + _COLOR_BG_RED = 0x40, + _COLOR_BG_MAGENTA = 0x50, + _COLOR_BG_BROWN = 0x60, + _COLOR_BG_LGRAY = 0x70 +} _vga_color_t; + +typedef struct __attribute__ ((packed)) { + char name[100]; + uint32_t size; + bool is_dir; + uint8_t pad[23]; +} _dir_info_entry_t; + enum _scn { _SCN_OPEN_FILE, _SCN_CLOSE_FILE, @@ -46,72 +136,74 @@ enum _scn { _SCN_ALLOCATE_RAM, _SCN_MEMORY_INFO, _SCN_WAIT_FOR_TASK, - _SCN_ENUMERATE_DIR + _SCN_ENUMERATE_DIR, + _SCN_PRINT_AT, + _SCN_COUNT_OF_DIR, + _SCN_CLEAR_SCREEN, + _SCN_SET_COLOR }; -typedef struct { - bool is_dir; - char name[100]; - uint32_t size; -} _dir_info_entry; - static inline uint32_t _sc0(enum _scn eax) { - volatile uint32_t out; - asm ( + uint32_t out; + asm volatile ( "int $0x30" : "=a" (out) : "a" (eax) : "ecx", "edx"); return out; } static inline uint32_t _sc1(enum _scn eax, uint32_t ebx) { - volatile uint32_t out; - asm ( + uint32_t out; + asm volatile ( "int $0x30" : "=a" (out) : "a" (eax), "b" (ebx) : "ecx", "edx"); return out; } static inline uint32_t _sc2(enum _scn eax, uint32_t ebx, uint32_t ecx) { - volatile uint32_t out; - asm ( + uint32_t out; + uint32_t dummy; + asm volatile ( "int $0x30" - : "=a" (out) : "a" (eax), "b" (ebx), "c" (ecx) : "edx"); + : "=a" (out), "=c" (dummy) : "a" (eax), "b" (ebx), "c" (ecx) : "edx"); return out; } static inline uint32_t _sc3(enum _scn eax, uint32_t ebx, uint32_t ecx, uint32_t edx) { - volatile uint32_t out; - asm ( + uint32_t out; + uint32_t dummy; + asm volatile ( "int $0x30" - : "=a" (out) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx)); + : "=a" (out), "=c" (dummy), "=d" (dummy) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx)); return out; } static inline uint32_t _sc4(enum _scn eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi) { - volatile uint32_t out; - asm ( + uint32_t out; + uint32_t dummy; + asm volatile ( "int $0x30" - : "=a" (out) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi)); + : "=a" (out), "=c" (dummy), "=d" (dummy) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi)); return out; } static inline uint32_t _sc5(enum _scn eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi) { - volatile uint32_t out; - asm ( + uint32_t out; + uint32_t dummy; + asm volatile ( "int $0x30" - : "=a" (out) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi)); + : "=a" (out), "=c" (dummy), "=d" (dummy) : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi)); return out; } static inline void _yield_task() { - asm ( + asm volatile ( "int $0x39" : : : "eax"); } __attribute__ ((noreturn)) static inline void _exit_task() { - asm ( + asm volatile ( "int $0x38" ); __builtin_unreachable(); @@ -145,27 +237,27 @@ static inline _key_code_t _get_key() { return _sc0(_SCN_GET_KEY); } -static inline void *_allocate_ram(_pages_t pages) { +static inline void *_allocate_ram(uint32_t pages) { return (void *)_sc1(_SCN_ALLOCATE_RAM, pages); } -static inline _pages_t _kernel_dynamic_area_size() { +static inline uint32_t _kernel_dynamic_area_size() { return _sc1(_SCN_MEMORY_INFO, 0x0); } -static inline _pages_t _kernel_dynamic_area_left() { +static inline uint32_t _kernel_dynamic_area_left() { return _sc1(_SCN_MEMORY_INFO, 0x1); } -static inline _pages_t _total_userspace_size() { +static inline uint32_t _total_userspace_size() { return _sc1(_SCN_MEMORY_INFO, 0x2); } -static inline _pages_t _total_userspace_left() { +static inline uint32_t _total_userspace_left() { return _sc1(_SCN_MEMORY_INFO, 0x3); } -static inline _pages_t _this_process_memory_left() { +static inline uint32_t _this_process_memory_left() { return _sc1(_SCN_MEMORY_INFO, 0x4); } @@ -173,8 +265,24 @@ static inline void _wait_for_task(_process_handle_t handle) { _sc1(_SCN_WAIT_FOR_TASK, handle); } -static inline uint32_t _enumerate_dir(_drive_number_t drive_number, const char *path, _dir_info_entry *buffer, uint32_t max_count) { +static inline uint32_t _enumerate_dir(_drive_number_t drive_number, const char *path, _dir_info_entry_t *buffer, uint32_t max_count) { return _sc4(_SCN_ENUMERATE_DIR, drive_number, (uint32_t)path, (uint32_t)buffer, max_count); } +static inline void _print_at(uint8_t row, uint8_t col, const char *sz) { + _sc2(_SCN_PRINT_AT, (row << 8) | col, (uint32_t)sz); +} + +static inline uint32_t _count_of_dir(uint8_t drive_number, const char *path) { + return _sc2(_SCN_COUNT_OF_DIR, drive_number, (uint32_t)path); +} + +static inline void _clear_screen() { + _sc0(_SCN_CLEAR_SCREEN); +} + +static inline void _set_color(_vga_color_t color) { + _sc1(_SCN_SET_COLOR, color); +} + #endif \ No newline at end of file diff --git a/src/user/knob/block.c b/src/user/knob/block.c index 7524ad3..4ec0564 100644 --- a/src/user/knob/block.c +++ b/src/user/knob/block.c @@ -14,4 +14,13 @@ bool blockequ(const void *a, const void *b, uint32_t size) { if (*(uint8_t *)(a++) != *(uint8_t *)(b++)) return false; return true; +} + +//returns length without null-terminator +uint32_t strcpy(char *to, const char *from) { + uint32_t i = 0; + do + to[i] = from[i]; + while (from[i++]); + return i - 1; } \ No newline at end of file diff --git a/src/user/knob/entry.asm b/src/user/knob/entry.asm deleted file mode 100644 index e9548d4..0000000 --- a/src/user/knob/entry.asm +++ /dev/null @@ -1,23 +0,0 @@ -bits 32 - -global _entry - -extern main -extern quit - -extern current_disk - -section .text -_entry: - mov esp, stack - push edx - - ;TODO: determine current_disk - ;any further needed initialization - - push quit - jmp main - -section .stack nobits alloc noexec write align=16 -resb 4096 -stack: \ No newline at end of file diff --git a/src/user/knob/file.c b/src/user/knob/file.c index 23b7564..f1a039d 100644 --- a/src/user/knob/file.c +++ b/src/user/knob/file.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -11,11 +12,13 @@ struct ofl_node { static struct ofl_node *head_ofl_node = 0; -void _close_all_files() { +static void _close_all_files() { for (struct ofl_node *i = head_ofl_node; i; i = i->next) _close_file(i->handle); } +BEFORE_QUIT(_close_all_files) + struct file { struct ofl_node *node; _file_handle_t handle; @@ -121,4 +124,20 @@ int32_t seek_file_by(struct file *f, int32_t by) { __attribute__ ((pure)) uint32_t file_size(struct file *f) { return f->length; +} + +//return value must be manually freed, unless it is a null pointer +_dir_info_entry_t *get_directory_info(const char *path, uint32_t *count_out) { + uint8_t dn; + path = remove_prefix(path, &dn); + + uint32_t count = _count_of_dir(dn, path); + if (!count) { + *count_out = 0; + return 0; + } + + _dir_info_entry_t *buffer = get_block(count * sizeof(_dir_info_entry_t)); + *count_out = _enumerate_dir(dn, path, buffer, count); + return buffer; } \ No newline at end of file diff --git a/src/user/knob/quit.c b/src/user/knob/quit.c deleted file mode 100644 index 98881b7..0000000 --- a/src/user/knob/quit.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -__attribute__ ((noreturn)) -void quit() { - _close_all_files(); - _exit_task(); -} \ No newline at end of file diff --git a/src/user/knob/user.c b/src/user/knob/user.c index b642f79..dfcb791 100644 --- a/src/user/knob/user.c +++ b/src/user/knob/user.c @@ -116,10 +116,8 @@ static const uint8_t shifted[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static char get_key_char() { - _key_code_t key; - while (!(key = _get_key())) - _yield_task(); +__attribute__ ((const)) +char key_to_char(_key_code_t key) { return key & _KEY_CAPS ? key & _KEY_SHIFT @@ -130,6 +128,13 @@ static char get_key_char() { : key & 0xff; } +static char get_key_char() { + _key_code_t key; + while (!(key = _get_key())) + _yield_task(); + return key_to_char(key); +} + void tell_user_sz(const char *sz) { _log_string(sz); } diff --git a/src/user/runtimes/asm/elf.ld b/src/user/runtimes/asm/elf.ld new file mode 100644 index 0000000..aaef517 --- /dev/null +++ b/src/user/runtimes/asm/elf.ld @@ -0,0 +1,8 @@ +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386) +ENTRY(_entry) + +MEMORY { + kernel (!a) : ORIGIN = 0x00000000, LENGTH = 0x08000000 + user (awx) : ORIGIN = 0x08000000, LENGTH = 0xf8000000 +} \ No newline at end of file diff --git a/src/user/runtimes/c/elf.ld b/src/user/runtimes/c/elf.ld new file mode 100644 index 0000000..f321be2 --- /dev/null +++ b/src/user/runtimes/c/elf.ld @@ -0,0 +1,22 @@ +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386) +ENTRY(__pcrt_entry) + +MEMORY { + kernel (!a) : ORIGIN = 0x00000000, LENGTH = 0x08000000 + user (awx) : ORIGIN = 0x08000000, LENGTH = 0xf8000000 +} + +SECTIONS { + .__pcrt_before_main : { + __pcrt_before_main_start = .; + *(.__pcrt_before_main) + __pcrt_before_main_end = .; + } + + .__pcrt_before_quit : { + __pcrt_before_quit_start = .; + *(.__pcrt_before_quit) + __pcrt_before_quit_end = .; + } +} \ No newline at end of file diff --git a/src/user/runtimes/c/entry.asm b/src/user/runtimes/c/entry.asm new file mode 100644 index 0000000..bba8060 --- /dev/null +++ b/src/user/runtimes/c/entry.asm @@ -0,0 +1,42 @@ +bits 32 + +global __pcrt_entry +global __pcrt_quit + +extern main +extern __pcrt_before_main_start +extern __pcrt_before_main_end +extern __pcrt_before_quit_start +extern __pcrt_before_quit_end + +section .text +__pcrt_entry: + mov esp, stack + push edx + + mov ebx, __pcrt_before_main_start +.before_main_loop: + cmp ebx, __pcrt_before_main_end + je .call_main + call dword [ebx] + add ebx, 4 + jmp .before_main_loop + +.call_main: + call main + +__pcrt_quit: + mov ebx, __pcrt_before_quit_start +.before_quit_loop: + cmp ebx, __pcrt_before_quit_end + je .end_task + call dword [ebx] + add ebx, 4 + jmp .before_quit_loop + +.end_task: + int 0x38 + +section .stack nobits alloc noexec write align=16 +resb 4096 +stack: \ No newline at end of file -- cgit v1.2.3