#include <stddef.h>
int
-memcmp(const void*, const void*, size_t);
+memcmp(const void* dest, const void* src, size_t size);
void*
-memcpy(void* __restrict, const void* __restrict, size_t);
+memcpy(void* dest, const void* src, size_t size);
void*
-memmove(void*, const void*, size_t);
+memmove(void* dest, const void* src, size_t size);
void*
-memset(void*, int, size_t);
+memset(void* dest, int val, size_t size);
size_t
strlen(const char* str);
--- /dev/null
+#ifndef __LUNAIX_FIFO_BUF_H
+#define __LUNAIX_FIFO_BUF_H
+
+#include <lunaix/ds/mutex.h>
+
+#define FIFO_DIRTY 1
+
+struct fifo_buffer
+{
+ void* data;
+ unsigned int wr_pos;
+ unsigned int rd_pos;
+ unsigned int size;
+ unsigned int flags;
+ mutex_t lock;
+};
+
+#endif /* __LUNAIX_FIFO_BUF_H */
--- /dev/null
+#ifndef __LUNAIX_LXCONSOLE_H
+#define __LUNAIX_LXCONSOLE_H
+
+void
+lxconsole_init();
+
+void
+console_write_str(char* str);
+
+void
+console_write_char(char chr);
+
+void
+console_start_flushing();
+#endif /* __LUNAIX_LXCONSOLE_H */
#define __LUNAIX_PMM_H
// Physical memory manager
-#include <stdint.h>
-#include <stddef.h>
#include <lunaix/process.h>
+#include <stddef.h>
+#include <stdint.h>
-#define PM_PAGE_SIZE 4096
-#define PM_BMP_MAX_SIZE (1024 * 1024)
+#define PM_PAGE_SIZE 4096
+#define PM_BMP_MAX_SIZE (1024 * 1024)
+/**
+ * @brief 长久页:不会被缓存,但允许释放
+ *
+ */
+#define PP_FGPERSIST 0x1
-#define PP_FGPERSIST 0x1
+/**
+ * @brief 锁定页:不会被缓存,不能被释放
+ *
+ */
+#define PP_FGLOCKED 0x2
typedef uint32_t pp_attr_t;
-struct pp_struct {
+struct pp_struct
+{
pid_t owner;
uint32_t ref_counts;
pp_attr_t attr;
/**
* @brief 标注物理页为可使用
- *
+ *
* @param ppn page number
*/
-void pmm_mark_page_free(uintptr_t ppn);
+void
+pmm_mark_page_free(uintptr_t ppn);
/**
* @brief 标注物理页为已占用
- *
- * @param ppn
+ *
+ * @param ppn
*/
-void pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr);
+void
+pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr);
/**
* @brief 标注多个连续的物理页为可用
- *
+ *
* @param start_ppn 起始PPN
* @param page_count 数量
*/
-void pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count);
+void
+pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count);
/**
* @brief 标注多个连续的物理页为已占用
- *
+ *
* @param start_ppn 起始PPN
* @param page_count 数量
*/
-void pmm_mark_chunk_occupied(pid_t owner, uintptr_t start_ppn, size_t page_count, pp_attr_t attr);
+void
+pmm_mark_chunk_occupied(pid_t owner,
+ uintptr_t start_ppn,
+ size_t page_count,
+ pp_attr_t attr);
/**
* @brief 分配一个可用的物理页
- *
+ *
* @return void* 可用的页地址,否则为 NULL
*/
-void* pmm_alloc_page(pid_t owner, pp_attr_t attr);
+void*
+pmm_alloc_page(pid_t owner, pp_attr_t attr);
/**
* @brief 分配一个连续的物理内存区域
- *
- * @param owner
+ *
+ * @param owner
* @param num_pages 区域大小,单位为页
- * @param attr
- * @return void*
+ * @param attr
+ * @return void*
*/
void*
pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr);
/**
* @brief 初始化物理内存管理器
- *
+ *
* @param mem_upper_lim 最大可用内存地址
*/
-void pmm_init(uintptr_t mem_upper_lim);
+void
+pmm_init(uintptr_t mem_upper_lim);
-struct pp_struct* pmm_query(void* pa);
+struct pp_struct*
+pmm_query(void* pa);
/**
* @brief 释放一个已分配的物理页,假若页地址不存在,则无操作。
- *
+ *
* @param page 页地址
* @return 是否成功
*/
-int pmm_free_page(pid_t owner, void* page);
-
+int
+pmm_free_page(pid_t owner, void* page);
-int pmm_ref_page(pid_t owner, void* page);
+int
+pmm_ref_page(pid_t owner, void* page);
#endif /* __LUNAIX_PMM_H */
*/
#define VMAP_NOMAP 2
+/**
+ * @brief 规定下一个可用页映射应当限定在指定的4MB地址空间内
+ *
+ */
+#define VALLOC_PDE 1
+
/**
* @brief 初始化虚拟内存管理器
*
void*
vmm_unmount_pd(uintptr_t mnt);
+void*
+vmm_next_free(uintptr_t start, int options);
+
#endif /* __LUNAIX_VMM_H */
--- /dev/null
+#ifndef __LUNAIX_CONSOLE_H
+#define __LUNAIX_CONSOLE_H
+
+#include <lunaix/ds/fifobuf.h>
+#include <lunaix/timer.h>
+
+struct console
+{
+ struct lx_timer* flush_timer;
+ struct fifo_buffer buffer;
+};
+
+#endif /* __LUNAIX_CONSOLE_H */
#define VGA_COLOR_RED 4
#define VGA_COLOR_MAGENTA 5
#define VGA_COLOR_BROWN 6
-#define VGA_COLOR_LIGHT_GREY 7
#define VGA_COLOR_DARK_GREY 8
+#define VGA_COLOR_LIGHT_GREY 7
#define VGA_COLOR_LIGHT_BLUE 9
#define VGA_COLOR_LIGHT_GREEN 10
#define VGA_COLOR_LIGHT_CYAN 11
#define VGA_COLOR_LIGHT_BROWN 14
#define VGA_COLOR_WHITE 15
-void
-tty_init(void* vga_buf);
+#define TTY_WIDTH 80
+#define TTY_HEIGHT 25
void
-tty_set_buffer(void* vga_buf);
+tty_init(void* vga_buf);
void
tty_set_theme(vga_attribute fg, vga_attribute bg);
-void
-tty_put_char(char chr);
-
-void
-tty_put_str(char* str);
-
-void
-tty_scroll_up();
-
-void
-tty_clear();
-
-void
-tty_clear_line(unsigned int y);
-
-void
-tty_set_cpos(unsigned int x, unsigned int y);
-
-void
-tty_get_cpos(unsigned int* x, unsigned int* y);
-
vga_attribute
tty_get_theme();
-void tty_set_cursor(unsigned char x, unsigned char y);
+size_t
+tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size);
-void tty_sync_cursor();
+void
+tty_clear_line(int line_num);
+void
+tty_put_str_at(char* str, int x, int y);
#endif /* __LUNAIX_TTY_H */
#include <lunaix/tty/tty.h>
#include <lunaix/clock.h>
+#include <lunaix/lxconsole.h>
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/pmm.h>
vmm_init();
rtc_init();
- tty_init((void*)VGA_BUFFER_PADDR);
+ unsigned int map_size =
+ _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
+
+ setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size);
+
+ tty_init((void*)VGA_BUFFER_VADDR);
tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
__kernel_ptd = cpu_rcr3();
void
_kernel_init()
{
- kprintf("[MM] Mem: %d KiB, Extended Mem: %d KiB\n",
- _k_init_mb_info->mem_lower,
- _k_init_mb_info->mem_upper);
-
- unsigned int map_size =
- _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
-
- setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size);
+ lxconsole_init();
kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n",
KSTACK_SIZE >> PG_SIZE_BITS,
// First pass, to mark the physical pages
for (unsigned int i = 0; i < map_size; i++) {
multiboot_memory_map_t mmap = map[i];
- kprintf("[MM] Base: 0x%x, len: %u KiB, type: %u\n",
- map[i].addr_low,
- map[i].len_low >> 10,
- map[i].type);
if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) {
// 整数向上取整除法
uintptr_t pg = map[i].addr_low + 0x0fffU;
pmm_mark_chunk_free(pg >> PG_SIZE_BITS,
map[i].len_low >> PG_SIZE_BITS);
- kprintf(KINFO "[MM] Freed %u pages start from 0x%x\n",
- map[i].len_low >> PG_SIZE_BITS,
- pg & ~0x0fffU);
}
}
// 将内核占据的页,包括前1MB,hhk_init 设为已占用
size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS;
pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0);
- kprintf(KINFO "[MM] Allocated %d pages for kernel.\n", pg_count);
size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS;
- // 首先,标记VGA部分为已占用
+ // 首先,标记VGA部分为已占用,并且锁定
pmm_mark_chunk_occupied(
- KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0);
+ KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, PP_FGLOCKED);
// 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer)
for (size_t i = 0; i < vga_buf_pgs; i++) {
VMAP_NULL);
}
- assert_msg(!((uintptr_t)&__usrtext_start & 0xfff) &&
- !((uintptr_t)&__usrtext_end & 0xfff),
- "Bad usrtext alignment");
-
for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) {
vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL);
}
-
- // 更新VGA缓冲区位置至虚拟地址
- tty_set_buffer((void*)VGA_BUFFER_VADDR);
-
- kprintf(KINFO "[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR);
}
+#include <klibc/stdio.h>
+#include <lunaix/lxconsole.h>
#include <lunaix/syslog.h>
#include <lunaix/tty/tty.h>
-#include <klibc/stdio.h>
#define MAX_KPRINTF_BUF_SIZE 1024
#define MAX_XFMT_SIZE 1024
static char buf[MAX_KPRINTF_BUF_SIZE];
void
-__kprintf(const char* component, const char* fmt, va_list args) {
- if (!fmt) return;
+__kprintf(const char* component, const char* fmt, va_list args)
+{
+ if (!fmt)
+ return;
char log_level = '0';
char expanded_fmt[MAX_XFMT_SIZE];
- vga_attribute current_theme = tty_get_theme();
if (*fmt == '\x1b') {
log_level = *(++fmt);
fmt++;
}
- switch (log_level)
- {
- case '0':
- snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "INFO", component, fmt);
- break;
- case '1':
- tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12);
- snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "WARN", component, fmt);
- break;
- case '2':
- tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12);
- snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "EROR", component, fmt);
- break;
- case '3':
- tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12);
- snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "DEBG", component, fmt);
- break;
- default:
- snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "LOG", component, fmt);
- break;
+ switch (log_level) {
+ case '0':
+ snprintf(expanded_fmt,
+ MAX_XFMT_SIZE,
+ "[%s] (%s) %s",
+ "INFO",
+ component,
+ fmt);
+ break;
+ case '1':
+ // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12);
+ snprintf(expanded_fmt,
+ MAX_XFMT_SIZE,
+ "\x033[6;0m[%s] (%s) %s\x033[39;49m",
+ "WARN",
+ component,
+ fmt);
+ break;
+ case '2':
+ // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12);
+ snprintf(expanded_fmt,
+ MAX_XFMT_SIZE,
+ "\x033[12;0m[%s] (%s) %s\x033[39;49m",
+ "EROR",
+ component,
+ fmt);
+ break;
+ case '3':
+ // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12);
+ snprintf(expanded_fmt,
+ MAX_XFMT_SIZE,
+ "\x033[9;0m[%s] (%s) %s\x033[39;49m",
+ "DEBG",
+ component,
+ fmt);
+ break;
+ default:
+ snprintf(expanded_fmt,
+ MAX_XFMT_SIZE,
+ "[%s] (%s) %s",
+ "LOG",
+ component,
+ fmt);
+ break;
}
__sprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args);
- tty_put_str(buf);
- tty_set_theme(current_theme >> 8, current_theme >> 12);
+ console_write_str(buf);
}
void
-kprint_panic(const char* fmt, ...) {
+kprint_panic(const char* fmt, ...)
+{
va_list args;
va_start(args, fmt);
-
+
tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED);
tty_clear_line(10);
tty_clear_line(11);
tty_clear_line(12);
- tty_set_cpos(0, 11);
__sprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args);
- tty_put_str(buf);
+ tty_put_str_at(buf, 0, 11);
va_end(args);
}
\ No newline at end of file
--- /dev/null
+#include <klibc/string.h>
+#include <lunaix/lxconsole.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/tty/console.h>
+#include <lunaix/tty/tty.h>
+
+static struct console lx_console;
+
+volatile int can_flush = 0;
+
+void
+lxconsole_init()
+{
+ memset(&lx_console, 0, sizeof(lx_console));
+ lx_console.buffer.data = VGA_BUFFER_VADDR + 0x1000;
+ lx_console.buffer.size = 8192;
+ mutex_init(&lx_console.buffer.lock);
+
+ // 分配控制台缓存
+ for (size_t i = 0; i < PG_ALIGN(lx_console.buffer.size); i += PG_SIZE) {
+ uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
+ vmm_set_mapping(PD_REFERENCED,
+ (uintptr_t)lx_console.buffer.data + i,
+ pa,
+ PG_PREM_URW,
+ 0);
+ }
+
+ memset(lx_console.buffer.data, 0, lx_console.buffer.size);
+
+ lx_console.flush_timer = NULL;
+}
+
+void
+console_schedule_flush()
+{
+ // TODO make the flush on-demand rather than periodic
+}
+
+void
+console_view_up(struct fifo_buffer* buffer)
+{
+ // mutex_lock(&buffer->lock);
+ size_t p = buffer->rd_pos - 2;
+ while (p < buffer->rd_pos && p != buffer->wr_pos &&
+ ((char*)buffer->data)[p] != '\n') {
+ p--;
+ }
+ p++;
+
+ if (p < buffer->rd_pos) {
+ p = 0;
+ }
+
+ buffer->rd_pos = p;
+ // mutex_unlock(&buffer->lock);
+}
+
+void
+console_view_down(struct fifo_buffer* buffer)
+{
+ // mutex_lock(&buffer->lock);
+ size_t p = buffer->rd_pos;
+ while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n') {
+ p = (p + 1) % buffer->size;
+ }
+
+ buffer->rd_pos = p + 1;
+ // mutex_unlock(&buffer->lock);
+}
+
+void
+__flush_cb(void* arg)
+{
+ if (mutex_on_hold(&lx_console.buffer.lock)) {
+ return;
+ }
+ if (!(lx_console.buffer.flags & FIFO_DIRTY)) {
+ return;
+ }
+
+ size_t pos = tty_flush_buffer(lx_console.buffer.data,
+ lx_console.buffer.rd_pos,
+ lx_console.buffer.wr_pos,
+ lx_console.buffer.size);
+ lx_console.flush_timer = NULL;
+ if (pos < lx_console.buffer.wr_pos) {
+ console_view_down(&lx_console.buffer);
+ } else {
+ // clear the dirty bit only if we have flush all the data
+ // that means: read pointer == write pointer
+ lx_console.buffer.flags &= ~FIFO_DIRTY;
+ }
+}
+
+void
+console_write(struct console* console, uint8_t* data, size_t size)
+{
+ mutex_lock(&console->buffer.lock);
+ uint8_t* buffer = console->buffer.data;
+ uintptr_t ptr = console->buffer.wr_pos;
+ uintptr_t rd_ptr = console->buffer.rd_pos;
+
+ for (size_t i = 0; i < size; i++) {
+ buffer[(ptr + i) % console->buffer.size] = data[i];
+ }
+
+ uintptr_t new_ptr = (ptr + size) % console->buffer.size;
+ console->buffer.wr_pos = new_ptr;
+ if (new_ptr < ptr + size && new_ptr > rd_ptr) {
+ console->buffer.rd_pos = new_ptr;
+ }
+ console->buffer.flags |= FIFO_DIRTY;
+ mutex_unlock(&console->buffer.lock);
+}
+
+void
+console_write_str(char* str)
+{
+ console_write(&lx_console, str, strlen(str));
+}
+
+void
+console_write_char(char str)
+{
+ console_write(&lx_console, &str, 1);
+}
+
+void
+console_start_flushing()
+{
+ struct lx_timer* timer =
+ timer_run_ms(20, __flush_cb, NULL, TIMER_MODE_PERIODIC);
+ lx_console.flush_timer = timer;
+}
\ No newline at end of file
#include <lunaix/clock.h>
#include <lunaix/keyboard.h>
#include <lunaix/lunistd.h>
+#include <lunaix/lxconsole.h>
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/proc.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <lunaix/tty/tty.h>
extern uint8_t __kernel_start;
if (i == 3) {
i = *(int*)0xdeadc0de; // seg fault!
}
- tty_put_char('0' + i);
- tty_put_char('\n');
+ kprintf(KINFO "%d\n", i);
_exit(0);
}
kprintf(KINFO "Forked %d\n", pid);
}
if ((keyevent.state & KBD_KEY_FPRESSED) &&
(keyevent.keycode & 0xff00) <= KEYPAD) {
- tty_put_char((char)(keyevent.keycode & 0x00ff));
+ console_write_char((char)(keyevent.keycode & 0x00ff));
// FIXME: io to vga port is privileged and cause #GP in user mode
// tty_sync_cursor();
}
void
pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr)
{
- pm_table[ppn] = (struct pp_struct) {
- .owner = owner,
- .ref_counts = 1,
- .attr = attr
- };
+ pm_table[ppn] =
+ (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr };
}
void
pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count)
{
- for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
- {
+ for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
pm_table[i].ref_counts = 0;
}
}
void
-pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr)
+pmm_mark_chunk_occupied(pid_t owner,
+ uint32_t start_ppn,
+ size_t page_count,
+ pp_attr_t attr)
{
- for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
- {
- pm_table[i] = (struct pp_struct) {
- .owner = owner,
- .ref_counts = 1,
- .attr = attr
- };
+ for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
+ pm_table[i] =
+ (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr };
}
}
// mark all as occupied
for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
- pm_table[i] = (struct pp_struct) {
- .owner = 0,
- .attr = 0,
- .ref_counts = 1
- };
+ pm_table[i] =
+ (struct pp_struct){ .owner = 0, .attr = 0, .ref_counts = 1 };
}
}
void*
-pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) {
+pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr)
+{
size_t p1 = 0;
size_t p2 = 0;
- while (p2 < max_pg && p2 - p1 < num_pages)
- {
+ while (p2 < max_pg && p2 - p1 < num_pages) {
(!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2);
}
pm = &pm_table[pg_lookup_ptr];
if (!pm->ref_counts) {
- *pm = (struct pp_struct) {
- .attr = attr,
- .owner = owner,
- .ref_counts = 1
- };
+ *pm = (struct pp_struct){ .attr = attr,
+ .owner = owner,
+ .ref_counts = 1 };
good_page_found = pg_lookup_ptr << 12;
break;
} else {
pmm_free_page(pid_t owner, void* page)
{
struct pp_struct* pm = &pm_table[(intptr_t)page >> 12];
-
+
// Is this a MMIO mapping or double free?
if (((intptr_t)page >> 12) >= max_pg || !(pm->ref_counts)) {
return 0;
}
- // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; 2) 内核可释放所有页。
+ // 如果是锁定页,则不作处理
+ if ((pm->attr & PP_FGLOCKED)) {
+ return 0;
+ }
+
+ // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放;
+ // 2) 内核可释放所有页。
pm->ref_counts--;
return 1;
}
-int pmm_ref_page(pid_t owner, void* page) {
- (void*) owner; // TODO: do smth with owner
-
+int
+pmm_ref_page(pid_t owner, void* page)
+{
+ (void*)owner; // TODO: do smth with owner
+
uint32_t ppn = (uintptr_t)page >> 12;
-
+
if (ppn >= PM_BMP_MAX_SIZE) {
return 0;
}
return 1;
}
-struct pp_struct* pmm_query(void* pa) {
+struct pp_struct*
+pmm_query(void* pa)
+{
uint32_t ppn = (uintptr_t)pa >> 12;
-
+
if (ppn >= PM_BMP_MAX_SIZE) {
return NULL;
}
#include <arch/x86/boot/multiboot.h>
#include <lunaix/common.h>
#include <lunaix/lunistd.h>
+#include <lunaix/lxconsole.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/peripheral/ps2kbd.h>
{
assert_msg(kalloc_init(), "Fail to initialize heap");
- // Fuck it, I will no longer bother this little 1MiB
- // I just release 4 pages for my APIC & IOAPIC remappings
- // for (size_t i = 0; i < 3; i++) {
- // vmm_del_mapping(PD_REFERENCED, (void*)(i << PG_SIZE_BITS));
- // }
-
// 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
lock_reserved_memory();
syscall_install();
+ console_start_flushing();
+
unlock_reserved_memory();
for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
#include <hal/io.h>
#include <klibc/string.h>
#include <lunaix/common.h>
+#include <lunaix/spike.h>
+#include <lunaix/tty/console.h>
#include <lunaix/tty/tty.h>
#include <stdint.h>
-#define TTY_WIDTH 80
-#define TTY_HEIGHT 25
+vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR;
-static vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR;
+vga_attribute tty_theme_color = VGA_COLOR_BLACK;
-static vga_attribute tty_theme_color = VGA_COLOR_BLACK;
-
-static uint32_t tty_x = 0;
-static uint32_t tty_y = 0;
+#define TTY_CLEAR \
+ asm volatile("rep stosw" ::"D"(tty_vga_buffer), \
+ "c"(TTY_HEIGHT * TTY_WIDTH), \
+ "a"(tty_theme_color) \
+ : "memory");
void
tty_init(void* vga_buf)
{
tty_vga_buffer = (vga_attribute*)vga_buf;
- tty_clear();
+
+ TTY_CLEAR
io_outb(0x3D4, 0x0A);
io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13);
io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15);
}
-void
-tty_set_buffer(void* vga_buf)
-{
- tty_vga_buffer = (vga_attribute*)vga_buf;
-}
-
void
tty_set_theme(vga_attribute fg, vga_attribute bg)
{
tty_theme_color = (bg << 4 | fg) << 8;
}
-void
-tty_put_char(char chr)
+size_t
+tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size)
{
- switch (chr) {
- case '\t':
- tty_x += 4;
- break;
- case '\n':
- tty_y++;
- // fall through
- case '\r':
- tty_x = 0;
- break;
- case '\x08':
- tty_x = tty_x ? tty_x - 1 : 0;
- *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) =
- (tty_theme_color | 0x20);
- break;
- default:
- *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) =
- (tty_theme_color | chr);
- tty_x++;
- break;
- }
+ int x = 0, y = 0;
- if (tty_x >= TTY_WIDTH) {
- tty_x = 0;
- tty_y++;
- }
- if (tty_y >= TTY_HEIGHT) {
- tty_scroll_up();
- }
-}
+ // Clear screen
+ TTY_CLEAR
-void
-tty_sync_cursor()
-{
- tty_set_cursor(tty_x, tty_y);
+ int state = 0;
+ int g[2] = { 0, 0 };
+ vga_attribute current_theme = tty_theme_color;
+ while (1) {
+ size_t ptr = pos % buf_size;
+ if (pos == limit) {
+ break;
+ }
+ char chr = data[pos];
+ if (state == 0 && chr == '\x033') {
+ state = 1;
+ } else if (state == 1 && chr == '[') {
+ state = 2;
+ } else if (state > 1) {
+ if ('0' <= chr && chr <= '9') {
+ g[state - 2] = (chr - '0') + g[state - 2] * 10;
+ } else if (chr == ';' && state == 2) {
+ state = 3;
+ } else {
+ if (g[0] == 39 && g[1] == 49) {
+ current_theme = tty_theme_color;
+ } else {
+ current_theme = (g[1] << 4 | g[0]) << 8;
+ }
+ g[0] = 0;
+ g[1] = 0;
+ state = 0;
+ }
+ } else {
+ state = 0;
+ switch (chr) {
+ case '\t':
+ x += 4;
+ break;
+ case '\n':
+ y++;
+ // fall through
+ case '\r':
+ x = 0;
+ break;
+ case '\x08':
+ x = x ? x - 1 : 0;
+ *(tty_vga_buffer + x + y * TTY_WIDTH) =
+ (current_theme | 0x20);
+ break;
+ default:
+ *(tty_vga_buffer + x + y * TTY_WIDTH) =
+ (current_theme | chr);
+ (x)++;
+ break;
+ }
+
+ if (x >= TTY_WIDTH) {
+ x = 0;
+ y++;
+ }
+ if (y >= TTY_HEIGHT) {
+ y--;
+ break;
+ }
+ }
+ pos++;
+ }
+ tty_set_cursor(x, y);
+ return pos;
}
void
}
void
-tty_put_str(char* str)
-{
- while (*str != '\0') {
- tty_put_char(*str);
- str++;
- }
- // FIXME: This does not work in user mode.
- // Work around:
- // 1. (Easy) Define an IO Permission bitmap in TSS
- // 2. (More effort) Mount onto file system. (/dev/tty)
- // tty_sync_cursor();
-}
-
-void
-tty_scroll_up()
+tty_clear_line(int line_num)
{
- size_t last_line = TTY_WIDTH * (TTY_HEIGHT - 1);
- memcpy(tty_vga_buffer, tty_vga_buffer + TTY_WIDTH, last_line * 2);
- for (size_t i = 0; i < TTY_WIDTH; i++) {
- *(tty_vga_buffer + i + last_line) = tty_theme_color;
- }
- tty_y = tty_y == 0 ? 0 : TTY_HEIGHT - 1;
+ asm volatile("rep stosw" ::"D"(tty_vga_buffer + line_num * TTY_WIDTH),
+ "c"(TTY_WIDTH),
+ "a"(tty_theme_color)
+ : "memory");
}
void
-tty_clear()
+tty_put_str_at(char* str, int x, int y)
{
- for (uint32_t i = 0; i < TTY_WIDTH * TTY_HEIGHT; i++) {
- *(tty_vga_buffer + i) = tty_theme_color;
- }
- tty_x = 0;
- tty_y = 0;
-}
-
-void
-tty_clear_line(unsigned int y)
-{
- for (size_t i = 0; i < TTY_WIDTH; i++) {
- *(tty_vga_buffer + i + y * TTY_WIDTH) = tty_theme_color;
+ char c;
+ while ((c = (*str)) && y < TTY_HEIGHT) {
+ *(tty_vga_buffer + x + y * TTY_WIDTH) = c | tty_theme_color;
+ x++;
+ if (x >= TTY_WIDTH) {
+ y++;
+ x = 0;
+ }
+ str++;
}
-}
-
-void
-tty_set_cpos(unsigned int x, unsigned int y)
-{
- tty_x = x % TTY_WIDTH;
- tty_y = y % TTY_HEIGHT;
-}
-
-void
-tty_get_cpos(unsigned int* x, unsigned int* y)
-{
- *x = tty_x;
- *y = tty_y;
-}
-
-vga_attribute
-tty_get_theme()
-{
- return tty_theme_color;
}
\ No newline at end of file