]> Zhao Yanbai Git Server - kernel.git/commitdiff
添加serial_monitor的清屏能力
authoracevest <zhaoyanbai@126.com>
Tue, 30 Dec 2025 07:29:57 +0000 (15:29 +0800)
committeracevest <zhaoyanbai@126.com>
Tue, 30 Dec 2025 07:29:57 +0000 (15:29 +0800)
boot/acpi.c
boot/boot.c
boot/multiboot2_header.c
boot/vbe.c
gdbscript
include/system.h
kernel/apic.c
kernel/setup.c
mm/mm.c
qemu.sh
scripts/iso.grub.cfg

index cbe87272c975a8e9daa3743f393e4be5ba8c5e95..faf8a0953f29986a4a16d2a90507619fa8e7d9a6 100644 (file)
@@ -171,7 +171,7 @@ void parse_rsdt(void *addr) {
 }
 
 
-void check_acpi(void *tag) {
+void parse_acpi(void *tag) {
     printk("ACPI[old].RSDP ");
     struct multiboot_tag_old_acpi *acpi_tag = (struct multiboot_tag_old_acpi *)tag;
     uint8_t *rsdp = (uint8_t *)acpi_tag->rsdp;
index 1b2905b9ecadf36513961f071d60e0bf2fa48720..5f3fa451811702bf7f0cbac9c40982ecd7729f12 100644 (file)
@@ -66,16 +66,44 @@ void parse_framebuffer(void *addr) {
     uint32_t type = fb->common.type;
     uint32_t size = fb->common.size;
     uint64_t fb_addr = fb->common.framebuffer_addr;
+    // pitch(也称为 stride 或 bytes per scanline) 表示在帧缓冲区中,从一行像素的开始到下一行像素开始的字节数。
+    // 简单说: 每行像素占用字节数
+    // 比如 800x600x32 的pitch为3200,则每行像素数为 pitch / (bpp/8) = 3200 / (32/8) = 800
+    // 既然分辨率上写了 800 为什么要多此一举搞个pitch,主要是为了内存对齐
+    //
+    // 例[只是举例,不代表一定是这样]:
+    // 800x600 16位色
+    // 理论:800 × 2 = 1600 字节
+    // 如果显卡要求 2048 字节对齐(2KB边界)
+    // 实际 pitch = 2048
+    // 填充:2048 - 1600 = 448 字节/行
+    //
+    // 所以每行的实际的内存空间可能更大
+    // 所以应该按如下方法访问像素
+    // uint32_t *framebuffer = (uint32_t *)fb_addr;
+    // uint32_t pixels_per_row = pitch / (bpp / 8);  // 每行像素数(包括填充)
+    // uint32_t pixel = framebuffer[y * pixels_per_row + x];
+    //
+    // 而不是这种方法
+    // uint32_t *framebuffer = (uint32_t *)fb_addr;
+    // uint32_t pixel = framebuffer[y * width + x];  // 下一行开头的内容可能写到上一行不显示的内存区域去了
+    //
     uint32_t fb_pitch = fb->common.framebuffer_pitch;
     uint32_t fb_width = fb->common.framebuffer_width;
     uint32_t fb_height = fb->common.framebuffer_height;
     uint8_t fb_bpp = fb->common.framebuffer_bpp;
     uint8_t fb_type = fb->common.framebuffer_type;
 
+
+    system.vbe_phys_addr = fb_addr;
+    system.x_resolution = fb_width;
+    system.y_resolution = fb_height;
+
     printk("type %u size %u addr %lx pitch %u width %u height %u bpp %u type %u\n",
             type, size, fb_addr, fb_pitch, fb_width, fb_height, fb_bpp, fb_type);
 
-
+    // 直接就不打算支持32位以外的色深
+    // assert(fb_bpp == 32);
 }
 
 
@@ -203,7 +231,7 @@ void check_kernel(unsigned long addr, unsigned long magic) {
             vbe = (struct multiboot_tag_vbe *)tag;
             void *vci = (void *)vbe->vbe_control_info.external_specification;
             void *vmi = (void *)vbe->vbe_mode_info.external_specification;
-            printk("VBE MODE %04x\n", vbe->vbe_mode);
+            printk("VBE[deprecated] mode %04x\n", vbe->vbe_mode);
             init_vbe(vci, vmi);
             break;
         case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
@@ -250,8 +278,8 @@ void check_kernel(unsigned long addr, unsigned long magic) {
             printk("load base addr %08x\n", ((struct multiboot_tag_load_base_addr *)tag)->load_base_addr);
             break;
         case MULTIBOOT_TAG_TYPE_ACPI_OLD:
-            extern void check_acpi(void *);
-            check_acpi(tag);
+            extern void parse_acpi(void *);
+            parse_acpi(tag);
             break;
         case MULTIBOOT_TAG_TYPE_ACPI_NEW:
             printk("ACPI new\n");
index b493c3a2041ccf23f3b46fe50195f435e7c72c27..85b7618f82fdfa4163fd0437517247cdf165eeba 100644 (file)
@@ -9,25 +9,30 @@
 
 
 
- #include <multiboot2.h>
+#include <multiboot2.h>
 
 
- #define ENABLE_FB 0
+// 启用FB这个功能,需要修改grub.cfg,添加如下内容
+// load_video
+// set gfxmode=auto
+// set gfxpayload=keep
+// terminal_output gfxterm
+#define ENABLE_FB 0
 
- #define ALIGN8 __attribute__((aligned(8)))
+#define ALIGN8 __attribute__((aligned(8)))
 
- typedef struct ALIGN8 multiboot2_elf_header {
+typedef struct ALIGN8 multiboot2_elf_header {
     ALIGN8 struct multiboot_header header;
 #if ENABLE_FB
     ALIGN8 struct multiboot_header_tag_framebuffer fb;
 #endif
     ALIGN8 struct multiboot_header_tag end;
- } multiboot2_bin_header_t;
+} multiboot2_bin_header_t;
 
 
 
- __attribute__((section(".multiboot2_header"), used))
- const multiboot2_bin_header_t multiboot2_elf_header = {
+__attribute__((section(".multiboot2_header"), used))
+const multiboot2_bin_header_t multiboot2_elf_header = {
     .header = {
         .magic = MULTIBOOT2_HEADER_MAGIC,
         .architecture = MULTIBOOT_ARCHITECTURE_I386,
@@ -39,9 +44,9 @@
         .type = MULTIBOOT_HEADER_TAG_FRAMEBUFFER,
         .flags = MULTIBOOT_HEADER_TAG_OPTIONAL,
         .size = sizeof(struct multiboot_header_tag_framebuffer),
-        .width = 0,
-        .height = 0,
-        .depth = 0,
+        .width = 1280,
+        .height = 800,
+        .depth = 32,
     },
 #endif
     .end = {
@@ -52,4 +57,4 @@
         .flags = 0,
         .size = sizeof(struct multiboot_header_tag),
     },
- };
+};
index 598905d03e74d18efc2651393cc7a9eda082c452..57913b21cc2e3b0e1ac7223e772aff1935962dec 100644 (file)
@@ -123,10 +123,14 @@ vbe_mode_info_t *get_vbe_mode_info(uint16_t) {
 }
 // extern pde_t init_pgd[];
 void init_vbe(void *vciptr, void *vmiptr) {
+    // VBE是传统BIOS接口,在现代系统上可能没有被正确初始化
+    // 也无法在保护模式下调用VBE BIOS功能
+    // 因此这里只是打印VBE信息
+    // 更可靠的数据是 MULTIBOOT_TAG_TYPE_FRAMEBUFFER 的数据
     vbe_controller_info_t *vci = vciptr;
     vbe_mode_info_t *vmi = (vbe_mode_info_t *)vmiptr;
 
-    printk("VBE:\n");
+    printk("VBE[deprecated]:\n");
     printk("Signature %c%c%c%c\n", vci->signature[0], vci->signature[1], vci->signature[2], vci->signature[3]);
     printk("version %04x\n", vci->version);
     printk("total memory %u x 64K\n", vci->total_memory);
@@ -137,18 +141,24 @@ void init_vbe(void *vciptr, void *vmiptr) {
 
     printk("SEG %04X OFFSET %04X\n", vci->video_mode_ptr.segment, vci->video_mode_ptr.offset);
     uint16_t *modes = (uint16_t *)segoff_to_addr(vci->video_mode_ptr);
+    printk("vbe modes:");
     while (*modes != VBE_MODE_END) {
-        printk("mode: %04x\n", *modes);
-        // vbe_mode_info_t *mi = get_vbe_mode_info(*modes);
-        // if (mi->mode_attributes & 0x01) {
-        //     printk("R %u x %u\n", mi->x_resolution, mi->y_resolution);
-        // }
+        printk(" %04x", *modes);
+        vbe_mode_info_t *mi = get_vbe_mode_info(*modes);
+
+        // 目前以下判断不会生效
+        if ((mi != 0) && (mi->mode_attributes & 0x01)) {
+            printk("R %u x %u\n", mi->x_resolution, mi->y_resolution);
+        }
+
         modes++;
     }
+    printk("\n");
 
+    printk("vbe[deprecated] phys addr %08x resolution %u x %u\n", vmi->phys_base_ptr, vmi->x_resolution, vmi->y_resolution);
+#if 0
     system.vbe_phys_addr = vmi->phys_base_ptr;
     system.x_resolution = vmi->x_resolution;
     system.y_resolution = vmi->y_resolution;
-
-    printk(" phys addr %08x resolution %u x %u\n", system.vbe_phys_addr, system.x_resolution, system.y_resolution);
+#endif
 }
index 06a6b20f80d73417b644b618781558259c0409ca..a5dc4f185e766b57544ca9ba7c437503545bee84 100644 (file)
--- a/gdbscript
+++ b/gdbscript
@@ -3,6 +3,7 @@ set confirm off
 
 set architecture i386
 
+#b slub.c:62 if cache->name[0] != 'b'
 #b acpi.c:144
 #b main
 #b boot_paging
index 81054b327b4d920569264c70b2130113cfa7bae7..3a58745c94ff0311729ebee6c8550307bd4f1058 100644 (file)
@@ -81,6 +81,7 @@ extern char etext, edata, end;
 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
 
 // 定义最大显存为 16MB
+// 后续内核不映射显存了,以后可以提供映射到用户空间的功能,由用户态程序操作
 #define VRAM_VADDR_SIZE (16 << 20)
 
 // 最大支持的线性地址空间为1G
index c23a3b260fd3be18366bb463981edd1ac7510390..a18268a8235d8f3a8fc2bdf418fbe38734f640d9 100644 (file)
@@ -65,5 +65,7 @@
 
 
 void init_apic() {
+#if 0
     lapic_init();
+#endif
 }
index 70689f18947fe7d36354ce986b2ea42926a4e679..c75f3018d31d671faad8b7be8b4c52100d9025f8 100644 (file)
@@ -91,7 +91,7 @@ void setup_kernel() {
 
     init_buffer();
 
-    #if 1
+    #if 0
     parse_rsdt(system.rsdt_addr);
 
     void init_apic();
diff --git a/mm/mm.c b/mm/mm.c
index 7aa09e8c365ec960db8c62ea990e1df207a4fe5f..c370ea73c8ef4d06cffc99233f95a79e1d119e78 100644 (file)
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -76,6 +76,7 @@ void init_paging() {
 
     // 接下来为显存建立页映射
     unsigned long vram_phys_addr = system.vbe_phys_addr;
+    printk("vram_phys_addr: 0x%x\n", vram_phys_addr);
     for (int pde_inx = 0; pde_inx < get_npde(VRAM_VADDR_SIZE); pde_inx++) {
         pgtb_addr = (unsigned long *)(alloc_from_bootmem(PAGE_SIZE, "vrampaging"));
         if (0 == pgtb_addr) {
@@ -97,27 +98,46 @@ void init_paging() {
 
     LoadCR3(va2pa(init_pgd));
 
-    // // 测试显存
-    // for (int i = 0; i < system.x_resolution * (system.y_resolution - 32); i++) {
-    //     unsigned long *vram = (unsigned long *)VRAM_VADDR_BASE;
-    //     vram[i] = 0x000000FF;
-    // }
-
-    // while (1) {
-    //     u16 lineH = 32;
-    //     unsigned long *vram = (unsigned long *)VRAM_VADDR_BASE;
-    //     int sep = system.x_resolution * (system.y_resolution - lineH);
-    //     for (int i = 0; i < sep; i++) {
-    //         vram[i] = vram[i + system.x_resolution * lineH];
-    //     }
-
-    //     unsigned int long color = 0x0000FF;
-    //     color = (vram[0] == 0x0000FF ? 0x00FF00 : 0x0000FF);
-
-    //     for (int i = sep; i < sep + system.x_resolution * lineH; i++) {
-    //         vram[i] = color;
-    //     }
-    // }
+    // 测试显存
+    for (int i = 0; i < system.x_resolution * (system.y_resolution - 32); i++) {
+        unsigned long *vram = (unsigned long *)VRAM_VADDR_BASE;
+        // 仅为32bit色深
+        // 在内存中 [B, G, R, A] 因为x86是小端序 所以实际是 ARGB 顺序
+        vram[i] = 0x000000FF;
+    }
+
+#if 0
+    bool flag = false;
+    while (1) {
+        u16 lineH = 32;
+        unsigned long *vram = (unsigned long *)VRAM_VADDR_BASE;
+        int sep = system.x_resolution * (system.y_resolution - lineH);
+        for (int i = 0; i < sep; i++) {
+            vram[i] = vram[i + system.x_resolution * lineH] | 0x00FF0000;
+        }
+
+        unsigned int long color = 0x0000FF;
+        color = (vram[0] == 0x0000FF ? 0x00FF00 : 0x0000FF);
+
+        for (int i = sep; i < sep + system.x_resolution * lineH; i++) {
+            vram[i] = color;
+        }
+
+        for(int i=0; i<32; i++) {
+            for(int j=0; j<64; j++) {
+                unsigned int long c = vram[j*system.x_resolution+i];
+                c = flag ? 0x00FFFFFF : 0x000000FF;
+                // c &= 0x00FFFFFF;
+                vram[j*system.x_resolution+i] = c;
+            }
+        }
+        flag = !flag;
+
+        for(int i=0; i<10*1000*10000; i++) {
+            asm("nop");
+        }
+    }
+#endif
 }
 
 extern void init_ttys();
diff --git a/qemu.sh b/qemu.sh
index 456d4761e5c13eea7879e42e5bc1a1b1b86d4a74..455675e67345fcf03d0953f209ccb67eb497dacc 100755 (executable)
--- a/qemu.sh
+++ b/qemu.sh
@@ -19,7 +19,7 @@ set -m
 
 qemu-system-i386 \
     -boot d \
-    -m 128 \
+    -m 3100\
     -smp 2 \
     -cpu qemu32,+x2apic \
     -serial tcp::6666,server,nowait \
index f8a932ce011490d1dac2b89787ba2b632773b110..3b8c8a89b3b5fd6cbb7de458ccb19b3678461f4a 100644 (file)
@@ -10,7 +10,7 @@
 load_video
 set gfxmode=auto
 set gfxpayload=keep
-terminal_output gfxterm
+terminal_output gfxterm
 
 set default="0"
 set timeout=0