[ASM]
[reactos.git] / reactos / 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 #define ASM
27
28 #include <arch.h>
29
30
31 /*
32 * U32 PnpBiosSupported(VOID);
33 *
34 * RETURNS:
35 */
36 _pnp_bios_entry_point:
37 .long 0
38 _pnp_bios_data_segment:
39 .word 0
40
41 EXTERN(PnpBiosSupported)
42 .code64
43
44 push rdi
45 push rsi
46 push rcx
47 push rdx
48
49 xor edi, edi
50
51 /* init esi */
52 mov esi, 0xF0000
53
54 pnp_again:
55 mov eax, [%esi]
56 cmp eax, 0x506E5024 /* "$PnP" */
57 je pnp_found
58
59 cmp esi, 0xFFFF0
60 je pnp_not_found
61
62 pnp_add:
63 add esi, 0x10
64 jmp pnp_again
65
66 pnp_found:
67 /* first calculate the checksum */
68 push rsi
69
70 push 0x21
71 pop rcx
72 xor edx, edx
73
74 pnp_loop:
75 lodsb
76 add dl, al
77 loop pnp_loop
78
79 test dl, dl
80 pop rsi
81 jnz pnp_add
82
83 mov edi, esi
84
85 /* Calculate the bios entry point (far pointer) */
86 xor eax, eax
87 mov ax, [esi + 0x0F]
88 shl eax, 16
89 mov ax, [esi + 0x0D]
90 mov _pnp_bios_entry_point, eax
91
92 /* Store bios data segment */
93 mov ax, [esi + 0x1B]
94 mov _pnp_bios_data_segment, ax
95
96 pnp_not_found:
97 mov eax, edi
98
99 pop rdx
100 pop rcx
101 pop rsi
102 pop rdi
103
104 ret
105
106
107 /*
108 * U32 PnpBiosGetDeviceNodeCount(U32 *NodeSize, U32 *NodeCount);
109 *
110 * RETURNS:
111 */
112 _pnp_result:
113 .long 0
114 _pnp_node_size:
115 .word 0
116 _pnp_node_count:
117 .word 0
118
119 EXTERN(PnpBiosGetDeviceNodeCount)
120 .code64
121
122 push rbp
123 mov rbp, rsp
124
125 // pushal FIXME
126 // push es
127
128 call x86_64_SwitchToReal
129 .code16
130
131 mov ax, _pnp_bios_data_segment
132 push ax
133
134 push cs
135 mov ax, _pnp_node_size
136 push ax
137
138 push cs
139 mov ax, _pnp_node_count
140 push ax
141
142 push 0
143
144 call [_pnp_bios_entry_point]
145 add sp, 12
146
147 movzx ecx, ax
148 mov _pnp_result, ecx
149
150 call x86_16_SwitchToLong
151 .code64
152
153 mov esi, [rbp + 0x08]
154 mov ax, _pnp_node_size
155 movzx ecx, ax
156 mov [rsi], ecx
157
158 mov rsi, [ebp + 0x0C]
159 mov ax, _pnp_node_count
160 movzx ecx, ax
161 mov [rsi], eax
162
163 // pop es
164 // popal
165
166 mov rsp, rbp
167 pop rbp
168
169 xor rax, rax
170 mov eax, _pnp_result
171
172 ret
173
174
175 /*
176 * U32 PnpBiosGetDeviceNode(U8 *NodeId, U8 *NodeBuffer);
177 *
178 * RETURNS:
179 */
180 _pnp_buffer_segment:
181 .word 0
182 _pnp_buffer_offset:
183 .word 0
184
185 _pnp_node_number:
186 .byte 0
187
188 EXTERN(PnpBiosGetDeviceNode)
189 .code64
190
191 push rbp
192 mov rbp, rsp
193
194 // pushal
195 // push es
196
197 /* get current node number */
198 mov rsi, [rbp + 0x08]
199 mov al, [rsi]
200 mov _pnp_node_number, al
201
202 /* convert pointer to node buffer to segment/offset */
203 mov eax, [rbp + 0x0C]
204 shr eax, 4
205 and eax, 0xf000
206 mov _pnp_buffer_segment , ax
207 mov eax, [rbp + 0x0C]
208 and eax, 0xffff
209 mov _pnp_buffer_offset, ax
210
211 call x86_64_SwitchToReal
212 .code16
213
214 /* push bios segment */
215 mov ax, _pnp_bios_data_segment
216 push ax
217
218 /* push control flag */
219 push 0x0001
220
221 /* push pointer to node buffer (segment/offset) */
222 mov ax, _pnp_buffer_segment
223 push ax
224 mov ax, _pnp_buffer_offset
225 push ax
226
227 /* push pointer to node number (segment/offset) */
228 push cs
229 mov ax, _pnp_node_number
230 push ax
231
232 /* push function number */
233 push 1
234
235 /* call entry point */
236 call [_pnp_bios_entry_point]
237 add sp, 14
238
239 movzx ecx, ax
240 mov _pnp_result, ecx
241
242 call x86_16_SwitchToLong
243 .code64
244
245 /* update node number */
246 mov rsi, [rbp + 0x08]
247 mov al, _pnp_node_number
248 mov [rsi], al
249
250 // pop es
251 // popal
252
253 mov rsp, rbp
254 pop rbp
255
256 xor rax, rax
257 mov eax, _pnp_result
258
259 ret
260
261 END
262 /* EOF */