[SeaBIOS] [PATCH 3/4] bochsvga: Implement vbe 15h function

Hiroshi Miura miurahr at linux.com
Sun Oct 28 03:19:20 CET 2012


This patch adds the ability for the Bochs VGA ROM to return information
about a HD wide monitor.

It is constructed from defitions at run time.

Inspired by this patch I digged out from the vgabios mailing list:
http://old.nabble.com/VBE-BIOS-support-for-monitor-information-(EDID)-td22952446.html

Signed-off-by: Hiroshi Miura <miurahr at linux.com>
---
 Makefile           |    3 +-
 vgasrc/bochsedid.c |  101 ++++++++++++++++++++++++++++++++++++++
 vgasrc/bochsedid.h |  137 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 vgasrc/bochsvga.c  |    1 +
 vgasrc/vgahw.h     |    5 ++
 5 files changed, 246 insertions(+), 1 deletion(-)
 create mode 100644 vgasrc/bochsedid.c
 create mode 100644 vgasrc/bochsedid.h

diff --git a/Makefile b/Makefile
index 45ea48a..d3e22b9 100644
--- a/Makefile
+++ b/Makefile
@@ -189,7 +189,8 @@ $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
 SRCVGA=src/output.c src/util.c src/pci.c \
     vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgafonts.c vgasrc/vbe.c \
     vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \
-    vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c
+    vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c \
+    vgasrc/bochsedid.c
 
 CFLAGS16VGA = $(CFLAGS16INC) -Isrc
 
