自定义OS开发:GRUB配置1024x768x32后无法切换至图形模式
自定义OS GRUB图形模式切换失败问题
开发自定义操作系统,使用GRUB引导加载内核时遇到图形模式切换失败问题:已在GRUB配置中设置启动为1024x768x32图形模式,但系统启动后仍处于文本模式——内核中面向文本模式的print函数可正常运行,图形模式相关操作无效果。已在多台虚拟机和物理机测试,GRUB版本为2.06。
引导加载程序代码(bootloader.asm)
[bits 32] section .multiboot align 4 dd 0x1BADB002 ; Multiboot magic number dd 0x00 ; Flags dd -(0x1BADB002 + 0x00) ; Checksum (must be such that all the dword sums to zero) section .bootstrap_stack align 16 stack_bottom: times 16384 db 0 ; Declare a stack of 16KB stack_top: section .text extern kmain ; This should be in your kernel code global start start: mov esp, stack_top ; Set up the stack call kmain ; Call the main function in the kernel cli ; Disable interrupts .hang: hlt ; Halt the CPU jmp .hang ; Infinite loop just in case
内核代码(kernel.c)
#define VIDEO_MEMORY 0xA0000 void print(char *str, int x, int y) { volatile char *video = (volatile char*)(0xB8000 + 2*x + 160*y); while (*str != 0) { *video = *str; video += 2; str++; } } #define VIDEO_MEMORY 0xA0000 void fill_screen(unsigned char color) { unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY; int i; for (i = 0; i < 320 * 200; i++) video_memory[i] = color; } void draw_pixel(int x, int y, unsigned char color) { unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY; int offset = y * 320 + x; video_memory[offset] = color; } void fillRect(int x, int y, int width, int height, unsigned char color) { unsigned char* video_memory = (unsigned char*)0xA0000; int i, j; for (i = y; i < y + height; i++) { for (j = x; j < x + width; j++) { draw_pixel(x+i,y+j, color); } } } void kmain() { print("hello", 0, 0); fill_screen(0x0F); // Fill the screen with white color (0x0F) draw_pixel(160, 100, 0x0); // Draw a black pixel at (160, 100) fillRect(5,10,20,20,0xFF); uint8_t* framebuffer = (uint8_t*)0xA0000; // Replace with your framebuffer address unsigned int bytes_per_pixel = 3; // Replace with your bytes per pixel unsigned int bytes_per_scanline = 1920; // Replace with your bytes per scanline unsigned int x = 10; // The x coordinate of the pixel unsigned int y = 10; // The y coordinate of the pixel uint8_t* pixel_address = framebuffer + y * bytes_per_scanline + x * bytes_per_pixel; pixel_address[0] = 0xFF; // Red pixel_address[1] = 0x00; // Green pixel_address[2] = 0x00; // Blue }
GRUB配置(grub.cfg)
set default=0 set timeout=0 menuentry "My OS" { multiboot /boot/myos.bin set gfxpayload=1024x768x32 insmod all_video boot }
排查方向与解决建议
- 修正GRUB配置顺序:
set gfxpayload和insmod all_video必须放在multiboot命令之前,GRUB需要在加载内核前就设置好图形模式。修正后的配置如下:set default=0 set timeout=0 menuentry "My OS" { insmod all_video set gfxpayload=1024x768x32 multiboot /boot/myos.bin boot } - 启用Multiboot图形支持标志:当前引导加载程序的Multiboot flags为
0x00,未启用图形模式支持。需要将flags改为0x00000003(同时启用内存信息和图形模式支持),并重新计算校验码:dd 0x1BADB002 ; Multiboot magic number dd 0x00000003 ; Flags: 0x1=内存信息, 0x2=图形模式支持 dd -(0x1BADB002 + 0x00000003) ; 重新计算校验码 - 读取GRUB传递的帧缓冲参数:内核中硬编码的
0xA0000是VGA 320x200 8位模式的地址,与GRUB设置的1024x768x32模式不匹配。需要修改kmain接收Multiboot信息指针,解析其中的帧缓冲地址、分辨率、像素格式:
同时修改引导加载程序,将Multiboot信息指针传递给#include <stdint.h> typedef struct multiboot_info { uint32_t flags; uint32_t mem_lower; uint32_t mem_upper; // 省略其他字段,仅保留图形相关部分 uint32_t framebuffer_addr; uint32_t framebuffer_pitch; uint32_t framebuffer_width; uint32_t framebuffer_height; uint8_t framebuffer_bpp; } multiboot_info_t; void kmain(multiboot_info_t *mbi) { // 检查是否支持图形模式 if (mbi->flags & (1 << 12)) { uint8_t* framebuffer = (uint8_t*)mbi->framebuffer_addr; uint32_t pitch = mbi->framebuffer_pitch; uint32_t width = mbi->framebuffer_width; uint32_t height = mbi->framebuffer_height; uint8_t bpp = mbi->framebuffer_bpp; // 绘制测试像素(注意部分格式为BGR) uint32_t x = 10, y = 10; uint8_t* pixel = framebuffer + y * pitch + x * (bpp / 8); pixel[0] = 0xFF; // 蓝 pixel[1] = 0x00; // 绿 pixel[2] = 0x00; // 红 } }kmain:start: mov esp, stack_top ; 设置栈 push ebx ; Multiboot信息指针存于ebx,传递给kmain call kmain ; 调用内核主函数 cli ; 禁用中断 .hang: hlt ; 暂停CPU jmp .hang ; 无限循环 - 验证图形模式支持性:在GRUB菜单按
c进入命令行,手动执行insmod all_video、set gfxpayload=1024x768x32、vbeinfo查看支持的模式列表,确认1024x768x32是否在其中。
内容的提问来源于stack exchange,提问作者TechMC
相关产品推荐
相关产品推荐

