From 21491514b3642a321ce65f2a07428f63c4d9feb5 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 8 Nov 2020 11:11:49 -0500 Subject: manual viewer, "swap colors" system call --- src/kernel/idt.c | 3 +- src/kernel/isrs.asm | 2 +- src/kernel/vga.c | 5 + src/kernel/vga.h | 1 + src/man/dev/kmemmap.pre | 34 +++++ src/man/index.pre | 13 ++ src/user/include/pland/syscall.h | 7 +- src/user/manual/manual.c | 268 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 330 insertions(+), 3 deletions(-) create mode 100644 src/man/dev/kmemmap.pre create mode 100644 src/man/index.pre create mode 100644 src/user/manual/manual.c (limited to 'src') diff --git a/src/kernel/idt.c b/src/kernel/idt.c index 1b8e548..ebeea17 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -120,7 +120,8 @@ void const *syscall_table[] = { &vga_print_at, &sc_count_of_dir, &vga_blank, - &vga_set_color + &vga_set_color, + &vga_swap_color }; //these aren't really void ()'s, but gcc complains if we take an address of a void, so we give it a type diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index e7573ae..472bb40 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -23,7 +23,7 @@ extern on_kbd_isr extern make_sure_tasks extern exception_halt -n_syscalls equ 0xf +n_syscalls equ 0x10 ;section .bss ;_debug_is_start_task resb 1 diff --git a/src/kernel/vga.c b/src/kernel/vga.c index 42da312..6ae1588 100644 --- a/src/kernel/vga.c +++ b/src/kernel/vga.c @@ -12,6 +12,11 @@ void vga_set_color(uint8_t new_color) { mask = new_color << 8; } +void vga_swap_color(uint16_t pos) { + uint8_t *color_byte = (uint8_t *)(VGA_START + (pos >> 8) * VGA_COLUMNS + (pos & 0xff)) + 1; + *color_byte = (*color_byte << 4) + (*color_byte >> 4); +} + static void vga_scroll() { for (uint32_t *i = (uint32_t *)VGA_START; i < (uint32_t *)(VGA_END - VGA_COLUMNS); ++i) *i = *(i + VGA_COLUMNS / 2); diff --git a/src/kernel/vga.h b/src/kernel/vga.h index fa97e11..dd1c906 100644 --- a/src/kernel/vga.h +++ b/src/kernel/vga.h @@ -7,5 +7,6 @@ void vga_print_at(uint16_t pos, const char *sz); void vga_set_color(uint8_t color); void vga_blank(); void vga_printch(char ch); +void vga_swap_color(uint16_t pos); #endif \ No newline at end of file diff --git a/src/man/dev/kmemmap.pre b/src/man/dev/kmemmap.pre new file mode 100644 index 0000000..73b4e09 --- /dev/null +++ b/src/man/dev/kmemmap.pre @@ -0,0 +1,34 @@ +\title{Portland Kernel Memory Map} + +This manual page describes the layout of the kernel area of memory. Unless you are doing kernel development, you do not need to know this. This is not guaranteed to remain backwards-compatible across versions. Unspecified memory under \color{07}0x0400.0000\color{0f} is reserved for future use. + +\color{0e}Passed from bootloader\color{0f} + +Starting at \color{07}0x0000.4000\color{0f} is information passed from the bootloader. + +\color{07}0x4000 byte:\color{0f} support flags +- \color{07}0x80:\color{0f} PCI support +- \color{07}0x40:\color{0f} PAE support +- The other flags are reserved. +\color{07}0x4001 byte:\color{0f} PCI's "hardware characteristics" byte +\color{07}0x4002 byte:\color{0f} PCI's minor version +\color{07}0x4003 byte:\color{0f} PCI's major version +\color{07}0x4004 byte:\color{0f} last PCI bus +\color{07}0x4006 word:\color{0f} length of BIOS's memory map + +From \color{07}0x0001.0000\color{0f} to \color{07}0x0001.ffff\color{0f} is the memory map from BIOS. + +\color{0e}Fixed kernel structures\color{0f} + +\color{07}0x0000.4f98 - 0x0000.4fff:\color{0f} the Task State Segment +\color{07}0x0000.5000 - 0x0000.5fff:\color{0f} identity page directory +\color{07}0x0004.0000 - 0x0005.ffff:\color{0f} a bitmap of allocated pages +\color{07}0x0040.0000 - 0x007f.ffff:\color{0f} page tables referenced by identity page directory + +\color{0e}Others\color{0f} + +\color{07}0x000a.0000 - 0x000f.0000\color{0f} and \color{07}0x00f0.0000 - 0x00ff.0000\color{0f} are assumed to be reserved by the motherboard for either memory-mapped hardware or BIOS. The standard VGA area is used as such, and the rest are avoided. + +The kernel is loaded with the text and data sections at \color{07}0x0003.0000 - 0x0003.7fff\color{0f}, and the bss at \color{07}0x0400.0000 - 0x07ff.7fff\color{0f}. \color{07}0x0003.8000 - 0x0003.ffff\color{0f} is used as a stack by the kernel, and whatever part of the bss area is unused is used as a sort of page-resolution "heap" for the kernel. + +Everything after \color{07}0x0800.0000\color{0f} that the BIOS indicates is available for use is used for user pages. \ No newline at end of file diff --git a/src/man/index.pre b/src/man/index.pre new file mode 100644 index 0000000..49f3d13 --- /dev/null +++ b/src/man/index.pre @@ -0,0 +1,13 @@ +\title{Portland Manual Index} + +Use the \color{07}up\color{0f} and \color{07}down\color{0f} arrows to scroll the manual one line at a time, or the \color{07}page up\color{0f} and \color{07}page down\color{0f} buttons to scroll a whole page at a time. Use the \color{07}left\color{0f} and \color{07}right\color{0f} arrows to focus the previous or next link, and the \color{07}space\color{0f} or \color{07}enter\color{0f} keys to follow those links. Use \color{07}escape\color{0f} to go back to the previous page, and \color{07}q\color{0f} to quit. + +\color{0e}Programs\color{0f} +\link{fileman (file manager):bin/fileman} +\link{Highway (command shell):bin/highway} + +\color{0e}Development\color{0f} +\link{System calls:dev/syscalls} +\link{Keycodes:dev/keycodes} +\link{Manual file format:dev/manfile} +\link{Kernel memory map:dev/kmemmap} \ No newline at end of file diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index 14164aa..ead5fea 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -140,7 +140,8 @@ enum _scn { _SCN_PRINT_AT, _SCN_COUNT_OF_DIR, _SCN_CLEAR_SCREEN, - _SCN_SET_COLOR + _SCN_SET_COLOR, + _SCN_SWAP_COLOR }; static inline uint32_t _sc0(enum _scn eax) { @@ -285,4 +286,8 @@ static inline void _set_color(_vga_color_t color) { _sc1(_SCN_SET_COLOR, color); } +static inline void _swap_color(uint8_t row, uint8_t col) { + _sc1(_SCN_SWAP_COLOR, (row << 8) | col); +} + #endif \ No newline at end of file diff --git a/src/user/manual/manual.c b/src/user/manual/manual.c new file mode 100644 index 0000000..48f4f65 --- /dev/null +++ b/src/user/manual/manual.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include +#include + +#define ERROR_COLOR _COLOR_BG_LGRAY | _COLOR_FG_RED +#define UI_COLOR _COLOR_BG_LGRAY | _COLOR_FG_BLACK +#define DEFAULT_TEXT_COLOR _COLOR_BG_BLACK | _COLOR_FG_WHITE + +#define MAN_ROOT "man/" +#define MRL 4 +#define MAN_EXT "man" + +#define MAX_PATH_LEN 255 + +#define SP80 " " +#define SP79 " " +#define SP69 " " +#define SP10 " " + +struct file *cur_file = 0; + +uint32_t *line_offsets = 0; +uint32_t n_lines; + +struct link { + uint32_t line; + uint8_t col; + uint8_t len; + char *lto; +}; + +struct link *link_table_start = 0; +struct link *link_table_end; + +struct link *cur_link = 0; + +uint32_t line_on; + +#define DATA_BUF_SIZE 2000 + +void print_page() { + uint8_t buf[DATA_BUF_SIZE];//1840 + up to 160 color codes + seek_file_to(cur_file, line_offsets[line_on]); + uint8_t *bufp = buf + DATA_BUF_SIZE; + uint8_t *bufend; + uint8_t row = 1, col = 0; + + _set_color(DEFAULT_TEXT_COLOR); + while (row != 24) { + if (bufp == buf + DATA_BUF_SIZE) { + bufp = buf; + uint16_t bl = read_from_file(cur_file, DATA_BUF_SIZE, buf); + bufend = bl == DATA_BUF_SIZE ? 0 : buf + bl; + } + if (bufp == bufend) { + uint32_t *i = buf; + uint16_t l = 80 - col + (23 - row) * 80; + uint32_t *e = i + l / 4 + 1; + while (i != e) + *(i++) = 0x20202020; + buf[l] = '\0'; + _print_at(row, col, buf); + break; + } + if (*bufp & 0x80) + _set_color(*bufp & 0x7f); + else { + char bufpb[2] = {*bufp, '\0'}; + _print_at(row, col, bufpb); + if (++col == 80) { + col = 0; + ++row; + } + } + ++bufp; + } + + if (cur_link) + for (uint8_t c = cur_link->col; c < cur_link->col + cur_link->len; ++c) + _swap_color(cur_link->line - line_on + 1, c); +} + +void scroll_to(uint32_t n) { + if (n > n_lines - 23) + n = n_lines - 23; + + if (cur_link && ((cur_link->line < n) || (cur_link->line >= n + 23))) + cur_link = 0; + + line_on = n; + print_page(); + + char b[16] = "Line "; + itosz(line_on, b + 5); + + _set_color(UI_COLOR); + _print_at(24, 0, SP69); + _print_at(24, 0, b); +} + +void scroll_link() { + if (cur_link->line < line_on) + scroll_to(cur_link->line); + else if (cur_link->line >= line_on + 23) + scroll_to(cur_link->line - 22); + else + print_page(); +} + +void load_file(const char *name) { + static char cur_page[MAX_PATH_LEN + 1] = MAN_ROOT; + uint32_t name_len = strcpy(cur_page + MRL, name); + strcpy(cur_page + MRL + name_len, "." MAN_EXT); + + struct file *new_file = open_file(cur_page); + if (!new_file) { + _set_color(ERROR_COLOR); + _print_at(24, 0, SP79); + _print_at(24, 0, "Could not open file."); + return; + } + + if (cur_file) + close_file(cur_file); + cur_file = new_file; + + uint32_t tlen; + read_from_file(cur_file, 4, &tlen); + char title[81]; + read_from_file(cur_file, tlen + 1, title); + + _set_color(UI_COLOR); + _print_at(0, 0, SP80); + _print_at(0, 0, title); + + if (link_table_start) { + for (struct link *l = link_table_start; l != link_table_end; ++l) + free_block(l->lto); + free_block(link_table_start); + } + + uint32_t linktc; + read_from_file(cur_file, 4, &linktc); + if (linktc) { + link_table_start = get_block(sizeof(struct link) * linktc); + link_table_end = link_table_start + linktc; + read_from_file(cur_file, 4, &linktc);//dummy + + for (struct link *l = link_table_start; l != link_table_end; ++l) { + read_from_file(cur_file, 4, &l->line); + read_from_file(cur_file, 1, &l->col); + read_from_file(cur_file, 1, &l->len); + uint32_t lto_l; + read_from_file(cur_file, 4, <o_l); + l->lto = get_block(lto_l + 1); + read_from_file(cur_file, lto_l + 1, l->lto); + } + } + else { + link_table_start = 0; + read_from_file(cur_file, 4, &linktc);//dummy + } + + cur_link = 0; + + if (line_offsets) + free_block(line_offsets); + + read_from_file(cur_file, 4, &n_lines); + line_offsets = get_block(n_lines * 4); + read_from_file(cur_file, n_lines * 4, line_offsets); + + char b[11]; + itosz(n_lines, b); + + _set_color(UI_COLOR); + _print_at(24, 69, SP10); + _print_at(24, 69, b); + + scroll_to(0); +} + +void main() { + _set_color(UI_COLOR); + _print_at(24, 79, " "); + + load_file("index"); + + while (true) { + switch (_get_key()) { + case 0: + default: + _yield_task(); + break; + case _KEY_UP: + if (n_lines <= 23) + break; + if (line_on) + scroll_to(line_on - 1); + break; + case _KEY_DOWN: + if (n_lines <= 23) + break; + if (line_on < n_lines - 23) + scroll_to(line_on + 1); + break; + case _KEY_PUP: + if (n_lines <= 23) + break; + scroll_to(line_on <= 22 ? 0 : line_on - 22); + break; + case _KEY_PDOWN: + if (n_lines <= 23) + break; + scroll_to(line_on + 22); + break; + case _KEY_LEFT: + if (cur_link == link_table_start) + break; + if (cur_link) { + --cur_link; + scroll_link(); + } + else if (link_table_start) { + struct link *l = link_table_end; + while (l != link_table_start) { + --l; + if (l->line <= line_on + 22) + break; + } + cur_link = l; + scroll_link(); + } + break; + case _KEY_RIGHT: + if (cur_link == link_table_end - 1) + break; + if (cur_link) { + ++cur_link; + scroll_link(); + } + else if (link_table_start) { + struct link *l = link_table_start; + while (l != link_table_end) { + if (l->line >= line_on) + break; + ++l; + } + cur_link = l; + scroll_link(); + } + break; + case ' ': + case '\n': + case _KEY_NENTER: + if (cur_link) + load_file(cur_link->lto); + break; + case _KEY_ESC: + //TODO + break; + case 'q': + return; + } + } +} \ No newline at end of file -- cgit v1.2.3