[SeaBIOS] FreeBSD VESA console not working with SeaBIOS
Kevin O'Connor
kevin at koconnor.net
Thu Apr 9 18:54:48 CEST 2015
On Thu, Apr 09, 2015 at 09:56:07AM -0400, Kevin O'Connor wrote:
> On Wed, Apr 08, 2015 at 10:32:23PM -0400, Kevin O'Connor wrote:
> > The problem is not with leal in hand written assembler - the problem
> > is with leal instructions generated by gcc. To see the assembler gcc
> > produces for the vgabios one can look at out/vgaccode16.raw.s . Or,
> > alternatively, one can run:
> > objdump -m i386 -M i8086 -M suffix -ldr out/vgarom.o
> >
> > We've fixed up gcc assembler in the past (see scripts/vgafixup.py) to
> > work around x86emu. However, the leal instruction seems painful to
> > patch out - particularly so when %esp is one of the registers read or
> > written in the leal instruction. If anyone wants to take a stab
> > at a workaround, feel free to submit a patch.
>
> It occurred to me that it might be possible to replace the leal
> instruction with a function call. The generic form of leal is:
>
> leal $offset(%base, %index, $scale), %destination
>
> which does:
>
> %destination = $offset + %base + (%index * $scale)
>
> if the above is found in the gcc assembler it could be replaced with
> something like:
>
> pushl %base
> pushl %index
> pushl $offset
> pushl $scale
> callw fake_leal
> popl %destination
>
> (The fake_leal assembler function that performs the actual calculation
> would also need to be written.) The above wouldn't work if %index is
> %esp, but I don't think that would happen in practice.
>
> I'm not going to tackle the above right now, but maybe someone else is
> interested in attempting it. A word of caution though - I know leal
> doesn't work in very old x86emu versions, but it's unclear if any
> other gcc produced instructions are also broken. The leal instruction
> might just be one of many instructions that don't work.
I gave it a shot anyway - seabios patch is below.
It's incredibly ugly. But, it does allow FC11 and FC12 to boot into
graphics which wasn't possible before. Also, I don't see any
indication in the x86emu commit logs (
http://anongit.freedesktop.org/git/xorg/xserver.git ) that any other
instructions besides leal will present a problem.
-Kevin
commit c900162603f19552ec8ad3648bbb71f2effc227d
Author: Kevin O'Connor <kevin at koconnor.net>
Date: Thu Apr 9 11:59:41 2015 -0400
vgabios: Hack for leal emulation
Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
diff --git a/scripts/vgafixup.py b/scripts/vgafixup.py
index a981bbf..f32c055 100644
--- a/scripts/vgafixup.py
+++ b/scripts/vgafixup.py
@@ -8,19 +8,26 @@
# The x86emu code widely used in Linux distributions when running Xorg
# in vesamode is known to have issues with "retl", "leavel", "entryl",
# and some variants of "calll". This code modifies those instructions
-# (ret and leave) that are known to be generated by gcc to avoid
-# triggering the x86emu bugs.
+# that are known to be generated by gcc to avoid triggering the x86emu
+# bugs. It also translates "leal" instructions into a function call
+# that emulates it at runtime.
# It is also known that the Windows vgabios emulator has issues with
# addressing negative offsets to the %esp register. That has been
# worked around by not using the gcc parameter "-fomit-frame-pointer"
# when compiling.
-import sys
+import sys, re
def main():
infilename, outfilename = sys.argv[1:]
infile = open(infilename, 'r')
+ re_leal = re.compile(
+ r'^(?P<offset>[^(]*)\('
+ r'(?P<base>[^,)]*)'
+ r'(?:,(?P<index>[^,)]*))?'
+ r'(?:,(?P<scale>[^,)]*))?\)'
+ r', (?P<dest>.*)$')
out = []
for line in infile:
sline = line.strip()
@@ -30,6 +37,25 @@ def main():
out.append('movl %ebp, %esp ; popl %ebp\n')
elif sline.startswith('call'):
out.append('pushw %ax ; callw' + sline[4:] + '\n')
+ elif sline.startswith('leal'):
+ m = re_leal.match(sline[5:])
+ if m is None or m.group('index') == '%esp':
+ print("Invalid leal instruction: %s" % (sline,))
+ sys.exit(-1)
+ offset, base, index, scale, dest = m.group(
+ 'offset', 'base', 'index', 'scale', 'dest')
+ if not offset:
+ offset = '0'
+ if not base:
+ base = '$0'
+ if not index:
+ index = '$0'
+ if not scale:
+ scale = '1'
+ scale = {'1': 0, '2': 1, '4': 2, '8': 3}[scale]
+ out.append('pushl %s ; pushl %s ; pushl $%s ; pushw $%d'
+ ' ; callw fake_leal ; popl %s\n' % (
+ base, index, offset, scale, dest))
else:
out.append(line)
infile.close()
diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S
index e0ab954..21128c5 100644
--- a/vgasrc/vgaentry.S
+++ b/vgasrc/vgaentry.S
@@ -45,31 +45,32 @@ _rom_header_signature:
* Entry points
****************************************************************/
- // Force a fault if found to be running on broken x86emu versions.
- DECLFUNC x86emu_fault
-msg: .ascii "SeaVGABIOS: x86emu leal trap!\n"
-x86emu_fault:
-#if CONFIG_DEBUG_IO
- movw %cs:DebugOutputPort, %dx
- movw $msg, %si
-1: movb %cs:(%si), %al
- outb %al, (%dx)
- incw %si
- cmpw $x86emu_fault, %si
- jl 1b
-#endif
-1: hlt
- jmp 1b
+ // Emulate a leal instruction (see scripts/vgafixup.py)
+ // On entry stack contains: base, index, offset, scale
+ DECLFUNC fake_leal
+ .global fake_leal
+fake_leal:
+ pushl %ebp
+ movl %esp, %ebp
+ pushfl
+ pushl %eax
+ pushl %ecx
+
+ movb 6(%ebp), %cl
+ movl 12(%ebp), %eax
+ shll %cl, %eax
+ addl 8(%ebp), %eax
+ addl %eax, 16(%ebp)
+
+ popl %ecx
+ popl %eax
+ popfl
+ popl %ebp
+ retw $10
// This macro implements a call while avoiding instructions
// that old versions of x86emu have problems with.
.macro VGA_CALLL cfunc
- // Make sure leal instruction works.
- movl $0x8000, %ecx
- leal (%ecx, %ecx, 1), %ecx
- cmpl $0x10000, %ecx
- jne x86emu_fault
- // Use callw instead of calll
push %ax
callw \cfunc
.endm
More information about the SeaBIOS
mailing list