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

[Xen-changelog] [xen-unstable] x86: Allow selection of graphical video modes during boot.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1181487488 -3600
# Node ID 3cc79ef896a2c2a0586c987691322105e86e3612
# Parent  6d6b4b48773b7776e3762b998f23cd553f55f8ee
x86: Allow selection of graphical video modes during boot.

The 'vga=' boot option is extended as follows:

----------
 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:

   'vga=ask':
      display a vga menu of available modes

   'vga=text-80x<rows>':
      text mode, where <rows> is one of {25,28,30,34,43,50,60}

   'vga=gfx-<width>x<height>x<depth>':
      graphics mode, e.g., vga=gfx-1024x768x16

   'vga=mode-<mode>:
      specifies a mode as specified in 'vga=ask' menu
      (NB. menu modes are displayed in hex, so mode numbers here must
           be prefixed with '0x' (e.g., 'vga=mode-0x0318'))

 The option 'keep' causes Xen to continue to print to the VGA console even
 after domain 0 starts to boot. The default behaviour is to relinquish
 control of the console to domain 0.
----------

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/boot/Makefile     |    2 
 xen/arch/x86/boot/cmdline.S    |  285 +++++++++++
 xen/arch/x86/boot/head.S       |    6 
 xen/arch/x86/boot/trampoline.S |   11 
 xen/arch/x86/boot/video.S      |  994 +++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/boot/video.h      |   30 +
 xen/arch/x86/setup.c           |   82 +++
 xen/drivers/video/vga.c        |  646 ++------------------------
 xen/include/public/xen.h       |    2 
 xen/include/xen/vga.h          |    1 
 10 files changed, 1467 insertions(+), 592 deletions(-)

diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/Makefile
--- a/xen/arch/x86/boot/Makefile        Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/Makefile        Sun Jun 10 15:58:08 2007 +0100
@@ -1,3 +1,3 @@ obj-y += head.o
 obj-y += head.o
 
-head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S
+head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/cmdline.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/cmdline.S       Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,285 @@
+/******************************************************************************
+ * cmdline.S
+ *
+ * Early command-line parsing.
+ */
+
+        .code32
+
+#include "video.h"
+
+# NB. String pointer on stack is modified to point past parsed digits.
+.Latoi:
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        xor     %ebx,%ebx       /* %ebx = accumulator */
+        mov     $10,%ecx        /* %ecx = base (default base 10) */
+        mov     16+4(%esp),%esi /* %esi = pointer into ascii string. */
+        lodsb
+        cmpb    $'0',%al
+        jne     2f
+        mov     $8,%ecx         /* Prefix '0' => octal (base 8) */
+        lodsb
+        cmpb    $'x',%al
+        jne     2f
+        mov     $16,%ecx        /* Prefix '0x' => hex (base 16) */
+1:      lodsb
+2:      sub     $'0',%al
+        jb      4f
+        cmp     $9,%al
+        jbe     3f
+        sub     $'A'-'0'-10,%al
+        jb      4f
+        cmp     $15,%al
+        jbe     3f
+        sub     $'a'-'A',%al
+        jb      4f
+3:      cmp     %cl,%al
+        jae     4f
+        movzbl  %al,%eax
+        xchg    %eax,%ebx
+        mul     %ecx
+        xchg    %eax,%ebx
+        add     %eax,%ebx
+        jmp     1b
+4:      mov     %ebx,%eax
+        dec     %esi
+        mov     %esi,16+4(%esp)
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        ret
+
+.Lstrstr:
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+        xor     %eax,%eax
+        xor     %ecx,%ecx
+        not     %ecx
+        mov     16+4(%esp),%esi
+        mov     16+8(%esp),%edi
+        repne   scasb
+        not     %ecx
+        dec     %ecx
+        mov     %ecx,%edx
+1:      mov     16+8(%esp),%edi
+        mov     %esi,%eax
+        mov     %edx,%ecx
+        repe    cmpsb
+        je      2f
+        xchg    %eax,%esi
+        inc     %esi
+        cmpb    $0,-1(%eax)
+        jne     1b
+        xor     %eax,%eax
+2:      pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        ret
+
+.Lstr_prefix:
+        push    %esi
+        push    %edi
+        mov     8+4(%esp),%esi /* 1st arg is prefix string */
+        mov     8+8(%esp),%edi /* 2nd arg is main string */
+1:      lodsb
+        test    %al,%al
+        jz      2f
+        scasb
+        je      1b
+        sbb     %eax,%eax
+        or      $1,%al
+        jmp     3f
+2:      xor     %eax,%eax
+3:      pop     %edi
+        pop     %esi
+        ret
+
+.Lstrlen:
+        push    %ecx
+        push    %esi
+        push    %edi
+        xor     %eax,%eax
+        xor     %ecx,%ecx
+        not     %ecx
+        mov     12+4(%esp),%edi
+        repne   scasb
+        not     %ecx
+        dec     %ecx
+        mov     %ecx,%eax
+        pop     %edi
+        pop     %esi
+        pop     %ecx
+        ret
+
+.Lfind_option:
+        push    %ebx
+        push    4+8(%esp)
+        push    4+8(%esp)
+        call    .Lstrstr
+        add     $8,%esp
+        test    %eax,%eax
+        jz      3f
+        cmp     %eax,4+4(%esp)
+        je      1f
+        cmpb    $' ',-1(%eax)
+        jne     2f
+1:      mov     %eax,%ebx
+        push    4+8(%esp)
+        call    .Lstrlen
+        add     $4,%esp
+        xchg    %eax,%ebx
+        add     %eax,%ebx
+        cmpb    $'\0',(%ebx)
+        je      3f
+        cmpb    $' ',(%ebx)
+        je      3f
+        cmpb    $'=',(%ebx)
+        je      3f
+2:      xor     %eax,%eax
+3:      pop     %ebx
+        ret
+
+/* multiboot_info structure offsets. */
+#define MB_flags   0
+#define MB_cmdline 16
+
+cmdline_parse_early:
+        pusha
+
+        /* Bail if there is no command line to parse. */
+        mov     sym_phys(multiboot_ptr),%ebx
+        mov     MB_flags(%ebx),%eax
+        test    $4,%al
+        jz      1f
+        mov     MB_cmdline(%ebx),%eax
+        test    %eax,%eax
+        jz      1f
+
+        /* Check for 'no-real-mode' command-line option. */
+        pushl   $sym_phys(.Lno_rm_opt)
+        pushl   MB_cmdline(%ebx)
+        call    .Lfind_option
+        test    %eax,%eax
+        setnz   bootsym_phys(skip_realmode)
+
+        /* Check for 'vga=' command-line option. */
+        movl    $sym_phys(.Lvga_opt),4(%esp)
+        call    .Lfind_option
+        add     $8,%esp
+        test    %eax,%eax
+        jz      1f
+        cmpb    $'=',3(%eax)
+        jne     1f
+        add     $4,%eax
+
+        /* Found the 'vga=' option. Default option is to display vga menu. */
+        movw    $ASK_VGA,bootsym_phys(boot_vid_mode)
+
+        /* Check for 'vga=text-80x<rows>. */
+        mov     %eax,%ebx
+        push    %ebx
+        pushl   $sym_phys(.Lvga_text80)
+        call    .Lstr_prefix
+        add     $8,%esp
+        test    %eax,%eax
+        jnz     3f
+
+        /* We have 'vga=text-80x<rows>'. */
+        add     $8,%ebx
+        push    %ebx
+        call    .Latoi
+        add     $4,%esp
+        mov     %ax,%bx
+        lea     sym_phys(.Lvga_text_modes),%esi
+2:      lodsw
+        test    %ax,%ax
+        jz      1f
+        cmp     %ax,%bx
+        lodsw
+        jne     2b
+        mov     %ax,bootsym_phys(boot_vid_mode)
+        jmp     1f
+
+        /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
+3:      push    %ebx
+        pushl   $sym_phys(.Lvga_gfx)
+        call    .Lstr_prefix
+        add     $8,%esp
+        test    %eax,%eax
+        jnz     3f
+
+        /* We have 'vga=gfx-<width>x<height>x<depth>'. */
+        /* skip 'gfx-' */
+        add     $4,%ebx
+        /* parse <width> */
+        push    %ebx
+        call    .Latoi
+        pop     %esi
+        mov     %ax,bootsym_phys(vesa_size)+0
+        /* skip 'x' */
+        lodsb
+        cmpb    $'x',%al
+        jne     1f
+        /* parse <height> */
+        push    %esi
+        call    .Latoi
+        pop     %esi
+        mov     %ax,bootsym_phys(vesa_size)+2
+        /* skip 'x' */
+        lodsb
+        cmpb    $'x',%al
+        jne     1f
+        /* parse <depth> */
+        push    %esi
+        call    .Latoi
+        pop     %esi
+        mov     %ax,bootsym_phys(vesa_size)+4
+        /* commit to vesa mode */
+        movw    $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
+        jmp     1f
+
+        /* Check for 'vga=mode-<mode>'. */
+3:      push    %ebx
+        pushl   $sym_phys(.Lvga_mode)
+        call    .Lstr_prefix
+        add     $8,%esp
+        test    %eax,%eax
+        jnz     1f
+
+        /* We have 'vga=mode-<mode>'. */
+        add     $5,%ebx
+        push    %ebx
+        call    .Latoi
+        add     $4,%esp
+        mov     %ax,bootsym_phys(boot_vid_mode)
+
+1:      popa
+        ret
+
+.Lvga_text_modes: /* rows, mode_number */
+        .word   25,VIDEO_80x25
+        .word   50,VIDEO_80x50
+        .word   43,VIDEO_80x43
+        .word   28,VIDEO_80x28
+        .word   30,VIDEO_80x30
+        .word   34,VIDEO_80x34
+        .word   60,VIDEO_80x60
+        .word   0
+
+.Lvga_opt:
+        .asciz  "vga"
+.Lvga_text80:
+        .asciz  "text-80x"
+.Lvga_gfx:
+        .asciz  "gfx-"
+.Lvga_mode:
+        .asciz  "mode-"
+.Lno_rm_opt:
+        .asciz  "no-real-mode"
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/head.S
--- a/xen/arch/x86/boot/head.S  Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/head.S  Sun Jun 10 15:58:08 2007 +0100
@@ -73,6 +73,7 @@ __start:
         mov     $BOOT_DS,%ecx
         mov     %ecx,%ds
         mov     %ecx,%es
