1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
/*
* 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)
* Oct., 1994 NetBSD port (1.0 BETA 10/2) by ukai
*/
/*
* 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 */
push %ebp /* save original base pointer */
/* ebp is used as a register variable */
/*
* save old data segments: We assume that %ds == %es && %ds == %ss
*/
push %fs
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 $0xf000, %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_BADVER), 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_DISCONNECT), %al /* just in case bootloader connected*/
data32
movl $(PMDV_APMBIOS), %ebx
sti
int $(SYSTEM_BIOS)
cli
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
pop %fs
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
|