diff --git a/Makefile b/Makefile index d4598ca..20389f9 100644 --- a/Makefile +++ b/Makefile @@ -225,6 +225,7 @@ BIOS_CFLAGS += -march=i386 BIOS_CFLAGS += -mregparm=3 BIOS_CFLAGS += -fno-stack-protector +BIOS_CFLAGS += -I../../arch/$(ARCH) bios.o: bios/bios.bin bios/bios-rom.h diff --git a/bios.c b/bios.c index 6aefd1b..47b1f54 100644 --- a/bios.c +++ b/bios.c @@ -103,6 +103,20 @@ static void e820_setup(struct kvm *kvm) e820->nr_map = i; } +static void setup_vga_rom(struct kvm *kvm) +{ + u16 *mode; + void *p; + + p = guest_flat_to_host(kvm, VGA_ROM_OEM_STRING); + memset(p, 0, VGA_ROM_OEM_STRING_SIZE); + strncpy(p, "KVM VESA", VGA_ROM_OEM_STRING_SIZE); + + mode = guest_flat_to_host(kvm, VGA_ROM_MODES); + mode[0] = 0x0112; + mode[1] = 0xffff; +} + /** * setup_bios - inject BIOS into guest memory * @kvm - guest system descriptor @@ -137,6 +151,9 @@ void setup_bios(struct kvm *kvm) /* E820 memory map must be present */ e820_setup(kvm); + /* VESA needs own tricks */ + setup_vga_rom(kvm); + /* * Setup a *fake* real mode vector table, it has only * one real hadler which does just iret diff --git a/bios/int10.c b/bios/int10.c index 32f7c92..7cc0b3f 100644 --- a/bios/int10.c +++ b/bios/int10.c @@ -4,59 +4,17 @@ #include "bios/memcpy.h" -#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) +#include -/* VESA General Information table */ -struct vesa_general_info { - u32 signature; /* 0 Magic number = "VESA" */ - u16 version; /* 4 */ - void *vendor_string; /* 6 */ - u32 capabilities; /* 10 */ - void *video_mode_ptr; /* 14 */ - u16 total_memory; /* 18 */ - u16 modes[2]; /* 20 */ - char oem_string[11]; /* 24 */ +static far_ptr gen_far_ptr(unsigned int pa) +{ + far_ptr ptr; - u8 reserved[223]; /* 35 */ -} __attribute__ ((packed)); + ptr.seg = (pa >> 4); + ptr.off = pa - (ptr.seg << 4); -struct vminfo { - u16 mode_attr; /* 0 */ - u8 win_attr[2]; /* 2 */ - u16 win_grain; /* 4 */ - u16 win_size; /* 6 */ - u16 win_seg[2]; /* 8 */ - u32 win_scheme; /* 12 */ - u16 logical_scan; /* 16 */ - - u16 h_res; /* 18 */ - u16 v_res; /* 20 */ - u8 char_width; /* 22 */ - u8 char_height; /* 23 */ - u8 memory_planes; /* 24 */ - u8 bpp; /* 25 */ - u8 banks; /* 26 */ - u8 memory_layout; /* 27 */ - u8 bank_size; /* 28 */ - u8 image_planes; /* 29 */ - u8 page_function; /* 30 */ - - u8 rmask; /* 31 */ - u8 rpos; /* 32 */ - u8 gmask; /* 33 */ - u8 gpos; /* 34 */ - u8 bmask; /* 35 */ - u8 bpos; /* 36 */ - u8 resv_mask; /* 37 */ - u8 resv_pos; /* 38 */ - u8 dcm_info; /* 39 */ - - u32 lfb_ptr; /* 40 Linear frame buffer address */ - u32 offscreen_ptr; /* 44 Offscreen memory address */ - u16 offscreen_size; /* 48 */ - - u8 reserved[206]; /* 50 */ -}; + return ptr; +} static inline void outb(unsigned short port, unsigned char val) { @@ -76,9 +34,9 @@ static inline void int10_putchar(struct biosregs *args) static void vbe_get_mode(struct biosregs *args) { - struct vminfo *info = (struct vminfo *) args->edi; + struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi; - *info = (struct vminfo) { + *info = (struct vesa_mode_info) { .mode_attr = 0xd9, /* 11011011 */ .logical_scan = VESA_WIDTH*4, .h_res = VESA_WIDTH, @@ -105,12 +63,10 @@ static void vbe_get_info(struct biosregs *args) info = (struct vesa_general_info) { .signature = VESA_MAGIC, .version = 0x102, - .vendor_string = &infop->oem_string, + .vendor_string = gen_far_ptr(VGA_ROM_BEGIN), .capabilities = 0x10, - .video_mode_ptr = &infop->modes, + .video_mode_ptr = gen_far_ptr(VGA_ROM_MODES), .total_memory = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000, - .oem_string = "KVM VESA", - .modes = { 0x0112, 0xffff }, }; memcpy16(args->es, infop, args->ds, &info, sizeof(info)); diff --git a/include/kvm/bios.h b/include/kvm/bios.h index 39cc972..c12fba7 100644 --- a/include/kvm/bios.h +++ b/include/kvm/bios.h @@ -33,6 +33,10 @@ #define VGA_RAM_END 0x000bffff #define VGA_ROM_BEGIN 0x000c0000 +#define VGA_ROM_OEM_STRING VGA_ROM_BEGIN +#define VGA_ROM_OEM_STRING_SIZE 16 +#define VGA_ROM_MODES (VGA_ROM_OEM_STRING + VGA_ROM_OEM_STRING_SIZE) +#define VGA_ROM_MODES_SIZE 32 #define VGA_ROM_END 0x000c7fff /* we handle one page only */