WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: Allow selection of graphical video m

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Allow selection of graphical video modes during boot.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 11 Jun 2007 02:22:37 -0700
Delivery-date: Tue, 12 Jun 2007 05:08:43 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: Allow selection of graphical video modes during boot., Xen patchbot-unstable <=