Support multiboot VBE info.
* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): Take VBE info into account. (fill_vbe_info) [GRUB_MACHINE_HAS_VBE]: New function. (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: Call fill_vbe_info when appropriate. (grub_multiboot_make_mbi): Account for the size occupied by VBE info. * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare tags as supported. (grub_multiboot_get_mbi_size): Take new tags into account. (fill_vbe_tag) [GRUB_MACHINE_HAS_VBE]: New function. (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: Call fill_vbe_tag when appropriate. (grub_multiboot_make_mbi): Properly align tags. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_pm_interface): New function. * include/grub/i386/pc/vbe.h (grub_vbe_bios_get_pm_interface): New proto. * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): New definition.
This commit is contained in:
commit
f218b09c99
7 changed files with 215 additions and 9 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2010-09-20 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Support multiboot VBE info.
|
||||
|
||||
* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size):
|
||||
Take VBE info into account.
|
||||
(fill_vbe_info) [GRUB_MACHINE_HAS_VBE]: New function.
|
||||
(retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]:
|
||||
Call fill_vbe_info when appropriate.
|
||||
(grub_multiboot_make_mbi): Account for the size occupied by VBE info.
|
||||
* grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare tags
|
||||
as supported.
|
||||
(grub_multiboot_get_mbi_size): Take new tags into account.
|
||||
(fill_vbe_tag) [GRUB_MACHINE_HAS_VBE]: New function.
|
||||
(retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]:
|
||||
Call fill_vbe_tag when appropriate.
|
||||
(grub_multiboot_make_mbi): Properly align tags.
|
||||
* grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_pm_interface): New
|
||||
function.
|
||||
* include/grub/i386/pc/vbe.h (grub_vbe_bios_get_pm_interface): New
|
||||
proto.
|
||||
* include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): New definition.
|
||||
|
||||
2010-09-20 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Suport manual terminal geometry specification.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
#include <grub/machine/biosnum.h>
|
||||
#include <grub/machine/apm.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#endif
|
||||
#include <grub/multiboot.h>
|
||||
#include <grub/cpu/relocator.h>
|
||||
|
@ -195,6 +196,10 @@ grub_multiboot_get_mbi_size (void)
|
|||
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
|
||||
+ elf_sec_entsize * elf_sec_num
|
||||
+ 256 * sizeof (struct multiboot_color)
|
||||
#if GRUB_MACHINE_HAS_VBE
|
||||
+ sizeof (struct grub_vbe_info_block)
|
||||
+ sizeof (struct grub_vbe_mode_info_block)
|
||||
#endif
|
||||
+ ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
|
||||
}
|
||||
|
||||
|
@ -238,6 +243,77 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
|
|||
grub_mmap_iterate (hook);
|
||||
}
|
||||
|
||||
#if GRUB_MACHINE_HAS_VBE
|
||||
static grub_err_t
|
||||
fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
|
||||
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)
|
||||
return grub_error (GRUB_ERR_IO, "Can't get controller info.");
|
||||
|
||||
mbi->vbe_control_info = ptrdest;
|
||||
grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
|
||||
ptrorig += sizeof (struct grub_vbe_info_block);
|
||||
ptrdest += sizeof (struct grub_vbe_info_block);
|
||||
|
||||
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");
|
||||
mbi->vbe_mode = vbe_mode;
|
||||
|
||||
mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
|
||||
mbi->vbe_mode_info = ptrdest;
|
||||
/* 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);
|
||||
|
||||
grub_vbe_bios_get_pm_interface (&mbi->vbe_interface_seg,
|
||||
&mbi->vbe_interface_off,
|
||||
&mbi->vbe_interface_len);
|
||||
|
||||
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
|
||||
|
||||
static grub_err_t
|
||||
retrieve_video_parameters (struct multiboot_info *mbi,
|
||||
grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
|
||||
|
@ -258,8 +334,13 @@ retrieve_video_parameters (struct multiboot_info *mbi,
|
|||
grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
|
||||
|
||||
driv_id = grub_video_get_driver_id ();
|
||||
#if GRUB_MACHINE_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);
|
||||
if (err)
|
||||
|
@ -307,6 +388,11 @@ retrieve_video_parameters (struct multiboot_info *mbi,
|
|||
|
||||
mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
|
||||
|
||||
#if GRUB_MACHINE_HAS_VBE
|
||||
if (driv_id == GRUB_VIDEO_DRIVER_VBE)
|
||||
return fill_vbe_info (mbi, ptrorig, ptrdest, 0);
|
||||
#endif
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -440,6 +526,12 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
|||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
#if GRUB_MACHINE_HAS_VBE
|
||||
ptrorig += sizeof (struct grub_vbe_info_block);
|
||||
ptrdest += sizeof (struct grub_vbe_info_block);
|
||||
ptrorig += sizeof (struct grub_vbe_mode_info_block);
|
||||
ptrdest += sizeof (struct grub_vbe_mode_info_block);
|
||||
#endif
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
/*
|
||||
* FIXME: The following features from the Multiboot specification still
|
||||
* need to be implemented:
|
||||
* - VBE support
|
||||
* - drives table
|
||||
* - ROM configuration table
|
||||
*/
|
||||
|
|
|
@ -139,11 +139,11 @@ grub_multiboot_load (grub_file_t file)
|
|||
case MULTIBOOT_TAG_TYPE_BOOTDEV:
|
||||
case MULTIBOOT_TAG_TYPE_MMAP:
|
||||
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
|
||||
break;
|
||||
|
||||
case MULTIBOOT_TAG_TYPE_VBE:
|
||||
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
|
||||
case MULTIBOOT_TAG_TYPE_APM:
|
||||
break;
|
||||
|
||||
default:
|
||||
grub_free (buffer);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_OS,
|
||||
|
@ -274,12 +274,15 @@ grub_multiboot_get_mbi_size (void)
|
|||
+ (sizeof (struct multiboot_tag_string)
|
||||
+ ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
|
||||
+ (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
|
||||
+ sizeof (struct multiboot_tag_basic_meminfo)
|
||||
+ ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo),
|
||||
MULTIBOOT_TAG_ALIGN)
|
||||
+ ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
|
||||
+ sizeof (struct multiboot_tag_elf_sections)
|
||||
+ elf_sec_entsize * elf_sec_num
|
||||
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
|
||||
* sizeof (struct multiboot_mmap_entry))
|
||||
+ ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN)
|
||||
+ ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN)
|
||||
+ ALIGN_UP ((sizeof (struct multiboot_tag_mmap)
|
||||
+ grub_get_multiboot_mmap_count ()
|
||||
* sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
|
||||
+ ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
|
||||
+ sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1
|
||||
+ sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1;
|
||||
}
|
||||
|
@ -329,6 +332,54 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
|
|||
grub_mmap_iterate (hook);
|
||||
}
|
||||
|
||||
#if defined (GRUB_MACHINE_PCBIOS)
|
||||
static void
|
||||
fill_vbe_tag (struct multiboot_tag_vbe *tag)
|
||||
{
|
||||
grub_vbe_status_t status;
|
||||
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
|
||||
tag->type = MULTIBOOT_TAG_TYPE_VBE;
|
||||
tag->size = 0;
|
||||
|
||||
status = grub_vbe_bios_get_controller_info (scratch);
|
||||
if (status != GRUB_VBE_STATUS_OK)
|
||||
return;
|
||||
|
||||
grub_memcpy (&tag->vbe_control_info, scratch,
|
||||
sizeof (struct grub_vbe_info_block));
|
||||
|
||||
status = grub_vbe_bios_get_mode (scratch);
|
||||
tag->vbe_mode = *(grub_uint32_t *) scratch;
|
||||
if (status != GRUB_VBE_STATUS_OK)
|
||||
return;
|
||||
|
||||
/* get_mode_info isn't available for mode 3. */
|
||||
if (tag->vbe_mode == 3)
|
||||
{
|
||||
struct grub_vbe_mode_info_block *mode_info = (void *) &tag->vbe_mode_info;
|
||||
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 (tag->vbe_mode, scratch);
|
||||
if (status != GRUB_VBE_STATUS_OK)
|
||||
return;
|
||||
grub_memcpy (&tag->vbe_mode_info, scratch,
|
||||
sizeof (struct grub_vbe_mode_info_block));
|
||||
}
|
||||
grub_vbe_bios_get_pm_interface (&tag->vbe_interface_seg,
|
||||
&tag->vbe_interface_off,
|
||||
&tag->vbe_interface_len);
|
||||
|
||||
tag->size = sizeof (*tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
static grub_err_t
|
||||
retrieve_video_parameters (grub_uint8_t **ptrorig)
|
||||
{
|
||||
|
@ -417,6 +468,16 @@ retrieve_video_parameters (grub_uint8_t **ptrorig)
|
|||
return GRUB_ERR_NONE;
|
||||
#endif
|
||||
|
||||
#if GRUB_MACHINE_HAS_VBE
|
||||
{
|
||||
struct multiboot_tag_vbe *tag_vbe = (struct multiboot_tag_vbe *) *ptrorig;
|
||||
|
||||
fill_vbe_tag (tag_vbe);
|
||||
|
||||
*ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN);
|
||||
}
|
||||
#endif
|
||||
|
||||
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -482,7 +543,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
|||
|
||||
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
|
||||
0, 0xffffffff - bufsize,
|
||||
bufsize, 4,
|
||||
bufsize, MULTIBOOT_TAG_ALIGN,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -248,6 +248,32 @@ grub_vbe_bios_get_display_start (grub_uint32_t *x,
|
|||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f0a. */
|
||||
grub_vbe_status_t
|
||||
grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset,
|
||||
grub_uint16_t *length)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.eax = 0x4f0a;
|
||||
regs.ebx = 0x0000;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x10, ®s);
|
||||
|
||||
if ((regs.eax & 0xffff) != GRUB_VBE_STATUS_OK)
|
||||
{
|
||||
*segment = 0;
|
||||
*offset = 0;
|
||||
*length = 0;
|
||||
}
|
||||
|
||||
*segment = regs.es & 0xffff;
|
||||
*offset = regs.edi & 0xffff;
|
||||
*length = regs.ecx & 0xffff;
|
||||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t
|
||||
grub_vbe_probe (struct grub_vbe_info_block *info_block)
|
||||
{
|
||||
|
|
|
@ -209,6 +209,9 @@ grub_err_t grub_vbe_set_video_mode (grub_uint32_t mode,
|
|||
grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
|
||||
grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
|
||||
struct grub_vbe_mode_info_block *mode_info);
|
||||
grub_vbe_status_t
|
||||
grub_vbe_bios_get_pm_interface (grub_uint16_t *seg, grub_uint16_t *offset,
|
||||
grub_uint16_t *length);
|
||||
|
||||
|
||||
#endif /* ! GRUB_VBE_MACHINE_HEADER */
|
||||
|
|
|
@ -56,8 +56,10 @@ grub_err_t grub_multiboot_set_video_mode (void);
|
|||
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
|
||||
#include <grub/i386/pc/vbe.h>
|
||||
#define GRUB_MACHINE_HAS_VGA_TEXT 1
|
||||
#define GRUB_MACHINE_HAS_VBE 1
|
||||
#else
|
||||
#define GRUB_MACHINE_HAS_VGA_TEXT 0
|
||||
#define GRUB_MACHINE_HAS_VBE 0
|
||||
#endif
|
||||
|
||||
#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1
|
||||
|
|
Loading…
Reference in a new issue