From 3961c0e1be51945996f90dae1c60b0a4643ddb7d Mon Sep 17 00:00:00 2001 From: fslongjin Date: Tue, 22 Feb 2022 20:45:32 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20printk=E6=96=B0=E5=A2=9E=E7=BF=BB?= =?UTF-8?q?=E9=A1=B5=E6=BB=9A=E5=8A=A8=E5=8A=9F=E8=83=BD=EF=BC=88bug:?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=80=81=E8=A7=A6=E5=8F=91=E4=B8=AD=E6=96=AD?= =?UTF-8?q?=E6=97=B6=E7=BF=BB=E9=A1=B5=E4=BC=9A=E5=87=BA=E7=8E=B0#UD?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +-- kernel/common/glib.h | 15 ++-- kernel/common/printk.c | 145 ++++++++++++++++++++++++++++++++------- kernel/common/printk.h | 16 +++++ kernel/main.c | 14 ++-- kernel/process/process.c | 15 ++-- 6 files changed, 162 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 58668442..ae75eaa2 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,11 @@ bximage 1. clone本项目 -2. 在根目录下创建bin文件夹 - -3. 将boot(empty).img复制到bin/,并重命名为boot.img - -4. 使用sudo权限运行run_in_bochs.sh +2. 运行命令 bash run.sh ## To do list: -- [x] bootloader +- [x] multiboot2 - [x] printk diff --git a/kernel/common/glib.h b/kernel/common/glib.h index a4c014c7..531bb117 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -44,6 +44,9 @@ typedef unsigned long long int ull; typedef long long int ll; #define ABS(x) ((x) > 0 ? (x) : -(x)) // 绝对值 +// 最大最小值 +#define max(x, y) ((x > y) ? (x) : (y)) +#define min(x, y) ((x < y) ? (x) : (y)) // 四舍五入成整数 ul round(double x) @@ -53,14 +56,14 @@ ul round(double x) /** * @brief 地址按照align进行对齐 - * - * @param addr - * @param _align + * + * @param addr + * @param _align * @return ul 对齐后的地址 */ ul ALIGN(const ul addr, const ul _align) { - return (ul)((addr+_align-1)&(~(_align-1))); + return (ul)((addr + _align - 1) & (~(_align - 1))); } //链表数据结构 @@ -166,7 +169,7 @@ static inline int strlen(char *s) return __res; } -void *memset(void *dst, unsigned char C, ul Count) +void *memset(void *dst, unsigned char C, ul size) { int d0, d1; @@ -185,7 +188,7 @@ void *memset(void *dst, unsigned char C, ul Count) "stosb \n\t" "3: \n\t" : "=&c"(d0), "=&D"(d1) - : "a"(tmp), "q"(Count), "0"(Count / 8), "1"(dst) + : "a"(tmp), "q"(size), "0"(size / 8), "1"(dst) : "memory"); return dst; } diff --git a/kernel/common/printk.c b/kernel/common/printk.c index 5ce2e5cf..2c154487 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -2,30 +2,13 @@ // Created by longjin on 2022/1/22. // #include "printk.h" +#include "kprint.h" #include "../driver/multiboot2/multiboot2.h" #include "../mm/mm.h" //#include "linkage.h" struct screen_info pos; -void show_color_band(int width, int height, char a, char b, char c, char d) -{ - /** 向帧缓冲区写入像素值 - * @param address: 帧缓存区的地址 - * @param val:像素值 - */ - - for (int i = 0; i < width * height; ++i) - { - - *((char *)pos.FB_address + 0) = d; - *((char *)pos.FB_address + 1) = c; - *((char *)pos.FB_address + 2) = b; - *((char *)pos.FB_address + 3) = a; - ++pos.FB_address; - } -} - int calculate_max_charNum(int len, int size) { /** @@ -33,7 +16,7 @@ int calculate_max_charNum(int len, int size) * @param len 屏幕长/宽 * @param size 字符长/宽 */ - return len / size; + return len / size - 1; } int init_printk(const int char_size_x, const int char_size_y) @@ -41,20 +24,21 @@ int init_printk(const int char_size_x, const int char_size_y) struct multiboot_tag_framebuffer_info_t info; int reserved; multiboot2_iter(multiboot2_get_Framebuffer_info, &info, &reserved); - + pos.width = info.framebuffer_width; pos.height = info.framebuffer_height; pos.char_size_x = char_size_x; pos.char_size_y = char_size_y; pos.max_x = calculate_max_charNum(pos.width, char_size_x); pos.max_y = calculate_max_charNum(pos.height, char_size_y); - + // @todo:将来需要将帧缓冲区物理地址填写到这个地址的页表项中 - pos.FB_address = 0xa00000; - pos.FB_length = pos.width*pos.height*4; + pos.FB_address = 0xa00000; + pos.FB_length = pos.width * pos.height; pos.x = 0; pos.y = 0; + cls(); return 0; } @@ -95,7 +79,12 @@ void auto_newline() ++pos.y; } if (pos.y > pos.max_y) - pos.y = 0; + { + pos.y = pos.max_y; + int lines_to_scroll=2; + scroll(true, lines_to_scroll*pos.char_size_y, false); + pos.y-=lines_to_scroll; + } } static int vsprintf(char *buf, const char *fmt, va_list args) @@ -646,6 +635,7 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. { pos.x = 0; ++pos.y; + auto_newline(); } else if (current == '\t') // 输出制表符 { @@ -685,4 +675,111 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. } return i; +} + +int do_scroll(bool direction, int pixels) +{ + if (direction == true) // 向上滚动 + { + pixels = pixels; + if (pixels > pos.height) + return EPOS_OVERFLOW; + // 无需滚动 + if (pixels == 0) + return 0; + unsigned int src = pixels * pos.width; + unsigned int count = pos.FB_length - src; + + memcpy(pos.FB_address, (pos.FB_address + src), sizeof(unsigned int)*(pos.FB_length - src)); + memset(pos.FB_address+(pos.FB_length-src), 0, sizeof(unsigned int)*(src)); + return 0; + } + else + return EUNSUPPORTED; + return 0; +} +/** + * @brief 滚动窗口(尚不支持向下滚动) + * + * @param direction 方向,向上滑动为true,否则为false + * @param pixels 要滑动的像素数量 + * @param animation 是否包含滑动动画 + */ +int scroll(bool direction, int pixels, bool animation) +{ + // 暂时不支持反方向滚动 + if (direction == false) + return EUNSUPPORTED; + // 为了保证打印字符正确,需要对pixel按照字体高度对齐 + int md = pixels % pos.char_size_y; + if (md) + pixels = pixels + pos.char_size_y - md; + + if (animation == false) + return do_scroll(direction, pixels); + else + { + int steps; + if (pixels > 10) + steps = 5; + else + steps = pixels % 5; + int half_steps = steps / 2; + + // 计算加速度 + double accelerate = 0.5 * pixels / (half_steps * half_steps); + int current_pixels = 0; + double delta_x; + + int trace[13] = {0}; + int js_trace = 0; + // 加速阶段 + for (int i = 1; i <= half_steps; ++i) + { + trace[js_trace] = (int)(accelerate * i + 0.5); + current_pixels += trace[js_trace]; + do_scroll(direction, trace[js_trace]); + + ++js_trace; + } + + + // 强制使得位置位于1/2*pixels + if (current_pixels < pixels / 2) + { + delta_x = pixels / 2 - current_pixels; + do_scroll(direction, delta_x); + } + + // 减速阶段,是加速阶段的重放 + for (int i = js_trace - 1; i >= 0; --i) + { + current_pixels += trace[i]; + do_scroll(direction, trace[i]); + } + + if (current_pixels > pixels) + kerror("During scrolling: scrolled pixels over bound!"); + + // 强制使得位置位于pixels + if (current_pixels < pixels) + { + delta_x = pixels - current_pixels; + do_scroll(direction, delta_x); + } + } + + return 0; +} + +/** + * @brief 清屏 + * + */ +int cls() +{ + memset(pos.FB_address, BLACK, pos.FB_length * sizeof(unsigned int)); + pos.x = 0; + pos.y = 0; + return 0; } \ No newline at end of file diff --git a/kernel/common/printk.h b/kernel/common/printk.h index 1e81c0ad..081c4b39 100644 --- a/kernel/common/printk.h +++ b/kernel/common/printk.h @@ -29,6 +29,7 @@ // 异常的宏定义 #define EPOS_OVERFLOW 1 // 坐标溢出 #define EFB_MISMATCH 2 // 帧缓冲区与指定的屏幕大小不匹配 +#define EUNSUPPORTED 3 // 当前操作暂不被支持 #include "font.h" #include "glib.h" @@ -118,3 +119,18 @@ static void putchar(unsigned int *fb, int Xsize, int x, int y, unsigned int FRco #define printk(...) printk_color( WHITE, BLACK, __VA_ARGS__ ) int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char*fmt, ...); + +/** + * @brief 滚动窗口(尚不支持向下滚动) + * + * @param direction 方向,向上滑动为true,否则为false + * @param pixels 要滑动的像素数量 + * @param animation 是否包含滑动动画 + */ +int scroll(bool direction, int pixels, bool animation); + +/** + * @brief 清屏 + * + */ +int cls(); \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index 274eac8e..a9fe1e8c 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -13,7 +13,7 @@ #include "syscall/syscall.h" unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址 - // char fxsave_region[512] __attribute__((aligned(16))); + // char fxsave_region[512] __attribute__((aligned(16))); struct memory_desc memory_management_struct = {{0}, 0}; // struct Global_Memory_Descriptor memory_management_struct = {{0}, 0}; @@ -62,17 +62,17 @@ void test_mm() // 初始化系统各模块 void system_initialize() { - + // 初始化printk - + init_printk(8, 16); - + load_TR(10); // 加载TR寄存器 ul tss_item_addr = 0x7c00; set_TSS64(_stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr); - + // 初始化中断描述符表 init_sys_vector(); @@ -85,6 +85,8 @@ void system_initialize() // 先初始化系统调用模块 syscall_init(); + + // 再初始化进程模块。顺序不能调转 process_init(); } @@ -94,7 +96,7 @@ void Start_Kernel(void) { system_initialize(); - + // show_welcome(); // test_mm(); diff --git a/kernel/process/process.c b/kernel/process/process.c index f8bb6670..3149857c 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -30,7 +30,6 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc __asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs)); } - /** * @brief 这是一个用户态的程序 * @@ -39,13 +38,13 @@ void user_level_function() { kinfo("Program (user_level_function) is runing..."); kinfo("Try to enter syscall id 15..."); - enter_syscall(15,0,0,0,0,0,0,0,0); + enter_syscall(15, 0, 0, 0, 0, 0, 0, 0, 0); + enter_syscall(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0); - enter_syscall(SYS_PRINTF, (ul)"test_sys_printf\n", 0,0,0,0,0,0,0); kinfo("Return from syscall id 15..."); - - while(1); + while (1) + ; } /** * @brief 使当前进程去执行新的代码 @@ -78,7 +77,7 @@ ul do_execve(struct pt_regs *regs) ul initial_kernel_thread(ul arg) { kinfo("initial proc running...\targ:%#018lx", arg); - + struct pt_regs *regs; current_pcb->thread->rip = (ul)ret_from_system_call; @@ -201,8 +200,6 @@ void process_init() initial_mm.stack_start = _stack_start; - - // 初始化进程和tss set_TSS64(initial_thread.rbp, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7); @@ -265,7 +262,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned thd->rip = regs->rip; thd->rsp = (ul)tsk + STACK_SIZE - sizeof(struct pt_regs); thd->fs = KERNEL_DS; - thd->gs = KERNEL_DS; + thd->gs = KERNEL_DS; // 若进程不是内核层的进程,则跳转到ret from system call if (!(tsk->flags & PF_KTHREAD))