xref: /kvmtool/x86/bios/int10.c (revision 9759db0dd916586ff022f5d16bde5ab52cc05e83)
1 #include "kvm/bios.h"
2 #include "kvm/vesa.h"
3 
4 #include "asm/bios/memcpy.h"
5 
6 #include "asm/bios/vesa.h"
7 
gen_far_ptr(unsigned int pa)8 static far_ptr gen_far_ptr(unsigned int pa)
9 {
10 	far_ptr ptr;
11 
12 	ptr.seg = (pa >> 4);
13 	ptr.off = pa - (ptr.seg << 4);
14 
15 	return ptr;
16 }
17 
outb(unsigned short port,unsigned char val)18 static inline void outb(unsigned short port, unsigned char val)
19 {
20 	asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
21 }
22 
23 /*
24  * It's probably much more useful to make this print to the serial
25  * line rather than print to a non-displayed VGA memory
26  */
int10_putchar(struct biosregs * args)27 static inline void int10_putchar(struct biosregs *args)
28 {
29 	u8 al = args->eax & 0xFF;
30 
31 	outb(0x3f8, al);
32 }
33 
vbe_get_mode(struct biosregs * args)34 static void vbe_get_mode(struct biosregs *args)
35 {
36 	struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
37 
38 	*info = (struct vesa_mode_info) {
39 		.mode_attr		= 0xd9, /* 11011011 */
40 		.logical_scan		= VESA_WIDTH*4,
41 		.h_res			= VESA_WIDTH,
42 		.v_res			= VESA_HEIGHT,
43 		.bpp			= VESA_BPP,
44 		.memory_layout		= 6,
45 		.memory_planes		= 1,
46 		.lfb_ptr		= VESA_MEM_ADDR,
47 		.rmask			= 8,
48 		.gmask			= 8,
49 		.bmask			= 8,
50 		.resv_mask		= 8,
51 		.resv_pos		= 24,
52 		.bpos			= 16,
53 		.gpos			= 8,
54 	};
55 }
56 
vbe_get_info(struct biosregs * args)57 static void vbe_get_info(struct biosregs *args)
58 {
59 	struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
60 	struct vesa_general_info info;
61 
62 	info = (struct vesa_general_info) {
63 		.signature		= VESA_MAGIC,
64 		.version		= 0x102,
65 		.vendor_string		= gen_far_ptr(VGA_ROM_BEGIN),
66 		.capabilities		= 0x10,
67 		.video_mode_ptr		= gen_far_ptr(VGA_ROM_MODES),
68 		.total_memory		= (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
69 	};
70 
71 	memcpy16(args->es, infop, args->ds, &info, sizeof(info));
72 }
73 
74 #define VBE_STATUS_OK		0x004F
75 
int10_vesa(struct biosregs * args)76 static void int10_vesa(struct biosregs *args)
77 {
78 	u8 al;
79 
80 	al = args->eax & 0xff;
81 
82 	switch (al) {
83 	case 0x00:
84 		vbe_get_info(args);
85 		break;
86 	case 0x01:
87 		vbe_get_mode(args);
88 		break;
89 	}
90 
91 	args->eax = VBE_STATUS_OK;
92 }
93 
int10_handler(struct biosregs * args)94 bioscall void int10_handler(struct biosregs *args)
95 {
96 	u8 ah;
97 
98 	ah = (args->eax & 0xff00) >> 8;
99 
100 	switch (ah) {
101 	case 0x0e:
102 		int10_putchar(args);
103 		break;
104 	case 0x4f:
105 		int10_vesa(args);
106 		break;
107 	}
108 
109 }
110