//
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
//
-// This file may be distributed under the terms of the GNU GPLv3 license.
+// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "util.h" // usleep
#include "bregs.h" // struct bregs
#include "config.h" // SEG_BIOS
#include "farptr.h" // GET_FARPTR
+#include "biosvar.h" // get_ebda_seg
// Call a function with a specified register state. Note that on
// return, the interrupt enable/disable flag may be altered.
#endif
: "+a" (callregs), "+m" (*callregs)
:
- : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc");
+ : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc", "memory");
}
inline void
call16big(struct bregs *callregs)
{
-#if MODE16 == 1
- extern void __force_link_error__only_in_32bit_mode();
- __force_link_error__only_in_32bit_mode();
-#endif
+ extern void __force_link_error__call16big_only_in_32bit_mode();
+ if (MODE16)
+ __force_link_error__call16big_only_in_32bit_mode();
+
asm volatile(
"calll __call16big_from32\n"
: "+a" (callregs), "+m" (*callregs)
:
- : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc");
+ : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc", "memory");
}
inline void
call16(callregs);
}
+inline void
+call16_simpint(int nr, u32 *eax, u32 *flags)
+{
+ extern void __force_link_error__call16_simpint_only_in_16bit_mode();
+ if (!MODE16)
+ __force_link_error__call16_simpint_only_in_16bit_mode();
+
+ asm volatile(
+ "stc\n"
+ "int %2\n"
+ "pushfl\n"
+ "popl %1\n"
+ "cld\n"
+ "cli\n"
+ : "+a"(*eax), "=r"(*flags)
+ : "i"(nr)
+ : "cc", "memory");
+}
+
+// Switch to the extra stack in ebda and call a function.
+inline u32
+stack_hop(u32 eax, u32 edx, u32 ecx, void *func)
+{
+ extern void __force_link_error__stack_hop_only_in_16bit_mode();
+ if (!MODE16)
+ __force_link_error__stack_hop_only_in_16bit_mode();
+
+ u32 ebda_seg = get_ebda_seg();
+ u32 tmp;
+ asm volatile(
+ // Backup current %ss value.
+ "movl %%ss, %4\n"
+ // Copy ebda seg to %ss and %ds
+ "movl %3, %%ss\n"
+ "movl %3, %%ds\n"
+ // Backup %esp and set it to new value
+ "movl %%esp, %3\n"
+ "movl %5, %%esp\n"
+ // Call func
+ "calll %6\n"
+ // Restore segments and stack
+ "movl %3, %%esp\n"
+ "movl %4, %%ss\n"
+ "movl %4, %%ds\n"
+ : "+a" (eax), "+d" (edx), "+c" (ecx), "+r" (ebda_seg), "=r" (tmp)
+ : "i" (EBDA_OFFSET_TOP_STACK), "m" (*(u8*)func)
+ : "cc", "memory");
+ return eax;
+}
+
// Sum the bytes in the specified area.
u8
checksum(u8 *far_data, u32 len)