+        mov     %ecx,%ss
 
         /* Check for Multiboot bootloader */
         cmp     $0x2BADB002,%eax
@@ -166,8 +167,13 @@ 1:      stosl   /* low mappings cover up
         mov     $trampoline_end - trampoline_start,%ecx
         rep     movsb
 
+        mov     $0x98000,%esp
+        call    cmdline_parse_early
+
         /* Jump into the relocated trampoline. */
         jmp     $BOOT_CS32,$bootsym_phys(trampoline_boot_cpu_entry)
+
+#include "cmdline.S"
 
         .globl trampoline_start, trampoline_end
 trampoline_start:
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/trampoline.S
--- a/xen/arch/x86/boot/trampoline.S    Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/trampoline.S    Sun Jun 10 15:58:08 2007 +0100
@@ -6,7 +6,6 @@
 
         .globl trampoline_realmode_entry
 trampoline_realmode_entry:
-        nop                               # We use this byte as a progress flag
         movb    $0xA5,bootsym(trampoline_cpu_started)
         cld
         cli
@@ -117,6 +116,9 @@ high_start:
 
         .code32
 trampoline_boot_cpu_entry:
+        cmpb    $0,bootsym_phys(skip_realmode)
+        jnz     .Lskip_realmode
+
         /* Load pseudo-real-mode segments. */
         mov     $BOOT_PSEUDORM_DS,%eax
         mov     %eax,%ds
@@ -148,8 +150,10 @@ 1:      mov     $(BOOT_TRAMPOLINE>>4),%a
         /*
          * Do real-mode work:
          *  1. Get memory map.
+         *  2. Set video mode.
          */
         call    get_memory_map
+        call    video
 
         /* Disable irqs before returning to protected mode. */
         cli
@@ -170,12 +174,17 @@ 1:      mov     $BOOT_DS,%eax
         mov     %eax,%gs
         mov     %eax,%ss
 
+.Lskip_realmode:
         /* EBX == 0 indicates we are the BP (Boot Processor). */
         xor     %ebx,%ebx
 
         /* Jump to the common bootstrap entry point. */
         jmp     trampoline_protmode_entry
 
+skip_realmode:
+        .byte   0
+
 rm_idt: .word   256*4-1, 0, 0
 
 #include "mem.S"
