[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Fix VBE EDID interrogation. Add a new boot option 'edid={no, force}'.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1181642667 -3600
# Node ID 9766af047b6cd10e4259a5c3bde3cee5c24785af
# Parent  112703751b192ce120023e5b1f8f67243ab68f69
x86: Fix VBE EDID interrogation. Add a new boot option 'edid={no,force}'.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 docs/src/user.tex           |    7 ++++
 xen/arch/x86/boot/cmdline.S |   73 ++++++++++++++++++++++++++++++++------------
 xen/arch/x86/boot/video.S   |   56 +++++++++++++++++----------------
 xen/arch/x86/setup.c        |   36 +++++++++++++++++++--
 4 files changed, 123 insertions(+), 49 deletions(-)

diff -r 112703751b19 -r 9766af047b6c docs/src/user.tex
--- a/docs/src/user.tex Tue Jun 12 09:22:06 2007 +0100
+++ b/docs/src/user.tex Tue Jun 12 11:04:27 2007 +0100
@@ -3188,6 +3188,13 @@ editing \path{grub.conf}.
   \end{description}
 The mode may optionally be followed by `{\bf,keep}' to cause Xen to keep
 writing to the VGA console after domain 0 starts booting (e.g., 
`vga=text-80x50,keep').
+\item [ no-real-mode ] (x86 only) Do not execute real-mode bootstrap
+  code when booting Xen. This option should not be used except for
+  debugging. It will effectively disable the {\bf vga} option, which
+  relies on real mode to set the video mode.
+\item [ edid=no,force ] (x86 only) Either force retrieval of monitor
+  EDID information via VESA DDC, or disable it (edid=no). This option
+  should not normally be required except for debugging purposes.
 \item [ console\_to\_ring ] Place guest console output into the
   hypervisor console ring buffer. This is disabled by default.
   When enabled, both hypervisor output and guest console output
diff -r 112703751b19 -r 9766af047b6c xen/arch/x86/boot/cmdline.S
--- a/xen/arch/x86/boot/cmdline.S       Tue Jun 12 09:22:06 2007 +0100
+++ b/xen/arch/x86/boot/cmdline.S       Tue Jun 12 11:04:27 2007 +0100
@@ -157,10 +157,10 @@ cmdline_parse_early:
         mov     sym_phys(multiboot_ptr),%ebx
         mov     MB_flags(%ebx),%eax
         test    $4,%al
-        jz      1f
+        jz      .Lcmdline_exit
         mov     MB_cmdline(%ebx),%eax
         test    %eax,%eax
-        jz      1f
+        jz      .Lcmdline_exit
 
         /* Check for 'no-real-mode' command-line option. */
         pushl   $sym_phys(.Lno_rm_opt)
@@ -169,14 +169,40 @@ cmdline_parse_early:
         test    %eax,%eax
         setnz   bootsym_phys(skip_realmode)
 
+        /* Check for 'edid=' command-line option. */
+        movl    $sym_phys(.Ledid_opt),4(%esp)
+        call    .Lfind_option
+        test    %eax,%eax
+        jz      .Lparse_vga
+        cmpb    $'=',4(%eax)
+        jne     .Lparse_vga
+        add     $5,%eax
+        mov     %eax,%ebx
+        push    %ebx
+        pushl   $sym_phys(.Ledid_force)
+        call    .Lstr_prefix
+        add     $8,%esp
+        movb    $2,bootsym_phys(opt_edid) /* opt_edid=2: edid=force */
+        test    %eax,%eax
+        jz      .Lparse_vga
+        push    %ebx
+        pushl   $sym_phys(.Ledid_no)
+        call    .Lstr_prefix
+        add     $8,%esp
+        decb    bootsym_phys(opt_edid)    /* opt_edid=1: edid=no */
+        test    %eax,%eax
+        jz      .Lparse_vga
+        decb    bootsym_phys(opt_edid)    /* opt_edid=0: default */
+
+.Lparse_vga:
         /* Check for 'vga=' command-line option. */
         movl    $sym_phys(.Lvga_opt),4(%esp)
         call    .Lfind_option
         add     $8,%esp
         test    %eax,%eax
-        jz      1f
+        jz      .Lcmdline_exit
         cmpb    $'=',3(%eax)
-        jne     1f
+        jne     .Lcmdline_exit
         add     $4,%eax
 
         /* Found the 'vga=' option. Default option is to display vga menu. */
@@ -189,7 +215,7 @@ cmdline_parse_early:
         call    .Lstr_prefix
         add     $8,%esp
         test    %eax,%eax
-        jnz     3f
+        jnz     .Lparse_vga_gfx
 
         /* We have 'vga=text-80x<rows>'. */
         add     $8,%ebx
@@ -198,22 +224,23 @@ cmdline_parse_early:
         add     $4,%esp
         mov     %ax,%bx
         lea     sym_phys(.Lvga_text_modes),%esi
-2:      lodsw
+1:      lodsw
         test    %ax,%ax
-        jz      1f
+        jz      .Lcmdline_exit
         cmp     %ax,%bx
         lodsw
-        jne     2b
+        jne     1b
         mov     %ax,bootsym_phys(boot_vid_mode)
-        jmp     1f
-
+        jmp     .Lcmdline_exit
+
+.Lparse_vga_gfx:
         /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
-3:      push    %ebx
+        push    %ebx
         pushl   $sym_phys(.Lvga_gfx)
         call    .Lstr_prefix
         add     $8,%esp
         test    %eax,%eax
-        jnz     3f
+        jnz     .Lparse_vga_mode
 
         /* We have 'vga=gfx-<width>x<height>x<depth>'. */
         /* skip 'gfx-' */
@@ -226,7 +253,7 @@ 3:      push    %ebx
         /* skip 'x' */
         lodsb
         cmpb    $'x',%al
-        jne     1f
+        jne     .Lcmdline_exit
         /* parse <height> */
         push    %esi
         call    .Latoi
@@ -235,7 +262,7 @@ 3:      push    %ebx
         /* skip 'x' */
         lodsb
         cmpb    $'x',%al
-        jne     1f
+        jne     .Lcmdline_exit
         /* parse <depth> */
         push    %esi
         call    .Latoi
@@ -243,15 +270,16 @@ 3:      push    %ebx
         mov     %ax,bootsym_phys(vesa_size)+4
         /* commit to vesa mode */
         movw    $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
-        jmp     1f
-
+        jmp     .Lcmdline_exit
+
+.Lparse_vga_mode:
         /* Check for 'vga=mode-<mode>'. */
-3:      push    %ebx
+        push    %ebx
         pushl   $sym_phys(.Lvga_mode)
         call    .Lstr_prefix
         add     $8,%esp
         test    %eax,%eax
-        jnz     1f
+        jnz     .Lcmdline_exit
 
         /* We have 'vga=mode-<mode>'. */
         add     $5,%ebx
@@ -260,7 +288,8 @@ 3:      push    %ebx
         add     $4,%esp
         mov     %ax,bootsym_phys(boot_vid_mode)
 
-1:      popa
+.Lcmdline_exit:
+        popa
         ret
 
 .Lvga_text_modes: /* rows, mode_number */
@@ -283,3 +312,9 @@ 1:      popa
         .asciz  "mode-"
 .Lno_rm_opt:
         .asciz  "no-real-mode"
+.Ledid_opt:
+        .asciz  "edid"
+.Ledid_force:
+        .asciz  "force"
+.Ledid_no:
+        .asciz  "no"
diff -r 112703751b19 -r 9766af047b6c xen/arch/x86/boot/video.S
--- a/xen/arch/x86/boot/video.S Tue Jun 12 09:22:06 2007 +0100
+++ b/xen/arch/x86/boot/video.S Tue Jun 12 11:04:27 2007 +0100
@@ -882,27 +882,18 @@ gettime:
 
 store_edid:
 #ifdef CONFIG_FIRMWARE_EDID
-        pushw   %es                     # just save all registers
         pushw   %ax
         pushw   %bx
         pushw   %cx
         pushw   %dx
         pushw   %di
 
-        pushw   %fs
-        popw    %es
-
-        movl    $0x13131313, %eax       # memset block with 0x13
-        movw    $32, %cx
-        movw    $0x140, %di
-        cld
-        rep
-        stosl
+        cmpb    $1, bootsym(opt_edid)   # EDID disabled on cmdline (edid=no)?
+        je      .Lno_edid
 
         cmpw    $0x0200, bootsym(vbe_version)  # only do EDID on >= VBE2.0
-        jl      no_edid
-
-        pushw   %es                     # save ES
+        jl      .Lno_edid
+
         xorw    %di, %di                # Report Capability
         pushw   %di
         popw    %es                     # ES:DI must be 0:0
@@ -910,31 +901,40 @@ store_edid:
         xorw    %bx, %bx
         xorw    %cx, %cx
         int     $0x10
-        popw    %es                     # restore ES
-
-        cmpb    $0x00, %ah              # call successful
-        jne     no_edid
-
-        cmpb    $0x4f, %al              # function supported
-        jne     no_edid
-
+        cmpw    $0x004f, %ax            # Call failed?
+        jne     .Lno_edid
+
+        movw    %bx, bootsym(boot_edid_caps)
+
+        cmpb    $2, bootsym(opt_edid)   # EDID forced on cmdline (edid=force)?
+        je      .Lforce_edid
+
+        /* EDID not forced on cmdline, so perform further sanity checks. */
+        testb   $3,%bl                  # No DDC capabilities?
+        jz      .Lno_edid
+        cmpb    $5,%bh                  # Longer than 5s to read EDID?
+        ja      .Lno_edid
+
+.Lforce_edid:
         movw    $0x4f15, %ax            # do VBE/DDC
         movw    $0x01, %bx
         movw    $0x00, %cx
         movw    $0x00, %dx
-        movw    $0x140, %di
-        int     $0x10
-
-no_edid:
+        pushw   %ds
+        popw    %es
+        movw    $bootsym(boot_edid_info), %di
+        int     $0x10
+
+.Lno_edid:
         popw    %di                     # restore all registers
         popw    %dx
         popw    %cx
         popw    %bx
         popw    %ax
-        popw    %es
 #endif
         ret
 
+opt_edid:       .byte   0       # EDID parsing option (force/no/default)
 mt_end:         .word   0       # End of video mode table if built
 edit_buf:       .space  6       # Line editor buffer
 card_name:      .word   0       # Pointer to adapter name
@@ -983,7 +983,7 @@ force_size:     .word   0       # Use th
 
 vesa_size:      .word   0,0,0   # width x depth x height
 
-                .globl  boot_vid_info
+                .globl  boot_vid_info, boot_edid_info, boot_edid_caps
 /* If we don't run at all, assume basic video mode 3 at 80x25. */
 boot_vid_mode:  .word   VIDEO_80x25
 boot_vid_info:  .byte   0, 0    /* orig_x, orig_y */
@@ -992,3 +992,5 @@ boot_vid_info:  .byte   0, 0    /* orig_
                 .byte   1       /* isVGA          */
                 .word   16      /* 8x16 font      */
                 .fill   0x28,1,0
+boot_edid_info: .fill   128,1,0x13
+boot_edid_caps: .word   0x1313
diff -r 112703751b19 -r 9766af047b6c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Tue Jun 12 09:22:06 2007 +0100
+++ b/xen/arch/x86/setup.c      Tue Jun 12 11:04:27 2007 +0100
@@ -47,6 +47,10 @@ extern void generic_apic_probe(void);
 extern void generic_apic_probe(void);
 extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
 
+extern u16 boot_edid_caps;
+extern u8 boot_edid_info[128];
+extern struct boot_video_info boot_vid_info;
+
 /*
  * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
  * page_info table and allocation bitmap.
@@ -348,7 +352,6 @@ struct boot_video_info {
 
 static void __init parse_video_info(void)
 {
-    extern struct boot_video_info boot_vid_info;
     struct boot_video_info *bvi = &bootsym(boot_vid_info);
 
     if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
@@ -444,20 +447,47 @@ void __init __start_xen(multiboot_info_t
 
     printk("Command line: %s\n", cmdline);
 
+    printk("Video information:\n");
+
+    /* Print VGA display mode information. */
     switch ( vga_console_info.video_type )
     {
     case XEN_VGATYPE_TEXT_MODE_3:
-        printk("VGA is text mode %dx%d, font 8x%d\n",
+        printk(" VGA is text mode %dx%d, font 8x%d\n",
                vga_console_info.u.text_mode_3.columns,
                vga_console_info.u.text_mode_3.rows,
                vga_console_info.u.text_mode_3.font_height);
         break;
     case XEN_VGATYPE_VESA_LFB:
-        printk("VGA is graphics mode %dx%d, %d bpp\n",
+        printk(" VGA is graphics mode %dx%d, %d bpp\n",
                vga_console_info.u.vesa_lfb.width,
                vga_console_info.u.vesa_lfb.height,
                vga_console_info.u.vesa_lfb.bits_per_pixel);
         break;
+    default:
+        printk(" No VGA detected\n");
+        break;
+    }
+
+    /* Print VBE/DDC EDID information. */
+    if ( bootsym(boot_edid_caps) != 0x1313 )
+    {
+        u16 caps = bootsym(boot_edid_caps);
+        printk(" VBE/DDC methods:%s%s%s; ",
+               (caps & 1) ? " V1" : "",
+               (caps & 2) ? " V2" : "",
+               !(caps & 3) ? " none" : "");
+        printk("EDID transfer time: %d seconds\n", caps >> 8);
+        if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
+        {
+            printk(" EDID info not retrieved because ");
+            if ( !(caps & 3) )
+                printk("no DDC retrieval method detected\n");
+            else if ( (caps >> 8) > 5 )
+                printk("takes longer than 5 seconds\n");
+            else
+                printk("of reasons unknown\n");
+        }
     }
 
     /* Check that we have at least one Multiboot module. */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.