diff --git a/include/grub/efi/graphics_output.h b/include/grub/efi/graphics_output.h
new file mode 100644
index 0000000..a100c09
--- /dev/null
+++ b/include/grub/efi/graphics_output.h
@@ -0,0 +1,92 @@
+/* graphics_output.h - definitions of the graphics output protocol */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_EFI_GRAPHICS_OUTPUT_HEADER
+#define GRUB_EFI_GRAPHICS_OUTPUT_HEADER 1
+
+#include
+
+#define GRUB_EFI_GRAPHICS_OUTPUT_GUID \
+ { 0x9042a9de, 0x23dc, 0x4a38, { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a }}
+
+struct grub_efi_pixel_bitmask
+{
+ grub_uint32_t red_mask;
+ grub_uint32_t green_mask;
+ grub_uint32_t blue_mask;
+ grub_uint32_t reserved_mask;
+};
+
+enum grub_efi_graphics_pixel_format
+ {
+ GRUB_EFI_PIXEL_RGB_RESERVED_8BIT_PER_COLOR,
+ GRUB_EFI_PIXEL_BGR_RESERVED_8BIT_PER_COLOR,
+ GRUB_EFI_PIXEL_BIT_MASK,
+ GRUB_EFI_PIXEL_BLT_ONLY,
+ GRUB_EFI_PIXEL_FORMAT_MAX
+ };
+
+struct grub_efi_graphics_output_mode_information
+{
+ grub_uint32_t version;
+ grub_uint32_t horizontal_resolution;
+ grub_uint32_t vertical_resolution;
+ enum grub_efi_graphics_pixel_format pixel_format;
+ struct grub_efi_pixel_bitmask pixel_information;
+ grub_uint32_t pixels_per_scan_line;
+};
+
+struct grub_efi_graphics_output_mode
+{
+ grub_uint32_t max_mode;
+ grub_uint32_t mode;
+ struct grub_efi_graphics_output_mode_information *info;
+ grub_efi_uintn_t size_of_info;
+ grub_efi_physical_address_t frame_buffer_base;
+ grub_efi_uintn_t frame_buffer_size;
+};
+
+struct grub_efi_graphics_output_protocol
+{
+ grub_efi_status_t
+ (*query_mode) (struct grub_efi_graphics_output_protocol *this,
+ grub_uint32_t mode_number,
+ grub_efi_uintn_t *size_of_info,
+ struct grub_efi_graphics_output_mode_information **info);
+
+ grub_efi_status_t
+ (*set_mode) (struct grub_efi_graphics_output_protocol *this,
+ grub_uint32_t mode_number);
+
+ grub_efi_status_t
+ (*blt) (struct grub_efi_uga_draw_protocol *this,
+ struct grub_efi_uga_pixel *blt_buffer,
+ enum grub_efi_uga_blt_operation blt_operation,
+ grub_efi_uintn_t src_x,
+ grub_efi_uintn_t src_y,
+ grub_efi_uintn_t dest_x,
+ grub_efi_uintn_t dest_y,
+ grub_efi_uintn_t width,
+ grub_efi_uintn_t height,
+ grub_efi_uintn_t delta);
+
+ struct grub_efi_graphics_output_mode *mode;
+};
+
+#endif
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index f96c60e..8d3b555 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -425,7 +426,7 @@ grub_linux_unload (void)
}
static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
-
+static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GRAPHICS_OUTPUT_GUID;
#define RGB_MASK 0xffffff
#define RGB_MAGIC 0x121314
@@ -539,32 +540,55 @@ find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
static int
grub_linux_setup_video (struct linux_kernel_params *params)
{
- grub_efi_uga_draw_protocol_t *c;
- grub_uint32_t width, height, depth, rate, pixel, fb_base, line_len;
+ struct grub_efi_graphics_output_protocol *gop;
+ grub_uint32_t width, height, depth, fb_base, fb_size, line_len;
int ret;
- c = grub_efi_locate_protocol (&uga_draw_guid, 0);
- if (! c)
- return 1;
+ gop = grub_efi_locate_protocol (&graphics_output_guid, 0);
+ if (gop)
+ {
+ width = gop->mode->info->horizontal_resolution;
+ height = gop->mode->info->vertical_resolution;
+ depth = 32;
+ line_len = 4 * gop->mode->info->pixels_per_scan_line;
+ fb_base = gop->mode->frame_buffer_base;
+ fb_size = gop->mode->frame_buffer_size;
+ }
+ else
+ {
+ grub_efi_uga_draw_protocol_t *c;
+ grub_uint32_t rate, pixel;
+
+ c = grub_efi_locate_protocol (&uga_draw_guid, 0);
+ if (! c)
+ {
+ grub_printf ("Can\'t locate uga protocol\n");
+ return 1;
+ }
- if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
- return 1;
+ if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
+ {
+ grub_printf ("Can\'t get mode\n");
+ return 1;
+ }
- grub_printf ("Video mode: address@hidden", width, height, depth, rate);
+ grub_efi_set_text_mode (0);
+ pixel = RGB_MAGIC;
+ efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
+ GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
+ ret = find_framebuf (&fb_base, &line_len);
+ grub_efi_set_text_mode (1);
- grub_efi_set_text_mode (0);
- pixel = RGB_MAGIC;
- efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
- GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
- ret = find_framebuf (&fb_base, &line_len);
- grub_efi_set_text_mode (1);
+ if (! ret)
+ {
+ grub_printf ("Can\'t find frame buffer address\n");
+ return 1;
+ }
- if (! ret)
- {
- grub_printf ("Can\'t find frame buffer address\n");
- return 1;
+ fb_size = (line_len * params->lfb_height + 65535) >> 16;
}
+ grub_printf ("Video mode: %ux%u-%u\n", width, height, depth);
grub_printf ("Frame buffer base: 0x%x\n", fb_base);
grub_printf ("Video line length: %d\n", line_len);
@@ -574,7 +598,7 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->lfb_line_len = line_len;
params->lfb_base = fb_base;
- params->lfb_size = (line_len * params->lfb_height + 65535) >> 16;
+ params->lfb_size = fb_size;
params->red_mask_size = 8;
params->red_field_pos = 16;