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

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

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:

  1. [bits 32]
  2. section .multiboot
  3. align 4
  4. dd 0x1BADB002 ; Multiboot magic number
  5. dd 0x00 ; Flags
  6. dd -(0x1BADB002 + 0x00) ; Checksum (must be such that all the dword sums to zero)
  7. section .bootstrap_stack
  8. align 16
  9. stack_bottom:
  10. times 16384 db 0 ; Declare a stack of 16KB
  11. stack_top:
  12. section .text
  13. extern kmain ; This should be in your kernel code
  14. global start
  15. start:
  16. mov esp, stack_top ; Set up the stack
  17. call kmain ; Call the main function in the kernel
  18. cli ; Disable interrupts
  19. .hang:
  20. hlt ; Halt the CPU
  21. jmp .hang ; Infinite loop just in case

My kernel.c file looks like:

  1. #define VIDEO_MEMORY 0xA0000
  2. void print(char *str, int x, int y) {
  3. volatile char *video = (volatile char*)(0xB8000 + 2*x + 160*y);
  4. while (*str != 0) {
  5. *video = *str;
  6. video += 2;
  7. str++;
  8. }
  9. }
  10. #define VIDEO_MEMORY 0xA0000
  11. void fill_screen(unsigned char color) {
  12. unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
  13. int i;
  14. for (i = 0; i < 320 * 200; i++)
  15. video_memory[i] = color;
  16. }
  17. void draw_pixel(int x, int y, unsigned char color) {
  18. unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
  19. int offset = y * 320 + x;
  20. video_memory[offset] = color;
  21. }
  22. void fillRect(int x, int y, int width, int height, unsigned char color) {
  23. unsigned char* video_memory = (unsigned char*)0xA0000;
  24. int i, j;
  25. for (i = y; i < y + height; i++) {
  26. for (j = x; j < x + width; j++) {
  27. draw_pixel(x+i,y+j, color);
  28. }
  29. }
  30. }
  31. void kmain() {
  32. print("hello", 0, 0);
  33. fill_screen(0x0F); // Fill the screen with white color (0x0F)
  34. draw_pixel(160, 100, 0x0); // Draw a black pixel at (160, 100)
  35. fillRect(5,10,20,20,0xFF);
  36. uint8_t* framebuffer = (uint8_t*)0xA0000; // Replace with your framebuffer address
  37. unsigned int bytes_per_pixel = 3; // Replace with your bytes per pixel
  38. unsigned int bytes_per_scanline = 1920; // Replace with your bytes per scanline
  39. unsigned int x = 10; // The x coordinate of the pixel
  40. unsigned int y = 10; // The y coordinate of the pixel
  41. uint8_t* pixel_address = framebuffer + y * bytes_per_scanline + x * bytes_per_pixel;
  42. pixel_address[0] = 0xFF; // Red
  43. pixel_address[1] = 0x00; // Green
  44. pixel_address[2] = 0x00; // Blue
  45. }

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

  1. set default=0
  2. set timeout=0
  3. menuentry "My OS" {
  4. multiboot /boot/myos.bin
  5. set gfxpayload=1024x768x32
  6. insmod all_video
  7. boot
  8. }

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

  1. [bits 32]
  2. section .multiboot
  3. align 4
  4. dd 0x1BADB002 ; Multiboot magic number
  5. dd 0x00 ; Flags
  6. dd -(0x1BADB002 + 0x00) ; Checksum (must be such that all the dword sums to zero)
  7. section .bootstrap_stack
  8. align 16
  9. stack_bottom:
  10. times 16384 db 0 ; Declare a stack of 16KB
  11. stack_top:
  12. section .text
  13. extern kmain ; This should be in your kernel code
  14. global start
  15. start:
  16. mov esp, stack_top ; Set up the stack
  17. call kmain ; Call the main function in the kernel
  18. cli ; Disable interrupts
  19. .hang:
  20. hlt ; Halt the CPU
  21. jmp .hang ; Infinite loop just in case

my kernel.c file looks like:
// kernel.c

  1. #define VIDEO_MEMORY 0xA0000
  2. void print(char *str, int x, int y) {
  3. volatile char *video = (volatile char*)(0xB8000 + 2*x + 160*y);
  4. while (*str != 0) {
  5. *video = *str;
  6. video += 2;
  7. str++;
  8. }
  9. }
  10. #define VIDEO_MEMORY 0xA0000
  11. void fill_screen(unsigned char color) {
  12. unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
  13. int i;
  14. for (i = 0; i &lt; 320 * 200; i++)
  15. video_memory[i] = color;
  16. }
  17. void draw_pixel(int x, int y, unsigned char color) {
  18. unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
  19. int offset = y * 320 + x;
  20. video_memory[offset] = color;
  21. }
  22. void fillRect(int x, int y, int width, int height, unsigned char color) {
  23. unsigned char* video_memory = (unsigned char*)0xA0000;
  24. int i, j;
  25. for (i = y; i &lt; y + height; i++) {
  26. for (j = x; j &lt; x + width; j++) {
  27. draw_pixel(x+i,y+j, color);
  28. }
  29. }
  30. }
  31. void kmain() {
  32. print(&quot;hello&quot;, 0, 0);
  33. fill_screen(0x0F); // Fill the screen with white color (0x0F)
  34. draw_pixel(160, 100, 0x0); // Draw a black pixel at (160, 100)
  35. fillRect(5,10,20,20,0xFF);
  36. uint8_t* framebuffer = (uint8_t*)0xA0000; // Replace with your framebuffer address
  37. unsigned int bytes_per_pixel = 3; // Replace with your bytes per pixel
  38. unsigned int bytes_per_scanline = 1920; // Replace with your bytes per scanline
  39. unsigned int x = 10; // The x coordinate of the pixel
  40. unsigned int y = 10; // The y coordinate of the pixel
  41. uint8_t* pixel_address = framebuffer + y * bytes_per_scanline + x * bytes_per_pixel;
  42. pixel_address[0] = 0xFF; // Red
  43. pixel_address[1] = 0x00; // Green
  44. pixel_address[2] = 0x00; // Blue
  45. }

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

  1. set default=0
  2. set timeout=0
  3. menuentry &quot;My OS&quot; {
  4. multiboot /boot/myos.bin
  5. set gfxpayload=1024x768x32
  6. insmod all_video
  7. boot
  8. }

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 标签。

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

  1. dw 5
  2. dw 0 ;而不是0,您可以指定您的标志
  3. dd 20
  4. dd 1024 ;而不是1024,您可以指定您的宽度
  5. dd 768 ;而不是768,您可以指定您的高度
  6. 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:

  1. dw 5
  2. dw 0 ;instead of 0, you can specify your flags
  3. dd 20
  4. dd 1024 ;instead of 1024, you can specify your width
  5. dd 768 ;instead of 768, you can specify your height
  6. 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:

确定