#include "kvm/bios.h" #include "kvm/vesa.h" #include "asm/bios/memcpy.h" #include "asm/bios/vesa.h" static far_ptr gen_far_ptr(unsigned int pa) { far_ptr ptr; ptr.seg = (pa >> 4); ptr.off = pa - (ptr.seg << 4); return ptr; } static inline void outb(unsigned short port, unsigned char val) { asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); } /* * It's probably much more useful to make this print to the serial * line rather than print to a non-displayed VGA memory */ static inline void int10_putchar(struct biosregs *args) { u8 al = args->eax & 0xFF; outb(0x3f8, al); } static void vbe_get_mode(struct biosregs *args) { struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi; *info = (struct vesa_mode_info) { .mode_attr = 0xd9, /* 11011011 */ .logical_scan = VESA_WIDTH*4, .h_res = VESA_WIDTH, .v_res = VESA_HEIGHT, .bpp = VESA_BPP, .memory_layout = 6, .memory_planes = 1, .lfb_ptr = VESA_MEM_ADDR, .rmask = 8, .gmask = 8, .bmask = 8, .resv_mask = 8, .resv_pos = 24, .bpos = 16, .gpos = 8, }; } static void vbe_get_info(struct biosregs *args) { struct vesa_general_info *infop = (struct vesa_general_info *) args->edi; struct vesa_general_info info; info = (struct vesa_general_info) { .signature = VESA_MAGIC, .version = 0x102, .vendor_string = gen_far_ptr(VGA_ROM_BEGIN), .capabilities = 0x10, .video_mode_ptr = gen_far_ptr(VGA_ROM_MODES), .total_memory = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000, }; memcpy16(args->es, infop, args->ds, &info, sizeof(info)); } #define VBE_STATUS_OK 0x004F static void int10_vesa(struct biosregs *args) { u8 al; al = args->eax & 0xff; switch (al) { case 0x00: vbe_get_info(args); break; case 0x01: vbe_get_mode(args); break; } args->eax = VBE_STATUS_OK; } bioscall void int10_handler(struct biosregs *args) { u8 ah; ah = (args->eax & 0xff00) >> 8; switch (ah) { case 0x0e: int10_putchar(args); break; case 0x4f: int10_vesa(args); break; } }