From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Multiboot video support
Date: Thu, 14 Jan 2010 15:55:25 +0100 [thread overview]
Message-ID: <4B4F305D.3080200@gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 58 bytes --]
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: mbivid.diff --]
[-- Type: text/x-diff; name="mbivid.diff", Size: 17128 bytes --]
=== added file 'ChangeLog.mbivid'
--- ChangeLog.mbivid 1970-01-01 00:00:00 +0000
+++ ChangeLog.mbivid 2010-01-14 14:44:14 +0000
@@ -0,0 +1,24 @@
+2010-01-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Video multiboot support.
+
+ * include/grub/multiboot.h (grub_multiboot_set_accepts_video):
+ New prototype.
+ * include/grub/video.h (grub_video_driver_id): New type.
+ (grub_video_adapter): New member 'id'. All users updated.
+ (grub_video_get_driver_id): New proto.
+ * include/multiboot.h: Resynced with multiboot specification.
+ * include/multiboot2.h: Likewise.
+ * loader/i386/multiboot.c (UNSUPPORTED_FLAGS): Support video flags.
+ (grub_multiboot): Parse MULTIBOOT_VIDEO_MODE fields.
+ * loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): New constant.
+ (HAS_VGA_TEXT): Likewise.
+ (HAS_VBE): Likewise.
+ (accepts_video): New variable.
+ (grub_multiboot_set_accepts_video): New function.
+ (grub_multiboot_get_mbi_size): Account for video structures.
+ (set_video_mode): New function.
+ (fill_vbe_info) [HAS_VBE]: Likewise.
+ (retrieve_video_parameters): Likewise.
+ (grub_multiboot_make_mbi): Fill video fields.
+ * video/video.c (grub_video_get_driver_id): New function.
=== modified file 'include/grub/multiboot.h'
--- include/grub/multiboot.h 2010-01-10 17:58:18 +0000
+++ include/grub/multiboot.h 2010-01-14 14:26:47 +0000
@@ -35,6 +35,8 @@
void grub_multiboot (int argc, char *argv[]);
void grub_module (int argc, char *argv[]);
+void grub_multiboot_set_accepts_video (int val);
+
grub_size_t grub_multiboot_get_mbi_size (void);
grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
grub_off_t buf_off, grub_size_t bufsize);
=== modified file 'include/grub/video.h'
--- include/grub/video.h 2009-08-14 12:41:58 +0000
+++ include/grub/video.h 2010-01-14 14:22:33 +0000
@@ -159,10 +159,19 @@
grub_uint8_t a; /* Reserved bits value (0-255). */
};
+typedef enum grub_video_driver_id
+ {
+ GRUB_VIDEO_DRIVER_NONE,
+ GRUB_VIDEO_DRIVER_VBE,
+ GRUB_VIDEO_DRIVER_EFI_UGA,
+ GRUB_VIDEO_DRIVER_EFI_GOP
+ } grub_video_driver_id_t;
+
struct grub_video_adapter
{
/* The video adapter name. */
const char *name;
+ grub_video_driver_id_t id;
/* Initialize the video adapter. */
grub_err_t (*init) (void);
@@ -310,4 +319,7 @@
int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
struct grub_video_mode_info *mode_info));
+grub_video_driver_id_t
+grub_video_get_driver_id (void);
+
#endif /* ! GRUB_VIDEO_HEADER */
=== modified file 'include/multiboot.h'
--- include/multiboot.h 2010-01-07 19:55:16 +0000
+++ include/multiboot.h 2010-01-14 14:22:27 +0000
@@ -85,10 +85,12 @@
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
-#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+#define MULTIBOOT_INFO_VBE_INFO 0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
+typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
@@ -187,9 +189,43 @@
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+ multiboot_uint8_t framebuffer_type;
+ union
+ {
+ struct
+ {
+ multiboot_uint32_t framebuffer_palette_addr;
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
};
typedef struct multiboot_info multiboot_info_t;
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
=== modified file 'include/multiboot2.h'
--- include/multiboot2.h 2010-01-07 21:05:25 +0000
+++ include/multiboot2.h 2010-01-14 14:22:27 +0000
@@ -85,10 +85,12 @@
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
-#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+#define MULTIBOOT_INFO_VBE_INFO 0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
+typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
@@ -187,9 +189,43 @@
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+ multiboot_uint8_t framebuffer_type;
+ union
+ {
+ struct
+ {
+ multiboot_uint32_t framebuffer_palette_addr;
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
};
typedef struct multiboot_info multiboot_info_t;
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c 2010-01-12 18:47:02 +0000
+++ loader/i386/multiboot.c 2010-01-14 14:22:27 +0000
@@ -20,7 +20,6 @@
/*
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
- * - VBE support
* - symbol table
* - drives table
* - ROM configuration table
@@ -28,13 +27,11 @@
*/
/* The bits in the required part of flags field we don't support. */
-#define UNSUPPORTED_FLAGS 0x0000fffc
+#define UNSUPPORTED_FLAGS 0x0000fff8
#include <grub/loader.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
-#include <grub/machine/init.h>
-#include <grub/machine/memory.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
#include <grub/aout.h>
@@ -232,6 +229,34 @@
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail;
+ if (header->flags & MULTIBOOT_VIDEO_MODE)
+ {
+ switch (header->mode_type)
+ {
+ case 1:
+ grub_env_set ("gfxpayload", "text");
+ break;
+
+ case 0:
+ {
+ char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")];
+ if (header->depth && header->width && header->height)
+ grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width,
+ header->height, header->depth, header->width,
+ header->height);
+ else if (header->width && header->height)
+ grub_sprintf (buf, "%dx%d,auto", header->width, header->height);
+ else
+ grub_sprintf (buf, "auto");
+
+ grub_env_set ("gfxpayload", buf);
+ break;
+ }
+ }
+ }
+
+ grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
+
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
=== modified file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c 2010-01-10 17:58:18 +0000
+++ loader/i386/multiboot_mbi.c 2010-01-14 14:29:26 +0000
@@ -29,6 +29,18 @@
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
+#include <grub/video.h>
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+#include <grub/i386/pc/vbe.h>
+#define DEFAULT_VIDEO_MODE "text"
+#define HAS_VGA_TEXT 1
+#define HAS_VBE 1
+#else
+#define DEFAULT_VIDEO_MODE "auto"
+#define HAS_VGA_TEXT 0
+#define HAS_VBE 0
+#endif
struct module
{
@@ -46,6 +58,13 @@
static char *cmdline = NULL;
static grub_uint32_t bootdev;
static int bootdev_set;
+static int accepts_video;
+
+void
+grub_multiboot_set_accepts_video (int val)
+{
+ accepts_video = val;
+}
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
@@ -73,7 +92,12 @@
{
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
- + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ();
+ + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+#if HAS_VBE
+ + sizeof (struct grub_vbe_info_block)
+ + sizeof (struct grub_vbe_mode_info_block)
+#endif
+ + 256 * sizeof (struct multiboot_color);
}
/* Fill previously allocated Multiboot mmap. */
@@ -106,6 +130,160 @@
grub_mmap_iterate (hook);
}
+static grub_err_t
+set_video_mode (void)
+{
+ grub_err_t err;
+ const char *modevar;
+
+ if (accepts_video || !HAS_VGA_TEXT)
+ {
+ modevar = grub_env_get ("gfxpayload");
+ if (! modevar || *modevar == 0)
+ err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+ else
+ {
+ char *tmp;
+ tmp = grub_malloc (grub_strlen (modevar)
+ + sizeof (DEFAULT_VIDEO_MODE) + 1);
+ if (! tmp)
+ return grub_errno;
+ grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+ err = grub_video_set_mode (tmp, 0);
+ grub_free (tmp);
+ }
+ }
+ else
+ err = grub_video_set_mode ("text", 0);
+
+ return err;
+}
+
+#if HAS_VBE
+static grub_err_t
+fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
+ grub_uint32_t ptrdest)
+{
+ grub_vbe_status_t status;
+ grub_uint32_t vbe_mode;
+ void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+ 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;
+
+ 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.");
+ mbi->vbe_mode_info = ptrdest;
+ grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_mode_info_block));
+ ptrorig += sizeof (struct grub_vbe_mode_info_block);
+ ptrdest += sizeof (struct grub_vbe_mode_info_block);
+
+ /* FIXME: retrieve those. */
+ mbi->vbe_interface_seg = 0;
+ mbi->vbe_interface_off = 0;
+ mbi->vbe_interface_len = 0;
+
+ mbi->flags |= MULTIBOOT_INFO_VBE_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)
+{
+ grub_err_t err;
+ struct grub_video_mode_info mode_info;
+ void *framebuffer;
+#if HAS_VBE
+ int vbe_active;
+#endif
+ struct grub_video_palette_data palette[256];
+
+ err = set_video_mode ();
+ if (err)
+ return err;
+
+ 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));
+ }
+#endif
+
+ err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
+ if (err)
+ return err;
+
+ mbi->framebuffer_addr = (grub_addr_t) framebuffer;
+ mbi->framebuffer_pitch = mode_info.pitch;
+
+ mbi->framebuffer_width = mode_info.width;
+ mbi->framebuffer_height = mode_info.height;
+
+ mbi->framebuffer_bpp = mode_info.bpp;
+
+ if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
+ {
+ struct multiboot_color *mb_palette;
+ unsigned i;
+ mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
+ mbi->framebuffer_palette_addr = ptrdest;
+ mbi->framebuffer_palette_num_colors = mode_info.number_of_colors;
+ if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
+ mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
+ mb_palette = (struct multiboot_color *) ptrorig;
+ for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
+ {
+ mb_palette[i].red = palette[i].r;
+ mb_palette[i].green = palette[i].g;
+ mb_palette[i].blue = palette[i].b;
+ }
+ ptrorig += mbi->framebuffer_palette_num_colors
+ * sizeof (struct multiboot_color);
+ ptrdest += mbi->framebuffer_palette_num_colors
+ * sizeof (struct multiboot_color);
+ }
+ else
+ {
+ mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+ mbi->framebuffer_red_field_position = mode_info.green_field_pos;
+ mbi->framebuffer_red_mask_size = mode_info.green_mask_size;
+ mbi->framebuffer_green_field_position = mode_info.green_field_pos;
+ mbi->framebuffer_green_mask_size = mode_info.green_mask_size;
+ mbi->framebuffer_blue_field_position = mode_info.blue_field_pos;
+ mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size;
+ }
+
+ mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+
+#if HAS_VBE
+ if (vbe_active)
+ fill_vbe_info (mbi, ptrorig, ptrdest);
+#endif
+
+ return GRUB_ERR_NONE;
+}
+
grub_err_t
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
grub_size_t bufsize)
@@ -117,6 +295,7 @@
unsigned i;
struct module *cur;
grub_size_t mmap_size;
+ grub_err_t err;
if (bufsize < grub_multiboot_get_mbi_size ())
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
@@ -182,6 +361,19 @@
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
}
+ err = retrieve_video_parameters (mbi, ptrorig, ptrdest);
+ if (err)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+#if 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;
}
=== modified file 'video/efi_gop.c'
--- video/efi_gop.c 2009-12-24 22:53:05 +0000
+++ video/efi_gop.c 2010-01-14 14:22:33 +0000
@@ -353,6 +353,7 @@
static struct grub_video_adapter grub_video_gop_adapter =
{
.name = "EFI GOP driver",
+ .id = GRUB_VIDEO_DRIVER_EFI_GOP,
.init = grub_video_gop_init,
.fini = grub_video_gop_fini,
=== modified file 'video/efi_uga.c'
--- video/efi_uga.c 2009-12-24 22:53:05 +0000
+++ video/efi_uga.c 2010-01-14 14:22:33 +0000
@@ -300,6 +300,7 @@
static struct grub_video_adapter grub_video_uga_adapter =
{
.name = "EFI UGA driver",
+ .id = GRUB_VIDEO_DRIVER_EFI_UGA,
.init = grub_video_uga_init,
.fini = grub_video_uga_fini,
=== modified file 'video/i386/pc/vbe.c'
--- video/i386/pc/vbe.c 2009-12-24 22:53:05 +0000
+++ video/i386/pc/vbe.c 2010-01-14 14:22:33 +0000
@@ -557,6 +557,7 @@
static struct grub_video_adapter grub_video_vbe_adapter =
{
.name = "VESA BIOS Extension Video Driver",
+ .id = GRUB_VIDEO_DRIVER_VBE,
.init = grub_video_vbe_init,
.fini = grub_video_vbe_fini,
=== modified file 'video/video.c'
--- video/video.c 2009-12-24 22:53:05 +0000
+++ video/video.c 2010-01-14 14:22:33 +0000
@@ -93,6 +93,14 @@
return grub_video_adapter_active->get_info (mode_info);
}
+grub_video_driver_id_t
+grub_video_get_driver_id (void)
+{
+ if (! grub_video_adapter_active)
+ return GRUB_VIDEO_DRIVER_NONE;
+ return grub_video_adapter_active->id;
+}
+
/* Get information about active video mode. */
grub_err_t
grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]
next reply other threads:[~2010-01-14 14:55 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-14 14:55 Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2010-01-15 14:50 ` [PATCH] Multiboot video support Vladimir 'phi-coder/phcoder' Serbinenko
2010-01-15 15:44 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-19 22:41 ` Robert Millan
2010-01-20 11:43 ` Michal Suchanek
2010-01-24 19:02 ` Robert Millan
2010-01-24 21:05 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-24 23:29 ` Michal Suchanek
2010-01-25 7:37 ` Robert Millan
2010-01-25 9:26 ` Michal Suchanek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B4F305D.3080200@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.