diff --git a/include/multiboot.h b/include/multiboot.h index 460347d22..57c154c98 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -195,6 +195,9 @@ struct multiboot_info multiboot_uint32_t framebuffer_width; multiboot_uint32_t framebuffer_height; multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 multiboot_uint8_t framebuffer_type; union { @@ -223,9 +226,6 @@ struct multiboot_color multiboot_uint8_t blue; }; -#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 -#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 - struct multiboot_mmap_entry { multiboot_uint32_t size; diff --git a/include/multiboot2.h b/include/multiboot2.h index 8bcf5a7e4..a241a70ad 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -195,6 +195,9 @@ struct multiboot_info multiboot_uint32_t framebuffer_width; multiboot_uint32_t framebuffer_height; multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 multiboot_uint8_t framebuffer_type; union { @@ -223,9 +226,6 @@ struct multiboot_color multiboot_uint8_t blue; }; -#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 -#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 - struct multiboot_mmap_entry { multiboot_uint32_t size; diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c index f362b800d..ddbbf3cfd 100644 --- a/loader/i386/multiboot_mbi.c +++ b/loader/i386/multiboot_mbi.c @@ -162,11 +162,12 @@ set_video_mode (void) #if HAS_VBE static grub_err_t fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, - grub_uint32_t ptrdest) + grub_uint32_t ptrdest, int fill_generic) { grub_vbe_status_t status; grub_uint32_t vbe_mode; void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + struct grub_vbe_mode_info_block *mode_info; status = grub_vbe_bios_get_controller_info (scratch); if (status != GRUB_VBE_STATUS_OK) @@ -180,14 +181,27 @@ fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, status = grub_vbe_bios_get_mode (scratch); vbe_mode = *(grub_uint32_t *) scratch; if (status != GRUB_VBE_STATUS_OK) - return grub_error (GRUB_ERR_IO, "Can't get VBE mode."); + return grub_error (GRUB_ERR_IO, "can't get VBE mode"); mbi->vbe_mode = vbe_mode; - status = grub_vbe_bios_get_mode_info (vbe_mode, scratch); - if (status != GRUB_VBE_STATUS_OK) - return grub_error (GRUB_ERR_IO, "Can't get mode info."); + mode_info = (struct grub_vbe_mode_info_block *) ptrorig; mbi->vbe_mode_info = ptrdest; - grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_mode_info_block)); + /* get_mode_info isn't available for mode 3. */ + if (vbe_mode == 3) + { + grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block)); + mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT; + mode_info->x_resolution = 80; + mode_info->y_resolution = 25; + } + else + { + status = grub_vbe_bios_get_mode_info (vbe_mode, scratch); + if (status != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_IO, "can't get mode info"); + grub_memcpy (mode_info, scratch, + sizeof (struct grub_vbe_mode_info_block)); + } ptrorig += sizeof (struct grub_vbe_mode_info_block); ptrdest += sizeof (struct grub_vbe_mode_info_block); @@ -198,6 +212,21 @@ fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, mbi->flags |= MULTIBOOT_INFO_VBE_INFO; + if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT) + { + mbi->framebuffer_addr = 0xb8000; + + mbi->framebuffer_pitch = 2 * mode_info->x_resolution; + mbi->framebuffer_width = mode_info->x_resolution; + mbi->framebuffer_height = mode_info->y_resolution; + + mbi->framebuffer_bpp = 16; + + mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; + + mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; + } + return GRUB_ERR_NONE; } #endif @@ -209,25 +238,25 @@ retrieve_video_parameters (struct multiboot_info *mbi, grub_err_t err; struct grub_video_mode_info mode_info; void *framebuffer; -#if HAS_VBE - int vbe_active; -#endif + grub_video_driver_id_t driv_id; struct grub_video_palette_data palette[256]; err = set_video_mode (); if (err) - return err; + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } grub_video_get_palette (0, ARRAY_SIZE (palette), palette); -#if HAS_VBE - { - grub_video_driver_id_t driv_id; - driv_id = grub_video_get_driver_id (); - - vbe_active = ((driv_id == GRUB_VIDEO_DRIVER_VBE) - || ((driv_id == GRUB_VIDEO_DRIVER_NONE) && HAS_VGA_TEXT)); - } + driv_id = grub_video_get_driver_id (); +#if HAS_VGA_TEXT + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return fill_vbe_info (mbi, ptrorig, ptrdest, 1); +#else + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return GRUB_ERR_NONE; #endif err = grub_video_get_info_and_fini (&mode_info, &framebuffer); @@ -277,8 +306,8 @@ retrieve_video_parameters (struct multiboot_info *mbi, mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; #if HAS_VBE - if (vbe_active) - fill_vbe_info (mbi, ptrorig, ptrdest); + if (driv_id == GRUB_VIDEO_DRIVER_VBE) + return fill_vbe_info (mbi, ptrorig, ptrdest, 0); #endif return GRUB_ERR_NONE;