133 lines
4.2 KiB
ArmAsm
133 lines
4.2 KiB
ArmAsm
/*
|
|
* ______ ____ ______ _____ ______
|
|
* | ____| | _ \| ____| / / _ \| ____|
|
|
* | |__ _ __ ___ ___| |_) | |__ / / |_| | |__
|
|
* | __| '__/ _ \/ _ \ _ <| __| / /| _ | __|
|
|
* | | | | | __/ __/ |_) | |____ / / | | | | |
|
|
* |_| |_| \___|\___|____/|______/_/ |_| |_|_|
|
|
*
|
|
*
|
|
* 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 */
|