[BACK]Return to bios.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/bios.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: bios.c,v 1.70 2007/08/06 16:12:25 gwk Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997-2001 Michael Shalayeff
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     25:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     26:  * THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: /* #define BIOS_DEBUG */
                     30:
                     31: #include <sys/param.h>
                     32: #include <sys/systm.h>
                     33: #include <sys/kernel.h>
                     34: #include <sys/device.h>
                     35: #include <sys/errno.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/malloc.h>
                     38: #include <sys/reboot.h>
                     39: #include <sys/extent.h>
                     40:
                     41: #include <uvm/uvm_extern.h>
                     42: #include <sys/sysctl.h>
                     43:
                     44: #include <dev/cons.h>
                     45: #include <stand/boot/bootarg.h>
                     46:
                     47: #include <machine/cpu.h>
                     48: #include <machine/pio.h>
                     49: #include <machine/cpufunc.h>
                     50: #include <machine/conf.h>
                     51: #include <machine/gdt.h>
                     52: #include <machine/pcb.h>
                     53: #include <machine/biosvar.h>
                     54: #include <machine/apmvar.h>
                     55: #include <machine/smbiosvar.h>
                     56:
                     57: #include <dev/isa/isareg.h>
                     58: #include <i386/isa/isa_machdep.h>
                     59:
                     60: #include "apm.h"
                     61: #include "pcibios.h"
                     62: #include "pci.h"
                     63:
                     64: struct bios_softc {
                     65:        struct  device sc_dev;
                     66: };
                     67:
                     68: int biosprobe(struct device *, void *, void *);
                     69: void biosattach(struct device *, struct device *, void *);
                     70: int bios_print(void *, const char *);
                     71: char *fixstring(char *);
                     72:
                     73: struct cfattach bios_ca = {
                     74:        sizeof(struct bios_softc), biosprobe, biosattach
                     75: };
                     76:
                     77: struct cfdriver bios_cd = {
                     78:        NULL, "bios", DV_DULL
                     79: };
                     80:
                     81: extern dev_t bootdev;
                     82:
                     83: #if NAPM > 0 || defined(DEBUG)
                     84: bios_apminfo_t *apm;
                     85: #endif
                     86: #if NPCI > 0
                     87: bios_pciinfo_t *bios_pciinfo;
                     88: #endif
                     89: bios_diskinfo_t *bios_diskinfo;
                     90: bios_memmap_t  *bios_memmap;
                     91: u_int32_t      bios_cksumlen;
                     92: struct bios32_entry bios32_entry;
                     93: struct smbios_entry smbios_entry;
                     94: #ifdef MULTIPROCESSOR
                     95: void           *bios_smpinfo;
                     96: #endif
                     97: #ifdef NFSCLIENT
                     98: bios_bootmac_t *bios_bootmac;
                     99: #endif
                    100:
                    101: void           smbios_info(char*);
                    102:
                    103: bios_diskinfo_t *bios_getdiskinfo(dev_t);
                    104:
                    105: /*
                    106:  * used by hw_sysctl
                    107:  */
                    108: extern char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver;
                    109: const char *smbios_uninfo[] = {
                    110:        "System",
                    111:        "Not ",
                    112:        "To be",
                    113:        "SYS-"
                    114: };
                    115:
                    116:
                    117: int
                    118: biosprobe(struct device *parent, void *match, void *aux)
                    119: {
                    120:        struct bios_attach_args *bia = aux;
                    121:
                    122: #ifdef BIOS_DEBUG
                    123:        printf("%s%d: boot API ver %x, %x; args %p[%d]\n",
                    124:            bia->bios_dev, bios_cd.cd_ndevs,
                    125:            bootapiver, BOOTARG_APIVER, bootargp, bootargc);
                    126: #endif
                    127:        /* there could be only one */
                    128:        if (bios_cd.cd_ndevs || strcmp(bia->bios_dev, bios_cd.cd_name))
                    129:                return 0;
                    130:
                    131:        if (!(bootapiver & BAPIV_VECTOR) || bootargp == NULL)
                    132:                return 0;
                    133:
                    134:        return 1;
                    135: }
                    136:
                    137: void
                    138: biosattach(struct device *parent, struct device *self, void *aux)
                    139: {
                    140:        struct bios_softc *sc = (struct bios_softc *)self;
                    141: #if (NPCI > 0 && NPCIBIOS > 0) || NAPM > 0
                    142:        struct bios_attach_args *bia = aux;
                    143: #endif
                    144:        struct smbios_struct_bios *sb;
                    145:        struct smbtable bios;
                    146:        volatile u_int8_t *va;
                    147:        char scratch[64], *str;
                    148:        int flags;
                    149:
                    150:        /* remember flags */
                    151:        flags = sc->sc_dev.dv_cfdata->cf_flags;
                    152:
                    153:        va = ISA_HOLE_VADDR(0xffff0);
                    154:        switch (va[14]) {
                    155:        default:
                    156:        case 0xff: str = "PC";          break;
                    157:        case 0xfe: str = "PC/XT";       break;
                    158:        case 0xfd: str = "PCjr";        break;
                    159:        case 0xfc: str = "AT/286+";     break;
                    160:        case 0xfb: str = "PC/XT+";      break;
                    161:        case 0xfa: str = "PS/2 25/30";  break;
                    162:        case 0xf9: str = "PC Convertible";break;
                    163:        case 0xf8: str = "PS/2 386+";   break;
                    164:        }
                    165:        printf(": %s BIOS, date %c%c/%c%c/%c%c",
                    166:            str, va[5], va[6], va[8], va[9], va[11], va[12]);
                    167:
                    168:        /*
                    169:         * Determining whether BIOS32 extensions are available is
                    170:         * done by searching for the BIOS32 service directory.
                    171:         * This 16-byte structure can be found somewhere in the
                    172:         * range 0E0000h - 0FFFFFh and must be 16-byte aligned.
                    173:         *
                    174:         *  _______________________________________________________
                    175:         * | Offset | Bytes | Description                          |
                    176:         * |-------------------------------------------------------|
                    177:         * |    0   |   4   | ASCII signature string of "_32_".    |
                    178:         * |    4   |   4   | 32-bit entry point.                  |
                    179:         * |    8   |   1   | Revision Level. Typically 00h.       |
                    180:         * |    9   |   1   | Header length in 16-byte units. So   |
                    181:         * |        |       | would have the value of 01h.         |
                    182:         * |    A   |   1   | Checksum. The sum of all bytes in    |
                    183:         * |        |       | this header must be zero.            |
                    184:         * |    B   |   5   | Reserved. Set to zero.               |
                    185:         *  -------------------------------------------------------
                    186:         *
                    187:         * To find the service directory, we first search for the
                    188:         * signature. If we find a match, we must also verify the
                    189:         * checksum. This service directory may then be used to
                    190:         * determine whether a PCI BIOS is present.
                    191:         *
                    192:         * For more information see the PCI BIOS Specification,
                    193:         * Revision 2.1 (August 26, 1994).
                    194:         */
                    195:
                    196:        if (!(flags & BIOSF_BIOS32)) {
                    197:                for (va = ISA_HOLE_VADDR(BIOS32_START);
                    198:                    va < (u_int8_t *)ISA_HOLE_VADDR(BIOS32_END); va += 16) {
                    199:                        bios32_header_t h = (bios32_header_t)va;
                    200:                        u_int8_t cksum;
                    201:                        int i;
                    202:
                    203:                        if (h->signature != BIOS32_SIGNATURE)
                    204:                                continue;
                    205:
                    206:                        /* verify checksum */
                    207:                        for (cksum = 0, i = h->length * 16; i--; cksum += va[i])
                    208:                                ;
                    209:                        if (cksum != 0)
                    210:                                continue;
                    211:
                    212:                        if (h->entry <= BIOS32_START || h->entry >= BIOS32_END)
                    213:                                continue;
                    214:
                    215:                        bios32_entry.segment = GSEL(GCODE_SEL, SEL_KPL);
                    216:                        bios32_entry.offset = (u_int32_t)ISA_HOLE_VADDR(h->entry);
                    217:                        printf(", BIOS32 rev. %d @ 0x%lx", h->rev, h->entry);
                    218:                        break;
                    219:                }
                    220:        }
                    221:
                    222:        /* see if we have SMBIOS extensions */
                    223:        if (!(flags & BIOSF_SMBIOS)) {
                    224:                for (va = ISA_HOLE_VADDR(SMBIOS_START);
                    225:                    va < (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END); va+= 16) {
                    226:                        struct smbhdr * sh = (struct smbhdr *)va;
                    227:                        u_int8_t chksum;
                    228:                        vaddr_t eva;
                    229:                        paddr_t pa, end;
                    230:                        int i;
                    231:
                    232:                        if (sh->sig != SMBIOS_SIGNATURE)
                    233:                                continue;
                    234:                        i = sh->len;
                    235:                        for (chksum = 0; i--; chksum += va[i])
                    236:                                ;
                    237:                        if (chksum != 0)
                    238:                                continue;
                    239:                        va += 0x10;
                    240:                        if (va[0] != '_' && va[1] != 'D' && va[2] != 'M' &&
                    241:                            va[3] != 'I' && va[4] != '_')
                    242:                                continue;
                    243:                        for (chksum = 0, i = 0xf; i--; chksum += va[i]);
                    244:                                ;
                    245:                        if (chksum != 0)
                    246:                                continue;
                    247:
                    248:                        pa = trunc_page(sh->addr);
                    249:                        end = round_page(sh->addr + sh->size);
                    250:                        eva = uvm_km_valloc(kernel_map, end-pa);
                    251:                        if (eva == 0)
                    252:                                break;
                    253:
                    254:                        smbios_entry.addr = (u_int8_t *)(eva +
                    255:                            (sh->addr & PGOFSET));
                    256:                        smbios_entry.len = sh->size;
                    257:                        smbios_entry.mjr = sh->majrev;
                    258:                        smbios_entry.min = sh->minrev;
                    259:                        smbios_entry.count = sh->count;
                    260:
                    261:                        for (; pa < end; pa+= NBPG, eva+= NBPG)
                    262:                                pmap_kenter_pa(eva, pa, VM_PROT_READ);
                    263:
                    264:                        printf(", SMBIOS rev. %d.%d @ 0x%lx (%d entries)",
                    265:                            sh->majrev, sh->minrev, sh->addr, sh->count);
                    266:
                    267:                        bios.cookie = 0;
                    268:                        if (smbios_find_table(SMBIOS_TYPE_BIOS, &bios)) {
                    269:                                sb = bios.tblhdr;
                    270:                                printf("\n%s:", sc->sc_dev.dv_xname);
                    271:
                    272:                                if ((smbios_get_string(&bios, sb->vendor,
                    273:                                    scratch, sizeof(scratch))) != NULL)
                    274:                                        printf(" vendor %s", scratch);
                    275:                                if ((smbios_get_string(&bios, sb->version,
                    276:                                    scratch, sizeof(scratch))) != NULL)
                    277:                                        printf(" version \"%s\"", scratch);
                    278:                                if ((smbios_get_string(&bios, sb->release,
                    279:                                    scratch, sizeof(scratch))) != NULL)
                    280:                                        printf(" date %s", scratch);
                    281:                        }
                    282:                        smbios_info(sc->sc_dev.dv_xname);
                    283:                        break;
                    284:                }
                    285:        }
                    286:
                    287:        printf("\n");
                    288:
                    289: #if NAPM > 0
                    290:        if (apm) {
                    291:                struct bios_attach_args ba;
                    292: #if defined(DEBUG) || defined(APMDEBUG)
                    293:                printf("apminfo: %x, code %x[%x]/%x[%x], data %x[%x], ept %x\n",
                    294:                    apm->apm_detail,
                    295:                    apm->apm_code32_base, apm->apm_code_len,
                    296:                    apm->apm_code16_base, apm->apm_code16_len,
                    297:                    apm->apm_data_base, apm->apm_data_len, apm->apm_entry);
                    298: #endif
                    299:                ba.bios_dev = "apm";
                    300:                ba.bios_func = 0x15;
                    301:                ba.bios_memt = bia->bios_memt;
                    302:                ba.bios_iot = bia->bios_iot;
                    303:                ba.bios_apmp = apm;
                    304:                config_found(self, &ba, bios_print);
                    305:        }
                    306: #endif
                    307: #if NPCI > 0 && NPCIBIOS > 0
                    308:        if (!(flags & BIOSF_PCIBIOS)) {
                    309:                struct bios_attach_args ba;
                    310:
                    311:                ba.bios_dev = "pcibios";
                    312:                ba.bios_func = 0x1A;
                    313:                ba.bios_memt = bia->bios_memt;
                    314:                ba.bios_iot = bia->bios_iot;
                    315:                config_found(self, &ba, bios_print);
                    316:        }
                    317: #endif
                    318:
                    319:        /*
                    320:         * now that we gave 'em a chance to attach,
                    321:         * scan and map all the proms we can find
                    322:         */
                    323:        if (!(flags & BIOSF_PROMSCAN)) {
                    324:                volatile u_int8_t *eva;
                    325:
                    326:                for (str = NULL, va = ISA_HOLE_VADDR(0xc0000),
                    327:                    eva = ISA_HOLE_VADDR(0xf0000);
                    328:                    va < eva; va += 512) {
                    329:                        extern struct extent *iomem_ex;
                    330:                        bios_romheader_t romh = (bios_romheader_t)va;
                    331:                        u_int32_t off, len;
                    332:                        u_int8_t cksum;
                    333:                        int i;
                    334:
                    335:                        if (romh->signature != 0xaa55)
                    336:                                continue;
                    337:
                    338:                        /*
                    339:                         * for this and the next check we probably want
                    340:                         * to reserve the page in the extent anyway
                    341:                         */
                    342:                        if (!romh->len || romh->len == 0xff)
                    343:                                continue;
                    344:
                    345:                        len = romh->len * 512;
                    346:                        if (va + len > eva)
                    347:                                continue;
                    348:
                    349:                        for (cksum = 0, i = len; i--; cksum += va[i])
                    350:                                ;
                    351: #ifdef __stinkpad_sucks__
                    352:                        if (cksum != 0)
                    353:                                continue;
                    354: #endif
                    355:
                    356:                        off = 0xc0000 + (va - (u_int8_t *)
                    357:                            ISA_HOLE_VADDR(0xc0000));
                    358:
                    359:                        if (!str)
                    360:                                printf("%s: ROM list:",
                    361:                                    str = sc->sc_dev.dv_xname);
                    362:                        printf(" 0x%05x/0x%x%s", off, len,
                    363:                            cksum? "!" : "");
                    364:
                    365:                        if ((i = extent_alloc_region(iomem_ex,
                    366:                            (paddr_t)off, len, EX_NOWAIT)))
                    367:                                printf(":%d", i);
                    368:
                    369:                        va += len - 512;
                    370:                }
                    371:        }
                    372:
                    373:        if (str)
                    374:                printf("\n");
                    375: }
                    376:
                    377: void
                    378: bios_getopt()
                    379: {
                    380:        bootarg_t *q;
                    381:
                    382: #ifdef BIOS_DEBUG
                    383:        printf("bootargv:");
                    384: #endif
                    385:
                    386:        for(q = bootargp; q->ba_type != BOOTARG_END; q = q->ba_next) {
                    387:                q->ba_next = (bootarg_t *)((caddr_t)q + q->ba_size);
                    388:                switch (q->ba_type) {
                    389:                case BOOTARG_MEMMAP:
                    390:                        bios_memmap = (bios_memmap_t *)q->ba_arg;
                    391: #ifdef BIOS_DEBUG
                    392:                        printf(" memmap %p", bios_memmap);
                    393: #endif
                    394:                        break;
                    395:                case BOOTARG_DISKINFO:
                    396:                        bios_diskinfo = (bios_diskinfo_t *)q->ba_arg;
                    397: #ifdef BIOS_DEBUG
                    398:                        printf(" diskinfo %p", bios_diskinfo);
                    399: #endif
                    400:                        break;
                    401: #if NAPM > 0 || defined(DEBUG)
                    402:                case BOOTARG_APMINFO:
                    403: #ifdef BIOS_DEBUG
                    404:                        printf(" apminfo %p", q->ba_arg);
                    405: #endif
                    406:                        apm = (bios_apminfo_t *)q->ba_arg;
                    407:                        break;
                    408: #endif
                    409:                case BOOTARG_CKSUMLEN:
                    410:                        bios_cksumlen = *(u_int32_t *)q->ba_arg;
                    411: #ifdef BIOS_DEBUG
                    412:                        printf(" cksumlen %d", bios_cksumlen);
                    413: #endif
                    414:                        break;
                    415: #if NPCI > 0
                    416:                case BOOTARG_PCIINFO:
                    417:                        bios_pciinfo = (bios_pciinfo_t *)q->ba_arg;
                    418: #ifdef BIOS_DEBUG
                    419:                        printf(" pciinfo %p", bios_pciinfo);
                    420: #endif
                    421:                        break;
                    422: #endif
                    423:                case BOOTARG_CONSDEV:
                    424:                        if (q->ba_size >= sizeof(bios_consdev_t))
                    425:                        {
                    426:                                bios_consdev_t *cdp = (bios_consdev_t*)q->ba_arg;
                    427: #include "com.h"
                    428: #include "pccom.h"
                    429: #if NCOM + NPCCOM > 0
                    430:                                extern int comdefaultrate; /* ic/com.c */
                    431:                                comdefaultrate = cdp->conspeed;
                    432: #endif
                    433: #ifdef BIOS_DEBUG
                    434:                                printf(" console 0x%x:%d",
                    435:                                    cdp->consdev, cdp->conspeed);
                    436: #endif
                    437:                                cnset(cdp->consdev);
                    438:                        }
                    439:                        break;
                    440: #ifdef MULTIPROCESSOR
                    441:                case BOOTARG_SMPINFO:
                    442:                        bios_smpinfo = q->ba_arg;
                    443:                        printf(" smpinfo %p", bios_smpinfo);
                    444:                        break;
                    445: #endif
                    446:
                    447: #ifdef NFSCLIENT
                    448:                case BOOTARG_BOOTMAC:
                    449:                        bios_bootmac = (bios_bootmac_t *)q->ba_arg;
                    450:                        break;
                    451: #endif
                    452:
                    453:                default:
                    454: #ifdef BIOS_DEBUG
                    455:                        printf(" unsupported arg (%d) %p", q->ba_type,
                    456:                            q->ba_arg);
                    457: #endif
                    458:                        break;
                    459:                }
                    460:        }
                    461:        printf("\n");
                    462:
                    463: }
                    464:
                    465: int
                    466: bios_print(void *aux, const char *pnp)
                    467: {
                    468:        struct bios_attach_args *ba = aux;
                    469:
                    470:        if (pnp)
                    471:                printf("%s at %s function 0x%x",
                    472:                    ba->bios_dev, pnp, ba->bios_func);
                    473:        return (UNCONF);
                    474: }
                    475:
                    476: int
                    477: bios32_service(u_int32_t service, bios32_entry_t e, bios32_entry_info_t ei)
                    478: {
                    479:        u_long pa, endpa;
                    480:        vaddr_t va, sva;
                    481:        u_int32_t base, count, off, ent;
                    482:        int slot;
                    483:
                    484:        if (bios32_entry.offset == 0)
                    485:                return 0;
                    486:
                    487:        base = 0;
                    488:        __asm __volatile("lcall *(%4)"
                    489:            : "+a" (service), "+b" (base), "=c" (count), "=d" (off)
                    490:            : "D" (&bios32_entry)
                    491:            : "%esi", "cc", "memory");
                    492:
                    493:        if (service & 0xff)
                    494:                return 0;       /* not found */
                    495:
                    496:        ent = base + off;
                    497:        if (ent <= BIOS32_START || ent >= BIOS32_END)
                    498:                return 0;
                    499:
                    500:
                    501:        endpa = round_page(BIOS32_END);
                    502:
                    503:        sva = va = uvm_km_valloc(kernel_map, endpa);
                    504:        if (va == 0)
                    505:                return (0);
                    506:
                    507:        slot = gdt_get_slot();
                    508:        setgdt(slot, (caddr_t)va, BIOS32_END, SDT_MEMERA, SEL_KPL, 1, 0);
                    509:
                    510:        for (pa = trunc_page(BIOS32_START),
                    511:            va += trunc_page(BIOS32_START);
                    512:            pa < endpa; pa += NBPG, va += NBPG) {
                    513:                pmap_enter(pmap_kernel(), va, pa,
                    514:                    VM_PROT_READ | VM_PROT_WRITE,
                    515:                    VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
                    516:
                    517:                /* for all you, broken hearted */
                    518:                if (pa >= trunc_page(base)) {
                    519:                        pmap_enter(pmap_kernel(), sva, pa,
                    520:                            VM_PROT_READ | VM_PROT_WRITE,
                    521:                            VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
                    522:                        sva += NBPG;
                    523:                }
                    524:        }
                    525:
                    526:        e->segment = GSEL(slot, SEL_KPL);
                    527:        e->offset = (vaddr_t)ent;
                    528:
                    529:        ei->bei_base = base;
                    530:        ei->bei_size = count;
                    531:        ei->bei_entry = ent;
                    532:
                    533:        return 1;
                    534: }
                    535:
                    536: int
                    537: biosopen(dev_t dev, int flag, int mode, struct proc *p)
                    538: {
                    539:        struct bios_softc *sc = bios_cd.cd_devs[0];
                    540:
                    541:        if (minor(dev))
                    542:                return (ENXIO);
                    543:
                    544:        (void)sc;
                    545:
                    546:        return 0;
                    547: }
                    548:
                    549: int
                    550: biosclose(dev_t dev, int flag, int mode, struct proc *p)
                    551: {
                    552:        struct bios_softc *sc = bios_cd.cd_devs[0];
                    553:
                    554:        if (minor(dev))
                    555:                return (ENXIO);
                    556:
                    557:        (void)sc;
                    558:
                    559:        return 0;
                    560: }
                    561:
                    562: int
                    563: biosioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    564: {
                    565:        struct bios_softc *sc = bios_cd.cd_devs[0];
                    566:
                    567:        if (minor(dev))
                    568:                return (ENXIO);
                    569:
                    570:        switch (cmd) {
                    571:        default:
                    572:                return ENXIO;
                    573:        }
                    574:
                    575:        (void)sc;
                    576:
                    577:        return 0;
                    578: }
                    579:
                    580: void
                    581: bioscnprobe(struct consdev *cn)
                    582: {
                    583: #if 0
                    584:        bios_init(I386_BUS_SPACE_MEM); /* XXX */
                    585:        if (!bios_cd.cd_ndevs)
                    586:                return;
                    587:
                    588:        if (0 && bios_call(BOOTC_CHECK, NULL))
                    589:                return;
                    590:
                    591:        cn->cn_pri = CN_NORMAL;
                    592:        cn->cn_dev = makedev(48, 0);
                    593: #endif
                    594: }
                    595:
                    596: void
                    597: bioscninit(struct consdev *cn)
                    598: {
                    599:
                    600: }
                    601:
                    602: void
                    603: bioscnputc(dev_t dev, int ch)
                    604: {
                    605:
                    606: }
                    607:
                    608: int
                    609: bioscngetc(dev_t dev)
                    610: {
                    611:        return -1;
                    612: }
                    613:
                    614: void
                    615: bioscnpollc(dev_t dev, int on)
                    616: {
                    617: }
                    618:
                    619: int
                    620: bios_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    621:     size_t newlen, struct proc *p)
                    622: {
                    623:        bios_diskinfo_t *pdi;
                    624:        int biosdev;
                    625:
                    626:        /* all sysctl names at this level except diskinfo are terminal */
                    627:        if (namelen != 1 && name[0] != BIOS_DISKINFO)
                    628:                return (ENOTDIR);               /* overloaded */
                    629:
                    630:        if (!(bootapiver & BAPIV_VECTOR))
                    631:                return EOPNOTSUPP;
                    632:
                    633:        switch (name[0]) {
                    634:        case BIOS_DEV:
                    635:                if ((pdi = bios_getdiskinfo(bootdev)) == NULL)
                    636:                        return ENXIO;
                    637:                biosdev = pdi->bios_number;
                    638:                return sysctl_rdint(oldp, oldlenp, newp, biosdev);
                    639:        case BIOS_DISKINFO:
                    640:                if (namelen != 2)
                    641:                        return ENOTDIR;
                    642:                if ((pdi = bios_getdiskinfo(name[1])) == NULL)
                    643:                        return ENXIO;
                    644:                return sysctl_rdstruct(oldp, oldlenp, newp, pdi, sizeof(*pdi));
                    645:        case BIOS_CKSUMLEN:
                    646:                return sysctl_rdint(oldp, oldlenp, newp, bios_cksumlen);
                    647:        default:
                    648:                return EOPNOTSUPP;
                    649:        }
                    650:        /* NOTREACHED */
                    651: }
                    652:
                    653: bios_diskinfo_t *
                    654: bios_getdiskinfo(dev_t dev)
                    655: {
                    656:        bios_diskinfo_t *pdi;
                    657:
                    658:        if (bios_diskinfo == NULL)
                    659:                return NULL;
                    660:
                    661:        for (pdi = bios_diskinfo; pdi->bios_number != -1; pdi++) {
                    662:                if ((dev & B_MAGICMASK) == B_DEVMAGIC) { /* search by bootdev */
                    663:                        if (pdi->bsd_dev == dev)
                    664:                                break;
                    665:                } else {
                    666:                        if (pdi->bios_number == dev)
                    667:                                break;
                    668:                }
                    669:        }
                    670:
                    671:        if (pdi->bios_number == -1)
                    672:                return NULL;
                    673:        else
                    674:                return pdi;
                    675: }
                    676:
                    677: /*
                    678:  * smbios_find_table() takes a caller supplied smbios struct type and
                    679:  * a pointer to a handle (struct smbtable) returning one if the structure
                    680:  * is sucessfully located and zero otherwise. Callers should take care
                    681:  * to initialize the cookie field of the smbtable structure to zero before
                    682:  * the first invocation of this function.
                    683:  * Multiple tables of the same type can be located by repeatedly calling
                    684:  * smbios_find_table with the same arguments.
                    685:  */
                    686: int
                    687: smbios_find_table(u_int8_t type, struct smbtable *st)
                    688: {
                    689:        u_int8_t *va, *end;
                    690:        struct smbtblhdr *hdr;
                    691:        int ret = 0, tcount = 1;
                    692:
                    693:        va = smbios_entry.addr;
                    694:        end = va + smbios_entry.len;
                    695:
                    696:        /*
                    697:         * The cookie field of the smtable structure is used to locate
                    698:         * multiple instances of a table of an arbitrary type. Following the
                    699:         * sucessful location of a table, the type is encoded as bits 0:7 of
                    700:         * the cookie value, the offset in terms of the number of structures
                    701:         * preceding that referenced by the handle is encoded in bits 15:31.
                    702:         */
                    703:        if ((st->cookie & 0xfff) == type && st->cookie >> 16) {
                    704:                if ((u_int8_t *)st->hdr >= va && (u_int8_t *)st->hdr < end) {
                    705:                        hdr = st->hdr;
                    706:                        if (hdr->type == type) {
                    707:                                va = (u_int8_t *)hdr + hdr->size;
                    708:                                for (; va + 1 < end; va++)
                    709:                                        if (*va == NULL && *(va + 1) == NULL)
                    710:                                                break;
                    711:                                va+= 2;
                    712:                                tcount = st->cookie >> 16;
                    713:                        }
                    714:                }
                    715:        }
                    716:        for (; va + sizeof(struct smbtblhdr) < end && tcount <=
                    717:            smbios_entry.count; tcount++) {
                    718:                hdr = (struct smbtblhdr *)va;
                    719:                if (hdr->type == type) {
                    720:                        ret = 1;
                    721:                        st->hdr = hdr;
                    722:                        st->tblhdr = va + sizeof(struct smbtblhdr);
                    723:                        st->cookie = (tcount + 1) << 16 | type;
                    724:                        break;
                    725:                }
                    726:                if (hdr->type == SMBIOS_TYPE_EOT)
                    727:                        break;
                    728:                va+= hdr->size;
                    729:                for (; va + 1 < end; va++)
                    730:                        if (*va == NULL && *(va + 1) == NULL)
                    731:                                break;
                    732:                va+=2;
                    733:        }
                    734:
                    735:        return ret;
                    736: }
                    737:
                    738: char *
                    739: smbios_get_string(struct smbtable *st, u_int8_t indx, char *dest, size_t len)
                    740: {
                    741:        u_int8_t *va, *end;
                    742:        char *ret = NULL;
                    743:        int i;
                    744:
                    745:        va = (u_int8_t *)st->hdr + st->hdr->size;
                    746:        end = smbios_entry.addr + smbios_entry.len;
                    747:        for (i = 1; va < end && i < indx && *va; i++)
                    748:                while (*va++)
                    749:                        ;
                    750:        if (i == indx) {
                    751:                if (va + len < end) {
                    752:                        ret = dest;
                    753:                        bcopy(va, ret, len);
                    754:                        ret[len - 1] = '\0';
                    755:                }
                    756:        }
                    757:
                    758:        return ret;
                    759: }
                    760:
                    761: char *
                    762: fixstring(char *s)
                    763: {
                    764:        char *p, *e;
                    765:        int i;
                    766:
                    767:        for (i= 0; i < sizeof(smbios_uninfo)/sizeof(smbios_uninfo[0]); i++)
                    768:                if ((strncasecmp(s, smbios_uninfo[i], strlen(smbios_uninfo[i])))==0)
                    769:                        return NULL;
                    770:        /*
                    771:         * Remove leading and trailing whitespace
                    772:         */
                    773:        for (p = s; *p == ' '; p++)
                    774:                ;
                    775:        /*
                    776:         * Special case entire string is whitespace
                    777:         */
                    778:        if (p == s + strlen(s))
                    779:                return NULL;
                    780:        for (e = s + strlen(s) - 1; e > s && *e == ' '; e--)
                    781:                ;
                    782:        if (p > s || e < s + strlen(s) - 1) {
                    783:                bcopy(p, s, e-p + 1);
                    784:                s[e - p + 1] = '\0';
                    785:        }
                    786:
                    787:        return s;
                    788: }
                    789:
                    790: void
                    791: smbios_info(char * str)
                    792: {
                    793:        char *sminfop, sminfo[64];
                    794:        struct smbtable stbl, btbl;
                    795:        struct smbios_sys *sys;
                    796:        struct smbios_board *board;
                    797:        int i, infolen, uuidf, havebb;
                    798:        char *p;
                    799:
                    800:        if (smbios_entry.mjr < 2)
                    801:                return;
                    802:        /*
                    803:         * According to the spec the system table among others is required,
                    804:         * if it is not we do not bother with this smbios implementation.
                    805:         */
                    806:        stbl.cookie = btbl.cookie = 0;
                    807:        if (!smbios_find_table(SMBIOS_TYPE_SYSTEM, &stbl))
                    808:                return;
                    809:        havebb = smbios_find_table(SMBIOS_TYPE_BASEBOARD, &btbl);
                    810:
                    811:        sys = (struct smbios_sys *)stbl.tblhdr;
                    812:        if (havebb)
                    813:                board = (struct smbios_board *)btbl.tblhdr;
                    814:        /*
                    815:         * Some smbios implementations have no system vendor or product strings,
                    816:         * some have very uninformative data which is harder to work around
                    817:         * and we must rely upon various heuristics to detect this. In both
                    818:         * cases we attempt to fall back on the base board information in the
                    819:         * perhaps naive belief that motherboard vendors will supply this
                    820:         * information.
                    821:         */
                    822:        sminfop = NULL;
                    823:        if ((p = smbios_get_string(&stbl, sys->vendor, sminfo,
                    824:            sizeof(sminfo))) != NULL)
                    825:                sminfop = fixstring(p);
                    826:        if (sminfop == NULL) {
                    827:                if (havebb) {
                    828:                        if ((p = smbios_get_string(&btbl, board->vendor,
                    829:                            sminfo, sizeof(sminfo))) != NULL)
                    830:                                sminfop = fixstring(p);
                    831:                }
                    832:        }
                    833:        if (sminfop) {
                    834:                infolen = strlen(sminfop) + 1;
                    835:                hw_vendor = malloc(infolen, M_DEVBUF, M_NOWAIT);
                    836:                if (hw_vendor)
                    837:                        strlcpy(hw_vendor, sminfop, infolen);
                    838:                sminfop = NULL;
                    839:        }
                    840:        if ((p = smbios_get_string(&stbl, sys->product, sminfo,
                    841:            sizeof(sminfo))) != NULL)
                    842:                sminfop = fixstring(p);
                    843:        if (sminfop == NULL) {
                    844:                if (havebb) {
                    845:                        if ((p = smbios_get_string(&btbl, board->product,
                    846:                            sminfo, sizeof(sminfo))) != NULL)
                    847:                                sminfop = fixstring(p);
                    848:                }
                    849:        }
                    850:        if (sminfop) {
                    851:                infolen = strlen(sminfop) + 1;
                    852:                hw_prod = malloc(infolen, M_DEVBUF, M_NOWAIT);
                    853:                if (hw_prod)
                    854:                        strlcpy(hw_prod, sminfop, infolen);
                    855:                sminfop = NULL;
                    856:        }
                    857:        if (hw_vendor != NULL && hw_prod != NULL)
                    858:                printf("\n%s: %s %s", str, hw_vendor, hw_prod);
                    859:        if ((p = smbios_get_string(&stbl, sys->version, sminfo,
                    860:            sizeof(sminfo))) != NULL)
                    861:                sminfop = fixstring(p);
                    862:        if (sminfop) {
                    863:                infolen = strlen(sminfop) + 1;
                    864:                hw_ver = malloc(infolen, M_DEVBUF, M_NOWAIT);
                    865:                if (hw_ver)
                    866:                        strlcpy(hw_ver, sminfop, infolen);
                    867:                sminfop = NULL;
                    868:        }
                    869:        if ((p = smbios_get_string(&stbl, sys->serial, sminfo,
                    870:            sizeof(sminfo))) != NULL)
                    871:                sminfop = fixstring(p);
                    872:        if (sminfop) {
                    873:                infolen = strlen(sminfop) + 1;
                    874:                hw_serial = malloc(infolen, M_DEVBUF, M_NOWAIT);
                    875:                if (hw_serial)
                    876:                        strlcpy(hw_serial, sminfop, infolen);
                    877:        }
                    878:        if (smbios_entry.mjr > 2 || (smbios_entry.mjr == 2 &&
                    879:            smbios_entry.min >= 1)) {
                    880:                /*
                    881:                 * If the uuid value is all 0xff the uuid is present but not
                    882:                 * set, if its all 0 then the uuid isn't present at all.
                    883:                 */
                    884:                uuidf |= SMBIOS_UUID_NPRESENT|SMBIOS_UUID_NSET;
                    885:                for (i = 0; i < sizeof(sys->uuid); i++) {
                    886:                        if (sys->uuid[i] != 0xff)
                    887:                                uuidf &= ~SMBIOS_UUID_NSET;
                    888:                        if (sys->uuid[i] != 0)
                    889:                                uuidf &= ~SMBIOS_UUID_NPRESENT;
                    890:                }
                    891:
                    892:                if (uuidf & SMBIOS_UUID_NPRESENT)
                    893:                        hw_uuid = NULL;
                    894:                else if (uuidf & SMBIOS_UUID_NSET)
                    895:                        hw_uuid = "Not Set";
                    896:                else {
                    897:                        hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
                    898:                            M_NOWAIT);
                    899:                        if (hw_uuid) {
                    900:                                snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
                    901:                                    SMBIOS_UUID_REP,
                    902:                                    sys->uuid[0], sys->uuid[1], sys->uuid[2],
                    903:                                    sys->uuid[3], sys->uuid[4], sys->uuid[5],
                    904:                                    sys->uuid[6], sys->uuid[7], sys->uuid[8],
                    905:                                    sys->uuid[9], sys->uuid[10], sys->uuid[11],
                    906:                                    sys->uuid[12], sys->uuid[13], sys->uuid[14],
                    907:                                    sys->uuid[15]);
                    908:                        }
                    909:                }
                    910:        }
                    911: }

CVSweb