[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Coreboot + Linux + kexec + Xen
This is in reply to an ancient post to the xen-devel list: http://ward.vandewege.net/blog/2008/08/kexecing-into-a-xen-kernel/ http://old-list-archives.xenproject.org/archives/html/xen-devel/2008-08/msg00298.html Ward Vandewege wrote (in 2008): > There seems to be a regression with regard to kexec'ing into > a Xen kernel between Xen 3.1.0 (confirmed working) and 3.1.3 > (confirmed not working). I would try 3.1.1 and 3.1.2 but > source for 3.1 versions older than 3.1.3 no longer seems to > be available for download. I still had source for 3.1.0 > lying around, luckily. I'm building a similar configuration to Ward's setup, although with a more modern version of Xen. My laptop has Coreboot with a Linux payload as a bootloader flashed into the ROM, which then validates and invokes Qubes' Xen 4.6 hypervisor with kexec(). It worked as long as I had a BIOS image in ROM, such as SeaBIOS, but not when I used Linux as the bootloader, even with "no-real-mode" as a parameter on the Xen command line. Keir Fraser replied to Ward's follow up question: > > Is there a significant difference between booting 3.1.4 and > > 3.2.1 with kexec in terms of BIOS requirements? > > If you specify no-real-mode in both cases then there > should be no difference. If Xen does not drop back into > real mode then it cannot make use of any legacy BIOS > services. After some tracing, I determined that this is not enitrely accurate and likely the cause of Ward's failure to boot 3.2.1 on real hardware. Xen assumes that there is an Extended BIOS Data Area (EBDA), which is not the case for the Linux-as-bootloader configuration. The parameters have not been parsed at this time in the boot code, so it always trusts that it can find this structure. Patching xen/arch/x86/boot/head.S to set trampoline_phys to point to the end of MB_mem_lower (as it was done in 3.1.0) and also passing in "no-real-mode" allows 4.6.3 to boot on the Coreboot system with Linux payload. However, it would then fault in the VGA configuration since at that same time the xen/drivers/video/vga.c was changed from "directly poking the registers to enter video mode 3" to doing it the right way by asking the VESA BIOS to configure the video card. Since my system has no VGA BIOS (Coreboot does native VGA init on the x230 and Qemu), this leads to faults when Xen attempts to invoke BIOS calls. Forward porting the ten year old vga.c file from 3.1.0 allowed 4.6.3 to work perfectly. Since this is the only mention I've seen of this setup since 2008, I understand that merging this patch into the Xen kernel might not be the highest priority. But for time travellers looking to boot Coreboot + Linux payload + kexec + Xen + Qubes on their Thinkpads, these patches might prove to be useful. -- Trammell diff --recursive -u /home/hudson/build/clean/xen-4.6.3/xen/arch/x86/boot/head.S ./xen/arch/x86/boot/head.S --- /home/hudson/build/clean/xen-4.6.3/xen/arch/x86/boot/head.S 2016-06-20 08:08:22.000000000 -0400 +++ ./xen/arch/x86/boot/head.S 2016-08-03 17:56:37.511121443 -0400 @@ -86,6 +86,8 @@ cmp $MULTIBOOT_BOOTLOADER_MAGIC,%eax jne not_multiboot +#if 0 + /* Set up trampoline segment 64k below EBDA */ movzwl 0x40e,%eax /* EBDA segment */ cmp $0xa000,%eax /* sanity check (high) */ @@ -108,6 +110,12 @@ shl $10-4,%edx cmp %eax,%edx /* compare with BDA value */ cmovb %edx,%eax /* and use the smaller */ +#else + // coreboot does not provide an Extended BIOS Data Area pointer + // just stash things the Multiboot structure, adjusted to bytes + mov MB_mem_lower(%ebx),%eax + shl $10-4,%eax +#endif 2: /* Reserve 64kb for the trampoline */ sub $0x1000,%eax diff --recursive -u /home/hudson/build/clean/xen-4.6.3/xen/drivers/video/vga.c ./xen/drivers/video/vga.c --- /home/hudson/build/clean/xen-4.6.3/xen/drivers/video/vga.c 2016-06-20 08:08:22.000000000 -0400 +++ ./xen/drivers/video/vga.c 2016-08-03 18:03:38.241443543 -0400 @@ -5,177 +5,691 @@ */ #include <xen/config.h> +#include <xen/compile.h> #include <xen/init.h> #include <xen/lib.h> #include <xen/mm.h> +#include <xen/errno.h> +#include <xen/event.h> +#include <xen/spinlock.h> +#include <xen/console.h> #include <xen/vga.h> -#include <xen/pci.h> #include <asm/io.h> +#include "font.h" /* Filled in by arch boot code. */ struct xen_vga_console_info vga_console_info; -static int vgacon_keep; -static unsigned int xpos, ypos; -static unsigned char *video; -static void vga_text_puts(const char *s); -static void vga_noop_puts(const char *s) {} -void (*video_puts)(const char *) = vga_noop_puts; - -/* - * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of: - * - * 'vga=ask': - * display a vga menu of available modes - * - * 'vga=current': - * use the current vga mode without modification - * - * '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. +/* 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 char __initdata opt_vga[30] = ""; + +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 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 :-) */ +void *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 ( page_is_ram_type(paddr_to_pfn(0xB8000), RAM_TYPE_CONVENTIONAL) ) + 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 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 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. + */ + +static int vgacon_enabled = 0; +static int vgacon_keep = 0; +static int vgacon_lines = 25; +static const struct font_desc *font; + +static int xpos, ypos; +static unsigned char *video; + +/* vga: comma-separated options. */ +static char opt_vga[30] = ""; string_param("vga", opt_vga); /* VGA text-mode definitions. */ -static unsigned int columns, lines; +#define COLUMNS 80 +#define LINES vgacon_lines #define ATTRIBUTE 7 +#define VIDEO_SIZE (COLUMNS * LINES * 2) -#ifdef CONFIG_X86 -void vesa_early_init(void); -void vesa_endboot(bool_t keep); -#else -#define vesa_early_init() ((void)0) -#define vesa_endboot(x) ((void)0) -#endif - -void __init video_init(void) +void video_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); } - switch ( vga_console_info.video_type ) + video = setup_vga(); + if ( !video ) + return; + + switch ( vgacon_lines ) { - case XEN_VGATYPE_TEXT_MODE_3: - if ( page_is_ram_type(paddr_to_pfn(0xB8000), RAM_TYPE_CONVENTIONAL) || - ((video = ioremap(0xB8000, 0x8000)) == NULL) ) - return; - outw(0x200a, 0x3d4); /* disable cursor */ - columns = vga_console_info.u.text_mode_3.columns; - lines = vga_console_info.u.text_mode_3.rows; - memset(video, 0, columns * lines * 2); - video_puts = vga_text_puts; - break; - case XEN_VGATYPE_VESA_LFB: - case XEN_VGATYPE_EFI_LFB: - vesa_early_init(); + case 25: + case 30: + font = &font_vga_8x16; break; - default: - memset(&vga_console_info, 0, sizeof(vga_console_info)); + case 28: + case 34: + font = &font_vga_8x14; + break; + case 43: + case 50: + case 60: + font = &font_vga_8x8; break; } + + 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; } -void __init video_endboot(void) +void video_endboot(void) { - if ( video_puts == vga_noop_puts ) + if ( !vgacon_enabled ) return; + if ( !vgacon_keep ) + vgacon_enabled = 0; + printk("Xen is %s VGA console.\n", vgacon_keep ? "keeping" : "relinquishing"); +} - if ( !vgacon_keep ) - video_puts = vga_noop_puts; - else - { - int bus, devfn; - for ( bus = 0; bus < 256; ++bus ) - for ( devfn = 0; devfn < 256; ++devfn ) - { - const struct pci_dev *pdev; - u8 b = bus, df = devfn, sb; +static void put_newline(void) +{ + xpos = 0; + ypos++; - spin_lock(&pcidevs_lock); - pdev = pci_get_pdev(0, bus, devfn); - spin_unlock(&pcidevs_lock); - - if ( !pdev || - pci_conf_read16(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - PCI_CLASS_DEVICE) != 0x0300 || - !(pci_conf_read16(0, bus, PCI_SLOT(devfn), - PCI_FUNC(devfn), PCI_COMMAND) & - (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) ) - continue; - - while ( b ) - { - switch ( find_upstream_bridge(0, &b, &df, &sb) ) - { - case 0: - b = 0; - break; - case 1: - switch ( pci_conf_read8(0, b, PCI_SLOT(df), - PCI_FUNC(df), - PCI_HEADER_TYPE) ) - { - case PCI_HEADER_TYPE_BRIDGE: - case PCI_HEADER_TYPE_CARDBUS: - if ( pci_conf_read16(0, b, PCI_SLOT(df), - PCI_FUNC(df), - PCI_BRIDGE_CONTROL) & - PCI_BRIDGE_CTL_VGA ) - continue; - break; - } - break; - } - break; - } - if ( !b ) - { - printk(XENLOG_INFO "Boot video device %02x:%02x.%u\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - pci_hide_device(bus, devfn); - } - } + if ( ypos >= LINES ) + { + ypos = LINES-1; + memmove((char*)video, + (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS); + memset((char*)video + (LINES-1)*2*COLUMNS, 0, 2*COLUMNS); } +} - switch ( vga_console_info.video_type ) +void vga_putchar(int c) +{ + if ( !vgacon_enabled ) + return; + + if ( c == '\n' ) { - case XEN_VGATYPE_TEXT_MODE_3: - if ( !vgacon_keep ) - memset(video, 0, columns * lines * 2); - break; - case XEN_VGATYPE_VESA_LFB: - case XEN_VGATYPE_EFI_LFB: - vesa_endboot(vgacon_keep); - break; - default: - BUG(); + put_newline(); } + else + { + if ( xpos >= COLUMNS ) + put_newline(); + video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF; + video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE; + ++xpos; + } +} + + +int 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; + + return 1; } static void vga_text_puts(const char *s) @@ -184,28 +698,25 @@ while ( (c = *s++) != '\0' ) { - if ( (c == '\n') || (xpos >= columns) ) + if ( (c == '\n') || (xpos >= COLUMNS) ) { - if ( ++ypos >= lines ) + if ( ++ypos >= LINES ) { - ypos = lines - 1; - memmove(video, video + 2 * columns, ypos * 2 * columns); - memset(video + ypos * 2 * columns, 0, 2 * xpos); + ypos = LINES - 1; + memmove(video, video + 2 * COLUMNS, ypos * 2 * COLUMNS); + memset(video + ypos * 2 * COLUMNS, 0, 2 * xpos); } xpos = 0; } if ( c != '\n' ) { - video[(xpos + ypos * columns) * 2] = c; - video[(xpos + ypos * columns) * 2 + 1] = ATTRIBUTE; + video[(xpos + ypos * COLUMNS) * 2] = c; + video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE; xpos++; } } } -int __init fill_console_start_info(struct dom0_vga_console_info *ci) -{ - memcpy(ci, &vga_console_info, sizeof(*ci)); - return 1; -} +// hard code it to always go to vga +void (*video_puts)(const char *) = vga_text_puts; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |