1 asm(".code16gcc");
2 #include <stddef.h>
3 #include "bios.h"
4 #include "segment.h"
5 #include "ioport.h"
6 #include "processor-flags.h"
7 #include "e820.h"
8 
set_fs(uint16_t seg)9 static inline void set_fs(uint16_t seg)
10 {
11 	asm volatile("movw %0,%%fs" : : "rm" (seg));
12 }
13 
rdfs8(unsigned long addr)14 static inline uint8_t rdfs8(unsigned long addr)
15 {
16 	uint8_t v;
17 
18 	asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr));
19 
20 	return v;
21 }
22 
rdfs32(unsigned long addr)23 static inline uint32_t rdfs32(unsigned long addr)
24 {
25 	uint32_t v;
26 
27 	asm volatile("addr32 movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
28 
29 	return v;
30 }
31 
rdcs16(void * p)32 static inline uint16_t rdcs16(void *p)
33 {
34 	uint32_t addr = ((uintptr_t) p) & 65535;
35 	uint16_t v;
36 
37 	asm volatile("addr32 movw %%cs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
38 
39 	return v;
40 }
41 
42 uint16_t e820_seg;
43 
e820_query_map(struct biosregs * regs)44 bioscall void e820_query_map(struct biosregs *regs)
45 {
46 	uint32_t map_size;
47 	uint32_t ndx;
48 
49 	set_fs(rdcs16(&e820_seg));
50 
51 	ndx		= regs->ebx;
52 
53 	map_size	= rdfs32(offsetof(struct e820map, nr_map));
54 
55 	if (ndx < map_size) {
56 		uint32_t start;
57 		unsigned int i;
58 		uint8_t *p;
59 
60 		start	= offsetof(struct e820map, map[ndx]);
61 
62 		p	= (void *) regs->edi;
63 
64 		for (i = 0; i < sizeof(struct e820entry); i++)
65 			*p++	= rdfs8(start + i);
66 	}
67 
68 	regs->eax	= SMAP;
69 	regs->ecx	= sizeof(struct e820entry);
70 	regs->ebx	= ++ndx;
71 
72 	if (ndx >= map_size)
73 		regs->ebx	= 0;	/* end of map */
74 }
75 
int15_handler(struct biosregs * regs)76 bioscall void int15_handler(struct biosregs *regs)
77 {
78 	switch (regs->eax) {
79 	case 0xe820:
80 		e820_query_map(regs);
81 		break;
82 	default:
83 		/* Set CF to indicate failure.  */
84 		regs->eflags	|= X86_EFLAGS_CF;
85 		break;
86 	}
87 }
88 /*
89  * It's probably much more useful to make this print to the serial
90  * line rather than print to a non-displayed VGA memory
91  */
int10_putchar(struct biosregs * args)92 static inline void int10_putchar(struct biosregs *args)
93 {
94 	uint8_t al = args->eax & 0xFF;
95 
96 	outb(0x3f8, al);
97 }
98 
99 #define VBE_STATUS_OK		0x004F
100 #define VBE_STATUS_FAIL		0x014F
101 
int10_vesa(struct biosregs * args)102 static void int10_vesa(struct biosregs *args)
103 {
104 	args->eax = VBE_STATUS_FAIL;
105 }
106 
int10_handler(struct biosregs * args)107 bioscall void int10_handler(struct biosregs *args)
108 {
109 	uint8_t ah;
110 
111 	ah = (args->eax & 0xff00) >> 8;
112 
113 	switch (ah) {
114 	case 0x0e:
115 		int10_putchar(args);
116 		break;
117 	case 0x4f:
118 		int10_vesa(args);
119 		break;
120 	}
121 
122 }
123