]> Zhao Yanbai Git Server - kernel.git/commitdiff
从vbe中读出显存物理地址并建立地址映射
authoracevest <zhaoyanbai@126.com>
Sat, 6 Nov 2021 10:22:53 +0000 (18:22 +0800)
committeracevest <zhaoyanbai@126.com>
Sat, 6 Nov 2021 10:22:53 +0000 (18:22 +0800)
.bochsrc
boot/boot.c
boot/multiboot.S
boot/vbe.c [new file with mode: 0644]
include/page.h
include/system.h
mm/bootmem.c
mm/mm.c

index bf4a75972a327618d6fb5c70e98aa37ffa9cf570..2cbfe7719c0490dbec38219f26fb1e338e76eb1e 100644 (file)
--- a/.bochsrc
+++ b/.bochsrc
@@ -444,6 +444,7 @@ vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
 #   vga: extension=cirrus, update_freq=10, ddc=builtin
 #=======================================================================
 #vga: extension=vbe, update_freq=5, realtime=1, ddc=file:monitor.bin
+vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin
 
 #=======================================================================
 # VOODOO:
index 18683ddbe246fcdb8d28021767981e01c3440ddf..066f34203600f29031031c211d0a459fa17d81cb 100644 (file)
@@ -20,7 +20,7 @@
 struct boot_params boot_params __attribute__((aligned(32)));
 
 void parse_cmdline(const char *cmdline);