diff --git a/vgasrc/bochsedid.c b/vgasrc/bochsedid.c
new file mode 100644
index 0000000..ec43d41
--- /dev/null
+++ b/vgasrc/bochsedid.c
@@ -0,0 +1,101 @@
+// VESA VBE EDID capability for virtual display
+//
+// Copyright (C) 2012  Hiroshi Miura <miurahr at linux.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC
+#include "biosvar.h" // GET_GLOBAL
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "bochsedid.h"
+
+struct edid_detailed_timing edid_dtd_1920x1200 VAR16 = {
+     0x4B7D,  0xB0, 0xA0, 0x72, 0xB0, 0x2D,
+     0x40, 0x88, 0xC8, 0x55, 0x75, 0x21,
+     0x00, 0x00, 0x1C};
+struct edid_monitor_range_limit edid_range_limit VAR16 = {
+    {0x00,0x00,0x00,0xfD,0x00},
+    50,150,   /* Vertical 50Hz - 150Hz */
+    31,135,   /* Horiz 31kHz - 135kHz */
+    20,       /* clock 200MHz */
+    0, /* no ext */
+    0x0A,0x20,0x20,
+    0x2020,
+    0x20,0x20 /* padding */
+    };
+struct edid_monitor_text edid_serial VAR16 = {
+    {0,0,0,0xFF,0},
+    {'1','2','3','4','5','6','7','8','9','0',0x0A, 0x20, 0x20}
+};
+struct edid_monitor_text edid_name VAR16 = {
+    {0,0,0,0xFC,0},
+    {'S','e','a',' ','V','G','A','B','I','O','S',0x0A, 0x20}
+};
+
+struct edid_info BochsEDID VAR16 = {
+    .header={0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00},
+    .vendor=0x2104, .product=0xCDAB, .serial=0x00000000,
+    .week=36, .year=22, .major_version=1, .minor_version=3,
+    .video_setup=0x0F,
+    /* Video signal interface (analogue, 0.700 : 0.300 : 1.000 V p-p,
+       Video Setup: Blank Level = Black Level, Separate Sync H & V Signals are
+       supported, Composite Sync Signal on Horizontal is supported, Composite 
+       Sync Signal on Green Video is supported, Serration on the Vertical Sync
+       is supported) */
+    .screen_width=0x21, .screen_height=0x19,/* 330 mm * 250 mm */
+    .gamma=0x78,/* 2.2 */
+    .feature_flag=0x0F,/* no DMPS states, RGB, display is continuous frequency, prefered mode */
+    .least_chromaticity={0x78, 0xF5},
+    .most_chromaticity={0xA6,0x55,0x48,0x9B,0x26,0x12,0x50,0x54},
+    .established_timing={0xFF,0xEF,0x80},
+    /* 720x400 at 70Hz, 720x400 at 88Hz, 640x480 at 60Hz, 640x480 at 67Hz, 640x480 at 72Hz, 640x480 at 75Hz,
+       800x600 at 56Hz, 800x600 at 60Hz, 800x600 at 72Hz, 800x600 at 75Hz, 832x624 at 75Hz, 1152x870 at 75Hz,
+       not 1024x768 at 87Hz(I), 1024x768 at 60Hz, 1024x768 at 70Hz, 1024x768 at 75Hz, 1280x1024 at 75Hz */
+    .standard_timing={EDID_STD_640x480_85Hz, EDID_STD_800x600_85Hz,
+     EDID_STD_1024x768_85Hz, EDID_STD_1280x720_70Hz,
+     EDID_STD_1280x960_60Hz, EDID_STD_1440x900_60Hz,
+     EDID_STD_1600x1200_60Hz,EDID_STD_NOP},
+}; 
+
+void bochs_pupulate_edid_block0(u8 next)
+{
+    /* detailed timing block */
+    memcpy_far(get_global_seg(), &(BochsEDID.desc[0]), get_global_seg(), 
+               &edid_dtd_1920x1200, sizeof (struct edid_detailed_timing));
+    /* monitor range */
+    memcpy_far(get_global_seg(), &(BochsEDID.desc[1].mrld), get_global_seg(), &edid_range_limit,
+               sizeof(edid_range_limit));
+    /* serial */
+    memcpy_far(get_global_seg(), &(BochsEDID.desc[2]), get_global_seg(), &edid_serial,
+               sizeof (struct edid_monitor_text));
+    /* monitor name */
+    memcpy_far(get_global_seg(), &(BochsEDID.desc[3]), get_global_seg(), &edid_name,
+               sizeof (struct edid_monitor_text));
+
+    SET_VGA(BochsEDID.extensions, next);
+    u8 sum = -checksum_far(get_global_seg(), &BochsEDID, sizeof(BochsEDID));
+    SET_VGA(BochsEDID.checksum, sum);
+}
+
+int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data)
+{
+    memcpy_far(seg, data, get_global_seg(), &BochsEDID, sizeof(BochsEDID));
+    return 0;
+}
+
+int bochs_get_ddc_capabilities(u16 unit)
+{
+    if (unit != 0)
+        return -1;
+
+    return (1 << 8) | VBE_DDC1_PROTOCOL_SUPPORTED;
+}
+
+int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data)
+{
+    if (unit != 0 || block != 0)
+        return -1;
+
+    return bochs_read_edid_block0(unit, block, seg, data);
+}
diff --git a/vgasrc/bochsedid.h b/vgasrc/bochsedid.h
new file mode 100644
index 0000000..b6b2e3a
--- /dev/null
+++ b/vgasrc/bochsedid.h
@@ -0,0 +1,137 @@
+#ifndef __BOCHEDID_H
+#define __BOCHEDID_H
+
+/* EDID infomation definitions */
+/* Detailed Timing Descriptor */
+struct edid_detailed_timing {
+    u16 pixel_clock;
+    u8 horizontal_addressable_low;
+    u8 horizontal_blanking_low;
+    u8 horizontal_high;
+    u8 vertical_addressable_low;
+    u8 vertical_blanking_low;
+    u8 vertical_high;
+    u8 horizontal_front_porch_low;
+    u8 horizontal_sync_pulse_low;
+    u8 vertical_low4;
+    u8 horizontal_vertical_sync_hi;
+    u8 horizontal_video_image_low;
+    u8 vertical_video_image_low;
+    u8 video_image_high;
+    u8 horizontal_border;
+    u8 vertical_border;
+    u8 features;
+} PACKED;
+
+/* Other Monitor Descriptors */
+/*
+  0xFF: Monitor serial number (text)
+  0xFE: Unspecified text (text)
+  0xFC: Monitor name (text)
+ */
+struct edid_monitor_text {
+    u8 header[5];
+    u8 text[13];
+} PACKED;
+
+/* Monitor Range Limits Descriptor */
+/*
+  0xFD: Monitor range limits. 6- or 13-byte binary descriptor.
+ */
+struct edid_monitor_range_limit {
+    u8 header[5];
+    u8 vertical_rate_min;
+    u8 vertical_rate_max;
+    u8 horizontal_rate_min;
+    u8 horizontal_rate_max;
+    u8 pixel_clock_max;
+    u8 extended_timing_type;
+    u8 reserved;
+    u8 start_frequency;
+    u8 gtf_c_val;
+    u16 gtf_m_val;
+    u8 gtf_k_val;
+    u8 gtf_j_val;
+} PACKED;
+
+/* White point Descriptor */
+/*
+  0xFB: Additional white point data. 2× 5-byte descriptors, padded with 0A 20 20.
+  0xFA: Additional standard timing identifiers. 6× 2-byte descriptors, padded with 0A
+ */
+struct edid_wp_desc {
+    u8 index;
+    u8 least;
+    u8 x;
+    u8 y;
+    u8 gamma;
+} PACKED;
+
+struct edid_white_point {
+    u8 header[5];
+    struct edid_wp_desc desc[2];
+    u8 padding[3];
+} PACKED;
+
+struct edid_additional_timing {
+    u8 header[5];
+    u16 standard_timing[6];
+    u8 padding;
+} PACKED;
+
+union edid_descriptors {
+    struct edid_detailed_timing     dtd;
+    struct edid_monitor_range_limit mrld;
+    struct edid_monitor_text        mtxtd;
+    struct edid_white_point         wpd;
+    struct edid_additional_timing   astd;
+} PACKED;
+
+struct edid_info {
+    u8 header[8];
+    u16 vendor;
+    u16 product;
+    u32 serial;
+    u8 week;
+    u8 year;
+    u8 major_version;
+    u8 minor_version;
+    u8 video_setup;
+    u8 screen_width;
+    u8 screen_height;
+    u8 gamma;
+    u8 feature_flag;
+    u8 least_chromaticity[2];
+    u8 most_chromaticity[8];
+    u8 established_timing[3];
+    u16 standard_timing[8];
+    union edid_descriptors desc[4];
+    u8 extensions;
+    u8 checksum;
+} PACKED;
+
+/* EDID Standard Timing Description */
+
+/* First byte: X resolution, divided by 8, less 31 (256–2288 pixels) */
+/* bit 7-6, X:Y pixel ratio: 00=16:10; 01=4:3; 10=5:4; 11=16:9 */
+/* bit 5-0, Vertical frequency, less 60 (60–123 Hz), nop 01 01 in Big Endian*/
+#define EDID_STD_640x480_85Hz                        0x5931
+#define EDID_STD_800x600_85Hz                        0x5945
+#define EDID_STD_1024x768_85Hz                       0x5961
+#define EDID_STD_1152x864_70Hz                       0x4A71
+#define EDID_STD_1280x720_70Hz                       0xCA81
+#define EDID_STD_1280x800_70Hz                       0x0A81
+#define EDID_STD_1280x960_60Hz                       0x4081
+#define EDID_STD_1280x1024_60Hz                      0x8081
+#define EDID_STD_1440x900_60Hz                       0x0095
+#define EDID_STD_1600x1200_60Hz                      0x40A9
+#define EDID_STD_1600x900_60Hz                       0xC0A9
+#define EDID_STD_1680x1050_60Hz                      0x00B3
+#define EDID_STD_1920x1080_60Hz                      0xC0D1
+#define EDID_STD_1920x1200_60Hz                      0x00D1
+#define EDID_STD_NOP                                 0x0101
+
+void bochs_pupulate_edid_block0(u8 next);
+int bochs_get_ddc_capabilities(u16 unit);
+int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data);
+#endif /* bochedid.h */
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c
index 2a8aeb1..7b8f430 100644
--- a/vgasrc/bochsvga.c
+++ b/vgasrc/bochsvga.c
@@ -388,6 +388,7 @@ bochsvga_init(void)
             SET_VGA(m->mode, 0xffff);
         }
     }
