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;