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

This commit is contained in:
fslongjin 2022-02-22 20:45:32 +08:00
parent 12cc6a8375
commit 3961c0e1be
6 changed files with 162 additions and 51 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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();

View File

@ -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))