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