From e03f549b3e11018b0ec0f44465f6bf5ca98ca993 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 16:22:19 +0000 Subject: [PATCH 01/10] Preferred resolution detection for VBE. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): New function. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. (grub_vbe_edid_checksum): Likewise. (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. (grub_video_vbe_setup): When the mode is "auto", try to get the preferred mode from VBE, and use the largest mode that is no larger than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. (struct grub_vbe_edid_info): Likewise. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. --- ChangeLog.vbe-autodetect | 25 ++++++ grub-core/video/i386/pc/vbe.c | 150 +++++++++++++++++++++++++++++++++- include/grub/i386/pc/vbe.h | 84 +++++++++++++++++++ util/grub.d/00_header.in | 2 +- 4 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 ChangeLog.vbe-autodetect diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect new file mode 100644 index 000000000..7d16ebee2 --- /dev/null +++ b/ChangeLog.vbe-autodetect @@ -0,0 +1,25 @@ +2010-12-14 Colin Watson + + Preferred resolution detection for VBE. + + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): + New function. + (grub_vbe_bios_get_ddc_capabilities): Likewise. + (grub_vbe_bios_read_edid): Likewise. + (grub_vbe_edid_checksum): Likewise. + (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the + Flat Panel extension, in line with the X.org VESA driver. + (grub_video_vbe_setup): When the mode is "auto", try to get the + preferred mode from VBE, and use the largest mode that is no larger + than the preferred mode (some BIOSes expose a preferred mode that is + not in their mode list!). If this fails, fall back to 640x480 as a + safe conservative choice. + * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New + structure. + (struct grub_vbe_edid_info): Likewise. + (grub_vbe_bios_get_flat_panel_info): Add prototype. + (grub_vbe_bios_get_ddc_capabilities): Likewise. + (grub_vbe_bios_read_edid): Likewise. + + * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This + is more appropriate on a wider range of platforms than 640x480. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 2ddb4ca80..1794addae 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -273,6 +273,56 @@ grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset, return regs.eax & 0xffff; } +/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f11; + regs.ebx = 0x0001; + regs.es = (((grub_addr_t) flat_panel_info) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) flat_panel_info) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f15; + regs.ebx = 0x0000; + regs.ecx = 0x0000; + regs.es = 0x0000; + regs.edi = 0x0000; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + *level = regs.ebx & 0xff; + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ +grub_vbe_status_t +grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_info) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f15; + regs.ebx = 0x0001; + regs.ecx = 0x0000; + regs.edx = 0x0000; + regs.es = (((grub_addr_t) edid_info) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) edid_info) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block) @@ -327,6 +377,70 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } +static grub_err_t +grub_vbe_edid_checksum (struct grub_vbe_edid_info *edid_info) +{ + const char *edid_bytes = (const char *) edid_info; + int i; + char checksum = 0; + + /* Check EDID checksum. */ + for (i = 0; i < 128; ++i) + checksum += edid_bytes[i]; + + if (checksum != 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + "invalid EDID checksum %d", checksum); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + +static grub_err_t +grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) +{ + grub_vbe_status_t status; + grub_uint8_t ddc_level; + struct grub_vbe_edid_info edid_info; + struct grub_vbe_flat_panel_info flat_panel_info; + + if (controller_info.version >= 0x200 + && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) + == GRUB_VBE_STATUS_OK) + { + status = grub_vbe_bios_read_edid (&edid_info); + /* Bit 1 in the Feature Support field indicates that the first + Detailed Timing Description is the preferred timing mode. */ + if (status == GRUB_VBE_STATUS_OK + && grub_vbe_edid_checksum (&edid_info) == GRUB_ERR_NONE + && edid_info.version == 1 /* we don't understand later versions */ + && (edid_info.feature_support + & GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE) + && edid_info.detailed_timings[0].pixel_clock) + { + *width = edid_info.detailed_timings[0].horizontal_active_lo + | (((unsigned int) + (edid_info.detailed_timings[0].horizontal_hi & 0xf0)) + << 4); + *height = edid_info.detailed_timings[0].vertical_active_lo + | (((unsigned int) + (edid_info.detailed_timings[0].vertical_hi & 0xf0)) + << 4); + return GRUB_ERR_NONE; + } + } + + status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); + if (status == GRUB_VBE_STATUS_OK) + { + *width = flat_panel_info.horizontal_size; + *height = flat_panel_info.vertical_size; + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot get preferred mode"); +} + grub_err_t grub_vbe_set_video_mode (grub_uint32_t vbe_mode, struct grub_vbe_mode_info_block *vbe_mode_info) @@ -695,11 +809,28 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, struct grub_vbe_mode_info_block best_vbe_mode_info; grub_uint32_t best_vbe_mode = 0; int depth; + int preferred_mode = 0; /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + if (width == 0 && height == 0) + { + grub_vbe_get_preferred_mode (&width, &height); + if (grub_errno == GRUB_ERR_NONE) + preferred_mode = 1; + else + { + /* Fall back to 640x480. This is conservative, but the largest + mode supported by the graphics card may not be safe for the + display device. */ + grub_errno = GRUB_ERR_NONE; + width = 640; + height = 480; + } + } + /* Walk thru mode list and try to find matching mode. */ for (p = vbe_mode_list; *p != 0xFFFF; p++) { @@ -742,10 +873,21 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Unsupported bitdepth . */ continue; - if (((vbe_mode_info.x_resolution != width) - || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) - /* Non matching resolution. */ - continue; + if (preferred_mode) + { + if (vbe_mode_info.x_resolution > width + || vbe_mode_info.y_resolution > height) + /* Resolution exceeds that of preferred mode. */ + continue; + } + else + { + if (((vbe_mode_info.x_resolution != width) + || (vbe_mode_info.y_resolution != height)) + && width != 0 && height != 0) + /* Non matching resolution. */ + continue; + } /* Check if user requested RGB or index color mode. */ if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index fba3ee642..5be34fdec 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -169,6 +169,81 @@ struct grub_vbe_palette_data grub_uint8_t alignment; } __attribute__ ((packed)); +struct grub_vbe_flat_panel_info +{ + grub_uint16_t horizontal_size; + grub_uint16_t vertical_size; + grub_uint16_t panel_type; + grub_uint8_t red_bpp; + grub_uint8_t green_bpp; + grub_uint8_t blue_bpp; + grub_uint8_t reserved_bpp; + grub_uint32_t reserved_offscreen_mem_size; + grub_vbe_farptr_t reserved_offscreen_mem_ptr; + + grub_uint8_t reserved[14]; +} __attribute__ ((packed)); + +struct grub_vbe_edid_info +{ + grub_uint8_t header[8]; + grub_uint16_t manufacturer_id; + grub_uint16_t product_id; + grub_uint32_t serial_number; + grub_uint8_t week_of_manufacture; + grub_uint8_t year_of_manufacture; + grub_uint8_t version; + grub_uint8_t revision; + + grub_uint8_t video_input_definition; + grub_uint8_t max_horizontal_image_size; + grub_uint8_t max_vertical_image_size; + grub_uint8_t display_gamma; + grub_uint8_t feature_support; +#define GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) + + grub_uint8_t red_green_lo; + grub_uint8_t blue_white_lo; + grub_uint8_t red_x_hi; + grub_uint8_t red_y_hi; + grub_uint8_t green_x_hi; + grub_uint8_t green_y_hi; + grub_uint8_t blue_x_hi; + grub_uint8_t blue_y_hi; + grub_uint8_t white_x_hi; + grub_uint8_t white_y_hi; + + grub_uint8_t established_timings_1; + grub_uint8_t established_timings_2; + grub_uint8_t manufacturer_reserved_timings; + + grub_uint16_t standard_timings[8]; + + struct { + grub_uint16_t pixel_clock; + /* Only valid if the pixel clock is non-null. */ + grub_uint8_t horizontal_active_lo; + grub_uint8_t horizontal_blanking_lo; + grub_uint8_t horizontal_hi; + grub_uint8_t vertical_active_lo; + grub_uint8_t vertical_blanking_lo; + grub_uint8_t vertical_hi; + grub_uint8_t horizontal_sync_offset_lo; + grub_uint8_t horizontal_sync_pulse_width_lo; + grub_uint8_t vertical_sync_lo; + grub_uint8_t sync_hi; + grub_uint8_t horizontal_image_size_lo; + grub_uint8_t vertical_image_size_lo; + grub_uint8_t image_size_hi; + grub_uint8_t horizontal_border; + grub_uint8_t vertical_border; + grub_uint8_t flags; + } detailed_timings[4]; + + grub_uint8_t extension_flag; + grub_uint8_t checksum; +} __attribute__ ((packed)); + /* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ grub_vbe_status_t @@ -197,6 +272,15 @@ grub_vbe_bios_get_scanline_length (grub_uint32_t *length); grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x, grub_uint32_t *y); +/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info); +/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); +/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ +grub_vbe_status_t +grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index a596e9c4a..55c686296 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -36,7 +36,7 @@ done if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi -if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi +if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=auto ; fi if [ "x${GRUB_DEFAULT_BUTTON}" = "x" ] ; then GRUB_DEFAULT_BUTTON="$GRUB_DEFAULT" ; fi if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_entry}' ; fi From 25d884a52a1819792bc97cac9890d44a72446b7c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 17:06:32 +0000 Subject: [PATCH 02/10] move generic parts of EDID handling (structure, checksumming) to generic location --- ChangeLog.vbe-autodetect | 7 ++-- grub-core/video/i386/pc/vbe.c | 27 +++------------ grub-core/video/video.c | 19 +++++++++++ include/grub/i386/pc/vbe.h | 64 ++--------------------------------- include/grub/video.h | 62 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 87 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 7d16ebee2..0d96fc0a2 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -2,11 +2,11 @@ Preferred resolution detection for VBE. + * grub-core/video/video.c (grub_video_edid_checksum): New function. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - New function. + Likewise. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_edid_checksum): Likewise. (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. (grub_video_vbe_setup): When the mode is "auto", try to get the @@ -14,9 +14,10 @@ than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. + * include/grub/video.h (struct grub_vbe_edid_info): New structure. + (grub_video_edid_checksum): Add prototype. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. - (struct grub_vbe_edid_info): Likewise. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 1794addae..e2dcc151e 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -308,7 +308,7 @@ grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_info) +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info) { struct grub_bios_int_registers regs; @@ -377,31 +377,12 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } -static grub_err_t -grub_vbe_edid_checksum (struct grub_vbe_edid_info *edid_info) -{ - const char *edid_bytes = (const char *) edid_info; - int i; - char checksum = 0; - - /* Check EDID checksum. */ - for (i = 0; i < 128; ++i) - checksum += edid_bytes[i]; - - if (checksum != 0) - return grub_error (GRUB_ERR_BAD_DEVICE, - "invalid EDID checksum %d", checksum); - - grub_errno = GRUB_ERR_NONE; - return grub_errno; -} - static grub_err_t grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) { grub_vbe_status_t status; grub_uint8_t ddc_level; - struct grub_vbe_edid_info edid_info; + struct grub_video_edid_info edid_info; struct grub_vbe_flat_panel_info flat_panel_info; if (controller_info.version >= 0x200 @@ -412,10 +393,10 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) /* Bit 1 in the Feature Support field indicates that the first Detailed Timing Description is the preferred timing mode. */ if (status == GRUB_VBE_STATUS_OK - && grub_vbe_edid_checksum (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE && edid_info.version == 1 /* we don't understand later versions */ && (edid_info.feature_support - & GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE) + & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) && edid_info.detailed_timings[0].pixel_clock) { *width = edid_info.detailed_timings[0].horizontal_active_lo diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 7a1a446e4..f3ecab94d 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -374,6 +374,25 @@ grub_video_get_active_render_target (struct grub_video_render_target **target) return grub_video_adapter_active->get_active_render_target (target); } +grub_err_t +grub_video_edid_checksum (struct grub_video_edid_info *edid_info) +{ + const char *edid_bytes = (const char *) edid_info; + int i; + char checksum = 0; + + /* Check EDID checksum. */ + for (i = 0; i < 128; ++i) + checksum += edid_bytes[i]; + + if (checksum != 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + "invalid EDID checksum %d", checksum); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + /* Parse x[x]*/ static grub_err_t parse_modespec (const char *current_mode, int *width, int *height, int *depth) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 5be34fdec..0422558db 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -19,6 +19,8 @@ #ifndef GRUB_VBE_MACHINE_HEADER #define GRUB_VBE_MACHINE_HEADER 1 +#include + /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 @@ -184,66 +186,6 @@ struct grub_vbe_flat_panel_info grub_uint8_t reserved[14]; } __attribute__ ((packed)); -struct grub_vbe_edid_info -{ - grub_uint8_t header[8]; - grub_uint16_t manufacturer_id; - grub_uint16_t product_id; - grub_uint32_t serial_number; - grub_uint8_t week_of_manufacture; - grub_uint8_t year_of_manufacture; - grub_uint8_t version; - grub_uint8_t revision; - - grub_uint8_t video_input_definition; - grub_uint8_t max_horizontal_image_size; - grub_uint8_t max_vertical_image_size; - grub_uint8_t display_gamma; - grub_uint8_t feature_support; -#define GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) - - grub_uint8_t red_green_lo; - grub_uint8_t blue_white_lo; - grub_uint8_t red_x_hi; - grub_uint8_t red_y_hi; - grub_uint8_t green_x_hi; - grub_uint8_t green_y_hi; - grub_uint8_t blue_x_hi; - grub_uint8_t blue_y_hi; - grub_uint8_t white_x_hi; - grub_uint8_t white_y_hi; - - grub_uint8_t established_timings_1; - grub_uint8_t established_timings_2; - grub_uint8_t manufacturer_reserved_timings; - - grub_uint16_t standard_timings[8]; - - struct { - grub_uint16_t pixel_clock; - /* Only valid if the pixel clock is non-null. */ - grub_uint8_t horizontal_active_lo; - grub_uint8_t horizontal_blanking_lo; - grub_uint8_t horizontal_hi; - grub_uint8_t vertical_active_lo; - grub_uint8_t vertical_blanking_lo; - grub_uint8_t vertical_hi; - grub_uint8_t horizontal_sync_offset_lo; - grub_uint8_t horizontal_sync_pulse_width_lo; - grub_uint8_t vertical_sync_lo; - grub_uint8_t sync_hi; - grub_uint8_t horizontal_image_size_lo; - grub_uint8_t vertical_image_size_lo; - grub_uint8_t image_size_hi; - grub_uint8_t horizontal_border; - grub_uint8_t vertical_border; - grub_uint8_t flags; - } detailed_timings[4]; - - grub_uint8_t extension_flag; - grub_uint8_t checksum; -} __attribute__ ((packed)); - /* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ grub_vbe_status_t @@ -280,7 +222,7 @@ grub_vbe_status_t grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_data); +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); diff --git a/include/grub/video.h b/include/grub/video.h index 97bd85bd1..2cf1424c4 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -210,6 +210,66 @@ struct grub_video_palette_data grub_uint8_t a; /* Reserved bits value (0-255). */ }; +struct grub_video_edid_info +{ + grub_uint8_t header[8]; + grub_uint16_t manufacturer_id; + grub_uint16_t product_id; + grub_uint32_t serial_number; + grub_uint8_t week_of_manufacture; + grub_uint8_t year_of_manufacture; + grub_uint8_t version; + grub_uint8_t revision; + + grub_uint8_t video_input_definition; + grub_uint8_t max_horizontal_image_size; + grub_uint8_t max_vertical_image_size; + grub_uint8_t display_gamma; + grub_uint8_t feature_support; +#define GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) + + grub_uint8_t red_green_lo; + grub_uint8_t blue_white_lo; + grub_uint8_t red_x_hi; + grub_uint8_t red_y_hi; + grub_uint8_t green_x_hi; + grub_uint8_t green_y_hi; + grub_uint8_t blue_x_hi; + grub_uint8_t blue_y_hi; + grub_uint8_t white_x_hi; + grub_uint8_t white_y_hi; + + grub_uint8_t established_timings_1; + grub_uint8_t established_timings_2; + grub_uint8_t manufacturer_reserved_timings; + + grub_uint16_t standard_timings[8]; + + struct { + grub_uint16_t pixel_clock; + /* Only valid if the pixel clock is non-null. */ + grub_uint8_t horizontal_active_lo; + grub_uint8_t horizontal_blanking_lo; + grub_uint8_t horizontal_hi; + grub_uint8_t vertical_active_lo; + grub_uint8_t vertical_blanking_lo; + grub_uint8_t vertical_hi; + grub_uint8_t horizontal_sync_offset_lo; + grub_uint8_t horizontal_sync_pulse_width_lo; + grub_uint8_t vertical_sync_lo; + grub_uint8_t sync_hi; + grub_uint8_t horizontal_image_size_lo; + grub_uint8_t vertical_image_size_lo; + grub_uint8_t image_size_hi; + grub_uint8_t horizontal_border; + grub_uint8_t vertical_border; + grub_uint8_t flags; + } detailed_timings[4]; + + grub_uint8_t extension_flag; + grub_uint8_t checksum; +} __attribute__ ((packed)); + typedef enum grub_video_driver_id { GRUB_VIDEO_DRIVER_NONE, @@ -423,6 +483,8 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); +grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); + grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modemask, unsigned int modevalue); From 129185cfaae5969be4e49f5d898ed553b18d8502 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 18:03:34 +0000 Subject: [PATCH 03/10] move more EDID-handling functions to generic code, and make videoinfo display EDID information --- ChangeLog.vbe-autodetect | 15 +++++++++--- grub-core/commands/videoinfo.c | 31 ++++++++++++++++++++++++ grub-core/video/i386/pc/vbe.c | 36 +++++++++++++--------------- grub-core/video/video.c | 43 ++++++++++++++++++++++++++++++++++ include/grub/video.h | 6 +++++ 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 0d96fc0a2..355ce00f6 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -3,24 +3,33 @@ Preferred resolution detection for VBE. * grub-core/video/video.c (grub_video_edid_checksum): New function. + (grub_video_get_edid): Likewise. + (grub_video_edid_preferred_mode): Likewise. Try EDID followed by + the Flat Panel extension, in line with the X.org VESA driver. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - Likewise. + New function. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the - Flat Panel extension, in line with the X.org VESA driver. + (grub_vbe_get_preferred_mode): Likewise. (grub_video_vbe_setup): When the mode is "auto", try to get the preferred mode from VBE, and use the largest mode that is no larger than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. + (grub_video_vbe_get_edid): New function. + (grub_video_vbe_adapter): Add get_edid. * include/grub/video.h (struct grub_vbe_edid_info): New structure. (grub_video_edid_checksum): Add prototype. + (grub_video_get_edid): Likewise. + (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. + * grub-core/commands/videoinfo.c (print_edid): New function. + (grub_cmd_videoinfo): Print EDID if available. + * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 10f77915b..56df943ec 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -77,6 +77,30 @@ hook (const struct grub_video_mode_info *info) return 0; } +static void +print_edid (struct grub_video_edid_info *edid_info) +{ + unsigned int edid_width, edid_height; + + if (grub_video_edid_checksum (edid_info)) + { + grub_printf (" EDID checksum invalid\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + grub_printf (" EDID version: %u.%u\n", + edid_info->version, edid_info->revision); + if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height) + == GRUB_ERR_NONE) + grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height); + else + { + grub_printf (" No preferred mode available\n"); + grub_errno = GRUB_ERR_NONE; + } +} + static grub_err_t grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) @@ -120,6 +144,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), FOR_VIDEO_ADAPTERS (adapter) { + struct grub_video_edid_info edid_info; + grub_printf ("Adapter '%s':\n", adapter->name); if (!adapter->iterate) @@ -143,6 +169,11 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); + if (adapter->get_edid (&edid_info) == GRUB_ERR_NONE) + print_edid (&edid_info); + else + grub_errno = GRUB_ERR_NONE; + if (adapter->id != id) { if (adapter->fini ()) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index e2dcc151e..c6bb733a9 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -389,26 +389,12 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) == GRUB_VBE_STATUS_OK) { - status = grub_vbe_bios_read_edid (&edid_info); - /* Bit 1 in the Feature Support field indicates that the first - Detailed Timing Description is the preferred timing mode. */ - if (status == GRUB_VBE_STATUS_OK - && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE - && edid_info.version == 1 /* we don't understand later versions */ - && (edid_info.feature_support - & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) - && edid_info.detailed_timings[0].pixel_clock) - { - *width = edid_info.detailed_timings[0].horizontal_active_lo - | (((unsigned int) - (edid_info.detailed_timings[0].horizontal_hi & 0xf0)) - << 4); - *height = edid_info.detailed_timings[0].vertical_active_lo - | (((unsigned int) - (edid_info.detailed_timings[0].vertical_hi & 0xf0)) - << 4); - return GRUB_ERR_NONE; - } + if (grub_video_get_edid (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_preferred_mode (&edid_info, width, height) + == GRUB_ERR_NONE) + return GRUB_ERR_NONE; + + grub_errno = GRUB_ERR_NONE; } status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); @@ -978,6 +964,15 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } +static grub_err_t +grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) +{ + if (grub_vbe_bios_read_edid (edid_info) != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + + return GRUB_ERR_NONE; +} + static void grub_video_vbe_print_adapter_specific_info (void) { @@ -1022,6 +1017,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, .iterate = grub_video_vbe_iterate, + .get_edid = grub_video_vbe_get_edid, .print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info, .next = 0 diff --git a/grub-core/video/video.c b/grub-core/video/video.c index f3ecab94d..84e98bb67 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -393,6 +393,49 @@ grub_video_edid_checksum (struct grub_video_edid_info *edid_info) return grub_errno; } +grub_err_t +grub_video_get_edid (struct grub_video_edid_info *edid_info) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + if (! grub_video_adapter_active->get_edid) + return grub_error (GRUB_ERR_BAD_DEVICE, + "EDID information unavailable for this video mode"); + + if (grub_video_adapter_active->get_edid (edid_info) != GRUB_ERR_NONE) + return grub_errno; + if (grub_video_edid_checksum (edid_info) != GRUB_ERR_NONE) + return grub_errno; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, + unsigned int *width, unsigned int *height) +{ + /* Bit 1 in the Feature Support field indicates that the first + Detailed Timing Description is the preferred timing mode. */ + if (edid_info->version == 1 /* we don't understand later versions */ + && (edid_info->feature_support + & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) + && edid_info->detailed_timings[0].pixel_clock) + { + *width = edid_info->detailed_timings[0].horizontal_active_lo + | (((unsigned int) + (edid_info->detailed_timings[0].horizontal_hi & 0xf0)) + << 4); + *height = edid_info->detailed_timings[0].vertical_active_lo + | (((unsigned int) + (edid_info->detailed_timings[0].vertical_hi & 0xf0)) + << 4); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_DEVICE, "no preferred mode available"); +} + /* Parse x[x]*/ static grub_err_t parse_modespec (const char *current_mode, int *width, int *height, int *depth) diff --git a/include/grub/video.h b/include/grub/video.h index 2cf1424c4..2251ed5f4 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -371,6 +371,8 @@ struct grub_video_adapter int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); + grub_err_t (*get_edid) (struct grub_video_edid_info *edid_info); + void (*print_adapter_specific_info) (void); }; typedef struct grub_video_adapter *grub_video_adapter_t; @@ -484,6 +486,10 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); +grub_err_t grub_video_get_edid (struct grub_video_edid_info *edid_info); +grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, + unsigned int *width, + unsigned int *height); grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modemask, From ef429417b2297c508685d9b1cc43e0bee74f0f44 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 18:08:27 +0000 Subject: [PATCH 04/10] mention struct grub_video_adapter change --- ChangeLog.vbe-autodetect | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 355ce00f6..d8034b885 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -19,6 +19,7 @@ (grub_video_vbe_get_edid): New function. (grub_video_vbe_adapter): Add get_edid. * include/grub/video.h (struct grub_vbe_edid_info): New structure. + (struct grub_video_adapter): Add get_edid. (grub_video_edid_checksum): Add prototype. (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. From 015e21571c2ecaacb7eb59c2cfde566d1290c445 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 19:03:28 +0000 Subject: [PATCH 05/10] check that adapter->get_edid is non-NULL --- grub-core/commands/videoinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 56df943ec..9bd0a0e78 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -169,7 +169,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); - if (adapter->get_edid (&edid_info) == GRUB_ERR_NONE) + if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE) print_edid (&edid_info); else grub_errno = GRUB_ERR_NONE; From 13fc463f17281442f13c5ed3dc586f22efaaa2af Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sat, 15 Jan 2011 14:18:16 -0600 Subject: [PATCH 06/10] Make new grub_vbe_bios_* functions static. --- ChangeLog.vbe-autodetect | 5 +---- grub-core/video/i386/pc/vbe.c | 6 +++--- include/grub/i386/pc/vbe.h | 9 --------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index d8034b885..46aacef7b 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -1,4 +1,4 @@ -2010-12-14 Colin Watson +2011-01-15 Colin Watson Preferred resolution detection for VBE. @@ -25,9 +25,6 @@ (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. - (grub_vbe_bios_get_flat_panel_info): Add prototype. - (grub_vbe_bios_get_ddc_capabilities): Likewise. - (grub_vbe_bios_read_edid): Likewise. * grub-core/commands/videoinfo.c (print_edid): New function. (grub_cmd_videoinfo): Print EDID if available. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index c6bb733a9..29b67beeb 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -274,7 +274,7 @@ grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset, } /* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info) { struct grub_bios_int_registers regs; @@ -289,7 +289,7 @@ grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_i } /* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) { struct grub_bios_int_registers regs; @@ -307,7 +307,7 @@ grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) } /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info) { struct grub_bios_int_registers regs; diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 0422558db..09ad7eb64 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -214,15 +214,6 @@ grub_vbe_bios_get_scanline_length (grub_uint32_t *length); grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x, grub_uint32_t *y); -/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ -grub_vbe_status_t -grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info); -/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ -grub_vbe_status_t -grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); -/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ -grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); From 4f8ba1461b82f886557293c26da82fe590d556cd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 11:56:36 +0000 Subject: [PATCH 07/10] Use low memory scratch area for EDID and FP calls. --- grub-core/video/i386/pc/vbe.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 29b67beeb..ea60c6074 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -383,7 +383,12 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) grub_vbe_status_t status; grub_uint8_t ddc_level; struct grub_video_edid_info edid_info; - struct grub_vbe_flat_panel_info flat_panel_info; + struct grub_vbe_flat_panel_info *flat_panel_info; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + flat_panel_info = (struct grub_vbe_flat_panel_info *) + (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info)); + grub_memset (flat_panel_info, 0, sizeof (*flat_panel_info)); if (controller_info.version >= 0x200 && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) @@ -397,7 +402,7 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) grub_errno = GRUB_ERR_NONE; } - status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); + status = grub_vbe_bios_get_flat_panel_info (flat_panel_info); if (status == GRUB_VBE_STATUS_OK) { *width = flat_panel_info.horizontal_size; @@ -967,9 +972,18 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, static grub_err_t grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) { - if (grub_vbe_bios_read_edid (edid_info) != GRUB_VBE_STATUS_OK) + struct grub_video_edid_info *edid_info_lowmem; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + edid_info_lowmem = + (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); + + if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); + return GRUB_ERR_NONE; } From cb918eddf4fd5c2d2d07ac5da6fa8074604b3e5f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 12:05:12 +0000 Subject: [PATCH 08/10] fix FP info handling --- grub-core/video/i386/pc/vbe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index ea60c6074..c2b35a851 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -405,8 +405,8 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) status = grub_vbe_bios_get_flat_panel_info (flat_panel_info); if (status == GRUB_VBE_STATUS_OK) { - *width = flat_panel_info.horizontal_size; - *height = flat_panel_info.vertical_size; + *width = flat_panel_info->horizontal_size; + *height = flat_panel_info->vertical_size; return GRUB_ERR_NONE; } From 9b300caf8455dd0b8c3910330b063ff5777f0a36 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 12:07:47 +0000 Subject: [PATCH 09/10] grub_video_get_edid is not usable from grub_vbe_get_preferred_mode, as a video adapter has not necessarily yet been set. Use grub_video_vbe_get_edid and grub_video_edid_checksum directly instead. Remove grub_video_get_edid as it now has no users. Reported by: Marjo Mercado. --- ChangeLog.vbe-autodetect | 4 +--- grub-core/video/i386/pc/vbe.c | 39 ++++++++++++++++++----------------- grub-core/video/video.c | 18 ---------------- include/grub/video.h | 1 - 4 files changed, 21 insertions(+), 41 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 46aacef7b..3341e8cc3 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -1,9 +1,8 @@ -2011-01-15 Colin Watson +2011-01-17 Colin Watson Preferred resolution detection for VBE. * grub-core/video/video.c (grub_video_edid_checksum): New function. - (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): @@ -21,7 +20,6 @@ * include/grub/video.h (struct grub_vbe_edid_info): New structure. (struct grub_video_adapter): Add get_edid. (grub_video_edid_checksum): Add prototype. - (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index c2b35a851..f94b06060 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -377,6 +377,24 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } +static grub_err_t +grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) +{ + struct grub_video_edid_info *edid_info_lowmem; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + edid_info_lowmem = + (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); + + if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + + grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); + + return GRUB_ERR_NONE; +} + static grub_err_t grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) { @@ -394,7 +412,8 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) == GRUB_VBE_STATUS_OK) { - if (grub_video_get_edid (&edid_info) == GRUB_ERR_NONE + if (grub_video_vbe_get_edid (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE && grub_video_edid_preferred_mode (&edid_info, width, height) == GRUB_ERR_NONE) return GRUB_ERR_NONE; @@ -969,24 +988,6 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } -static grub_err_t -grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) -{ - struct grub_video_edid_info *edid_info_lowmem; - - /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ - edid_info_lowmem = - (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); - - if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) - return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); - - grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); - - return GRUB_ERR_NONE; -} - static void grub_video_vbe_print_adapter_specific_info (void) { diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 84e98bb67..01bdd1ff3 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -393,24 +393,6 @@ grub_video_edid_checksum (struct grub_video_edid_info *edid_info) return grub_errno; } -grub_err_t -grub_video_get_edid (struct grub_video_edid_info *edid_info) -{ - if (! grub_video_adapter_active) - return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); - - if (! grub_video_adapter_active->get_edid) - return grub_error (GRUB_ERR_BAD_DEVICE, - "EDID information unavailable for this video mode"); - - if (grub_video_adapter_active->get_edid (edid_info) != GRUB_ERR_NONE) - return grub_errno; - if (grub_video_edid_checksum (edid_info) != GRUB_ERR_NONE) - return grub_errno; - - return GRUB_ERR_NONE; -} - grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, unsigned int *width, unsigned int *height) diff --git a/include/grub/video.h b/include/grub/video.h index 2251ed5f4..f42730a7d 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -486,7 +486,6 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); -grub_err_t grub_video_get_edid (struct grub_video_edid_info *edid_info); grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, unsigned int *width, unsigned int *height); From 421284f2998aa3e9134372379a2bd03de08a2740 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 30 Mar 2011 10:19:08 +0100 Subject: [PATCH 10/10] * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE documentation. --- ChangeLog.vbe-autodetect | 2 ++ docs/grub.texi | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 3341e8cc3..6308e5793 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -29,3 +29,5 @@ * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. + * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE + documentation. diff --git a/docs/grub.texi b/docs/grub.texi index 54a2d8791..885bb4731 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1140,7 +1140,8 @@ listed in @file{/boot/grub/video.lst}. Set the resolution used on the @samp{gfxterm} graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be -available. The default is @samp{640x480}. +available. The default is @samp{auto}, which tries to select a preferred +resolution. @item GRUB_BACKGROUND Set a background image for use with the @samp{gfxterm} graphical terminal.