+#include "video.S"
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/video.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/video.S Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,994 @@
+/******************************************************************************
+ * video.S
+ *
+ * Display adapter & video mode setup, version 2.13 (14-May-99)
+ *
+ * Copyright (C) 1995 -- 1998 Martin Mares <mj@xxxxxx>
+ * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
+ *
+ * Rewritten to use GNU 'as' by Chris Noe <stiker@xxxxxxxxxxxxx> May 1999
+ *
+ * Updated and ported for Xen by Keir Fraser <keir@xxxxxxxxxxxxx> June 2007
+ */
+
+        .code16
+
+#include "video.h"
+
+#define modelist (0x2000)
+
+/* Retrieve Extended Display Identification Data. */
+#define CONFIG_FIRMWARE_EDID
+
+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
+#undef CONFIG_VIDEO_400_HACK
+
+/* Positions of various video parameters passed to the kernel */
+/* (see also include/linux/tty.h) */
+#define PARAM_CURSOR_POS        0x00
+#define PARAM_VIDEO_MODE        0x02
+#define PARAM_VIDEO_COLS        0x03
+#define PARAM_VIDEO_LINES       0x04
+#define PARAM_HAVE_VGA          0x05
+#define PARAM_FONT_POINTS       0x06
+#define PARAM_CAPABILITIES      0x08
+#define PARAM_LFB_LINELENGTH    0x0c
+#define PARAM_LFB_WIDTH         0x0e
+#define PARAM_LFB_HEIGHT        0x10
+#define PARAM_LFB_DEPTH         0x12
+#define PARAM_LFB_BASE          0x14
+#define PARAM_LFB_SIZE          0x18
+#define PARAM_LFB_COLORS        0x1c
+#define PARAM_VESAPM_SEG        0x24
+#define PARAM_VESAPM_OFF        0x26
+#define _param(param) bootsym(boot_vid_info)+(param)
+
+video:  xorw    %ax, %ax
+        movw    %ax, %gs        # GS is zero
+        cld
+        call    basic_detect    # Basic adapter type testing (EGA/VGA/MDA/CGA)
+        cmpb    $0,_param(PARAM_HAVE_VGA)
+        je      1f                # Bail if there's no VGA
+        movw    bootsym(boot_vid_mode), %ax     # User selected video mode
+        cmpw    $ASK_VGA, %ax                   # Bring up the menu
+        jz      vid2
+
+        call    mode_set                        # Set the mode
+        jc      vid1
+
+        leaw    bootsym(badmdt), %si            # Invalid mode ID
+        call    prtstr
+vid2:   call    mode_menu
+vid1:   call    store_edid
+        call    mode_params                     # Store mode parameters
+1:      ret
+
+# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
+basic_detect:
+        movb    $0, _param(PARAM_HAVE_VGA)
+        movb    $0x12, %ah                      # Check EGA/VGA
+        movb    $0x10, %bl
+        int     $0x10
+        cmpb    $0x10, %bl                      # No, it's a CGA/MDA/HGA card.
+        je      basret
+        movw    $0x1a00, %ax                    # Check EGA or VGA?
+        int     $0x10
+        cmpb    $0x1a, %al                      # 1a means VGA...
+        jne     basret                          # anything else is EGA.
+        incb    _param(PARAM_HAVE_VGA)          # We've detected a VGA
+basret: ret
+
+# Store the video mode parameters for later usage by the kernel.
+# This is done by asking the BIOS except for the rows/columns
+# parameters in the default 80x25 mode -- these are set directly,
+# because some very obscure BIOSes supply insane values.
+mode_params:
+        cmpb    $0, bootsym(graphic_mode)
+        jnz     mopar_gr
+        movb    $0x03, %ah                      # Read cursor position
+        xorb    %bh, %bh
+        int     $0x10
+        movw    %dx, _param(PARAM_CURSOR_POS)
+        movb    $0x0f, %ah                      # Read page/mode/width
+        int     $0x10
+        movw    %ax, _param(PARAM_VIDEO_MODE)   # Video mode and screen width
+        movw    %gs:(0x485), %ax                # Font size
+        movw    %ax, _param(PARAM_FONT_POINTS)  # (valid only on EGA/VGA)
+        movw    bootsym(force_size), %ax        # Forced size?
+        orw     %ax, %ax
+        jz      mopar1
+
+        movb    %ah, _param(PARAM_VIDEO_COLS)
+        movb    %al, _param(PARAM_VIDEO_LINES)
+        ret
+
+mopar1: movb    %gs:(0x484), %al                # On EGA/VGA, use the EGA+ BIOS
+        incb    %al                             # location of max lines.
+mopar2: movb    %al, _param(PARAM_VIDEO_LINES)
+        ret
+
+# Fetching of VESA frame buffer parameters
+mopar_gr:
+        leaw    modelist+1024, %di
+        movb    $0x23, _param(PARAM_HAVE_VGA)
+        movw    16(%di), %ax
+        movw    %ax, _param(PARAM_LFB_LINELENGTH)
+        movw    18(%di), %ax
+        movw    %ax, _param(PARAM_LFB_WIDTH)
+        movw    20(%di), %ax
+        movw    %ax, _param(PARAM_LFB_HEIGHT)
+        movb    25(%di), %al
+        movb    $0, %ah
+        movw    %ax, _param(PARAM_LFB_DEPTH)
+        movl    40(%di), %eax
+        movl    %eax, _param(PARAM_LFB_BASE)
+        movl    31(%di), %eax
+        movl    %eax, _param(PARAM_LFB_COLORS)
+        movl    35(%di), %eax
+        movl    %eax, _param(PARAM_LFB_COLORS+4)
+
+# get video mem size
+        leaw    modelist+1024, %di
+        movw    $0x4f00, %ax
+        int     $0x10
+        xorl    %eax, %eax
+        movw    18(%di), %ax
+        movl    %eax, _param(PARAM_LFB_SIZE)
+
+# store mode capabilities
+        movl    10(%di), %eax
+        movl    %eax, _param(PARAM_CAPABILITIES)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+        movw    _param(PARAM_LFB_DEPTH), %ax
+        cmpw    $8, %ax
+        jg      dac_done
+
+# get DAC switching capability
+        xorl    %eax, %eax
+        movb    10(%di), %al
+        testb   $1, %al
+        jz      dac_set
+
+# attempt to switch DAC to 8-bit
+        movw    $0x4f08, %ax
+        movw    $0x0800, %bx
+        int     $0x10
+        cmpw    $0x004f, %ax
+        jne     dac_set
+        movb    %bh, bootsym(dac_size)          # store actual DAC size
+
+dac_set:
+# set color size to DAC size
+        movb    bootsym(dac_size), %al
+        movb    %al, _param(PARAM_LFB_COLORS+0)
+        movb    %al, _param(PARAM_LFB_COLORS+2)
+        movb    %al, _param(PARAM_LFB_COLORS+4)
+        movb    %al, _param(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+        movb    $0, _param(PARAM_LFB_COLORS+1)
+        movb    $0, _param(PARAM_LFB_COLORS+3)
+        movb    $0, _param(PARAM_LFB_COLORS+5)
+        movb    $0, _param(PARAM_LFB_COLORS+7)
+
+dac_done:
+# get protected mode interface informations
+        movw    $0x4f0a, %ax
+        xorw    %bx, %bx
+        xorw    %di, %di
+        int     $0x10
+        cmp     $0x004f, %ax
+        jnz     no_pm
+
+        movw    %es, _param(PARAM_VESAPM_SEG)
+        movw    %di, _param(PARAM_VESAPM_OFF)
+no_pm:  ret
+
+# The video mode menu
+mode_menu:
+        leaw    bootsym(keymsg), %si    # "Return/Space/Timeout" message
+        call    prtstr
+        call    flush
+nokey:  call    getkt
+
+        cmpb    $0x0d, %al              # ENTER ?
+        je      listm                   # yes - manual mode selection
+
+        cmpb    $0x20, %al              # SPACE ?
+        je      defmd1                  # no - repeat
+
+        call    beep
+        jmp     nokey
+
+defmd1: ret                             # No mode chosen? Default 80x25
+
+listm:  call    mode_table              # List mode table
+listm0: leaw    bootsym(name_bann), %si # Print adapter name
+        call    prtstr
+        movw    bootsym(card_name), %si
+        orw     %si, %si
+        jnz     an2
+
+        leaw    bootsym(vga_name), %si
+        jmp     an1
+
+an2:    call    prtstr
+        leaw    bootsym(svga_name), %si
+an1:    call    prtstr
+        leaw    bootsym(listhdr), %si   # Table header
+        call    prtstr
+        movb    $0x30, %dl              # DL holds mode number
+        leaw    modelist, %si
+lm1:    cmpw    $ASK_VGA, (%si)         # End?
+        jz      lm2
+
+        movb    %dl, %al                # Menu selection number
+        call    prtchr
+        call    prtsp2
+        lodsw
+        call    prthw                   # Mode ID
+        call    prtsp2
+        lodsw
+        call    prtdec                  # Width
+        movb    $0x78, %al              # the letter 'x'
+        call    prtchr
+        lodsw
+        call    prtdec                  # Height
+        testb   $0xff,(%si)
+        jnz     1f
+        push    %si
+        leaw    bootsym(textmode), %si
+        call    prtstr
+        pop     %si
+        lodsw
+        jmp     2f
+1:      movb    $0x78, %al              # the letter 'x'
+        call    prtchr
+        lodsw
+        call    prtdec                  # Depth
+2:      movb    $0x0d, %al              # New line
+        call    prtchr
+        movb    $0x0a, %al
+        call    prtchr
+        incb    %dl                     # Next character
+
+        cmpb    $'z'+1, %dl
+        jnz     skip_bail
+        leaw    bootsym(menu_bail_msg), %si
+        call    prtstr
+        jmp     lm2
+
+skip_bail:
+        cmpb    $'i', %dl
+        jnz     skip_pause
+        push    %si
+        push    %dx
+        leaw    bootsym(menu_more_msg), %si  # '<press space>'
+        call    prtstr
+        call    flush
+1:      call    getkey
+        cmpb    $0x20, %al              # SPACE ?
+        jne     1b                      # yes - manual mode selection
+        leaw    bootsym(crlft), %si
+        call    prtstr
+        pop     %dx
+        pop     %si
+
+skip_pause:
+        cmpb    $'9'+1, %dl
+        jnz     lm1
+        movb    $'a', %dl
+        jmp     lm1
+
+lm2:    leaw    bootsym(prompt), %si    # Mode prompt
+        call    prtstr
+        leaw    bootsym(edit_buf), %di  # Editor buffer
+lm3:    call    getkey
+        cmpb    $0x0d, %al              # Enter?
+        jz      lment
+
+        cmpb    $0x08, %al              # Backspace?
+        jz      lmbs
+
+        cmpb    $0x20, %al              # Printable?
+        jc      lm3
+
+        cmpw    $bootsym(edit_buf)+4, %di  # Enough space?
+        jz      lm3
+
+        stosb
+        call    prtchr
+        jmp     lm3
+
+lmbs:   cmpw    $bootsym(edit_buf), %di # Backspace
+        jz      lm3
+
+        decw    %di
+        movb    $0x08, %al
+        call    prtchr
+        call    prtspc
+        movb    $0x08, %al
+        call    prtchr
+        jmp     lm3
+        
+lment:  movb    $0, (%di)
+        leaw    bootsym(crlft), %si
+        call    prtstr
+        leaw    bootsym(edit_buf), %si
+        cmpb    $0, (%si)               # Empty string = default mode
+        jz      lmdef
+
+        cmpb    $0, 1(%si)              # One character = menu selection
+        jz      mnusel
+
+        cmpw    $0x656d, (%si)          # 'me'
+        jnz     lmhx
+        cmpw    $0x756e, 2(%si)         # 'nu'
+        jnz     lmhx
+        jmp     listm
+
+lmhx:   xorw    %bx, %bx                # Else => mode ID in hex
+lmhex:  lodsb
+        orb     %al, %al
+        jz      lmuse1
+
+        subb    $0x30, %al
+        jc      lmbad
+
+        cmpb    $10, %al
+        jc      lmhx1
+
+        subb    $7, %al
+        andb    $0xdf, %al
+        cmpb    $10, %al
+        jc      lmbad
+
+        cmpb    $16, %al
+        jnc     lmbad
+
+lmhx1:  shlw    $4, %bx
+        orb     %al, %bl
+        jmp     lmhex
+
+lmuse1: movw    %bx, %ax
+        jmp     lmuse
+
+mnusel: lodsb                           # Menu selection
+        xorb    %ah, %ah
+        subb    $0x30, %al
+        jc      lmbad
+
+        cmpb    $10, %al
+        jc      lmuse
+        
+        cmpb    $0x61-0x30, %al
+        jc      lmbad
+        
+        subb    $0x61-0x30-10, %al
+        cmpb    $36, %al
+        jnc     lmbad
+
+lmuse:  call    mode_set
+        jc      lmdef
+
+lmbad:  leaw    bootsym(unknt), %si
+        call    prtstr
+        jmp     mode_menu
+lmdef:  ret
+
+_setrec:    jmp setrec                  # Ugly...
+_set_80x25: jmp set_80x25
+
+# Setting of user mode (AX=mode ID) => CF=success
+mode_set:
+        movw    %ax, bootsym(boot_vid_mode)
+        movw    %ax, %bx
+
+        cmpw    $VIDEO_VESA_BY_SIZE, %ax
+        je      setvesabysize
+
+        testb   $VIDEO_RECALC>>8, %ah
+        jnz     _setrec
+
+        cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
+        jz      setspc
+
+        cmpb    $VIDEO_FIRST_VESA>>8, %ah
+        jnc     check_vesa
+
+        orb     %ah, %ah
+        jnz     setbad
+
+        jmp     setmenu
+
+setbad: clc
+        ret
+
+setspc: xorb    %bh, %bh                # Set special mode
+        cmpb    $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
+        jnc     setbad
+        
+        addw    %bx, %bx
+        jmp     *bootsym(spec_inits)(%bx)
+
+setmenu:
+        orb     %al, %al                # 80x25 is an exception
+        jz      _set_80x25
+        
+        pushw   %bx                     # Set mode chosen from menu
+        call    mode_table              # Build the mode table
+        popw    %ax
+        shlw    $3, %ax
+        addw    %ax, %si
+        cmpw    %di, %si
+        jnc     setbad
+        
+        movw    (%si), %ax              # Fetch mode ID
+        jmp     mode_set
+
+check_vesa:
+#ifdef CONFIG_FIRMWARE_EDID
+        leaw    modelist+1024, %di
+        movw    $0x4f00, %ax
+        int     $0x10
+        cmpw    $0x004f, %ax
+        jnz     setbad
+
+        movw    4(%di), %ax
+        movw    %ax, bootsym(vbe_version)
+#endif
+        leaw    modelist+1024, %di
+        subb    $VIDEO_FIRST_VESA>>8, %bh
+        movw    %bx, %cx                # Get mode information structure
+        movw    $0x4f01, %ax
+        int     $0x10
+        addb    $VIDEO_FIRST_VESA>>8, %bh
+        cmpw    $0x004f, %ax
+        jnz     setbad
+
+        movb    (%di), %al              # Check capabilities.
+        andb    $0x99, %al
+        cmpb    $0x99, %al
+        jnz     _setbad                 # Doh! No linear frame buffer.
+
+        subb    $VIDEO_FIRST_VESA>>8, %bh
+        orw     $0x4000, %bx            # Use linear frame buffer
+        movw    $0x4f02, %ax            # VESA BIOS mode set call
+        int     $0x10
+        cmpw    $0x004f, %ax            # AL=4f if implemented
+        jnz     _setbad                 # AH=0 if OK
+
+        movb    $1, bootsym(graphic_mode)  # flag graphic mode
+        stc
+        ret
+
+_setbad: jmp    setbad                  # Ugly...
+
+# Recalculate vertical display end registers -- this fixes various
+# inconsistencies of extended modes on many adapters. Called when
+# the VIDEO_RECALC flag is set in the mode ID.
+
+setrec: subb    $VIDEO_RECALC>>8, %ah   # Set the base mode
+        call    mode_set
+        jnc     rct3
+
+        movw    %gs:(0x485), %ax        # Font size in pixels
+        movb    %gs:(0x484), %bl        # Number of rows
+        incb    %bl
+        mulb    %bl                     # Number of visible
+        decw    %ax                     # scan lines - 1
+        movw    $0x3d4, %dx
+        movw    %ax, %bx
+        movb    $0x12, %al              # Lower 8 bits
+        movb    %bl, %ah
+        outw    %ax, %dx
+        movb    $0x07, %al              # Bits 8 and 9 in the overflow register
+        call    inidx
+        xchgb   %al, %ah
+        andb    $0xbd, %ah
+        shrb    %bh
+        jnc     rct1
+        orb     $0x02, %ah
+rct1:   shrb    %bh
+        jnc     rct2
+        orb     $0x40, %ah
+rct2:   movb    $0x07, %al
+        outw    %ax, %dx
+        stc
+rct3:   ret
+
+inidx:  outb    %al, %dx                # Read from indexed VGA register
+        incw    %dx                    # AL=index, DX=index reg port -> AL=data
+        inb     %dx, %al
+        decw    %dx
+        ret
+
+setvesabysize:
+        call    mode_table
+        leaw    modelist,%si
+1:      add     $8,%si
+        cmpw    $ASK_VGA,-8(%si)        # End?
+        je      _setbad
+        movw    -6(%si),%ax
+        cmpw    %ax,bootsym(vesa_size)+0
+        jne     1b
+        movw    -4(%si),%ax
+        cmpw    %ax,bootsym(vesa_size)+2
+        jne     1b
+        movw    -2(%si),%ax
+        cmpw    %ax,bootsym(vesa_size)+4
+        jne     1b
+        movw    -8(%si),%ax
+        movw    %ax,%bx
+        movw    %ax,bootsym(boot_vid_mode)
+        jmp     check_vesa
+
+# Table of routines for setting of the special modes.
+spec_inits:
+        .word   bootsym(set_80x25)
+        .word   bootsym(set_8pixel)
+        .word   bootsym(set_80x43)
+        .word   bootsym(set_80x28)
+        .word   bootsym(set_80x30)
+        .word   bootsym(set_80x34)
+        .word   bootsym(set_80x60)
+
+# Set the 80x25 mode. If already set, do nothing.
+set_80x25:
+        movw    $0x5019, bootsym(force_size)  # Override possibly broken BIOS
+use_80x25:
+        movw    $0x1202, %ax            # Force 400 scan lines
+        movb    $0x30, %bl
+        int     $0x10
+        movw    $0x0003, %ax            # Mode 3
+        int     $0x10
+        stc
+        ret
+
+# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
+set_8pixel:
+        call    use_80x25               # The base is 80x25
+set_8pt:
+        movw    $0x1112, %ax            # Use 8x8 font
+        xorb    %bl, %bl
+        int     $0x10
+        movw    $0x1200, %ax            # Use alternate print screen
+        movb    $0x20, %bl
+        int     $0x10
+        movw    $0x1201, %ax            # Turn off cursor emulation
+        movb    $0x34, %bl
+        int     $0x10
+        movb    $0x01, %ah              # Define cursor scan lines 6-7
+        movw    $0x0607, %cx
+        int     $0x10
+        stc
+        ret
+
+# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
+# 80x25 mode with 14-point fonts instead of 16-point.
+set_80x28:
+        call    use_80x25               # The base is 80x25
+set14:  movw    $0x1111, %ax            # Use 9x14 font
+        xorb    %bl, %bl
+        int     $0x10
+        movb    $0x01, %ah              # Define cursor scan lines 11-12
+        movw    $0x0b0c, %cx
+        int     $0x10
+        stc
+        ret
+
+# Set the 80x43 mode. This mode is works on all VGA's.
+# It's a 350-scanline mode with 8-pixel font.
+set_80x43:
+        movw    $0x1201, %ax            # Set 350 scans
+        movb    $0x30, %bl
+        int     $0x10
+        movw    $0x0003, %ax            # Reset video mode
+        int     $0x10
+        jmp     set_8pt                 # Use 8-pixel font
+
+# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
+set_80x30:
+        call    use_80x25               # Start with real 80x25
+        movw    $0x3cc, %dx             # Get CRTC port
+        inb     %dx, %al
+        movb    $0xd4, %dl
+        rorb    %al                     # Mono or color?
+        jc      set48a
+
+        movb    $0xb4, %dl
+set48a: movw    $0x0c11, %ax            # Vertical sync end (also unlocks 
CR0-7)
+        call    outidx
+        movw    $0x0b06, %ax            # Vertical total
+        call    outidx
+        movw    $0x3e07, %ax            # (Vertical) overflow
+        call    outidx
+        movw    $0xea10, %ax            # Vertical sync start
+        call    outidx
+        movw    $0xdf12, %ax            # Vertical display end
+        call    outidx
+        movw    $0xe715, %ax            # Vertical blank start
+        call    outidx
+        movw    $0x0416, %ax            # Vertical blank end
+        call    outidx
+        pushw   %dx
+        movb    $0xcc, %dl              # Misc output register (read)
+        inb     %dx, %al
+        movb    $0xc2, %dl              # (write)
+        andb    $0x0d, %al              # Preserve clock select bits and color 
bit
+        orb     $0xe2, %al              # Set correct sync polarity
+        outb    %al, %dx
+        popw    %dx
+        movw    $0x501e, bootsym(force_size)
+        stc                             # That's all.
+        ret
+
+# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
+set_80x34:
+        call    set_80x30               # Set 480 scans
+        call    set14                   # And 14-pt font
+        movw    $0xdb12, %ax            # VGA vertical display end
+        movw    $0x5022, bootsym(force_size)
+setvde: call    outidx
+        stc
+        ret
+
+# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
+set_80x60:
+        call    set_80x30               # Set 480 scans
+        call    set_8pt                 # And 8-pt font
+        movw    $0xdf12, %ax            # VGA vertical display end
+        movw    $0x503c, bootsym(force_size)
+        jmp     setvde
+
+# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
+outidx: outb    %al, %dx
+        pushw   %ax
+        movb    %ah, %al
+        incw    %dx
+        outb    %al, %dx
+        decw    %dx
+        popw    %ax
+        ret
+
+# Build the table of video modes (stored after the setup.S code at the
+# `modelist' label. Each video mode record looks like:
+#        .word        MODE-ID             (our special mode ID (see above))
+#        .byte        rows                (number of rows)
+#        .byte        columns             (number of columns)
+# Returns address of the end of the table in DI, the end is marked
+# with a ASK_VGA ID.
+mode_table:
+        movw    bootsym(mt_end), %di    # Already filled?
+        orw     %di, %di
+        jnz     mtab1
+
+        leaw    modelist, %di           # Store standard modes:
+        movw    $VIDEO_80x25,(%di)      # The 80x25 mode (ALL)
+        movw    $0x50,2(%di)
+        movw    $0x19,4(%di)
+        movw    $0x00,6(%di)
+        addw    $8,%di
+
+        leaw    bootsym(vga_modes), %si # All modes for std VGA
+        movw    $vga_modes_end-vga_modes, %cx
+        rep     movsb
+
+        call    vesa_modes              # Detect VESA VGA modes
+
+        movw    $ASK_VGA, (%di)         # End marker
+        movw    %di, bootsym(mt_end)
+mtab1:  leaw    modelist, %si           # SI=mode list, DI=list end
+ret0:   ret
+
+# Modes usable on all standard VGAs
+vga_modes:
+        .word   VIDEO_80x50, 0x50,0x32,0        # 80x50
+        .word   VIDEO_80x43, 0x50,0x2b,0        # 80x43
+        .word   VIDEO_80x28, 0x50,0x1c,0        # 80x28
+        .word   VIDEO_80x30, 0x50,0x1e,0        # 80x30
+        .word   VIDEO_80x34, 0x50,0x22,0        # 80x34
+        .word   VIDEO_80x60, 0x50,0x3c,0        # 80x60
+vga_modes_end:
+
+# Detect VESA modes.
+vesa_modes:
+        movw    %di, %bp                # BP=original mode table end
+        addw    $0x200, %di             # Buffer space
+        movw    $0x4f00, %ax            # VESA Get card info call
+        int     $0x10
+        movw    %bp, %di
+        cmpw    $0x004f, %ax            # Successful?
+        jnz     ret0
+        
+        cmpw    $0x4556, 0x200(%di)     # 'VE'
+        jnz     ret0
+        
+        cmpw    $0x4153, 0x202(%di)     # 'SA'
+        jnz     ret0
+        
+        movw    $bootsym(vesa_name), bootsym(card_name) # Set name to "VESA 
VGA"
+        pushw   %gs
+        lgsw    0x20e(%di), %si         # GS:SI=mode list
+        movw    $128, %cx               # Iteration limit
+vesa1:
+        gs;     lodsw
+        cmpw    $0xffff, %ax                        # End of the table?
+        jz      vesar
+        
+        cmpw    $0x0080, %ax                        # Check validity of mode ID
+        jc      vesa2
+        
+        orb     %ah, %ah        # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
+        jz      vesan                # Certain BIOSes report 0x80-0xff!
+
+        cmpw    $0x0800, %ax
+        jnc     vesae
+
+vesa2:  pushw   %cx
+        movw    %ax, %cx                # Get mode information structure
+        movw    $0x4f01, %ax
+        int     $0x10
+        movw    %cx, %bx                # BX=mode number
+        addb    $VIDEO_FIRST_VESA>>8, %bh
+        popw    %cx
+        cmpw    $0x004f, %ax
+        jnz     vesan                   # Don't report errors (buggy BIOSES)
+
+        movb    (%di), %al              # Check capabilities.
+        andb    $0x9b, %al              # LFB gfx mode in color?
+        cmpb    $0x9b, %al
+        jnz     vesan
+
+        movw    %bx, (%di)              # Store mode number
+        movw    0x12(%di), %bx          # Width
+        movw    %bx, 2(%di)
+        movw    0x14(%di), %bx          # Height
+        movw    %bx, 4(%di)
+        xorw    %bx, %bx
+        movb    0x19(%di), %bl          # Depth
+        movw    %bx, 6(%di)
+
+        addw    $8, %di                 # The mode is valid. Store it.
+vesan:  loop    vesa1                   # Next mode. Limit exceeded => error
+vesae:  leaw    bootsym(vesaer), %si
+        call    prtstr
+        movw    %bp, %di                # Discard already found modes.
+vesar:  popw    %gs
+        ret
+
+# Read a key and return the ASCII code in al, scan code in ah
+getkey: xorb    %ah, %ah
+        int     $0x16
+        ret
+
+# Read a key with a timeout of 30 seconds.
+# The hardware clock is used to get the time.
+getkt:  call    gettime
+        addb    $30, %al                # Wait 30 seconds
+        cmpb    $60, %al
+        jl      lminute
+
+        subb    $60, %al
+lminute:
+        movb    %al, %cl
+again:  movb    $0x01, %ah
+        int     $0x16
+        jnz     getkey                  # key pressed, so get it
+
+        call    gettime
+        cmpb    %cl, %al
+        jne     again
+
+        movb    $0x20, %al              # timeout, return `space'
+        ret
+
+# Flush the keyboard buffer
+flush:  movb    $0x01, %ah
+        int     $0x16
+        jz      empty
+        
+        xorb    %ah, %ah
+        int     $0x16
+        jmp     flush
+
+empty:  ret
+
+# Print hexadecimal number.
+prthw:  pushw   %ax
+        movb    %ah, %al
+        call    prthb
+        popw    %ax
+prthb:  pushw   %ax
+        shrb    $4, %al
+        call    prthn
+        popw    %ax
+        andb    $0x0f, %al
+prthn:  cmpb    $0x0a, %al
+        jc      prth1
+
+        addb    $0x07, %al
+prth1:  addb    $0x30, %al
+        jmp     prtchr
+
+# Print decimal number in ax
+prtdec: pushw   %ax
+        pushw   %cx
+        pushw   %dx
+        xorw    %dx, %dx
+        movw    $0x0a, %cx
+        divw    %cx
+        testw   %ax, %ax
+        jz      skip10
+        cmpw    $0x09, %ax
+        jbe     lt100
+
+        call    prtdec
+        jmp     skip10
+
+lt100:  addb    $0x30, %al
+        call    prtchr
+skip10: movb    %dl, %al
+        addb    $0x30, %al
+        call    prtchr        
+        popw    %dx
+        popw    %cx
+        popw    %ax
+        ret
+
+# Routine to print asciiz string at ds:si
+prtstr:
+        lodsb
+        andb    %al, %al
+        jz      fin
+
+        call    prtchr
+        jmp     prtstr
+
+fin:    ret
+
+# Space printing
+prtsp2: call    prtspc                  # Print double space
+prtspc: movb    $0x20, %al              # Print single space (note: fall-thru)
+
+# Part of above routine, this one just prints ascii al
+prtchr: pushw   %ax
+        pushw   %cx
+        movw    $7,%bx
+        movw    $0x01, %cx
+        movb    $0x0e, %ah
+        int     $0x10
+        popw    %cx
+        popw    %ax
+        ret
+
+beep:   movb    $0x07, %al
+        jmp     prtchr
+
+# Read the cmos clock. Return the seconds in al
+gettime:
+        pushw   %cx
+        movb    $0x02, %ah
+        int     $0x1a
+        movb    %dh, %al                # %dh contains the seconds
+        andb    $0x0f, %al
+        movb    %dh, %ah
+        movb    $0x04, %cl
+        shrb    %cl, %ah
+        aad
+        popw    %cx
+        ret
+
+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
+
+        cmpw    $0x0200, bootsym(vbe_version)  # only do EDID on >= VBE2.0
+        jl      no_edid
+
+        pushw   %es                     # save ES
+        xorw    %di, %di                # Report Capability
+        pushw   %di
+        popw    %es                     # ES:DI must be 0:0
+        movw    $0x4f15, %ax
+        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
+
+        movw    $0x4f15, %ax            # do VBE/DDC
+        movw    $0x01, %bx
+        movw    $0x00, %cx
+        movw    $0x00, %dx
+        movw    $0x140, %di
+        int     $0x10
+
+no_edid:
+        popw    %di                     # restore all registers
+        popw    %dx
+        popw    %cx
+        popw    %bx
+        popw    %ax
+        popw    %es
+#endif
+        ret
+
+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
+graphic_mode:   .byte   0       # Graphic mode with a linear frame buffer
+dac_size:       .byte   6       # DAC bit depth
+vbe_version:    .word   0       # VBE bios version
+
+# Status messages
+keymsg:         .ascii  "Press <RETURN> to see video modes available,"
+                .byte   0x0d, 0x0a
+                .ascii  "<SPACE> to continue or wait 30 secs"
+                .byte   0x0d, 0x0a, 0
+
+listhdr:        .byte   0x0d, 0x0a
+                .ascii  "MODE-KEY  MODE-ID  WIDTHxHEIGHTxDEPTH"
+
+crlft:          .byte   0x0d, 0x0a, 0
+
+prompt:         .byte   0x0d, 0x0a
+                .asciz  "Enter mode number or 'menu': "
+
+unknt:          .ascii  "Unknown mode ID. Try again."
+                .byte   0x0d, 0x0a, 0
+
+badmdt:         .ascii  "You passed an undefined mode number."
+                .byte   0x0d, 0x0a, 0
+
+vesaer:         .ascii  "Error: Scanning of VESA modes failed. Please "
+                .ascii  "report to <mj@xxxxxx>."
+                .byte   0x0d, 0x0a, 0
+
+textmode:       .asciz  " (text)"
+menu_more_msg:  .asciz  "<press SPACE for more>"
+menu_bail_msg:  .ascii  "<menu truncated>"
+                .byte   0x0d, 0x0a, 0
+
+svga_name:      .ascii  " "
+
+vga_name:       .asciz  "VGA"
+
+vesa_name:      .asciz  "VESA"
+
+name_bann:      .asciz  "Video adapter: "
+
+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
+/* 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 */
+                .byte   3       /* text mode 3    */
+                .byte   80, 25  /* 80x25          */
+                .byte   1       /* isVGA          */
+                .word   16      /* 8x16 font      */
+                .fill   0x28,1,0
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/video.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/video.h Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,30 @@
+#ifndef __BOOT_VIDEO_H__
+#define __BOOT_VIDEO_H__
+
+/*
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU    0x0000
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA    0x0200
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25         0x0f00
+#define VIDEO_80x50         0x0f01
+#define VIDEO_80x43         0x0f02
+#define VIDEO_80x28         0x0f03
+#define VIDEO_80x30         0x0f04
+#define VIDEO_80x34         0x0f05
+#define VIDEO_80x60         0x0f06
+#define VIDEO_LAST_SPECIAL  0x0f07
+
+#define ASK_VGA             0xfffd
+#define VIDEO_VESA_BY_SIZE  0xffff
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC        0x8000
+
+#endif /* __BOOT_VIDEO_H__ */
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/setup.c      Sun Jun 10 15:58:08 2007 +0100
@@ -18,6 +18,7 @@
 #include <xen/keyhandler.h>
 #include <xen/numa.h>
 #include <xen/rcupdate.h>
+#include <xen/vga.h>
 #include <public/version.h>
 #ifdef CONFIG_COMPAT
 #include <compat/platform.h>
@@ -313,6 +314,69 @@ static void __init reserve_in_boot_e820(
             boot_e820.map[i].addr = e;
             boot_e820.map[i].size = re - e;
         }
+    }
+}
+
+struct boot_video_info {
+    u8  orig_x;             /* 0x00 */
+    u8  orig_y;             /* 0x01 */
+    u8  orig_video_mode;    /* 0x02 */
+    u8  orig_video_cols;    /* 0x03 */
+    u8  orig_video_lines;   /* 0x04 */
+    u8  orig_video_isVGA;   /* 0x05 */
+    u16 orig_video_points;  /* 0x06 */
+
+    /* VESA graphic mode -- linear frame buffer */
+    u32 capabilities;       /* 0x08 */
+    u16 lfb_linelength;     /* 0x0c */
+    u16 lfb_width;          /* 0x0e */
+    u16 lfb_height;         /* 0x10 */
+    u16 lfb_depth;          /* 0x12 */
+    u32 lfb_base;           /* 0x14 */
+    u32 lfb_size;           /* 0x18 */
+    u8  red_size;           /* 0x1c */
+    u8  red_pos;            /* 0x1d */
+    u8  green_size;         /* 0x1e */
+    u8  green_pos;          /* 0x1f */
+    u8  blue_size;          /* 0x20 */
+    u8  blue_pos;           /* 0x21 */
+    u8  rsvd_size;          /* 0x22 */
+    u8  rsvd_pos;           /* 0x23 */
+    u16 vesapm_seg;         /* 0x24 */
+    u16 vesapm_off;         /* 0x26 */
+};
+
+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) )
+    {
+        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
+        vga_console_info.u.text_mode_3.font_height = bvi->orig_video_points;
+        vga_console_info.u.text_mode_3.cursor_x = bvi->orig_x;
+        vga_console_info.u.text_mode_3.cursor_y = bvi->orig_y;
+        vga_console_info.u.text_mode_3.rows = bvi->orig_video_lines;
+        vga_console_info.u.text_mode_3.columns = bvi->orig_video_cols;
+    }
+    else if ( bvi->orig_video_isVGA == 0x23 )
+    {
+        vga_console_info.video_type = XEN_VGATYPE_VESA_LFB;
+        vga_console_info.u.vesa_lfb.width = bvi->lfb_width;
+        vga_console_info.u.vesa_lfb.height = bvi->lfb_height;
+        vga_console_info.u.vesa_lfb.bytes_per_line = bvi->lfb_linelength;
+        vga_console_info.u.vesa_lfb.bits_per_pixel = bvi->lfb_depth;
+        vga_console_info.u.vesa_lfb.lfb_base = bvi->lfb_base;
+        vga_console_info.u.vesa_lfb.lfb_size = bvi->lfb_size;
+        vga_console_info.u.vesa_lfb.red_pos = bvi->red_pos;
+        vga_console_info.u.vesa_lfb.red_size = bvi->red_size;
+        vga_console_info.u.vesa_lfb.green_pos = bvi->green_pos;
+        vga_console_info.u.vesa_lfb.green_size = bvi->green_size;
+        vga_console_info.u.vesa_lfb.blue_pos = bvi->blue_pos;
+        vga_console_info.u.vesa_lfb.blue_size = bvi->blue_size;
+        vga_console_info.u.vesa_lfb.rsvd_pos = bvi->rsvd_pos;
+        vga_console_info.u.vesa_lfb.rsvd_size = bvi->rsvd_size;
     }
 }
 
