From db03d441056ab66dc609ea7e5c35619091abf30a Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 6 Nov 2021 18:22:53 +0800 Subject: [PATCH] =?utf8?q?=E4=BB=8Evbe=E4=B8=AD=E8=AF=BB=E5=87=BA=E6=98=BE?= =?utf8?q?=E5=AD=98=E7=89=A9=E7=90=86=E5=9C=B0=E5=9D=80=E5=B9=B6=E5=BB=BA?= =?utf8?q?=E7=AB=8B=E5=9C=B0=E5=9D=80=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .bochsrc | 1 + boot/boot.c | 24 ++++++++++---- boot/multiboot.S | 18 +++++------ boot/vbe.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ include/page.h | 2 +- include/system.h | 19 +++++++++-- mm/bootmem.c | 3 +- mm/mm.c | 37 +++++++++++++++++---- 8 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 boot/vbe.c diff --git a/.bochsrc b/.bochsrc index bf4a759..2cbfe77 100644 --- 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: diff --git a/boot/boot.c b/boot/boot.c index 18683dd..066f342 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -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) + // ; } diff --git a/boot/multiboot.S b/boot/multiboot.S index 5a914d2..971a19c 100644 --- a/boot/multiboot.S +++ b/boot/multiboot.S @@ -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 index 0000000..18aa2e3 --- /dev/null +++ b/boot/vbe.c @@ -0,0 +1,84 @@ +/* + * ------------------------------------------------------------------------ + * File Name: vbe.c + * Author: Zhao Yanbai + * 2021-11-06 15:56:23 Saturday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +// #include +#include +#include +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 diff --git a/include/page.h b/include/page.h index 0b0068d..e8c8406 100644 --- a/include/page.h +++ b/include/page.h @@ -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; diff --git a/include/system.h b/include/system.h index 8ce574a..4c477c9 100644 --- a/include/system.h +++ b/include/system.h @@ -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; diff --git a/mm/bootmem.c b/mm/bootmem.c index bd8a30b..8f3088c 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -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 02ca95e..1a10d05 100644 --- 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() { -- 2.44.0