[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     ! 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