| @@ -1,16 +1,16 @@ | | | @@ -1,16 +1,16 @@ |
1 | /* $NetBSD: bios32.c,v 1.1 2017/08/15 06:27:40 maxv Exp $ */ | | 1 | /* $NetBSD: bios32.c,v 1.2 2017/08/15 06:37:50 maxv Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /* |
4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center. | | 9 | * NASA Ames Research Center. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -31,38 +31,38 @@ | | | @@ -31,38 +31,38 @@ |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Copyright (c) 1999, by UCHIYAMA Yasushi | | 34 | * Copyright (c) 1999, by UCHIYAMA Yasushi |
35 | * All rights reserved. | | 35 | * All rights reserved. |
36 | * | | 36 | * |
37 | * Redistribution and use in source and binary forms, with or without | | 37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions | | 38 | * modification, are permitted provided that the following conditions |
39 | * are met: | | 39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright | | 40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. | | 41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. The name of the developer may NOT be used to endorse or promote products | | 42 | * 2. The name of the developer may NOT be used to endorse or promote products |
43 | * derived from this software without specific prior written permission. | | 43 | * derived from this software without specific prior written permission. |
44 | * | | 44 | * |
45 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 45 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
46 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 46 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
47 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 47 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
48 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 48 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
49 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 49 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
50 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 50 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
51 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 51 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
52 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 52 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
53 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 53 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
54 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 54 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
55 | * SUCH DAMAGE. | | 55 | * SUCH DAMAGE. |
56 | */ | | 56 | */ |
57 | | | 57 | |
58 | /* | | 58 | /* |
59 | * Copyright (c) 1997-2001 Michael Shalayeff | | 59 | * Copyright (c) 1997-2001 Michael Shalayeff |
60 | * All rights reserved. | | 60 | * All rights reserved. |
61 | * | | 61 | * |
62 | * Redistribution and use in source and binary forms, with or without | | 62 | * Redistribution and use in source and binary forms, with or without |
63 | * modification, are permitted provided that the following conditions | | 63 | * modification, are permitted provided that the following conditions |
64 | * are met: | | 64 | * are met: |
65 | * 1. Redistributions of source code must retain the above copyright | | 65 | * 1. Redistributions of source code must retain the above copyright |
66 | * notice, this list of conditions and the following disclaimer. | | 66 | * notice, this list of conditions and the following disclaimer. |
67 | * 2. Redistributions in binary form must reproduce the above copyright | | 67 | * 2. Redistributions in binary form must reproduce the above copyright |
68 | * notice, this list of conditions and the following disclaimer in the | | 68 | * notice, this list of conditions and the following disclaimer in the |
| @@ -76,31 +76,31 @@ | | | @@ -76,31 +76,31 @@ |
76 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 76 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
77 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 77 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
78 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 78 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
79 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | | 79 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
80 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 80 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
81 | * THE POSSIBILITY OF SUCH DAMAGE. | | 81 | * THE POSSIBILITY OF SUCH DAMAGE. |
82 | */ | | 82 | */ |
83 | | | 83 | |
84 | /* | | 84 | /* |
85 | * Basic interface to BIOS32 services. | | 85 | * Basic interface to BIOS32 services. |
86 | */ | | 86 | */ |
87 | | | 87 | |
88 | #include <sys/cdefs.h> | | 88 | #include <sys/cdefs.h> |
89 | __KERNEL_RCSID(0, "$NetBSD: bios32.c,v 1.1 2017/08/15 06:27:40 maxv Exp $"); | | 89 | __KERNEL_RCSID(0, "$NetBSD: bios32.c,v 1.2 2017/08/15 06:37:50 maxv Exp $"); |
90 | | | 90 | |
91 | #include <sys/param.h> | | 91 | #include <sys/param.h> |
92 | #include <sys/systm.h> | | 92 | #include <sys/systm.h> |
93 | #include <sys/device.h> | | 93 | #include <sys/device.h> |
94 | | | 94 | |
95 | #include <dev/isa/isareg.h> | | 95 | #include <dev/isa/isareg.h> |
96 | #include <machine/isa_machdep.h> | | 96 | #include <machine/isa_machdep.h> |
97 | | | 97 | |
98 | #include <machine/segments.h> | | 98 | #include <machine/segments.h> |
99 | #include <machine/bios32.h> | | 99 | #include <machine/bios32.h> |
100 | #include <x86/smbiosvar.h> | | 100 | #include <x86/smbiosvar.h> |
101 | #include <x86/efi.h> | | 101 | #include <x86/efi.h> |
102 | | | 102 | |
103 | #include <uvm/uvm.h> | | 103 | #include <uvm/uvm.h> |
104 | | | 104 | |
105 | #include "ipmi.h" | | 105 | #include "ipmi.h" |
106 | #include "opt_xen.h" | | 106 | #include "opt_xen.h" |
| @@ -182,26 +182,75 @@ bios32_init(void) | | | @@ -182,26 +182,75 @@ bios32_init(void) |
182 | for (p = ISA_HOLE_VADDR(SMBIOS_START); | | 182 | for (p = ISA_HOLE_VADDR(SMBIOS_START); |
183 | p < (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END); p+= 16) { | | 183 | p < (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END); p+= 16) { |
184 | if (smbios3_check_header(p)) { | | 184 | if (smbios3_check_header(p)) { |
185 | smbios3_map_kva(p); | | 185 | smbios3_map_kva(p); |
186 | return; | | 186 | return; |
187 | } | | 187 | } |
188 | if (smbios2_check_header(p)) { | | 188 | if (smbios2_check_header(p)) { |
189 | smbios2_map_kva(p); | | 189 | smbios2_map_kva(p); |
190 | return; | | 190 | return; |
191 | } | | 191 | } |
192 | } | | 192 | } |
193 | } | | 193 | } |
194 | | | 194 | |
| | | 195 | /* |
| | | 196 | * Call BIOS32 to locate the specified BIOS32 service, and fill |
| | | 197 | * in the entry point information. |
| | | 198 | */ |
| | | 199 | int |
| | | 200 | bios32_service(uint32_t service, bios32_entry_t e, bios32_entry_info_t ei) |
| | | 201 | { |
| | | 202 | #ifdef i386 |
| | | 203 | uint32_t eax, ebx, ecx, edx; |
| | | 204 | paddr_t entry; |
| | | 205 | |
| | | 206 | if (bios32_entry.offset == 0) |
| | | 207 | return 0; /* BIOS32 not present */ |
| | | 208 | |
| | | 209 | __asm volatile("lcall *(%%edi)" |
| | | 210 | : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| | | 211 | : "0" (service), "1" (0), "D" (&bios32_entry)); |
| | | 212 | |
| | | 213 | if ((eax & 0xff) != 0) |
| | | 214 | return 0; /* service not found */ |
| | | 215 | |
| | | 216 | entry = ebx + edx; |
| | | 217 | |
| | | 218 | if (entry < BIOS32_START || entry >= BIOS32_END) { |
| | | 219 | aprint_error("BIOS32: entry point for service %c%c%c%c is " |
| | | 220 | "outside allowable range\n", |
| | | 221 | service & 0xff, |
| | | 222 | (service >> 8) & 0xff, |
| | | 223 | (service >> 16) & 0xff, |
| | | 224 | (service >> 24) & 0xff); |
| | | 225 | return 0; |
| | | 226 | } |
| | | 227 | |
| | | 228 | e->offset = (void *)ISA_HOLE_VADDR(entry); |
| | | 229 | e->segment = GSEL(GCODE_SEL, SEL_KPL); |
| | | 230 | |
| | | 231 | ei->bei_base = ebx; |
| | | 232 | ei->bei_size = ecx; |
| | | 233 | ei->bei_entry = entry; |
| | | 234 | #else |
| | | 235 | (void)service; |
| | | 236 | (void)e; |
| | | 237 | (void)ei; |
| | | 238 | panic("bios32_service not implemented on amd64"); |
| | | 239 | #endif |
| | | 240 | |
| | | 241 | return 1; |
| | | 242 | } |
| | | 243 | |
195 | static int | | 244 | static int |
196 | smbios2_check_header(const uint8_t *p) | | 245 | smbios2_check_header(const uint8_t *p) |
197 | { | | 246 | { |
198 | const struct smbhdr *sh = (const struct smbhdr *)p; | | 247 | const struct smbhdr *sh = (const struct smbhdr *)p; |
199 | uint8_t chksum; | | 248 | uint8_t chksum; |
200 | int i; | | 249 | int i; |
201 | | | 250 | |
202 | if (sh->sig != BIOS32_MAKESIG('_', 'S', 'M', '_')) | | 251 | if (sh->sig != BIOS32_MAKESIG('_', 'S', 'M', '_')) |
203 | return 0; | | 252 | return 0; |
204 | i = sh->len; | | 253 | i = sh->len; |
205 | for (chksum = 0; i--; ) | | 254 | for (chksum = 0; i--; ) |
206 | chksum += p[i]; | | 255 | chksum += p[i]; |
207 | if (chksum != 0) | | 256 | if (chksum != 0) |
| @@ -238,28 +287,27 @@ smbios2_map_kva(const uint8_t *p) | | | @@ -238,28 +287,27 @@ smbios2_map_kva(const uint8_t *p) |
238 | smbios_entry.min = sh->minrev; | | 287 | smbios_entry.min = sh->minrev; |
239 | smbios_entry.doc = 0; | | 288 | smbios_entry.doc = 0; |
240 | smbios_entry.count = sh->count; | | 289 | smbios_entry.count = sh->count; |
241 | | | 290 | |
242 | for (; pa < end; pa+= NBPG, eva+= NBPG) | | 291 | for (; pa < end; pa+= NBPG, eva+= NBPG) |
243 | #ifdef XEN | | 292 | #ifdef XEN |
244 | pmap_kenter_ma(eva, pa, VM_PROT_READ, 0); | | 293 | pmap_kenter_ma(eva, pa, VM_PROT_READ, 0); |
245 | #else | | 294 | #else |
246 | pmap_kenter_pa(eva, pa, VM_PROT_READ, 0); | | 295 | pmap_kenter_pa(eva, pa, VM_PROT_READ, 0); |
247 | #endif | | 296 | #endif |
248 | pmap_update(pmap_kernel()); | | 297 | pmap_update(pmap_kernel()); |
249 | | | 298 | |
250 | aprint_debug("SMBIOS rev. %d.%d @ 0x%lx (%d entries)\n", | | 299 | aprint_debug("SMBIOS rev. %d.%d @ 0x%lx (%d entries)\n", |
251 | sh->majrev, sh->minrev, (u_long)sh->addr, | | 300 | sh->majrev, sh->minrev, (u_long)sh->addr, sh->count); |
252 | sh->count); | | | |
253 | } | | 301 | } |
254 | | | 302 | |
255 | static int | | 303 | static int |
256 | smbios3_check_header(const uint8_t *p) | | 304 | smbios3_check_header(const uint8_t *p) |
257 | { | | 305 | { |
258 | const struct smb3hdr *sh = (const struct smb3hdr *)p; | | 306 | const struct smb3hdr *sh = (const struct smb3hdr *)p; |
259 | uint8_t chksum; | | 307 | uint8_t chksum; |
260 | int i; | | 308 | int i; |
261 | | | 309 | |
262 | if (p[0] != '_' || p[1] != 'S' || p[2] != 'M' || | | 310 | if (p[0] != '_' || p[1] != 'S' || p[2] != 'M' || |
263 | p[3] != '3' || p[4] != '_') | | 311 | p[3] != '3' || p[4] != '_') |
264 | return 0; | | 312 | return 0; |
265 | i = sh->len; | | 313 | i = sh->len; |
| @@ -292,77 +340,28 @@ smbios3_map_kva(const uint8_t *p) | | | @@ -292,77 +340,28 @@ smbios3_map_kva(const uint8_t *p) |
292 | smbios_entry.mjr = sh->majrev; | | 340 | smbios_entry.mjr = sh->majrev; |
293 | smbios_entry.min = sh->minrev; | | 341 | smbios_entry.min = sh->minrev; |
294 | smbios_entry.doc = sh->docrev; | | 342 | smbios_entry.doc = sh->docrev; |
295 | smbios_entry.count = UINT16_MAX; | | 343 | smbios_entry.count = UINT16_MAX; |
296 | | | 344 | |
297 | for (; pa < end; pa += NBPG, eva += NBPG) | | 345 | for (; pa < end; pa += NBPG, eva += NBPG) |
298 | #ifdef XEN | | 346 | #ifdef XEN |
299 | pmap_kenter_ma(eva, pa, VM_PROT_READ, 0); | | 347 | pmap_kenter_ma(eva, pa, VM_PROT_READ, 0); |
300 | #else | | 348 | #else |
301 | pmap_kenter_pa(eva, pa, VM_PROT_READ, 0); | | 349 | pmap_kenter_pa(eva, pa, VM_PROT_READ, 0); |
302 | #endif | | 350 | #endif |
303 | pmap_update(pmap_kernel()); | | 351 | pmap_update(pmap_kernel()); |
304 | | | 352 | |
305 | aprint_debug("SMBIOS rev. %d.%d.%d @ 0x%lx\n", | | 353 | aprint_debug("SMBIOS rev. %d.%d.%d @ 0x%lx\n", sh->majrev, |
306 | sh->majrev, sh->minrev, sh->docrev, (u_long)sh->addr); | | 354 | sh->minrev, sh->docrev, (u_long)sh->addr); |
307 | } | | | |
308 | | | | |
309 | /* | | | |
310 | * Call BIOS32 to locate the specified BIOS32 service, and fill | | | |
311 | * in the entry point information. | | | |
312 | */ | | | |
313 | int | | | |
314 | bios32_service(uint32_t service, bios32_entry_t e, bios32_entry_info_t ei) | | | |
315 | { | | | |
316 | #ifdef i386 | | | |
317 | uint32_t eax, ebx, ecx, edx; | | | |
318 | paddr_t entry; | | | |
319 | | | | |
320 | if (bios32_entry.offset == 0) | | | |
321 | return (0); /* BIOS32 not present */ | | | |
322 | | | | |
323 | __asm volatile("lcall *(%%edi)" | | | |
324 | : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) | | | |
325 | : "0" (service), "1" (0), "D" (&bios32_entry)); | | | |
326 | | | | |
327 | if ((eax & 0xff) != 0) | | | |
328 | return (0); /* service not found */ | | | |
329 | | | | |
330 | entry = ebx + edx; | | | |
331 | | | | |
332 | if (entry < BIOS32_START || entry >= BIOS32_END) { | | | |
333 | aprint_error("BIOS32: entry point for service %c%c%c%c is " | | | |
334 | "outside allowable range\n", | | | |
335 | service & 0xff, | | | |
336 | (service >> 8) & 0xff, | | | |
337 | (service >> 16) & 0xff, | | | |
338 | (service >> 24) & 0xff); | | | |
339 | return (0); | | | |
340 | } | | | |
341 | | | | |
342 | e->offset = (void *)ISA_HOLE_VADDR(entry); | | | |
343 | e->segment = GSEL(GCODE_SEL, SEL_KPL); | | | |
344 | | | | |
345 | ei->bei_base = ebx; | | | |
346 | ei->bei_size = ecx; | | | |
347 | ei->bei_entry = entry; | | | |
348 | #else | | | |
349 | (void)service; | | | |
350 | (void)e; | | | |
351 | (void)ei; | | | |
352 | panic("bios32_service not implemented on amd64"); | | | |
353 | #endif | | | |
354 | | | | |
355 | return (1); | | | |
356 | } | | 355 | } |
357 | | | 356 | |
358 | /* | | 357 | /* |
359 | * smbios_find_table() takes a caller supplied smbios struct type and | | 358 | * smbios_find_table() takes a caller supplied smbios struct type and |
360 | * a pointer to a handle (struct smbtable) returning one if the structure | | 359 | * a pointer to a handle (struct smbtable) returning one if the structure |
361 | * is sucessfully located and zero otherwise. Callers should take care | | 360 | * is sucessfully located and zero otherwise. Callers should take care |
362 | * to initilize the cookie field of the smbtable structure to zero before | | 361 | * to initilize the cookie field of the smbtable structure to zero before |
363 | * the first invocation of this function. | | 362 | * the first invocation of this function. |
364 | * Multiple tables of the same type can be located by repeadtly calling | | 363 | * Multiple tables of the same type can be located by repeadtly calling |
365 | * smbios_find_table with the same arguments. | | 364 | * smbios_find_table with the same arguments. |
366 | */ | | 365 | */ |
367 | int | | 366 | int |
368 | smbios_find_table(uint8_t type, struct smbtable *st) | | 367 | smbios_find_table(uint8_t type, struct smbtable *st) |