* Sasha Levin <levinsasha928@xxxxxxxxx> wrote: > INT10 handler is a basic implementation of BIOS video services. > > The handler implements a VESA interface which is initialized at > the very beginning of loading the kernel. > > Signed-off-by: John Floren <john@xxxxxxxxxxx> > [ turning code into patches and cleanup ] > Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> > --- > tools/kvm/bios/bios-rom.S | 56 ++++++++-------- > tools/kvm/bios/int10.c | 161 +++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 189 insertions(+), 28 deletions(-) > create mode 100644 tools/kvm/bios/int10.c > > diff --git a/tools/kvm/bios/bios-rom.S b/tools/kvm/bios/bios-rom.S > index 8a53dcd..b636cb8 100644 > --- a/tools/kvm/bios/bios-rom.S > +++ b/tools/kvm/bios/bios-rom.S > @@ -27,36 +27,36 @@ ENTRY_END(bios_intfake) > * We ignore bx settings > */ > ENTRY(bios_int10) > - test $0x0e, %ah > - jne 1f > + pushw %fs > + pushl %es > + pushl %edi > + pushl %esi > + pushl %ebp > + pushl %esp > + pushl %edx > + pushl %ecx > + pushl %ebx > + pushl %eax > + > + movl %esp, %eax > + /* this is way easier than doing it in assembly */ > + /* just push all the regs and jump to a C handler */ > + call int10handler > + > + popl %eax > + popl %ebx > + popl %ecx > + popl %edx > + popl %esp > + popl %ebp > + popl %esi > + popl %edi > + popl %es > + popw %fs > > -/* > - * put char in AL at current cursor and > - * increment cursor position > - */ > -putchar: > - stack_swap > - > - push %fs > - push %bx > - > - mov $VGA_RAM_SEG, %bx > - mov %bx, %fs > - mov %cs:(cursor), %bx > - mov %al, %fs:(%bx) > - inc %bx > - test $VGA_PAGE_SIZE, %bx > - jb putchar_new > - xor %bx, %bx > -putchar_new: > - mov %bx, %fs:(cursor) > - > - pop %bx > - pop %fs > - > - stack_restore > -1: > IRET > + > + > /* > * private IRQ data > */ > diff --git a/tools/kvm/bios/int10.c b/tools/kvm/bios/int10.c > new file mode 100644 > index 0000000..98205c3 > --- /dev/null > +++ b/tools/kvm/bios/int10.c > @@ -0,0 +1,161 @@ > +#include "kvm/segment.h" > +#include "kvm/bios.h" > +#include "kvm/util.h" > +#include "kvm/vesa.h" > +#include <stdint.h> > + > +#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) > + > +struct int10args { > + u32 eax; > + u32 ebx; > + u32 ecx; > + u32 edx; > + u32 esp; > + u32 ebp; > + u32 esi; > + u32 edi; > + u32 es; > +}; > + > +/* 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 */ > + > + u8 reserved[236]; /* 20 */ > +} __attribute__ ((packed)); > + > + > +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 */ > +}; > + > +char oemstring[11] = "KVM VESA"; > +u16 modes[2] = { 0x0112, 0xffff }; > + > +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 int10putchar(struct int10args *args) > +{ > + u8 al, ah; > + > + al = args->eax & 0xFF; > + ah = (args->eax & 0xFF00) >> 8; > + > + outb(0x3f8, al); > +} > + > +static void int10vesa(struct int10args *args) > +{ > + u8 al, ah; > + struct vesa_general_info *destination; > + struct vminfo *vi; > + > + al = args->eax; > + ah = args->eax >> 8; > + > + switch (al) { > + case 0: > + /* Set controller info */ > + > + destination = (struct vesa_general_info *)args->edi; > + *destination = (struct vesa_general_info) { > + .signature = VESA_MAGIC, > + .version = 0x102, > + .vendor_string = oemstring, > + .capabilities = 0x10, > + .video_mode_ptr = modes, > + .total_memory = (4*VESA_WIDTH * VESA_HEIGHT) / 0x10000, > + }; > + > + break; > + case 1: > + vi = (struct vminfo *)args->edi; > + *vi = (struct vminfo) { > + .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, > + }; > + > + break; > + } > + > + args->eax = 0x004f; /* return success every time */ > + > +} > + > +bioscall void int10handler(struct int10args *args) > +{ > + u8 ah; > + > + ah = (args->eax & 0xff00) >> 8; > + > + switch (ah) { > + case 0x0e: > + int10putchar(args); > + break; > + case 0x4f: > + int10vesa(args); > + break; > + } Why are these functions prefixed in such a weird way? Why not int10_putchar(), int10_vesa(), etc. like all other bits in tools/kvm/? Thanks, Ingo -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html