Jan Beulich
2007-Mar-02 10:32 UTC
[Xen-devel] [PATCH 3/3] x86: real mode support: get EDID info
Obtain EDID info from BIOS and pass it up to Dom0. Signed-off-by: Jan Beulich <jbeulich@novell.com> Index: 2007-02-27/xen/arch/x86/Makefile ==================================================================--- 2007-02-27.orig/xen/arch/x86/Makefile 2007-02-22 15:57:24.000000000 +0100 +++ 2007-02-27/xen/arch/x86/Makefile 2007-02-22 15:48:44.000000000 +0100 @@ -78,7 +78,7 @@ xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(H boot/mkelf32: boot/mkelf32.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -boot/$(TARGET_SUBARCH).o: boot/realmode.S boot/edd.S +boot/$(TARGET_SUBARCH).o: boot/realmode.S boot/edd.S boot/video.S .PHONY: clean clean:: Index: 2007-02-27/xen/arch/x86/boot/realmode.S ==================================================================--- 2007-02-27.orig/xen/arch/x86/boot/realmode.S 2007-02-22 15:58:16.000000000 +0100 +++ 2007-02-27/xen/arch/x86/boot/realmode.S 2007-02-22 16:22:31.000000000 +0100 @@ -140,4 +140,11 @@ eddbuf: .skip EDDMAXNR * (EDDEXTSIZE + edd_mbr_sig_buf: .skip EDD_MBR_SIG_MAX * 4 eddnr: .skip 1 edd_mbr_sig_nr_buf: .skip 1 + + .globl ddc_capabilities, edid_transfer_time, edid +ddc_capabilities: .skip 1 +edid_transfer_time: .skip 1 +edid: .skip 128 .previous + +#include "video.S" Index: 2007-02-27/xen/arch/x86/boot/video.S ==================================================================--- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2007-02-27/xen/arch/x86/boot/video.S 2007-02-22 16:26:50.000000000 +0100 @@ -0,0 +1,35 @@ +store_edid: + movl $0x13131313, %eax # memset block with 0x13 + movw $32, %cx + movw $SYM_REAL(edid), %di + cld + rep + stosl + + pushw %es # save ES + xorw %di, %di # Report Capability + movw %di, %es # ES:DI must be 0:0 + movw $0x4f15, %ax + xorw %bx, %bx + xorw %cx, %cx + int $0x10 + popw %es # restore ES + + testb %ah, %ah # call successful + jnz no_edid + + cmpb $0x4f, %al # function supported + jne no_edid + + movb %bl, SYM_REAL(ddc_capabilities) + movb %bh, SYM_REAL(edid_transfer_time) + + movw $0x4f15, %ax # do VBE/DDC + movw $0x01, %bx + xorw %cx, %cx + xorw %dx, %dx + movw $SYM_REAL(edid), %di + int $0x10 + +no_edid: + ret Index: 2007-02-27/xen/arch/x86/boot/x86_32.S ==================================================================--- 2007-02-27.orig/xen/arch/x86/boot/x86_32.S 2007-02-21 18:08:44.000000000 +0100 +++ 2007-02-27/xen/arch/x86/boot/x86_32.S 2007-02-22 16:28:03.000000000 +0100 @@ -92,6 +92,8 @@ __start: pushl $SYM_PHYS(edd) call realmode + pushl $SYM_PHYS(store_edid) + call realmode #ifdef CONFIG_X86_PAE /* Initialize low and high mappings of all memory with 2MB pages */ Index: 2007-02-27/xen/arch/x86/boot/x86_64.S ==================================================================--- 2007-02-27.orig/xen/arch/x86/boot/x86_64.S 2007-02-21 17:55:02.000000000 +0100 +++ 2007-02-27/xen/arch/x86/boot/x86_64.S 2007-02-22 16:28:11.000000000 +0100 @@ -75,6 +75,8 @@ __start: lss SYM_PHYS(.Lstack_start),%esp pushl $SYM_PHYS(edd) call realmode + pushl $SYM_PHYS(store_edid) + call realmode /* We begin by interrogating the CPU for the presence of long mode. */ mov $0x80000000,%eax Index: 2007-02-27/xen/arch/x86/platform_hypercall.c ==================================================================--- 2007-02-27.orig/xen/arch/x86/platform_hypercall.c 2007-02-22 16:14:39.000000000 +0100 +++ 2007-02-27/xen/arch/x86/platform_hypercall.c 2007-02-22 16:22:49.000000000 +0100 @@ -24,10 +24,15 @@ #include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +struct ddc { + uint8_t capabilities, edid_transfer_time, edid[128]; +}; + #ifndef COMPAT typedef long ret_t; DEFINE_SPINLOCK(xenpf_lock); struct edd edd; +struct ddc ddc; # undef copy_from_compat # define copy_from_compat copy_from_guest # undef copy_to_compat @@ -35,6 +40,7 @@ struct edd edd; #else extern spinlock_t xenpf_lock; extern struct edd edd; +extern struct ddc ddc; #endif ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) @@ -219,6 +225,21 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe else ret = -ESRCH; break; + case XEN_FW_DDC_INFO: + if ( op->u.firmware_info.index == 0 ) + { + op->u.firmware_info.u.ddc_info.capabilities = ddc.capabilities; + op->u.firmware_info.u.ddc_info.edid_transfer_time = ddc.edid_transfer_time; + if ( copy_field_to_guest(u_xenpf_op, op, u.firmware_info.u.ddc_info.capabilities) || + copy_field_to_guest(u_xenpf_op, op, u.firmware_info.u.ddc_info.edid_transfer_time) || + copy_to_compat(op->u.firmware_info.u.ddc_info.edid, + &ddc.edid[0], + ARRAY_SIZE(ddc.edid)) ) + ret = -EFAULT; + } + else + ret = -ESRCH; + break; default: ret = -EINVAL; break; @@ -238,11 +259,17 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe #ifndef COMPAT static int __init firmware_init(void) { + extern uint8_t ddc_capabilities, edid_transfer_time, edid[]; + memcpy(edd.mbr_signature, edd_mbr_sig_buf, sizeof(edd.mbr_signature)); memcpy(edd.edd_info, eddbuf, sizeof(edd.edd_info)); edd.mbr_signature_nr = edd_mbr_sig_nr_buf; edd.edd_info_nr = eddnr; + ddc.capabilities = ddc_capabilities; + ddc.edid_transfer_time = edid_transfer_time; + memcpy(ddc.edid, edid, sizeof(ddc.edid)); + return 0; } __initcall(firmware_init); Index: 2007-02-27/xen/include/public/platform.h ==================================================================--- 2007-02-27.orig/xen/include/public/platform.h 2007-02-21 14:51:00.000000000 +0100 +++ 2007-02-27/xen/include/public/platform.h 2007-02-22 16:10:04.000000000 +0100 @@ -119,6 +119,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_platform_q #define XEN_FW_EDD_INFO 2 /* from int 13 AH=41 */ #define XEN_FW_EDD_PARAMS 3 /* from int 13 AH=48 */ #define XEN_FW_MBR_SIGNATURE 4 +#define XEN_FW_DDC_INFO 5 /* from int 10 AX=4f15 */ struct xenpf_firmware_info { /* IN variables. */ uint32_t type; @@ -138,6 +139,12 @@ struct xenpf_firmware_info { /* first uint16_t of buffer must be set to buffer size */ XEN_GUEST_HANDLE(void) edd_params; uint32_t mbr_signature; + struct { + uint8_t capabilities; + uint8_t edid_transfer_time; + /* must refer to 128-byte buffer */ + XEN_GUEST_HANDLE(uint8_t) edid; + } ddc_info; } u; }; typedef struct xenpf_firmware_info xenpf_firmware_info_t; Index: 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c ==================================================================--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c 2007-02-22 16:38:02.000000000 +0100 +++ 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c 2007-02-22 16:43:00.000000000 +0100 @@ -155,6 +155,9 @@ struct sys_desc_table_struct { }; struct edid_info edid_info; EXPORT_SYMBOL_GPL(edid_info); +#ifndef CONFIG_XEN +#define copy_edid() (edid_info = EDID_INFO) +#endif struct ist_info ist_info; #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \ defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) @@ -1620,7 +1623,7 @@ void __init setup_arch(char **cmdline_p) ROOT_DEV = MKDEV(UNNAMED_MAJOR,0); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; - edid_info = EDID_INFO; + copy_edid(); apm_info.bios = APM_BIOS_INFO; ist_info = IST_INFO; saved_videomode = VIDEO_MODE; Index: 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c ==================================================================--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c 2007-02-22 16:38:02.000000000 +0100 +++ 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c 2007-02-22 16:41:54.000000000 +0100 @@ -613,7 +613,7 @@ void __init setup_arch(char **cmdline_p) } else screen_info.orig_video_isVGA = 0; - edid_info = EDID_INFO; + copy_edid(); saved_video_mode = SAVED_VIDEO_MODE; bootloader_type = LOADER_TYPE; Index: 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c ==================================================================--- 2007-02-27.orig/linux-2.6-xen-sparse/drivers/xen/core/firmware.c 2007-02-22 16:38:02.000000000 +0100 +++ 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c 2007-02-22 16:37:30.000000000 +0100 @@ -2,6 +2,7 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/edd.h> +#include <video/edid.h> #include <xen/interface/platform.h> #include <asm/hypervisor.h> @@ -59,3 +60,20 @@ void __init copy_edd(void) } } #endif + +void __init copy_edid(void) +{ +#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86) + xen_platform_op_t op; + + if (!is_initial_xendomain()) + return; + + op.cmd = XENPF_firmware_info; + op.u.firmware_info.index = 0; + op.u.firmware_info.type = XEN_FW_DDC_INFO; + set_xen_guest_handle(op.u.firmware_info.u.ddc_info.edid, edid_info.dummy); + if (HYPERVISOR_platform_op(&op) != 0) + memset(edid_info.dummy, 0x13, sizeof(edid_info.dummy)); +#endif +} Index: 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h ==================================================================--- 2007-02-27.orig/linux-2.6-xen-sparse/include/xen/firmware.h 2007-02-22 16:38:02.000000000 +0100 +++ 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h 2007-02-22 16:32:13.000000000 +0100 @@ -2,5 +2,6 @@ #define __XEN_FIRMWARE_H__ void copy_edd(void); +void copy_edid(void); #endif /* __XEN_FIRMWARE_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel