[SeaBIOS] FreeBSD VESA console not working with SeaBIOS
Jon Doe
tuksgig at gmail.com
Thu Apr 9 23:32:25 CEST 2015
On Thu, Apr 9, 2015 at 6:54 PM, Kevin O'Connor <kevin at koconnor.net> wrote:
> 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
I can report that this patch also works for FreeBSD 8.2's VESA
console. There seems to be some unrelated problem when running
1.8-stable so I applied it to rel-1.7.5.2
More information about the SeaBIOS
mailing list