-
+void init_vbe(void *vmiptr);
 void check_kernel(unsigned long addr, unsigned long magic) {
     if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
         printk("Your boot loader does not support multiboot.\n");
@@ -34,9 +34,10 @@ void check_kernel(unsigned long addr, unsigned long magic) {
     printk("total size: %d tags: %x\n", total_size, tag);
 
     struct multiboot_tag_basic_meminfo *mminfo = 0;
-    multiboot_memory_map_t *mmap = 0;
-    struct multiboot_tag_mmap *mmap_tag = 0;
     struct multiboot_tag_bootdev *bootdev = 0;
+    struct multiboot_tag_mmap *mmap_tag = 0;
+    struct multiboot_tag_vbe *vbe = 0;
+    struct multiboot_tag_framebuffer *fb = 0;
 
     boot_params.e820map.map_cnt = 0;
 
@@ -65,7 +66,7 @@ void check_kernel(unsigned long addr, unsigned long magic) {
             break;
         case MULTIBOOT_TAG_TYPE_MMAP:
             mmap_tag = (struct multiboot_tag_mmap *)tag;
-            mmap = mmap_tag->entries;
+            multiboot_memory_map_t *mmap = mmap_tag->entries;
             while (((multiboot_uint32_t)mmap) < (((multiboot_uint32_t)mmap_tag) + mmap_tag->size)) {
                 boot_params.e820map.map[boot_params.e820map.map_cnt].addr = mmap->addr;
                 boot_params.e820map.map[boot_params.e820map.map_cnt].size = mmap->len;
@@ -74,6 +75,17 @@ void check_kernel(unsigned long addr, unsigned long magic) {
                 mmap = (multiboot_memory_map_t *)(((unsigned long)mmap) + mmap_tag->entry_size);
             }
             break;
+        case MULTIBOOT_TAG_TYPE_VBE:
+            vbe = (struct multiboot_tag_vbe *)tag;
+            void *vci = (void *)vbe->vbe_control_info.external_specification;
+            void *vmi = (void *)vbe->vbe_mode_info.external_specification;
+            // vbe->vbe_control_info;
+            // asm volatile("xchg %%bx, %%bx;nop;nop;" ::"a"(vci), "b"(vmi));
+            init_vbe(vmi);
+            break;
+        case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+            asm volatile("xchg %bx, %bx;nop;nop;nop;nop;");
+            break;
         default:
             printk("tag %x size %x\n", tag->type, tag->size);
             break;
@@ -133,6 +145,6 @@ void init_system_info() {
     printk("boot device: bios dev %x partition %x sub partition %x\n", boot_params.biosdev, boot_params.partition,
            boot_params.sub_partition);
     printk("mem lower %uKB upper %uKB\n", boot_params.mem_lower >> 10, boot_params.mem_upper >> 10);
-    while (1)
-        ;
+    // while (1)
+    //     ;
 }
index 5a914d22d9f6834d31be17dc6c3b6ff88e33aa3c..971a19ca0b562b903198ea141a839df034815cf1 100644 (file)
@@ -167,15 +167,15 @@ multiboot2_header_bgn:
     # checksum
     .long   -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (multiboot2_header_end - multiboot2_header_bgn))
 
-    // .align 8
-    // .framebuffer_tag_bgn:
-    // .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
-    // .short MULTIBOOT_HEADER_TAG_OPTIONAL
-    // .long .framebuffer_tag_end - .framebuffer_tag_bgn
-    // .long 1280
-    // .long 800
-    // .long 32
-    // .framebuffer_tag_end:
+    .align 8
+    .framebuffer_tag_bgn:
+    .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
+    .short MULTIBOOT_HEADER_TAG_OPTIONAL
+    .long .framebuffer_tag_end - .framebuffer_tag_bgn
+    .long 1280
+    .long 800
+    .long 32
+    .framebuffer_tag_end:
 
     .align 8
     .multiboot2_tag_end:
diff --git a/boot/vbe.c b/boot/vbe.c
new file mode 100644 (file)
index 0000000..18aa2e3
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: vbe.c
+ *      Author: Zhao Yanbai
+ *              2021-11-06 15:56:23 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include <linkage.h>
+// #include <page.h>
+#include <system.h>
+#include <types.h>
+typedef struct vbe_mode_info {
+    u16 mode_attributes;
+    u8 wina_attributes;
+    u8 winb_attributes;
+    u16 win_granularity;
+    u16 win_size;
+    u16 wina_segment;
+    u16 winb_segment;
+    u32 win_func_ptr;
+    u16 bytes_per_scan_line;
+    u16 x_resolution;
+    u16 y_resolution;
+    u8 xchar_size;
+    u8 ychar_size;
+    u8 number_of_planes;
+    u8 bits_per_pixel;
+    u8 number_of_banks;
+    u8 memory_model;
+    u8 bank_size;
+    u8 number_of_image_pages;
+    u8 _reserved0;
+    u8 red_mask_size;
+    u8 red_field_position;
+    u8 green_mask_size;
+    u8 green_field_position;
+    u8 blue_mask_size;
+    u8 blue_field_position;
+    u8 rsvd_mask_size;
+    u8 rsvd_field_position;
+    u8 direct_color_mode_info;
+    u32 phys_base_ptr;
+    u32 _reserved1;
+    u16 _reserved2;
+    u16 lin_bytes_per_scan_line;
+    u8 bank_number_of_image_pages;
+    u8 lin_number_of_image_pages;
+    u8 lin_red_mask_size;
+    u8 lin_red_field_position;
+    u8 lin_green_mask_size;
+    u8 lin_green_field_position;
+    u8 lin_blue_mask_size;
+    u8 lin_blue_field_position;
+    u8 lin_rvsd_mask_size;
+    u8 lin_rvsd_field_position;
+    u32 max_pixel_clock;
+    u8 _reserved3[189];
+} __attribute__((packed)) vbe_mode_info_t;
+
+// pte_t vbe_pte[PTECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE)));
+
+// extern pde_t init_pgd[];
+void init_vbe(void *vmiptr) {
+    vbe_mode_info_t *vmi = (vbe_mode_info_t *)vmiptr;
+    system.vbe_phys_addr = vmi->phys_base_ptr;
+    system.x_resolution = vmi->x_resolution;
+    system.y_resolution = vmi->y_resolution;
+    // unsigned long phys_base_addr = vmi->phys_base_ptr;
+
+    // asm volatile("xchg %%bx, %%bx;nop;" ::"a"(phys_base_addr));
+
+    // init_pgd[phys_base_addr >> 22] = va2pa(vbe_pte) | 7;
+    // asm volatile("xchg %bx, %bx;nop;nop;nop;nop;");
+    // for (int i = 0; i < PTECNT_PER_PAGE; i++) {
+    //     vbe_pte[i] = phys_base_addr + i * PAGE_SIZE + 7;
+    // }
+    // asm volatile("xchg %bx, %bx;nop;nop;nop;nop;");
+    // unsigned long *p = (unsigned long *)phys_base_addr;
+    // for (int i = 0; i < 1024; i++) {
+    //     p[i] = 0x00FF0000;
+    // }
+}
\ No newline at end of file
index 0b0068d5763b782c077ac9cd82c76fbbe585f63c..e8c8406c5f29e91bda4027968331c8ad8b5385c9 100644 (file)
@@ -66,7 +66,7 @@ typedef unsigned long pte_t;
 
 #define MAX_ORDER (11)
 
-#define LoadCR3(cr3) asm volatile ("movl %%edx, %%cr3"::"d"(cr3))
+#define LoadCR3(cr3) asm volatile("movl %%edx, %%cr3" ::"d"(cr3))
 
 typedef unsigned int gfp_t;
 
index 8ce574abccb4dc2a39553c900dbe4cb28eaf414c..4c477c95dbd2d84cd59d0c8eb827c85b8e1b3a95 100644 (file)
@@ -80,8 +80,19 @@ extern char gdtr[6], idtr[6];
 
 #define ALIGN(x, a) (((x) + (a)-1) & ~((a)-1))
 
-// 1 GB
-#define MAX_SUPT_PHYMM_SIZE (1UL << 30)
+// 定义最大显存为 16MB
+#define VRAM_VADDR_SIZE (16 << 20)
+
+// 最大支持的线性地址空间为1G
+#define MAX_SUPT_VADDR_SIZE (1UL << 30)
+
+// 把内核线性地址的最高部分留给显存
+// 余下的部分为支持映射其它物理内存的空间
+#define MAX_SUPT_PHYMM_SIZE (MAX_SUPT_VADDR_SIZE - VRAM_VADDR_SIZE)
+
+// 算出显存的线性地址
+// 之后要将这个地址映射到显存的物理地址
+#define VRAM_VADDR_BASE (PAGE_OFFSET + MAX_SUPT_PHYMM_SIZE)
 
 #define INT_STACK_SIZE PAGE_SIZE
 
@@ -155,6 +166,10 @@ typedef struct system {
     // More Infomation see 'info multiboot'
     u32 boot_device;
 
+    u32 vbe_phys_addr;
+    u16 x_resolution;
+    u16 y_resolution;
+
     dev_t root_dev;
 #define CMD_LINE_SIZE 128
     const char *cmdline;
index bd8a30bb7f5969d81d09eae48b7d902df536ac6d..8f3088c3dd4c5dee17636211919e37e44936780d 100644 (file)
@@ -112,7 +112,8 @@ void e820_init_bootmem_data() {
     unsigned long max_support_pfn = PFN_DW(MAX_SUPT_PHYMM_SIZE);
     if (bootmem_data.max_pfn > max_support_pfn) {
         bootmem_data.max_pfn = max_support_pfn;
-        printk("memory > 1G, only support to 1G.\n");
+        unsigned long ms = max_support_pfn / 1024 * 4;  // 1024个pfn正好4MB
+        printk("memory > %dMB, only support to %dMB.\n", ms, ms);
     }
 
     printk("pfn_min: %d pfn_max: %d\n", bootmem_data.min_pfn, bootmem_data.max_pfn);
diff --git a/mm/mm.c b/mm/mm.c
index 02ca95e69b4623fba27869ce4231a8e8d0e461e9..1a10d05679476cf488922078d8edd209a6aa59f4 100644 (file)
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -45,7 +45,8 @@ void init_paging() {
     unsigned int i;
     unsigned long pfn = 0;
     pte_t *pte = 0;
-    unsigned long pgtb_addr = 0;
+    unsigned long *pgtb_addr = 0;
+    void *alloc_from_bootmem(unsigned long size, char *title);
 
     // 在multiboot.S是已经初始化了BOOT_INIT_PAGETBL_CNT个页
     // 这里接着初始化剩余的页
@@ -54,16 +55,17 @@ void init_paging() {
         unsigned long ti = pfn % PAGE_PTE_CNT;
         unsigned long page_addr = pfn2pa(pfn);
         if (ti == 0) {
-            void *alloc_from_bootmem(unsigned long size, char *title);
-            pgtb_addr = (unsigned long)va2pa(alloc_from_bootmem(PAGE_SIZE, "paging"));
-            if (0 == pgtb_addr) panic("No Pages for Paging...");
+            pgtb_addr = (unsigned long *)alloc_from_bootmem(PAGE_SIZE, "paging");
+            if (0 == pgtb_addr) {
+                panic("no pages for paging...");
+            }
 
             memset((void *)pgtb_addr, 0, PAGE_SIZE);
 
-            init_pgd[get_npd(page_addr)] = (pde_t)(pgtb_addr | PAGE_P | PAGE_WR);
+            init_pgd[get_npd(page_addr)] = (pde_t)((unsigned long)va2pa(pgtb_addr) | PAGE_P | PAGE_WR);
         }
 
-        pte = ((pte_t *)pa2va(pgtb_addr)) + ti;
+        pte = ((pte_t *)pgtb_addr) + ti;
         *pte = (pte_t)(page_addr | PAGE_P | PAGE_WR);
     }
 
@@ -74,11 +76,34 @@ void init_paging() {
         init_pgd[i - delta] = 0;
     }
 
+    // 接下来为显存建立页映射
+    unsigned long vram_phys_addr = system.vbe_phys_addr;
+    for (int pde_inx = 0; pde_inx < get_npd(VRAM_VADDR_SIZE); pde_inx++) {
+        pgtb_addr = (unsigned long *)(alloc_from_bootmem(PAGE_SIZE, "vrampaging"));
+        if (0 == pgtb_addr) {
+            panic("no pages for paging...");
+        }
+        // 后续要初始化,所以此处不用memset
+        // memset((void *)pgtb_addr, 0, PAGE_SIZE);
+        init_pgd[get_npd(VRAM_VADDR_BASE) + pde_inx] = (pde_t)((unsigned long)va2pa(pgtb_addr) | PAGE_P | PAGE_WR);
+
+        for (int pte_inx = 0; pte_inx < PTECNT_PER_PAGE; pte_inx++) {
+            pgtb_addr[pte_inx] = vram_phys_addr | PAGE_P | PAGE_WR;
+            vram_phys_addr += PAGE_SIZE;
+        }
+    }
+
     // paging for user space
     extern void sysexit();
     set_page_shared(sysexit);
 
     LoadCR3(va2pa(init_pgd));
+
+    // 测试显存
+    for (int i = 0; i < 4096; i++) {
+        unsigned long *vram = (unsigned long *)VRAM_VADDR_BASE;
+        vram[i] = 0x00FF0000;
+    }
 }
 
 void init_mm() {