@@ -359,6 +423,8 @@ void __init __start_xen(multiboot_info_t
         cmdline = __va(mbi->cmdline);
     cmdline_parse(cmdline);
 
+    parse_video_info();
+
     set_current((struct vcpu *)0xfffff000); /* debug sanity */
     idle_vcpu[0] = current;
     set_processor_id(0); /* needed early, for smp_processor_id() */
@@ -377,6 +443,22 @@ void __init __start_xen(multiboot_info_t
     init_console();
 
     printk("Command line: %s\n", cmdline);
+
+    switch ( vga_console_info.video_type )
+    {
+    case XEN_VGATYPE_TEXT_MODE_3:
+        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",
+               vga_console_info.u.vesa_lfb.width,
+               vga_console_info.u.vesa_lfb.height,
+               vga_console_info.u.vesa_lfb.bits_per_pixel);
+        break;
+    }
 
     /* Check that we have at least one Multiboot module. */
     if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/drivers/video/vga.c
--- a/xen/drivers/video/vga.c   Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/drivers/video/vga.c   Sun Jun 10 15:58:08 2007 +0100
@@ -17,559 +17,43 @@
 #include <asm/io.h>
 #include "font.h"
 
-/* Some of the code below is taken from SVGAlib.  The original,
-   unmodified copyright notice for that code is below. */
-/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
-/*                                                                 */
-/* This library is free software; you can redistribute it and/or   */
-/* modify it without any restrictions. This library is distributed */
-/* in the hope that it will be useful, but without any warranty.   */
-
-/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
-/* partially copyrighted (C) 1993 by Hartmut Schirmer */
-
-/* VGA data register ports */
-#define VGA_CRT_DC     0x3D5   /* CRT Controller Data Register - color 
emulation */
-#define VGA_CRT_DM     0x3B5   /* CRT Controller Data Register - mono 
emulation */
-#define VGA_ATT_R      0x3C1   /* Attribute Controller Data Read Register */
-#define VGA_ATT_W      0x3C0   /* Attribute Controller Data Write Register */
-#define VGA_GFX_D      0x3CF   /* Graphics Controller Data Register */
-#define VGA_SEQ_D      0x3C5   /* Sequencer Data Register */
-#define VGA_MIS_R      0x3CC   /* Misc Output Read Register */
-#define VGA_MIS_W      0x3C2   /* Misc Output Write Register */
-#define VGA_FTC_R      0x3CA   /* Feature Control Read Register */
-#define VGA_IS1_RC     0x3DA   /* Input Status Register 1 - color emulation */
-#define VGA_IS1_RM     0x3BA   /* Input Status Register 1 - mono emulation */
-#define VGA_PEL_D      0x3C9   /* PEL Data Register */
-#define VGA_PEL_MSK    0x3C6   /* PEL mask register */
-
-/* EGA-specific registers */
-#define EGA_GFX_E0     0x3CC   /* Graphics enable processor 0 */
-#define EGA_GFX_E1     0x3CA   /* Graphics enable processor 1 */
-
-/* VGA index register ports */
-#define VGA_CRT_IC     0x3D4   /* CRT Controller Index - color emulation */
-#define VGA_CRT_IM     0x3B4   /* CRT Controller Index - mono emulation */
-#define VGA_ATT_IW     0x3C0   /* Attribute Controller Index & Data Write 
Register */
-#define VGA_GFX_I      0x3CE   /* Graphics Controller Index */
-#define VGA_SEQ_I      0x3C4   /* Sequencer Index */
-#define VGA_PEL_IW     0x3C8   /* PEL Write Index */
-#define VGA_PEL_IR     0x3C7   /* PEL Read Index */
-
-/* standard VGA indexes max counts */
-#define VGA_CRT_C      0x19    /* Number of CRT Controller Registers */
-#define VGA_ATT_C      0x15    /* Number of Attribute Controller Registers */
-#define VGA_GFX_C      0x09    /* Number of Graphics Controller Registers */
-#define VGA_SEQ_C      0x05    /* Number of Sequencer Registers */
-#define VGA_MIS_C      0x01    /* Number of Misc Output Register */
-
-/* VGA misc register bit masks */
-#define VGA_MIS_COLOR          0x01
-#define VGA_MIS_ENB_MEM_ACCESS 0x02
-#define VGA_MIS_DCLK_28322_720 0x04
-#define VGA_MIS_ENB_PLL_LOAD   (0x04 | 0x08)
-#define VGA_MIS_SEL_HIGH_PAGE  0x20
-
-/* VGA CRT controller register indices */
-#define VGA_CRTC_H_TOTAL       0
-#define VGA_CRTC_H_DISP                1
-#define VGA_CRTC_H_BLANK_START 2
-#define VGA_CRTC_H_BLANK_END   3
-#define VGA_CRTC_H_SYNC_START  4
-#define VGA_CRTC_H_SYNC_END    5
-#define VGA_CRTC_V_TOTAL       6
-#define VGA_CRTC_OVERFLOW      7
-#define VGA_CRTC_PRESET_ROW    8
-#define VGA_CRTC_MAX_SCAN      9
-#define VGA_CRTC_CURSOR_START  0x0A
-#define VGA_CRTC_CURSOR_END    0x0B
-#define VGA_CRTC_START_HI      0x0C
-#define VGA_CRTC_START_LO      0x0D
-#define VGA_CRTC_CURSOR_HI     0x0E
-#define VGA_CRTC_CURSOR_LO     0x0F
-#define VGA_CRTC_V_SYNC_START  0x10
-#define VGA_CRTC_V_SYNC_END    0x11
-#define VGA_CRTC_V_DISP_END    0x12
-#define VGA_CRTC_OFFSET                0x13
-#define VGA_CRTC_UNDERLINE     0x14
-#define VGA_CRTC_V_BLANK_START 0x15
-#define VGA_CRTC_V_BLANK_END   0x16
-#define VGA_CRTC_MODE          0x17
-#define VGA_CRTC_LINE_COMPARE  0x18
-#define VGA_CRTC_REGS          VGA_CRT_C
-
-/* VGA CRT controller bit masks */
-#define VGA_CR11_LOCK_CR0_CR7  0x80 /* lock writes to CR0 - CR7 */
-#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
-
-/* VGA attribute controller register indices */
-#define VGA_ATC_PALETTE0       0x00
-#define VGA_ATC_PALETTE1       0x01
-#define VGA_ATC_PALETTE2       0x02
-#define VGA_ATC_PALETTE3       0x03
-#define VGA_ATC_PALETTE4       0x04
-#define VGA_ATC_PALETTE5       0x05
-#define VGA_ATC_PALETTE6       0x06
-#define VGA_ATC_PALETTE7       0x07
-#define VGA_ATC_PALETTE8       0x08
-#define VGA_ATC_PALETTE9       0x09
-#define VGA_ATC_PALETTEA       0x0A
-#define VGA_ATC_PALETTEB       0x0B
-#define VGA_ATC_PALETTEC       0x0C
-#define VGA_ATC_PALETTED       0x0D
-#define VGA_ATC_PALETTEE       0x0E
-#define VGA_ATC_PALETTEF       0x0F
-#define VGA_ATC_MODE           0x10
-#define VGA_ATC_OVERSCAN       0x11
-#define VGA_ATC_PLANE_ENABLE   0x12
-#define VGA_ATC_PEL            0x13
-#define VGA_ATC_COLOR_PAGE     0x14
-
-#define VGA_AR_ENABLE_DISPLAY  0x20
-
-/* VGA sequencer register indices */
-#define VGA_SEQ_RESET          0x00
-#define VGA_SEQ_CLOCK_MODE     0x01
-#define VGA_SEQ_PLANE_WRITE    0x02
-#define VGA_SEQ_CHARACTER_MAP  0x03
-#define VGA_SEQ_MEMORY_MODE    0x04
-
-/* VGA sequencer register bit masks */
-#define VGA_SR01_CHAR_CLK_8DOTS        0x01 /* bit 0: character clocks 8 dots 
wide are generated */
-#define VGA_SR01_SCREEN_OFF    0x20 /* bit 5: Screen is off */
-#define VGA_SR02_ALL_PLANES    0x0F /* bits 3-0: enable access to all planes */
-#define VGA_SR04_EXT_MEM       0x02 /* bit 1: allows complete mem access to 
256K */
-#define VGA_SR04_SEQ_MODE      0x04 /* bit 2: directs system to use a 
sequential addressing mode */
-#define VGA_SR04_CHN_4M                0x08 /* bit 3: selects modulo 4 
addressing for CPU access to display memory */
-
-/* VGA graphics controller register indices */
-#define VGA_GFX_SR_VALUE       0x00
-#define VGA_GFX_SR_ENABLE      0x01
-#define VGA_GFX_COMPARE_VALUE  0x02
-#define VGA_GFX_DATA_ROTATE    0x03
-#define VGA_GFX_PLANE_READ     0x04
-#define VGA_GFX_MODE           0x05
-#define VGA_GFX_MISC           0x06
-#define VGA_GFX_COMPARE_MASK   0x07
-#define VGA_GFX_BIT_MASK       0x08
-
-/* VGA graphics controller bit masks */
-#define VGA_GR06_GRAPHICS_MODE 0x01
-
-/* macro for composing an 8-bit VGA register index and value
- * into a single 16-bit quantity */
-#define VGA_OUT16VAL(v, r)       (((v) << 8) | (r))
-
-#define vgabase 0         /* use in/out port-access macros  */
-#define VGA_OUTW_WRITE    /* can use outw instead of 2xoutb */
-
-/*
- * generic VGA port read/write
- */
- 
-static inline uint8_t vga_io_r(uint16_t port)
-{
-    return inb(port);
-}
-
-static inline void vga_io_w(uint16_t port, uint8_t val)
-{
-    outb(val, port);
-}
-
-static inline void vga_io_w_fast(uint16_t port, uint8_t reg, uint8_t val)
-{
-    outw(VGA_OUT16VAL(val, reg), port);
-}
-
-static inline uint8_t vga_mm_r(void __iomem *regbase, uint16_t port)
-{
-    return readb((char *)regbase + port);
-}
-
-static inline void vga_mm_w(void __iomem *regbase, uint16_t port, uint8_t val)
-{
-    writeb(val, (char *)regbase + port);
-}
-
-static inline void vga_mm_w_fast(void __iomem *regbase, uint16_t port, uint8_t 
reg, uint8_t val)
-{
-    writew(VGA_OUT16VAL(val, reg), (char *)regbase + port);
-}
-
-static inline uint8_t vga_r(void __iomem *regbase, uint16_t port)
-{
-    if (regbase)
-        return vga_mm_r(regbase, port);
-    else
-        return vga_io_r(port);
-}
-
-static inline void vga_w(void __iomem *regbase, uint16_t port, uint8_t val)
-{
-    if (regbase)
-        vga_mm_w(regbase, port, val);
-    else
-        vga_io_w(port, val);
-}
-
-
-static inline void vga_w_fast(void __iomem *regbase, uint16_t port, uint8_t 
reg, uint8_t val)
-{
-    if (regbase)
-        vga_mm_w_fast(regbase, port, reg, val);
-    else
-        vga_io_w_fast(port, reg, val);
-}
-
-
-/*
- * VGA CRTC register read/write
- */
- 
-static inline uint8_t vga_rcrt(void __iomem *regbase, uint8_t reg)
-{
-    vga_w(regbase, VGA_CRT_IC, reg);
-    return vga_r(regbase, VGA_CRT_DC);
-}
-
-static inline void vga_wcrt(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
-    vga_w_fast(regbase, VGA_CRT_IC, reg, val);
-#else
-    vga_w(regbase, VGA_CRT_IC, reg);
-    vga_w(regbase, VGA_CRT_DC, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA sequencer register read/write
- */
- 
-static inline uint8_t vga_rseq(void __iomem *regbase, uint8_t reg)
-{
-    vga_w(regbase, VGA_SEQ_I, reg);
-    return vga_r(regbase, VGA_SEQ_D);
-}
-
-static inline void vga_wseq(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
-    vga_w_fast(regbase, VGA_SEQ_I, reg, val);
-#else
-    vga_w(regbase, VGA_SEQ_I, reg);
-    vga_w(regbase, VGA_SEQ_D, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA graphics controller register read/write
- */
- 
-static inline uint8_t vga_rgfx(void __iomem *regbase, uint8_t reg)
-{
-    vga_w(regbase, VGA_GFX_I, reg);
-    return vga_r(regbase, VGA_GFX_D);
-}
-
-static inline void vga_wgfx(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
-    vga_w_fast(regbase, VGA_GFX_I, reg, val);
-#else
-    vga_w(regbase, VGA_GFX_I, reg);
-    vga_w(regbase, VGA_GFX_D, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA attribute controller register read/write
- */
- 
-static inline uint8_t vga_rattr(void __iomem *regbase, uint8_t reg)
-{
-    vga_w(regbase, VGA_ATT_IW, reg);
-    return vga_r(regbase, VGA_ATT_R);
-}
-
-static inline void vga_wattr(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-    vga_w(regbase, VGA_ATT_IW, reg);
-    vga_w(regbase, VGA_ATT_W, val);
-}
-
-static int __init detect_video(void *video_base)
-{
-    volatile u16 *p = (volatile u16 *)video_base;
-    u16 saved1 = p[0], saved2 = p[1];
-    int video_found = 1;
-
-    p[0] = 0xAA55;
-    p[1] = 0x55AA;
-    if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
-        video_found = 0;
-
-    p[0] = 0x55AA;
-    p[1] = 0xAA55;
-    if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
-        video_found = 0;
-
-    p[0] = saved1;
-    p[1] = saved2;
-
-    return video_found;
-}
-
-/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
-static void * __init setup_vga(void)
-{
-    /* The following VGA state was saved from a chip in text mode 3. */
-    static unsigned char regs[] = {
-        /* Sequencer registers */
-        0x03, 0x00, 0x03, 0x00, 0x02,
-        /* CRTC registers */
-        0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
-        0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
-        0xb9, 0xa3, 0xff,
-        /* Graphic registers */
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
-        /* Attribute registers */
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
-        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
-    };
-
-    char *video;
-    int i, j;
-
-    if ( memory_is_conventional_ram(0xB8000) )
-        goto no_vga;
-
-    inb(VGA_IS1_RC);
-    outb(0x00, VGA_ATT_IW);
-    
-    for ( i = j = 0; i < 5;  i++ )
-        vga_wseq(vgabase, i, regs[j++]);
-    
-    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
-    vga_wcrt(vgabase, 17, regs[5+17] & 0x7F);
-    
-    for ( i = 0; i < 25; i++ ) 
-        vga_wcrt(vgabase, i, regs[j++]);
-    
-    for ( i = 0; i < 9;  i++ )
-        vga_wgfx(vgabase, i, regs[j++]);
-    
-    inb(VGA_IS1_RC);
-    for ( i = 0; i < 21; i++ )
-        vga_wattr(vgabase, i, regs[j++]);
-    
-    inb(VGA_IS1_RC);
-    outb(0x20, VGA_ATT_IW);
-
-    video = ioremap(0xB8000, 0x8000);
-
-    if ( !detect_video(video) )
-    {
-        iounmap(video);
-        goto no_vga;
-    }
-
-    return video;
-
- no_vga:
-    printk("No VGA adaptor detected!\n");
-    return NULL;
-}
-
-static int __init vga_set_scanlines(unsigned scanlines)
-{
-    unsigned vtot, ovr, vss, vbs;
-    uint8_t vse, vbe, misc = 0;
-
-    switch (scanlines) {
-    case 43*8:
-        vtot = 0x1bf;
-        vss = 0x183;
-        vse = 0x05;
-        vbs = 0x163;
-        vbe = 0xba;
-        break;
-    case 25*16:
-    case 28*14:
-        vtot = 0x1bf;
-        vss = 0x19c;
-        vse = 0x0e;
-        vbs = 0x196;
-        vbe = 0xb9;
-        break;
-    case 30*16:
-    case 34*14:
-        vtot = 0x20b;
-        vss = 0x1ea;
-        vse = 0x0c;
-        vbs = 0x1e7;
-        vbe = 0x04;
-        /* Preserve clock select bits and color bit, set correct sync 
polarity. */
-        misc = (inb(VGA_MIS_R) & 0x0d) | 0xe2;
-        break;
-    default:
-        return -ENOSYS;
-    }
-
-    ovr = vga_rcrt(vgabase, VGA_CRTC_OVERFLOW);
-    if(vga_rcrt(vgabase, VGA_CRTC_V_DISP_END) + ((ovr & 0x02) << 7) + ((ovr & 
0x40) << 3) == scanlines - 1)
-        return 0;
-
-    ovr = (ovr & 0x10)
-        | ((vtot >> 8) & 0x01)
-        | ((vtot >> 4) & 0x20)
-        | (((scanlines - 1) >> 7) & 0x02)
-        | (((scanlines - 1) >> 3) & 0x40)
-        | ((vss >> 6) & 0x04)
-        | ((vss >> 2) & 0x80)
-        | ((vbs >> 5) & 0x08);
-    vse |= vga_rcrt(vgabase, VGA_CRTC_V_SYNC_END) & 0x70;
-
-    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse & 0x7f); /* Vertical sync end 
(also unlocks CR0-7) */
-    vga_wcrt(vgabase, VGA_CRTC_V_TOTAL, (uint8_t)vtot); /* Vertical total */
-    vga_wcrt(vgabase, VGA_CRTC_OVERFLOW, (uint8_t)ovr); /* Overflow */
-    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_START, (uint8_t)vss); /* Vertical sync 
start */
-    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse | 0x80); /* Vertical sync end 
(also locks CR0-7) */
-    vga_wcrt(vgabase, VGA_CRTC_V_DISP_END, (uint8_t)(scanlines - 1)); /* 
Vertical display end */
-    vga_wcrt(vgabase, VGA_CRTC_V_BLANK_START, (uint8_t)vbs); /* Vertical blank 
start */
-    vga_wcrt(vgabase, VGA_CRTC_V_BLANK_END, vbe); /* Vertical blank end */
-
-    if (misc)
-        outb(misc, VGA_MIS_W); /* Misc output register */
-
-    return 0;
-}
-
-#define FONT_COUNT_MAX 256
-#define FONT_HEIGHT_MAX 32
-#define CHAR_MAP_SIZE (FONT_COUNT_MAX * FONT_HEIGHT_MAX)
-
-/*
- * We use font slot 0 because ATI cards do not honour changes to the
- * character map select register. The fontslot parameter can be used to
- * choose a non-default slot if the video card supports it and you wish to
- * preserve the BIOS-initialised font data.
- */
-static unsigned font_slot = 0;
-integer_param("fontslot", font_slot);
-
-static int __init vga_load_font(const struct font_desc *font, unsigned rows)
-{
-    unsigned fontheight = font ? font->height : 16;
-    uint8_t fsr = vga_rcrt(vgabase, VGA_CRTC_MAX_SCAN); /* Font size register 
*/
-    int ret;
-
-    if (font_slot > 3 || (!font_slot && !font))
-        return -ENOSYS;
-
-    if (font
-        && (font->count > FONT_COUNT_MAX
-            || fontheight > FONT_HEIGHT_MAX
-            || font->width != 8))
-        return -EINVAL;
-
-    ret = vga_set_scanlines(rows * fontheight);
-    if (ret < 0)
-        return ret;
-
-    if ((fsr & 0x1f) == fontheight - 1)
-        return 0;
-
-    /* First, the Sequencer */
-    vga_wseq(vgabase, VGA_SEQ_RESET, 0x1);
-    /* CPU writes only to map 2 */
-    vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
-    /* Sequential addressing */
-    vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
-    /* Clear synchronous reset */
-    vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
-
-    /* Now, the graphics controller, select map 2 */
-    vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x02);
-    /* disable odd-even addressing */
-    vga_wgfx(vgabase, VGA_GFX_MODE, 0x00);
-    /* map start at A000:0000 */
-    vga_wgfx(vgabase, VGA_GFX_MISC, 0x00);
-
-    if ( font )
-    {
-        unsigned i, j;
-        const uint8_t *data = font->data;
-        uint8_t *map;
-
-        map = ioremap(0xA0000 + font_slot*2*CHAR_MAP_SIZE, CHAR_MAP_SIZE);
-
-        for ( i = j = 0; i < CHAR_MAP_SIZE; )
-        {
-            writeb(j < font->count * fontheight ? data[j++] : 0, map + i++);
-            if ( !(j % fontheight) )
-                while ( i & (FONT_HEIGHT_MAX - 1) )
-                    writeb(0, map + i++);
-        }
-
-        iounmap(map);
-    }
-
-    /* First, the sequencer, Synchronous reset */
-    vga_wseq(vgabase, VGA_SEQ_RESET, 0x01);
-    /* CPU writes to maps 0 and 1 */
-    vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
-    /* odd-even addressing */
-    vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
-    /* Character Map Select: The default font is kept in slot 0. */
-    vga_wseq(vgabase, VGA_SEQ_CHARACTER_MAP,
-             font ? font_slot | (font_slot << 2) : 0x00);
-    /* clear synchronous reset */
-    vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
-
-    /* Now, the graphics controller, select map 0 for CPU */
-    vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x00);
-    /* enable even-odd addressing */
-    vga_wgfx(vgabase, VGA_GFX_MODE, 0x10);
-    /* map starts at b800:0 */
-    vga_wgfx(vgabase, VGA_GFX_MISC, 0x0e);
-
-    /* Font size register */
-    fsr = (fsr & 0xe0) + (fontheight - 1);
-    vga_wcrt(vgabase, VGA_CRTC_MAX_SCAN, fsr);
-
-    /* Cursor shape registers */
-    fsr  = vga_rcrt(vgabase, VGA_CRTC_CURSOR_END) & 0xe0;
-    fsr |= fontheight - fontheight / 6;
-    vga_wcrt(vgabase, VGA_CRTC_CURSOR_END, fsr);
-    fsr  = vga_rcrt(vgabase, VGA_CRTC_CURSOR_START) & 0xe0;
-    fsr |= (fsr & 0x1f) - 1;
-    vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, fsr);
-
-    return 0;
-}
-
-
-/*
- * HIGH-LEVEL INITIALISATION AND TEXT OUTPUT.
- */
+/* Filled in by arch boot code. */
+struct xen_vga_console_info vga_console_info;
 
 static int vgacon_enabled = 0;
 static int vgacon_keep    = 0;
-static int vgacon_lines   = 50;
-static const struct font_desc *font;
+/*static const struct font_desc *font;*/
 
 static int xpos, ypos;
 static unsigned char *video;
 
-/* vga: comma-separated options. */
+/*
+ * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
+ * 
+ *   'vga=ask':
+ *      display a vga menu of available modes
+ * 
+ *   'vga=text-80x<rows>':
+ *      text mode, where <rows> is one of {25,28,30,34,43,50,60}
+ * 
+ *   'vga=gfx-<width>x<height>x<depth>':
+ *      graphics mode, e.g., vga=gfx-1024x768x16
+ * 
+ *   'vga=mode-<mode>:
+ *      specifies a mode as specified in 'vga=ask' menu
+ *      (NB. menu modes are displayed in hex, so mode numbers here must
+ *           be prefixed with '0x' (e.g., 'vga=mode-0x0318'))
+ * 
+ * The option 'keep' causes Xen to continue to print to the VGA console even 
+ * after domain 0 starts to boot. The default behaviour is to relinquish
+ * control of the console to domain 0.
+ */
 static char opt_vga[30] = "";
 string_param("vga", opt_vga);
 
 /* VGA text-mode definitions. */
-#define COLUMNS     80
-#define LINES       vgacon_lines
+#define COLUMNS vga_console_info.u.text_mode_3.columns
+#define LINES   vga_console_info.u.text_mode_3.rows
 #define ATTRIBUTE   7
 #define VIDEO_SIZE  (COLUMNS * LINES * 2)
 
@@ -577,49 +61,43 @@ void __init vga_init(void)
 {
     char *p;
 
+    /* Look for 'keep' in comma-separated options. */
     for ( p = opt_vga; p != NULL; p = strchr(p, ',') )
     {
         if ( *p == ',' )
             p++;
         if ( strncmp(p, "keep", 4) == 0 )
             vgacon_keep = 1;
-        else if ( strncmp(p, "text-80x", 8) == 0 )
-            vgacon_lines = simple_strtoul(p + 8, NULL, 10);
     }
 
-    video = setup_vga();
-    if ( !video )
+    switch ( vga_console_info.video_type )
+    {
+    case XEN_VGATYPE_TEXT_MODE_3:
+        if ( memory_is_conventional_ram(0xB8000) )
+            return;
+        video = ioremap(0xB8000, 0x8000);
+        if ( video == NULL )
+            return;
+        /* Disable cursor. */
+        outw(0x200a, 0x3d4);
+        memset(video, 0, VIDEO_SIZE);
+        break;
+    case XEN_VGATYPE_VESA_LFB:
+#if 0
+        /* XXX Implement me! */
+        video = ioremap(vga_console_info.u.vesa_lfb.lfb_base,
+                        vga_console_info.u.vesa_lfb.lfb_size);
+        if ( video == NULL )
+            return;
+        memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
+        break;
+#else
         return;
-
-    switch ( vgacon_lines )
-    {
-    case 25:
-    case 30:
-        font = &font_vga_8x16;
-        break;
-    case 28:
-    case 34:
-        font = &font_vga_8x14;
-        break;
-    case 43:
-    case 50:
-    case 60:
-        font = &font_vga_8x8;
-        break;
+#endif
+    default:
+        memset(&vga_console_info, 0, sizeof(vga_console_info));
+        return;
     }
-
-    if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) )
-    {
-        vgacon_lines = 25;
-        font = NULL;
-    }
-    
-    /* Clear the screen. */
-    memset(video, 0, VIDEO_SIZE);
-    xpos = ypos = 0;
-
-    /* Disable cursor. */
-    vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, 0x20);
 
     vgacon_enabled = 1;
 }
