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/dev/nvram2env/nvram2env.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) 2010 Aleksandr Rybalko.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * Pseudo driver to copy the NVRAM settings from various sources
   29  * into the kernel environment.
   30  *
   31  * Drivers (such as ethernet devices) can then use environment
   32  * variables to set default parameters.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/bus.h>
   41 #include <sys/endian.h>
   42 #include <sys/kernel.h>
   43 #include <sys/module.h>
   44 #include <sys/rman.h>
   45 #include <sys/malloc.h>
   46 
   47 #include <machine/bus.h>
   48 
   49 #include <dev/siba/siba_ids.h>
   50 #include <dev/siba/sibareg.h>
   51 #include <dev/siba/sibavar.h>
   52 
   53 #define nvram2env_read_1(sc, reg)                               \
   54         bus_space_read_1((sc)->sc_bt, (sc)->sc_bh,(reg))
   55 
   56 #define nvram2env_read_2(sc, reg)                               \
   57         bus_space_read_2((sc)->sc_bt, (sc)->sc_bh,(reg))
   58 
   59 #define nvram2env_read_4(sc, reg)                               \
   60         bus_space_read_4((sc)->sc_bt, (sc)->sc_bh,(reg))
   61 
   62 #define nvram2env_write_1(sc, reg, val)                 \
   63         bus_space_write_1((sc)->sc_bt, (sc)->sc_bh,     \
   64                          (reg), (val))
   65 
   66 #define nvram2env_write_2(sc, reg, val)                 \
   67         bus_space_write_2((sc)->sc_bt, (sc)->sc_bh,     \
   68                          (reg), (val))
   69 
   70 #define nvram2env_write_4(sc, reg, val)                 \
   71         bus_space_write_4((sc)->sc_bt, (sc)->sc_bh,     \
   72                          (reg), (val))
   73 
   74 struct nvram2env_softc {
   75         bus_space_tag_t bst;
   76         bus_space_handle_t bsh;
   77         bus_addr_t addr;
   78         int need_swap;
   79         uint32_t sig;
   80         uint32_t flags;
   81 #define NVRAM_FLAGS_NOCHECK     0x0001  /* Do not check(CRC or somthing else)*/
   82 #define NVRAM_FLAGS_GENERIC     0x0002  /* Format Generic, skip 4b and read */
   83 #define NVRAM_FLAGS_BROADCOM    0x0004  /* Format Broadcom, use struct nvram */
   84 #define NVRAM_FLAGS_UBOOT       0x0008  /* Format Generic, skip 4b of CRC and read */
   85         uint32_t maxsize;
   86         uint32_t crc;
   87 };
   88 
   89 static int      nvram2env_attach(device_t);
   90 static int      nvram2env_probe(device_t);
   91 
   92 #define NVRAM_MAX_SIZE 0x10000
   93 
   94 static void
   95 nvram2env_identify(driver_t * drv, device_t parent)
   96 {
   97         int i, ivar;
   98 
   99         for (i = 0; !resource_int_value("nvram", i, "base", &ivar); i++)
  100                 BUS_ADD_CHILD(parent, 0, "nvram2env", i);
  101 }
  102 
  103 static int
  104 nvram2env_probe(device_t dev)
  105 {
  106         uint32_t i, ivar, sig;
  107         struct nvram2env_softc * sc = device_get_softc(dev);
  108         sc->bst = mips_bus_space_generic;
  109 
  110         if (resource_int_value("nvram", device_get_unit(dev), "sig",
  111             &sc->sig) != 0 || sc->sig == 0)
  112                 sc->sig = 0x48534c46;
  113 
  114         if (resource_int_value("nvram", device_get_unit(dev), "maxsize",
  115             &sc->maxsize) != 0 || sc->maxsize == 0)
  116                 sc->maxsize = NVRAM_MAX_SIZE;
  117 
  118         if (resource_int_value("nvram", device_get_unit(dev), "flags", 
  119             &sc->flags) != 0 || sc->flags == 0)
  120                 sc->flags = NVRAM_FLAGS_GENERIC;
  121 
  122 
  123         for (i = 0; i < 2; i ++)
  124         {
  125                 if (resource_int_value("nvram", device_get_unit(dev), 
  126                         (!i)?"base":"fallbackbase", &ivar) != 0 ||
  127                     ivar == 0)
  128                         continue;
  129 
  130                 sc->addr = MIPS_PHYS_TO_KSEG1(ivar);
  131 
  132                 if (bootverbose)
  133                         device_printf(dev, "base=0x%08x sig=0x%08x "
  134                             "maxsize=0x%08x flags=0x%08x\n",
  135                             sc->addr, sc->sig, sc->maxsize, sc->flags);
  136 
  137                 if (bus_space_map(sc->bst, sc->addr, sc->maxsize, 0,
  138                     &sc->bsh) != 0)
  139                         continue;
  140 
  141                 sig = bus_space_read_4(sc->bst, sc->bsh, 0);
  142                 if ( sig == sc->sig /*FLSH*/)
  143                 {
  144                         device_printf(dev, "Found NVRAM at %#x\n", 
  145                             (uint32_t)ivar);
  146                         sc->need_swap = 0;
  147                         goto unmap_done;
  148                 }
  149                 else if ( htole32(sig) == sc->sig /*HSLF*/)
  150                 {
  151                         device_printf(dev, "Found NVRAM at %#x\n", 
  152                             (uint32_t)ivar);
  153                         sc->need_swap = 1;
  154                         goto unmap_done;
  155                 } else if (sc->flags & NVRAM_FLAGS_UBOOT) {
  156                         device_printf(dev, "Use NVRAM at %#x\n", 
  157                             (uint32_t)ivar);
  158                         sc->crc = sig;
  159                         goto unmap_done;
  160                 }
  161                 bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
  162         }
  163         sc->bst = 0;
  164         sc->bsh = 0;
  165         sc->addr = 0;
  166         return (ENXIO);
  167 
  168 unmap_done:
  169         bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
  170         device_set_desc(dev, "NVRAM to ENV pseudo-device");
  171         return (BUS_PROBE_SPECIFIC);
  172 
  173 }
  174 
  175 struct nvram {
  176         u_int32_t sig;
  177         u_int32_t size;
  178         u_int32_t unknown1;
  179         u_int32_t unknown2;
  180         u_int32_t unknown3;
  181         char data[];
  182 };
  183 
  184 static uint32_t read_4(struct nvram2env_softc * sc, int offset) 
  185 {
  186         if (sc->need_swap) 
  187                 return (bswap32(bus_space_read_4(sc->bst, sc->bsh, offset)));
  188         else
  189                 return (bus_space_read_4(sc->bst, sc->bsh, offset));
  190 }
  191 
  192 
  193 static int
  194 nvram2env_attach(device_t dev)
  195 {
  196         struct nvram2env_softc * sc = device_get_softc(dev);
  197         struct nvram * nv;
  198         char *pair, *value, *assign;
  199         uint32_t sig, size, i;
  200 
  201         if (sc->bst == 0 || sc->addr == 0)
  202                 return (ENXIO);
  203 
  204         if (bus_space_map(sc->bst, sc->addr, NVRAM_MAX_SIZE, 0,
  205                 &sc->bsh) != 0)
  206                 return (ENXIO);
  207 
  208         sig  = read_4(sc, 0);
  209         size = read_4(sc, 4);
  210 #if 1
  211         if (bootverbose)
  212                 device_printf(dev, " size=0x%05x maxsize=0x%05x\n", size, sc->maxsize);
  213 #endif
  214         size = (size > sc->maxsize)?sc->maxsize:size;
  215 
  216 
  217         if (sig == sc->sig || (sc->flags & NVRAM_FLAGS_UBOOT))
  218         {
  219 
  220                 /* align and shift size to 32bit size*/
  221                 size += 3;
  222                 size >>= 2;
  223 
  224                 nv = malloc(size<<2, M_DEVBUF, M_WAITOK | M_ZERO);
  225                 if (!nv)
  226                         return (ENOMEM);
  227 
  228                 for (i = 0; i < size; i ++)
  229                         ((uint32_t *)nv)[i] = read_4(sc, i<<2);
  230 
  231                 if (sc->flags & NVRAM_FLAGS_BROADCOM) {
  232                         device_printf(dev, "sig = %#x\n",  nv->sig);
  233                         device_printf(dev, "size = %#x\n", nv->size);
  234                 }
  235 
  236                 if (!(sc->flags & NVRAM_FLAGS_NOCHECK)) {
  237                         /* TODO: need checksum verification */
  238                 }
  239 
  240                 if (sc->flags & NVRAM_FLAGS_GENERIC)
  241                         pair = (char*)nv+4;
  242                 if (sc->flags & NVRAM_FLAGS_UBOOT)
  243                         pair = (char*)nv+4;
  244                 else if (sc->flags & NVRAM_FLAGS_BROADCOM)
  245                         pair = (char*)nv+20;
  246                 else
  247                         pair = (char*)nv+4;
  248 
  249                 for ( ; 
  250                     (u_int32_t)pair < ((u_int32_t)nv + size - 4); 
  251                     pair = pair + strlen(pair) + 1 + strlen(value) + 1 ) {
  252 
  253                         if (pair && strlen(pair)) {
  254 
  255 #if 0
  256                                 printf("ENV: %s\n", pair);
  257 #endif
  258                                 /* hint.nvram.0. */
  259                                 assign = strchr(pair,'=');
  260                                 assign[0] = '\0';
  261                                 value = assign+1;
  262 #if 1
  263                                 if (bootverbose)
  264                                         printf("ENV: %s=%s\n", pair, value);
  265 #endif
  266                                 setenv(pair, value);
  267 
  268                                 if (strcasecmp(pair, "WAN_MAC_ADDR") == 0) {
  269                                         /* Alias for MAC address of eth0 */
  270                                         if (bootverbose)
  271                                                 printf("ENV: aliasing "
  272                                                     "WAN_MAC_ADDR to ethaddr"
  273                                                     " = %s\n",  value);
  274                                         setenv("ethaddr", value);
  275                                 }
  276                                 else if (strcasecmp(pair, "LAN_MAC_ADDR") == 0){
  277                                         /* Alias for MAC address of eth1 */
  278                                         if (bootverbose)
  279                                                 printf("ENV: aliasing "
  280                                                     "LAN_MAC_ADDR to eth1addr"
  281                                                     " = %s\n",  value);
  282                                         setenv("eth1addr", value);
  283                                 }
  284 
  285                                 if (strcmp(pair, "bootverbose") == 0)
  286                                         bootverbose = strtoul(value, 0, 0);
  287                                 if (strcmp(pair, "boothowto"  ) == 0)
  288                                         boothowto   = strtoul(value, 0, 0);
  289                         }
  290                         else
  291                                 break;
  292                 }
  293                 free(nv, M_DEVBUF);
  294         }
  295 
  296         bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
  297 
  298         return (0);
  299 }
  300 
  301 static device_method_t nvram2env_methods[] = {
  302         /* Device interface */
  303         DEVMETHOD(device_identify,      nvram2env_identify),
  304         DEVMETHOD(device_probe,         nvram2env_probe),
  305         DEVMETHOD(device_attach,        nvram2env_attach),
  306         {0, 0},
  307 };
  308 
  309 static driver_t nvram2env_driver = {
  310         "nvram2env",
  311         nvram2env_methods,
  312         sizeof(struct nvram2env_softc),
  313 };
  314 static devclass_t nvram2env_devclass;
  315 
  316 DRIVER_MODULE(nvram2env, nexus, nvram2env_driver, nvram2env_devclass, 0, 0);
  317 

Cache object: d70bd92e437342b470c4b64d26028152


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