/* * ______ ____ ______ _____ ______ * | ____| | _ \| ____| / / _ \| ____| * | |__ _ __ ___ ___| |_) | |__ / / |_| | |__ * | __| '__/ _ \/ _ \ _ <| __| / /| _ | __| * | | | | | __/ __/ |_) | |____ / / | | | | | * |_| |_| \___|\___|____/|______/_/ |_| |_|_| * * * Startup and relocation code. * * See readme.txt for copyright information. */ .data .globl _hdraddr,_reladdr _hdraddr: .long 0 _reladdr: .long 0 .text .globl StartDriver, PlugAndPlayInit, OemExt /* helper for relocating the driver */ #define DO_RELOCATION() \ ; \ movl %ebx, _reladdr(%ebx) /* store relocations */ ; \ movl %edx, _hdraddr(%ebx) ; \ ; \ movl 876(%edx), %ecx /* get relocation count */ ; \ jecxz 1f ; \ ; \ pushl %esi /* get relocation data */ ; \ leal 880(%edx), %esi ; \ cld ; \ ; \ 0: ; \ lodsl ; \ addl %ebx, (%ebx, %eax) ; \ loop 0b ; \ ; \ popl %esi /* relocation is complete */ /* Entry point for the standard VBE/AF interface. When used with our * extension mechanism, the driver will already have been relocated by * the OemExt function, so this routine must detect that and do the * right thing in either case. After sorting out the relocation, it * chains to a C function called SetupDriver. */ PlugAndPlayInit: movl %ebx, %edx /* save base address in %edx */ movl 576(%ebx), %eax /* retrieve our actual address */ subl $PlugAndPlayInit, %eax /* subtract the linker address */ addl %eax, %ebx /* add to our base address */ cmpl $0, _reladdr(%ebx) /* quit if we are already relocated */ jne 1f DO_RELOCATION() /* relocate ourselves */ 1: pushl %edx /* do high-level initialization */ call _SetupDriver popl %edx ret /* Driver init function. This is just a wrapper for the C routine called * InitDriver, with a safety check to bottle out if we are being used * by a VBE/AF 1.0 program (in that case, we won't have been relocated yet * so we must give up in disgust). */ StartDriver: pushl %ebx /* check that we have been relocated */ movl 412(%ebx), %eax subl $StartDriver, %eax addl %eax, %ebx cmpl $0, _reladdr(%ebx) je 0f call _InitDriver /* ok, this program is using VBE/AF 2.0 */ popl %ebx ret 0: movl $-1, %eax /* argh, trying to use VBE/AF 1.0! */ popl %ebx ret /* Extension function for the FreeBE/AF enhancements. This will be the * very first thing called by a FreeBE/AF aware application, and must * relocate the driver in response. On subsequent calls it will just * chain to the C function called FreeBEX. */ OemExt: cmpl $0x494E4954, 8(%esp) /* check for FAFEXT_INIT parameter */ jne 2f pushl %ebx movl 8(%esp), %ebx /* read driver address from the stack */ movl %ebx, %edx /* save base address in %edx */ movl 580(%ebx), %eax /* retrieve our actual address */ subl $OemExt, %eax /* subtract the linker address */ addl %eax, %ebx /* add to our base address */ cmpl $0, _reladdr(%ebx) /* quit if we are already relocated */ jne 1f addl %edx, 580(%edx) /* relocate the OemExt pointer */ DO_RELOCATION() /* relocate the rest of the driver */ 1: popl %ebx movl $0x45583031, %eax /* return FAFEXT_MAGIC1 */ ret 2: jmp _FreeBEX /* let the driver handle this request */