Hi,

MacBooks 5.x supports the new graphics output protocol in UEFI, while
the older UGA draw protocol doesn't work anymore. This patch add
support for graphics output protocol so that linux loader can get
video information correctly.

-- 
Bean
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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_GRAPHICS_OUTPUT_HEADER
+#define GRUB_EFI_GRAPHICS_OUTPUT_HEADER	1
+
+#include <grub/efi/uga_draw.h>
+
+#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 <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/uga_draw.h>
+#include <grub/efi/graphics_output.h>
 #include <grub/pci.h>
 #include <grub/command.h>
 #include <grub/memory.h>
@@ -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: %ux%u...@%u\n", 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;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to