64bb0d8861
I think I have narrowed this down to the stack being overflown. I have taken the push/pop of %fs out, it shouldn't be needed anyway, but the real & correct solution might to save the registers on the stack in locore.s before calling this stuff.
208 lines
5.1 KiB
ArmAsm
208 lines
5.1 KiB
ArmAsm
/*
|
|
* LP (Laptop Package)
|
|
*
|
|
* Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
|
|
*
|
|
* This software may be used, modified, copied, and distributed, in
|
|
* both source and binary form provided that the above copyright and
|
|
* these terms are retained. Under no circumstances is the author
|
|
* responsible for the proper functioning of this software, nor does
|
|
* the author assume any responsibility for damages incurred with its
|
|
* use.
|
|
*
|
|
* Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
|
|
*
|
|
* $Id: apm_init.S,v 1.2 1994/10/01 05:12:29 davidg Exp $
|
|
*/
|
|
|
|
/*
|
|
* If you want to know the specification of APM BIOS, see the following
|
|
* documentations,
|
|
*
|
|
* [1] Intel Corporation and Microsoft Corporation, "Advanced Power
|
|
* Management, The Next Generation, Version 1.0", Feb.,1992.
|
|
*
|
|
* [2] Intel Corporation and Microsoft Corporation, "Advanced Power
|
|
* Management (APM) BIOS Interface Specification Revision 1.1",
|
|
* Sep.,1993, Intel Order Number: 241704-001, Microsoft Part
|
|
* Number: 781-110-X01
|
|
*
|
|
* or contact
|
|
*
|
|
* APM Support Desk (Intel Corporation, US)
|
|
* TEL: (800)628-8686
|
|
* FAX: (916)356-6100.
|
|
*/
|
|
|
|
.file "apm_init.S"
|
|
|
|
#define ASM
|
|
|
|
#include "real_prot.h"
|
|
#include "apm_bios.h"
|
|
#include "apm_segments.h"
|
|
|
|
/*
|
|
* APM BIOS initializer
|
|
*
|
|
* Return value:
|
|
* %eax 0xfffffff Can't find APM BIOS
|
|
* 0xffffffe Don't support 32bit connection
|
|
* 0xffffffd Connection error
|
|
* otherwise APM version (16bit BCD format)
|
|
* %ebx APM cs entry offset (32bit)
|
|
* %ecx lower 16bit APM 16bit cs base (real mode segment)
|
|
* upper 16bit APM 32bit cs base (real mode segment)
|
|
* %edx lower 16bit APM ds limit (real mode segment)
|
|
* upper 16bit [Reserved]
|
|
* %esi lower 16bit APM cs limit (APM 1.1 or later)
|
|
* upper 16bit APM ds limit (APM 1.1 or later)
|
|
* %edi bit0 = 1 16bit protected mode interface supported
|
|
* bit1 = 1 32bit protected mode interface supported
|
|
* bit2 = 1 "CPU idle" call slows processor clock speed
|
|
* bit3 = 1 APM BIOS Power Management disabled
|
|
* bit4 = 1 APM BIOS Power Management disengaged
|
|
*/
|
|
|
|
.text
|
|
ENTRY(apm_init)
|
|
cli /* disable interrupt */
|
|
pushl %ebp /* save original base pointer */
|
|
/* ebp is used as a register variable */
|
|
/*
|
|
* save old data segments: We assume that %ds == %es && %ds == %ss
|
|
*/
|
|
movw %ds, %ax
|
|
movw %ax, %fs
|
|
movw $(APM_INIT_DS_SEL), %ax /* initializer data segment */
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %ss
|
|
movl %esp, old_esp /* save original stack pointer */
|
|
movl $0x10000, %esp /* setup temporary stack */
|
|
/* (note that it isn't 0x00000000) */
|
|
|
|
sidt EXT(Idtr_prot) /* save current IDT */
|
|
call EXT(prot_to_real) /* return to real mode */
|
|
|
|
/*
|
|
* APM installation check
|
|
*/
|
|
movb $(APM_BIOS), %ah
|
|
movb $(APM_INSTCHECK), %al
|
|
data32
|
|
movl $(PMDV_APMBIOS), %ebx
|
|
sti
|
|
int $(SYSTEM_BIOS) /* call system BIOS */
|
|
cli
|
|
|
|
jnc 1f /* if found, goto 1f */
|
|
|
|
data32
|
|
call EXT(real_to_prot) /* come back again to protected mode */
|
|
movl $(APMINI_CANTFIND), apm_version
|
|
/* can't find APM BIOS */
|
|
jmp finish
|
|
|
|
1:
|
|
movl %eax, %edx /* actually, movw %ax, %dx */
|
|
/* save the value of %ax */
|
|
data32
|
|
call EXT(real_to_prot) /* come back again to protected mode */
|
|
cmpb $0x50, %bh /* %bh == 'P'? */
|
|
jnz 1f
|
|
cmpb $0x4d, %bl /* %bl == 'M'? */
|
|
jz 2f
|
|
|
|
1:
|
|
movl $(APMINI_CANTFIND), apm_version
|
|
/* can't find APM BIOS */
|
|
jmp finish
|
|
|
|
2:
|
|
testl $(APM_32BIT_SUPPORT), %ecx
|
|
/* supports 32bit connection? */
|
|
jnz 1f
|
|
|
|
movl $(APMINI_NOT32BIT), apm_version
|
|
/* don't support 32bit connection */
|
|
jmp finish
|
|
1:
|
|
movl %edx, apm_version
|
|
andl $0x0000ffff, %ecx
|
|
movl %ecx, apm_flags
|
|
|
|
/*
|
|
* APM Protected Mode 32-bit Interface Connect
|
|
*/
|
|
call EXT(prot_to_real) /* return to real mode */
|
|
|
|
movb $(APM_BIOS), %ah
|
|
movb $(APM_PROT32CONNECT), %al
|
|
data32
|
|
movl $(PMDV_APMBIOS), %ebx
|
|
sti
|
|
int $(SYSTEM_BIOS)
|
|
cli
|
|
jnc 1f /* if successed, go to 1f */
|
|
data32
|
|
call EXT(real_to_prot)
|
|
movl $(APMINI_CONNECTERR), apm_version
|
|
/* connection error */
|
|
jmp finish
|
|
1:
|
|
/* save PM 32bit code segment into %bp */
|
|
movl %eax, %ebp /* actually, movw %ax, %bp */
|
|
data32
|
|
call EXT(real_to_prot)
|
|
movl $0x0000ffff, %eax
|
|
andl %eax, %ebp /* 32bit cs base */
|
|
andl %eax, %ecx /* 16bit cs base */
|
|
andl %eax, %edx /* ds base */
|
|
andl %eax, %esi /* cs length (APM 1.1 or later) */
|
|
andl %eax, %edi /* ds length (APM 1.1 or later) */
|
|
/* %ebx is code offset */
|
|
/* pack 32bit cs and 16bit cs into %ecx */
|
|
shll $16, %ebp
|
|
orl %ebp, %ecx
|
|
/* pack cs length and ds length into %esi */
|
|
shll $16, %edi
|
|
orl %edi, %esi
|
|
finish:
|
|
cli
|
|
lidt EXT(Idtr_prot) /* restore old IDTR */
|
|
movl old_esp, %esp /* restore old stack pointer */
|
|
movl apm_version, %ebp /* stored to %eax later */
|
|
movl apm_flags, %edi
|
|
#if 0
|
|
movw $(BOOTSTRAP_DS_SEL), %ax
|
|
/* restore old data segments */
|
|
#else
|
|
movw %fs, %ax
|
|
#endif
|
|
movw %ax, %ss
|
|
movw %ax, %es
|
|
movw %ax, %ds
|
|
movl %ebp, %eax
|
|
popl %ebp /* restore old base pointer */
|
|
lret /* restore old code segment */
|
|
|
|
.data
|
|
|
|
.globl EXT(ouraddr)
|
|
LEXT(ouraddr)
|
|
.long APM_OURADDR
|
|
|
|
old_esp:
|
|
.long 0
|
|
apm_version:
|
|
.long 0
|
|
apm_flags:
|
|
.long 0
|
|
old_ds:
|
|
.word 0
|
|
old_es:
|
|
.word 0
|
|
old_ss:
|
|
.word 0
|