aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-06-12 11:04:27 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-06-12 11:04:27 +0100
commitb2023adb2e06555b6ab32541fb1d87824d2c216f (patch)
treec3f1215f894dca96844907052d609709ce2a84ed
parentf64134cdb81cfd4da7ab674a863eb976f5bf5669 (diff)
downloadxen-b2023adb2e06555b6ab32541fb1d87824d2c216f.tar.gz
xen-b2023adb2e06555b6ab32541fb1d87824d2c216f.tar.bz2
xen-b2023adb2e06555b6ab32541fb1d87824d2c216f.zip
x86: Fix VBE EDID interrogation. Add a new boot option 'edid={no,force}'.
Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r--docs/src/user.tex7
-rw-r--r--xen/arch/x86/boot/cmdline.S69
-rw-r--r--xen/arch/x86/boot/video.S44
-rw-r--r--xen/arch/x86/setup.c36
4 files changed, 115 insertions, 41 deletions
diff --git a/docs/src/user.tex b/docs/src/user.tex
index f93fcab4fa..64b0fa4c1a 100644
--- a/docs/src/user.tex
+++ b/docs/src/user.tex
@@ -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 --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S
index bbbaed83b2..45798dda65 100644
--- a/xen/arch/x86/boot/cmdline.S
+++ b/xen/arch/x86/boot/cmdline.S
@@ -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 @@ cmdline_parse_early:
/* skip 'x' */
lodsb
cmpb $'x',%al
- jne 1f
+ jne .Lcmdline_exit
/* parse <height> */
push %esi
call .Latoi
@@ -235,7 +262,7 @@ cmdline_parse_early:
/* skip 'x' */
lodsb
cmpb $'x',%al
- jne 1f
+ jne .Lcmdline_exit
/* parse <depth> */
push %esi
call .Latoi
@@ -243,15 +270,16 @@ cmdline_parse_early:
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 @@ cmdline_parse_early:
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 @@ cmdline_parse_early:
.asciz "mode-"
.Lno_rm_opt:
.asciz "no-real-mode"
+.Ledid_opt:
+ .asciz "edid"
+.Ledid_force:
+ .asciz "force"
+.Ledid_no:
+ .asciz "no"
diff --git a/xen/arch/x86/boot/video.S b/xen/arch/x86/boot/video.S
index 03ce6ab578..e4c45298a8 100644
--- a/xen/arch/x86/boot/video.S
+++ b/xen/arch/x86/boot/video.S
@@ -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
+ jl .Lno_edid
- pushw %es # save ES
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
+ cmpw $0x004f, %ax # Call failed?
+ jne .Lno_edid
- cmpb $0x00, %ah # call successful
- jne no_edid
+ movw %bx, bootsym(boot_edid_caps)
- cmpb $0x4f, %al # function supported
- jne no_edid
+ 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
+ pushw %ds
+ popw %es
+ movw $bootsym(boot_edid_info), %di
int $0x10
-no_edid:
+.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 this size instead of the one in BIOS vars
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_x, orig_y */
.byte 1 /* isVGA */
.word 16 /* 8x16 font */
.fill 0x28,1,0
+boot_edid_info: .fill 128,1,0x13
+boot_edid_caps: .word 0x1313
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index a942ab5c75..fbc9f4db52 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -47,6 +47,10 @@ extern void dmi_scan_machine(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 *mbi)
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. */