* Sync to recent trunk (r52563).
[reactos.git] / boot / freeldr / freeldr / arch / amd64 / i386pnp.S
1 /*
2 * FreeLoader
3 * Copyright (C) 2003 Eric Kohl
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <asm.inc>
21
22
23 .text
24 .code16
25
26 #include <arch/pc/x86common.h>
27
28
29 /*
30 * U32 PnpBiosSupported(VOID);
31 *
32 * RETURNS:
33 */
34 _pnp_bios_entry_point:
35 .long 0
36 _pnp_bios_data_segment:
37 .word 0
38
39 EXTERN(PnpBiosSupported)
40 .code64
41
42 push rdi
43 push rsi
44 push rcx
45 push rdx
46
47 xor edi, edi
48
49 /* init esi */
50 mov esi, 0xF0000
51
52 pnp_again:
53 mov eax, [%esi]
54 cmp eax, 0x506E5024 /* "$PnP" */
55 je pnp_found
56
57 cmp esi, 0xFFFF0
58 je pnp_not_found
59
60 pnp_add:
61 add esi, 0x10
62 jmp pnp_again
63
64 pnp_found:
65 /* first calculate the checksum */
66 push rsi
67
68 push 0x21
69 pop rcx
70 xor edx, edx
71
72 pnp_loop:
73 lodsb
74 add dl, al
75 loop pnp_loop
76
77 test dl, dl
78 pop rsi
79 jnz pnp_add
80
81 mov edi, esi
82
83 /* Calculate the bios entry point (far pointer) */
84 xor eax, eax
85 mov ax, [esi + 0x0F]
86 shl eax, 16
87 mov ax, [esi + 0x0D]
88 mov _pnp_bios_entry_point, eax
89
90 /* Store bios data segment */
91 mov ax, [esi + 0x1B]
92 mov _pnp_bios_data_segment, ax
93
94 pnp_not_found:
95 mov eax, edi
96
97 pop rdx
98 pop rcx
99 pop rsi
100 pop rdi
101
102 ret
103
104
105 /*
106 * U32 PnpBiosGetDeviceNodeCount(U32 *NodeSize, U32 *NodeCount);
107 *
108 * RETURNS:
109 */
110 _pnp_result:
111 .long 0
112 _pnp_node_size:
113 .word 0
114 _pnp_node_count:
115 .word 0
116
117 EXTERN(PnpBiosGetDeviceNodeCount)
118 .code64
119
120 push rbp
121 mov rbp, rsp
122
123 // pushal FIXME
124 // push es
125
126 call x86_64_SwitchToReal
127 .code16
128
129 mov ax, _pnp_bios_data_segment
130 push ax
131
132 push cs
133 mov ax, _pnp_node_size
134 push ax
135
136 push cs
137 mov ax, _pnp_node_count
138 push ax
139
140 push 0
141
142 call [_pnp_bios_entry_point]
143 add sp, 12
144
145 movzx ecx, ax
146 mov _pnp_result, ecx
147
148 call x86_16_SwitchToLong
149 .code64
150
151 mov esi, [rbp + 0x08]
152 mov ax, _pnp_node_size
153 movzx ecx, ax
154 mov [rsi], ecx
155
156 mov rsi, [ebp + 0x0C]
157 mov ax, _pnp_node_count
158 movzx ecx, ax
159 mov [rsi], eax
160
161 // pop es
162 // popal
163
164 mov rsp, rbp
165 pop rbp
166
167 xor rax, rax
168 mov eax, _pnp_result
169
170 ret
171
172
173 /*
174 * U32 PnpBiosGetDeviceNode(U8 *NodeId, U8 *NodeBuffer);
175 *
176 * RETURNS:
177 */
178 _pnp_buffer_segment:
179 .word 0
180 _pnp_buffer_offset:
181 .word 0
182
183 _pnp_node_number:
184 .byte 0
185
186 EXTERN(PnpBiosGetDeviceNode)
187 .code64
188
189 push rbp
190 mov rbp, rsp
191
192 // pushal
193 // push es
194
195 /* get current node number */
196 mov rsi, [rbp + 0x08]
197 mov al, [rsi]
198 mov _pnp_node_number, al
199
200 /* convert pointer to node buffer to segment/offset */
201 mov eax, [rbp + 0x0C]
202 shr eax, 4
203 and eax, 0xf000
204 mov _pnp_buffer_segment , ax
205 mov eax, [rbp + 0x0C]
206 and eax, 0xffff
207 mov _pnp_buffer_offset, ax
208
209 call x86_64_SwitchToReal
210 .code16
211
212 /* push bios segment */
213 mov ax, _pnp_bios_data_segment
214 push ax
215
216 /* push control flag */
217 push 0x0001
218
219 /* push pointer to node buffer (segment/offset) */
220 mov ax, _pnp_buffer_segment
221 push ax
222 mov ax, _pnp_buffer_offset
223 push ax
224
225 /* push pointer to node number (segment/offset) */
226 push cs
227 mov ax, _pnp_node_number
228 push ax
229
230 /* push function number */
231 push 1
232
233 /* call entry point */
234 call [_pnp_bios_entry_point]
235 add sp, 14
236
237 movzx ecx, ax
238 mov _pnp_result, ecx
239
240 call x86_16_SwitchToLong
241 .code64
242
243 /* update node number */
244 mov rsi, [rbp + 0x08]
245 mov al, _pnp_node_number
246 mov [rsi], al
247
248 // pop es
249 // popal
250
251 mov rsp, rbp
252 pop rbp
253
254 xor rax, rax
255 mov eax, _pnp_result
256
257 ret
258
259 END
260 /* EOF */