@@ -629,11 +107,10 @@ void __init vga_endboot(void)
     if ( !vgacon_enabled )
         return;
 
-    if ( !vgacon_keep )
-        vgacon_enabled = 0;
-        
     printk("Xen is %s VGA console.\n",
            vgacon_keep ? "keeping" : "relinquishing");
+
+    vgacon_enabled = vgacon_keep;
 }
 
 
@@ -672,17 +149,6 @@ void vga_putchar(int c)
 
 int __init fill_console_start_info(struct dom0_vga_console_info *ci)
 {
-    memset(ci, 0, sizeof(*ci));
-
-    if ( !vgacon_enabled )
-        return 0;
-
-    ci->video_type = XEN_VGATYPE_TEXT_MODE_3;
-    ci->u.text_mode_3.rows     = LINES;
-    ci->u.text_mode_3.columns  = COLUMNS;
-    ci->u.text_mode_3.cursor_x = 0;
-    ci->u.text_mode_3.cursor_y = LINES - 1;
-    ci->u.text_mode_3.font_height = font ? font->height : 16;
-
+    memcpy(ci, &vga_console_info, sizeof(*ci));
     return 1;
 }
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/include/public/xen.h  Sun Jun 10 15:58:08 2007 +0100
@@ -568,6 +568,8 @@ typedef struct dom0_vga_console_info {
         } vesa_lfb;
     } u;
 } dom0_vga_console_info_t;
+#define xen_vga_console_info dom0_vga_console_info
+#define xen_vga_console_info_t dom0_vga_console_info_t
 
 typedef uint8_t xen_domain_handle_t[16];
 
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/include/xen/vga.h
--- a/xen/include/xen/vga.h     Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/include/xen/vga.h     Sun Jun 10 15:58:08 2007 +0100
@@ -12,6 +12,7 @@
 #include <xen/config.h>
 
 #ifdef CONFIG_VGA
+extern struct xen_vga_console_info vga_console_info;
 void vga_init(void);
 void vga_endboot(void);
 void vga_putchar(int c);

_______________________________________________
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®.