GRUB未在自定义操作系统开发中切换到图形模式

huangapple go评论83阅读模式
英文:

GRUB not Switching to Graphics Mode in Custom OS Development

问题

I am developing a custom operating system and using the GRUB bootloader to load my kernel. In my development process, I've encountered an issue where I am unable to switch the display mode from text to graphics mode. Despite configuring GRUB to start in a graphics mode (1024x768x32), the system appears to remain in text mode during booting.

The assembly bootloader and the section of the kernel where I try to use graphics mode are provided below:

[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

My kernel.c file looks like:

#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
}

Here's the configuration in my grub.cfg file:

set default=0
set timeout=0
menuentry "My OS" {
multiboot /boot/myos.bin
set gfxpayload=1024x768x32
insmod all_video
boot
}

In my kernel, I implemented a print function that prints text to the screen. My expectation was that, if the system had successfully switched to graphics mode, this function would fail as it is designed for text mode. However, the print function worked as if the system was still in text mode, which suggests that the system never made the switch to graphics mode.

I've tried this setup on several virtual machines and physical machines, and I am consistently experiencing the same issue. I am currently using GRUB version 2.06.

I am stumped as to why the switch to graphics mode isn't happening, despite being specified in the GRUB configuration. Any advice or pointers would be greatly appreciated!

英文:

I am developing a custom operating system and using the GRUB bootloader to load my kernel. In my development process, I've encountered an issue where I am unable to switch the display mode from text to graphics mode. Despite configuring GRUB to start in a graphics mode (1024x768x32), the system appears to remain in text mode during booting.

The assembly bootloader and the section of the kernel where I try to use graphics mode are provided below:
; 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

my kernel.c file looks like:
// 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 &lt; 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 &lt; y + height; i++) {
        for (j = x; j &lt; x + width; j++) {
            draw_pixel(x+i,y+j, color);
        }
    }
}

void kmain() {
	print(&quot;hello&quot;, 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

}

Here's the configuration in my grub.cfg file:

set default=0
set timeout=0
menuentry &quot;My OS&quot; {
multiboot /boot/myos.bin
set gfxpayload=1024x768x32
insmod all_video
boot
}

In my kernel, I implemented a print function that prints text to the screen. My expectation was that, if the system had successfully switched to graphics mode, this function would fail as it is designed for text mode. However, the print function worked as if the system was still in text mode, which suggests that the system never made the switch to graphics mode.

I've tried this setup on several virtual machines and physical machines, and I am consistently experiencing the same issue. I am currently using GRUB version 2.06.

I am stumped as to why the switch to graphics mode isn't happening, despite being specified in the GRUB configuration. Any advice or pointers would be greatly appreciated!

Please remember to replace the comments "More drawing functions" and "More drawing code" with the actual drawing functions and code you are using. This will help others diagnose your issue more accurately.

答案1

得分: 0

不要 gfxpayload 在 grub.cfg 中更改分辨率,可以在您的 Multiboot2 标头中使用 framebuffer 标签。

要做到这一点,在校验和之后添加以下内容:

dw 5
dw 0 ;而不是0,您可以指定您的标志
dd 20
dd 1024 ;而不是1024,您可以指定您的宽度
dd 768 ;而不是768,您可以指定您的高度
dd 32 ;而不是32,您可以指定您的 BPP

此外,不要忘记 0xA0000 有 64,000 字节的限制,并且您可以在 32 BPP 下最多绘制 16,000 个像素。

英文:

Instead of gfxpayload in grub.cfg to change the resolution, you can use the framebuffer tag in your Multiboot2 header.

To do this, after checksum add this:

dw 5
dw 0 ;instead of 0, you can specify your flags
dd 20
dd 1024 ;instead of 1024, you can specify your width
dd 768 ;instead of 768, you can specify your height
dd 32 ;instead of 32, you can specify your BPP

Also don't forget that 0xA0000 has a limit of 64,000 bytes and that you can paint over a maximum of 16,000 pixels at 32 BPP.

huangapple
  • 本文由 发表于 2023年7月13日 11:36:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76675725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定