The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/bios.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1997 Michael Smith
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 /*
   30  * Code for dealing with the BIOS in x86 PC systems.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <vm/vm.h>
   37 #include <vm/pmap.h>
   38 #include <machine/md_var.h>
   39 
   40 #include <machine/pc/bios.h>
   41 
   42 #define BIOS_START      0xe0000
   43 #define BIOS_SIZE       0x20000
   44 
   45 /* exported lookup results */
   46 struct bios32_SDentry           PCIbios = {entry : 0};
   47 static struct SMBIOS_table      *SMBIOStable = 0;
   48 static struct DMI_table         *DMItable = 0;
   49 
   50 static caddr_t          bios32_SDCI = NULL;
   51 
   52 static void             bios32_init(void *junk);
   53 
   54 /* start fairly early */
   55 SYSINIT(bios32, SI_SUB_CPU, SI_ORDER_ANY, bios32_init, NULL);
   56 
   57 /*
   58  * bios32_init
   59  *
   60  * Locate various bios32 entities.
   61  */
   62 static void
   63 bios32_init(void *junk)
   64 {
   65     u_long                      sigaddr;
   66     struct bios32_SDheader      *sdh;
   67     struct SMBIOS_table         *sbt;
   68     struct DMI_table            *dmit;
   69     u_int8_t                    ck, *cv;
   70     int                         i;
   71     
   72 
   73     /*
   74      * BIOS32 Service Directory
   75      */
   76     
   77     /* look for the signature */
   78     if ((sigaddr = bios_sigsearch(0, "_32_", 4, 16, 0)) != 0) {
   79 
   80         /* get a virtual pointer to the structure */
   81         sdh = (struct bios32_SDheader *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
   82         for (cv = (u_int8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) {
   83             ck += cv[i];
   84         }
   85         /* If checksum is OK, enable use of the entrypoint */
   86         if ((ck == 0) && (sdh->entry < (BIOS_START + BIOS_SIZE))) {
   87             bios32_SDCI = (caddr_t)BIOS_PADDRTOVADDR(sdh->entry);
   88             if (bootverbose) {
   89                 printf("Found BIOS32 Service Directory header at %p\n", sdh);
   90                 printf("Entry = 0x%x (%p)  Rev = %d  Len = %d\n", 
   91                        sdh->entry, bios32_SDCI, sdh->revision, sdh->len);
   92             }
   93             /* See if there's a PCI BIOS entrypoint here */
   94             PCIbios.ident.id = 0x49435024;      /* PCI systems should have this */
   95             if (!bios32_SDlookup(&PCIbios) && bootverbose)
   96                 printf("PCI BIOS entry at 0x%x\n", PCIbios.entry);
   97         } else {
   98             printf("Bad BIOS32 Service Directory!\n");
   99         }
  100     }
  101 
  102     /*
  103      * System Management BIOS
  104      */
  105     /* look for the SMBIOS signature */
  106     if ((sigaddr = bios_sigsearch(0, "_SM_", 4, 16, 0)) != 0) {
  107 
  108         /* get a virtual pointer to the structure */
  109         sbt = (struct SMBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
  110         for (cv = (u_int8_t *)sbt, ck = 0, i = 0; i < sbt->len; i++) {
  111             ck += cv[i];
  112         }
  113         /* if checksum is OK, we have action */
  114         if (ck == 0) {
  115             SMBIOStable = sbt;          /* save reference */
  116             DMItable = &sbt->dmi;       /* contained within */
  117             if (bootverbose) {
  118                 printf("SMIBIOS header at %p\n", sbt);
  119                 printf("Version %d.%d\n", sbt->major, sbt->minor);
  120                 printf("Table at 0x%x, %d entries, %d bytes, largest entry %d bytes\n",
  121                        sbt->dmi.st_base, (int)sbt->dmi.st_entries, (int)sbt->dmi.st_size,
  122                        (int)sbt->st_maxsize);
  123             }
  124         } else {
  125             printf("Bad SMBIOS table checksum!\n");
  126         }
  127         
  128     }
  129 
  130     /* look for the DMI signature */
  131     if ((sigaddr = bios_sigsearch(0, "_DMI_", 5, 16, 0)) != 0) {
  132 
  133         /* get a virtual pointer to the structure */
  134         dmit = (struct DMI_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
  135         for (cv = (u_int8_t *)dmit, ck = 0, i = 0; i < 15; i++) {
  136             ck += cv[i];
  137         }
  138         /* if checksum is OK, we have action */
  139         if (ck == 0) {
  140             DMItable = dmit;            /* save reference */
  141             if (bootverbose) {
  142                 printf("DMI header at %p\n", dmit);
  143                 printf("Version %d.%d\n", (dmit->bcd_revision >> 4),
  144                        (dmit->bcd_revision & 0x0f));
  145                 printf("Table at 0x%x, %d entries, %d bytes\n",
  146                        dmit->st_base, (int)dmit->st_entries,
  147                        (int)dmit->st_size);
  148             }
  149         } else {
  150             printf("Bad DMI table checksum!\n");
  151         }
  152     }
  153     if (bootverbose) {
  154             /* look for other know signatures */
  155             printf("Other BIOS signatures found:\n");
  156             printf("ACPI: %08x\n", bios_sigsearch(0, "RST PTR", 8, 16, 0));
  157             printf("$PnP: %08x\n", bios_sigsearch(0, "$PnP", 4, 16, 0));
  158     }
  159 }
  160 
  161 /*
  162  * bios32_SDlookup
  163  *
  164  * Query the BIOS32 Service Directory for the service named in (ent),
  165  * returns nonzero if the lookup fails.  The caller must fill in
  166  * (ent->ident), the remainder are populated on a successful lookup.
  167  */
  168 int
  169 bios32_SDlookup(struct bios32_SDentry *ent)
  170 {
  171     struct bios32_args  args;
  172     
  173     if (bios32_SDCI != NULL) {
  174 
  175         args.eax = ent->ident.id;               /* set up arguments */
  176         args.ebx = args.ecx = args.edx = 0;
  177         bios32(bios32_SDCI, &args);             /* make the BIOS call */
  178         if ((args.eax & 0xff) == 0) {           /* success? */
  179             ent->base = args.ebx;
  180             ent->len = args.ecx;
  181             ent->entry = args.edx;
  182             return(0);                          /* all OK */
  183         }
  184     }
  185     return(1);                                  /* failed */
  186 }
  187 
  188 /*
  189  * bios_sigsearch
  190  *
  191  * Search some or all of the BIOS region for a signature string.
  192  *
  193  * (start)      Optional offset returned from this function 
  194  *              (for searching for multiple matches), or NULL
  195  *              to start the search from the base of the BIOS.
  196  *              Note that this will be a _physical_ address in
  197  *              the range 0xe0000 - 0xfffff.
  198  * (sig)        is a pointer to the byte(s) of the signature.
  199  * (siglen)     number of bytes in the signature.
  200  * (paralen)    signature paragraph (alignment) size.
  201  * (sigofs)     offset of the signature within the paragraph.
  202  *
  203  * Returns the _physical_ address of the found signature, 0 if the
  204  * signature was not found.
  205  */
  206 
  207 u_int32_t
  208 bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs)
  209 {
  210     u_char      *sp, *end;
  211     
  212     /* compute the starting address */
  213     if ((start >= BIOS_START) && (start <= (BIOS_START + BIOS_SIZE))) {
  214         sp = (char *)BIOS_PADDRTOVADDR(start);
  215     } else if (start == 0) {
  216         sp = (char *)BIOS_PADDRTOVADDR(BIOS_START);
  217     } else {
  218         return 0;                               /* bogus start address */
  219     }
  220 
  221     /* compute the end address */
  222     end = (u_char *)BIOS_PADDRTOVADDR(BIOS_START + BIOS_SIZE);
  223 
  224     /* loop searching */
  225     while ((sp + sigofs + siglen) < end) {
  226         
  227         /* compare here */
  228         if (!bcmp(sp + sigofs, sig, siglen)) {
  229             /* convert back to physical address */
  230             return((u_int32_t)BIOS_VADDRTOPADDR(sp));
  231         }
  232         sp += paralen;
  233     }
  234     return(0);
  235 }
  236 
  237     
  238             

Cache object: 2d830d63294a9ffa4be0473c9054b6e3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.