Browse Source

:new: printk新增翻页滚动功能(bug:用户态触发中断时翻页会出现#UD)

fslongjin 3 years ago
parent
commit
3961c0e1be
6 changed files with 162 additions and 51 deletions
  1. 2 6
      README.md
  2. 9 6
      kernel/common/glib.h
  3. 121 24
      kernel/common/printk.c
  4. 16 0
      kernel/common/printk.h
  5. 8 6
      kernel/main.c
  6. 6 9
      kernel/process/process.c

+ 2 - 6
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
 

+ 9 - 6
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;
 }

+ 121 - 24
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;
 }

+ 16 - 0
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();

+ 8 - 6
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();
 

+ 6 - 9
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))