1 // Misc utility functions.
3 // Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
7 #include "util.h" // call16
8 #include "bregs.h" // struct bregs
9 #include "farptr.h" // GET_FLATPTR
10 #include "biosvar.h" // get_ebda_seg
12 // Call a function with a specified register state. Note that on
13 // return, the interrupt enable/disable flag may be altered.
15 call16(struct bregs *callregs)
21 "calll __call16_from32\n"
23 : "+a" (callregs), "+m" (*callregs)
25 : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc", "memory");
29 call16big(struct bregs *callregs)
31 extern void __force_link_error__call16big_only_in_32bit_mode();
33 __force_link_error__call16big_only_in_32bit_mode();
36 "calll __call16big_from32\n"
37 : "+a" (callregs), "+m" (*callregs)
39 : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc", "memory");
43 __call16_int(struct bregs *callregs, u16 offset)
46 callregs->cs = GET_SEG(CS);
48 callregs->cs = SEG_BIOS;
49 callregs->ip = offset;
54 call16_simpint(int nr, u32 *eax, u32 *flags)
56 extern void __force_link_error__call16_simpint_only_in_16bit_mode();
58 __force_link_error__call16_simpint_only_in_16bit_mode();
67 : "+a"(*eax), "=r"(*flags)
72 // Switch to the extra stack in ebda and call a function.
74 stack_hop(u32 eax, u32 edx, u32 ecx, void *func)
76 extern void __force_link_error__stack_hop_only_in_16bit_mode();
78 __force_link_error__stack_hop_only_in_16bit_mode();
80 u16 ebda_seg = get_ebda_seg(), bkup_ss;
83 // Backup current %ss/%esp values.
86 // Copy ebda seg to %ds/%ss and set %esp
92 // Restore segments and stack
96 : "+a" (eax), "+d" (edx), "+c" (ecx), "=&r" (bkup_ss), "=&r" (bkup_esp)
97 : "i" (EBDA_OFFSET_TOP_STACK), "r" (ebda_seg), "m" (*(u8*)func)
102 // Sum the bytes in the specified area.
104 checksum_far(u16 buf_seg, u8 *buf_far, u32 len)
106 SET_SEG(ES, buf_seg);
109 for (i=0; i<len; i++)
110 sum += GET_VAR(ES, buf_far[i]);
115 checksum(u8 *buf, u32 len)
117 return checksum_far(GET_SEG(SS), buf, len);
121 memset(void *s, int c, size_t n)
124 ((char *)s)[--n] = c;
129 memcpy_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len)
136 "rep movsb (%%si),%%es:(%%di)\n"
138 : "=&r"(bkup_ds), "+c"(len), "+S"(s_far), "+D"(d_far)
144 memcpy(void *d1, const void *s1, size_t len)
146 u8 *d = (u8*)d1, *s = (u8*)s1;
153 memmove(void *d, const void *s, size_t len)
156 return memcpy(d, s, len);
161 *(char*)d = *(char*)s;
169 // Wait for 'usec' microseconds with irqs enabled.
174 memset(&br, 0, sizeof(br));
178 call16_int(0x15, &br);
181 // See if a keystroke is pending in the keyboard buffer.
183 check_for_keystroke()
186 memset(&br, 0, sizeof(br));
188 call16_int(0x16, &br);
189 return !(br.flags & F_ZF);
192 // Return a keystroke - waiting forever if necessary.
197 memset(&br, 0, sizeof(br));
198 call16_int(0x16, &br);
202 // Read a keystroke - waiting up to 'msec' milliseconds.
204 get_keystroke(int msec)
207 if (check_for_keystroke())
208 return get_raw_keystroke();