+    bochs_pupulate_edid_block0(0);
 
     return 0;
 }
diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h
index 01d2609..130462c 100644
--- a/vgasrc/vgahw.h
+++ b/vgasrc/vgahw.h
@@ -8,6 +8,7 @@
 #include "bochsvga.h" // bochsvga_set_mode
 #include "stdvga.h" // stdvga_set_mode
 #include "geodevga.h" // geodevga_init
+#include "bochsedid.h"
 
 static inline struct vgamode_s *vgahw_find_mode(int mode) {
     if (CONFIG_VGA_CIRRUS)
@@ -130,10 +131,14 @@ static inline int vgahw_restore_state(u16 seg, void *data, int states) {
 }
 
 static inline int vgahw_get_ddc_capabilities(u16 unit) {
+    if (CONFIG_VGA_BOCHS)
+        return bochs_get_ddc_capabilities(unit);
     return stdvga_get_ddc_capabilities(unit);
 }
 
 static inline int vgahw_read_edid(u16 unit, u16 block, u16 seg, void *data) {
+    if (CONFIG_VGA_BOCHS)
+        return bochs_read_edid(unit, block, seg, data);
     return stdvga_read_edid(unit, block, seg, data);
 }
 
-- 
1.7.9.5





More information about the SeaBIOS mailing list