1 /*- 2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/poll.h> 34 #include <sys/selinfo.h> 35 36 #include <sys/module.h> 37 #include <sys/bus.h> 38 39 #include <machine/bus.h> 40 #include <machine/resource.h> 41 #include <sys/rman.h> 42 #include <sys/watchdog.h> 43 44 #include <vm/vm.h> 45 #include <vm/vm_param.h> 46 #include <vm/pmap.h> 47 #include <machine/pc/bios.h> 48 49 #ifdef LOCAL_MODULE 50 #include <ipmi.h> 51 #include <ipmivars.h> 52 #else 53 #include <sys/ipmi.h> 54 #include <dev/ipmi/ipmivars.h> 55 #endif 56 57 struct smbios_table_entry { 58 uint8_t anchor_string[4]; 59 uint8_t checksum; 60 uint8_t length; 61 uint8_t major_version; 62 uint8_t minor_version; 63 uint16_t maximum_structure_size; 64 uint8_t entry_point_revision; 65 uint8_t formatted_area[5]; 66 uint8_t DMI_anchor_string[5]; 67 uint8_t intermediate_checksum; 68 uint16_t structure_table_length; 69 uint32_t structure_table_address; 70 uint16_t number_structures; 71 uint8_t BCD_revision; 72 }; 73 74 struct structure_header { 75 uint8_t type; 76 uint8_t length; 77 uint16_t handle; 78 }; 79 80 struct ipmi_device { 81 uint8_t type; 82 uint8_t length; 83 uint16_t handle; 84 uint8_t interface_type; 85 uint8_t spec_revision; 86 uint8_t i2c_slave_address; 87 uint8_t NV_storage_device_address; 88 uint64_t base_address; 89 uint8_t base_address_modifier; 90 uint8_t interrupt_number; 91 }; 92 93 #define SMBIOS_START 0xf0000 94 #define SMBIOS_STEP 0x10 95 #define SMBIOS_OFF 0 96 #define SMBIOS_LEN 4 97 #define SMBIOS_SIG "_SM_" 98 99 devclass_t ipmi_devclass; 100 typedef void (*dispatchproc_t)(uint8_t *p, char **table, 101 struct ipmi_get_info *info); 102 103 static void smbios_run_table(uint8_t *, int, dispatchproc_t *, 104 struct ipmi_get_info *); 105 static char *get_strings(char *, char **); 106 static int smbios_cksum (struct smbios_table_entry *); 107 static void smbios_t38_proc_info(uint8_t *, char **, struct ipmi_get_info *); 108 static int ipmi_smbios_attach (device_t); 109 static int ipmi_smbios_modevent(module_t, int, void *); 110 111 static void 112 smbios_t38_proc_info(uint8_t *p, char **table, struct ipmi_get_info *info) 113 { 114 struct ipmi_device *s = (struct ipmi_device *) p; 115 116 bzero(info, sizeof(struct ipmi_get_info)); 117 if (s->interface_type == 0x01) 118 info->kcs_mode = 1; 119 if (s->interface_type == 0x02) 120 info->smic_mode = 1; 121 info->address = s->base_address & ~1; 122 switch (s->base_address_modifier >> 6) { 123 case 0x00: 124 info->offset = 1; 125 break; 126 case 0x01: 127 info->offset = 4; 128 break; 129 case 0x10: 130 info->offset = 2; 131 break; 132 case 0x11: 133 info->offset = 0; 134 break; 135 } 136 info->io_mode = s->base_address & 1; 137 } 138 139 static char * 140 get_strings(char *p, char **table) 141 { 142 /* Scan for strings, stoping at a single null byte */ 143 while (*p != 0) { 144 *table++ = p; 145 p += strlen(p) + 1; 146 } 147 *table = 0; 148 149 /* Skip past terminating null byte */ 150 return p + 1; 151 } 152 153 154 static void 155 smbios_run_table(uint8_t *p, int entries, dispatchproc_t *dispatchstatus, 156 struct ipmi_get_info *info) 157 { 158 struct structure_header *s; 159 char *table[20]; 160 uint8_t *nextp; 161 162 while(entries--) { 163 s = (struct structure_header *) p; 164 nextp = get_strings(p + s->length, table); 165 166 /* 167 * No strings still has a double-null at the end, 168 * skip over it 169 */ 170 if (table[0] == 0) 171 nextp++; 172 173 if (dispatchstatus[*p]) { 174 (dispatchstatus[*p])(p, table, info); 175 } 176 p = nextp; 177 } 178 } 179 180 device_t 181 ipmi_smbios_identify (driver_t *driver, device_t parent) 182 { 183 device_t child = NULL; 184 u_int32_t addr; 185 int length; 186 int rid1, rid2; 187 188 addr = bios_sigsearch(SMBIOS_START, SMBIOS_SIG, SMBIOS_LEN, 189 SMBIOS_STEP, SMBIOS_OFF); 190 if (addr != 0) { 191 rid1 = 0; 192 length = ((struct smbios_table_entry *)BIOS_PADDRTOVADDR(addr)) 193 ->length; 194 195 child = BUS_ADD_CHILD(parent, 0, "ipmi", -1); 196 if (driver != NULL) 197 device_set_driver(child, driver); 198 bus_set_resource(child, SYS_RES_MEMORY, rid1, addr, length); 199 rid2 = 1; 200 length = ((struct smbios_table_entry *)BIOS_PADDRTOVADDR(addr)) 201 ->structure_table_length; 202 addr = ((struct smbios_table_entry *)BIOS_PADDRTOVADDR(addr)) 203 ->structure_table_address; 204 bus_set_resource(child, SYS_RES_MEMORY, rid2, addr, length); 205 device_set_desc(child, "System Management BIOS"); 206 } else { 207 device_printf(parent, "Failed to find SMBIOS signature\n"); 208 } 209 210 return child; 211 } 212 213 int 214 ipmi_smbios_probe(device_t dev) 215 { 216 struct resource *res1 = NULL, *res2 = NULL; 217 int rid1, rid2; 218 int error; 219 220 if (ipmi_attached) 221 return(EBUSY); 222 223 error = 0; 224 rid1 = 0; 225 rid2 = 1; 226 res1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid1, 227 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE); 228 229 if (res1 == NULL) { 230 device_printf(dev, "Unable to allocate memory resource.\n"); 231 error = ENOMEM; 232 goto bad; 233 } 234 res2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid2, 235 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE); 236 if (res2 == NULL) { 237 device_printf(dev, "Unable to allocate memory resource.\n"); 238 error = ENOMEM; 239 goto bad; 240 } 241 242 if (smbios_cksum( 243 (struct smbios_table_entry *)rman_get_virtual(res1))) { 244 device_printf(dev, "SMBIOS checksum failed.\n"); 245 error = ENXIO; 246 goto bad; 247 } 248 249 bad: 250 if (res1) 251 bus_release_resource(dev, SYS_RES_MEMORY, rid1, res1); 252 if (res2) 253 bus_release_resource(dev, SYS_RES_MEMORY, rid2, res2); 254 return error; 255 } 256 257 258 int 259 ipmi_smbios_query(device_t dev) 260 { 261 struct ipmi_softc *sc = device_get_softc(dev); 262 dispatchproc_t dispatch_smbios_ipmi[256]; 263 struct resource *res = NULL , *res2 = NULL; 264 int rid, rid2; 265 int error; 266 267 error = 0; 268 269 rid = 0; 270 res = bus_alloc_resource(sc->ipmi_smbios_dev, SYS_RES_MEMORY, &rid, 271 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE ); 272 if (res == NULL) { 273 device_printf(dev, "Unable to allocate memory resource.\n"); 274 error = ENOMEM; 275 goto bad; 276 } 277 rid2 = 1; 278 res2 = bus_alloc_resource(sc->ipmi_smbios_dev, SYS_RES_MEMORY, &rid2, 279 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE); 280 if (res2 == NULL) { 281 device_printf(dev, "Unable to allocate memory resource.\n"); 282 error = ENOMEM; 283 goto bad; 284 } 285 286 sc->ipmi_smbios = 287 (struct smbios_table_entry *)rman_get_virtual(res); 288 289 sc->ipmi_busy = 0; 290 291 device_printf(sc->ipmi_smbios_dev, "SMBIOS Version: %d.%02d", 292 sc->ipmi_smbios->major_version, 293 sc->ipmi_smbios->minor_version); 294 if (bcd2bin(sc->ipmi_smbios->BCD_revision)) 295 printf(", revision: %d.%02d", 296 bcd2bin(sc->ipmi_smbios->BCD_revision >> 4), 297 bcd2bin(sc->ipmi_smbios->BCD_revision & 0x0f)); 298 printf("\n"); 299 300 bzero(&sc->ipmi_bios_info, sizeof(sc->ipmi_bios_info)); 301 302 bzero((void *)dispatch_smbios_ipmi, sizeof(dispatch_smbios_ipmi)); 303 dispatch_smbios_ipmi[38] = (void *)smbios_t38_proc_info; 304 smbios_run_table( 305 (void *)rman_get_virtual(res2), 306 sc->ipmi_smbios->number_structures, 307 dispatch_smbios_ipmi, 308 (void*)&sc->ipmi_bios_info); 309 310 bad: 311 if (res) 312 bus_release_resource(sc->ipmi_smbios_dev, SYS_RES_MEMORY, 313 rid, res); 314 res = NULL; 315 if (res2) 316 bus_release_resource(sc->ipmi_smbios_dev, SYS_RES_MEMORY, 317 rid2, res2); 318 res2 = NULL; 319 return 0; 320 } 321 322 static int 323 ipmi_smbios_attach(device_t dev) 324 { 325 struct ipmi_softc *sc = device_get_softc(dev); 326 int error; 327 int status, flags; 328 329 error = 0; 330 sc->ipmi_smbios_dev = dev; 331 sc->ipmi_dev = dev; 332 ipmi_smbios_query(dev); 333 334 if (sc->ipmi_bios_info.kcs_mode) { 335 if (sc->ipmi_bios_info.io_mode) 336 device_printf(dev, "KCS mode found at io 0x%llx " 337 "alignment 0x%x on %s\n", 338 (long long)sc->ipmi_bios_info.address, 339 sc->ipmi_bios_info.offset, 340 device_get_name(device_get_parent(sc->ipmi_dev))); 341 else 342 device_printf(dev, "KCS mode found at mem 0x%llx " 343 "alignment 0x%x on %s\n", 344 (long long)sc->ipmi_bios_info.address, 345 sc->ipmi_bios_info.offset, 346 device_get_name(device_get_parent(sc->ipmi_dev))); 347 348 sc->ipmi_kcs_status_reg = sc->ipmi_bios_info.offset; 349 sc->ipmi_kcs_command_reg = sc->ipmi_bios_info.offset; 350 sc->ipmi_kcs_data_out_reg = 0; 351 sc->ipmi_kcs_data_in_reg = 0; 352 353 if (sc->ipmi_bios_info.io_mode) { 354 sc->ipmi_io_rid = 2; 355 sc->ipmi_io_res = bus_alloc_resource(dev, 356 SYS_RES_IOPORT, &sc->ipmi_io_rid, 357 sc->ipmi_bios_info.address, 358 sc->ipmi_bios_info.address + 359 (sc->ipmi_bios_info.offset * 2), 360 sc->ipmi_bios_info.offset * 2, 361 RF_ACTIVE); 362 } else { 363 sc->ipmi_mem_rid = 2; 364 sc->ipmi_mem_res = bus_alloc_resource(dev, 365 SYS_RES_MEMORY, &sc->ipmi_mem_rid, 366 sc->ipmi_bios_info.address, 367 sc->ipmi_bios_info.address + 368 (sc->ipmi_bios_info.offset * 2), 369 sc->ipmi_bios_info.offset * 2, 370 RF_ACTIVE); 371 } 372 373 if (!sc->ipmi_io_res){ 374 device_printf(dev, 375 "couldn't configure smbios io res\n"); 376 goto bad; 377 } 378 379 status = INB(sc, sc->ipmi_kcs_status_reg); 380 if (status == 0xff) { 381 device_printf(dev, "couldn't find it\n"); 382 error = ENXIO; 383 goto bad; 384 } 385 if(status & KCS_STATUS_OBF){ 386 ipmi_read(dev, NULL, 0); 387 } 388 } else if (sc->ipmi_bios_info.smic_mode) { 389 if (sc->ipmi_bios_info.io_mode) 390 device_printf(dev, "SMIC mode found at io 0x%llx " 391 "alignment 0x%x on %s\n", 392 (long long)sc->ipmi_bios_info.address, 393 sc->ipmi_bios_info.offset, 394 device_get_name(device_get_parent(sc->ipmi_dev))); 395 else 396 device_printf(dev, "SMIC mode found at mem 0x%llx " 397 "alignment 0x%x on %s\n", 398 (long long)sc->ipmi_bios_info.address, 399 sc->ipmi_bios_info.offset, 400 device_get_name(device_get_parent(sc->ipmi_dev))); 401 402 sc->ipmi_smic_data = 0; 403 sc->ipmi_smic_ctl_sts = sc->ipmi_bios_info.offset; 404 sc->ipmi_smic_flags = sc->ipmi_bios_info.offset * 2; 405 406 if (sc->ipmi_bios_info.io_mode) { 407 sc->ipmi_io_rid = 2; 408 sc->ipmi_io_res = bus_alloc_resource(dev, 409 SYS_RES_IOPORT, &sc->ipmi_io_rid, 410 sc->ipmi_bios_info.address, 411 sc->ipmi_bios_info.address + 412 (sc->ipmi_bios_info.offset * 3), 413 sc->ipmi_bios_info.offset * 3, 414 RF_ACTIVE); 415 } else { 416 sc->ipmi_mem_res = bus_alloc_resource(dev, 417 SYS_RES_MEMORY, &sc->ipmi_mem_rid, 418 sc->ipmi_bios_info.address, 419 sc->ipmi_bios_info.address + 420 (sc->ipmi_bios_info.offset * 2), 421 sc->ipmi_bios_info.offset * 2, 422 RF_ACTIVE); 423 } 424 425 if (!sc->ipmi_io_res && !sc->ipmi_mem_res){ 426 device_printf(dev, "couldn't configure smbios res\n"); 427 error = ENXIO; 428 goto bad; 429 } 430 431 flags = INB(sc, sc->ipmi_smic_flags); 432 if (flags == 0xff) { 433 device_printf(dev, "couldn't find it\n"); 434 error = ENXIO; 435 goto bad; 436 } 437 if ((flags & SMIC_STATUS_SMS_ATN) 438 && (flags & SMIC_STATUS_RX_RDY)){ 439 /* skip in smbio mode 440 ipmi_read(dev, NULL, 0); 441 */ 442 } 443 } else { 444 device_printf(dev, "No IPMI interface found\n"); 445 error = ENXIO; 446 goto bad; 447 } 448 ipmi_attach(dev); 449 450 return 0; 451 bad: 452 /* 453 device_delete_child(device_get_parent(dev), dev); 454 */ 455 return error; 456 } 457 458 static int 459 smbios_cksum (struct smbios_table_entry *e) 460 { 461 u_int8_t *ptr; 462 u_int8_t cksum; 463 int i; 464 465 ptr = (u_int8_t *)e; 466 cksum = 0; 467 for (i = 0; i < e->length; i++) { 468 cksum += ptr[i]; 469 } 470 471 return cksum; 472 } 473 474 475 static int 476 ipmi_smbios_detach (device_t dev) 477 { 478 struct ipmi_softc *sc; 479 480 sc = device_get_softc(dev); 481 ipmi_detach(dev); 482 if (sc->ipmi_ev_tag) 483 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_ev_tag); 484 485 if (sc->ipmi_mem_res) 486 bus_release_resource(dev, SYS_RES_MEMORY, sc->ipmi_mem_rid, 487 sc->ipmi_mem_res); 488 if (sc->ipmi_io_res) 489 bus_release_resource(dev, SYS_RES_IOPORT, sc->ipmi_io_rid, 490 sc->ipmi_io_res); 491 return 0; 492 } 493 494 495 static device_method_t ipmi_methods[] = { 496 /* Device interface */ 497 DEVMETHOD(device_identify, ipmi_smbios_identify), 498 DEVMETHOD(device_probe, ipmi_smbios_probe), 499 DEVMETHOD(device_attach, ipmi_smbios_attach), 500 DEVMETHOD(device_detach, ipmi_smbios_detach), 501 { 0, 0 } 502 }; 503 504 static driver_t ipmi_smbios_driver = { 505 "ipmi", 506 ipmi_methods, 507 sizeof(struct ipmi_softc), 508 }; 509 510 static int 511 ipmi_smbios_modevent (mod, what, arg) 512 module_t mod; 513 int what; 514 void * arg; 515 { 516 device_t * devs; 517 int count; 518 int i; 519 520 switch (what) { 521 case MOD_LOAD: 522 return 0; 523 case MOD_UNLOAD: 524 devclass_get_devices(ipmi_devclass, &devs, &count); 525 for (i = 0; i < count; i++) { 526 device_delete_child(device_get_parent(devs[i]), 527 devs[i]); 528 } 529 break; 530 default: 531 break; 532 } 533 534 return 0; 535 } 536 537 DRIVER_MODULE(ipmi, isa, ipmi_smbios_driver, ipmi_devclass, 538 ipmi_smbios_modevent, 0); 539