Attachment 'nvram2env.c'

Download

   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 for copy NVRAM to kenv.
  29  */
  30 
  31 #include <sys/cdefs.h>
  32 __FBSDID("$FreeBSD$");
  33 
  34 #include <sys/param.h>
  35 #include <sys/systm.h>
  36 #include <sys/bus.h>
  37 #include <sys/endian.h>
  38 #include <sys/kernel.h>
  39 #include <sys/module.h>
  40 #include <sys/rman.h>
  41 #include <sys/malloc.h>
  42 
  43 #include <machine/bus.h>
  44 
  45 #include <dev/siba/siba_ids.h>
  46 #include <dev/siba/sibareg.h>
  47 #include <dev/siba/sibavar.h>
  48 
  49 
  50 #define nvram2env_read_1(sc, reg)				\
  51 	bus_space_read_1((sc)->sc_bt, (sc)->sc_bh,(reg))
  52 
  53 #define nvram2env_read_2(sc, reg)				\
  54 	bus_space_read_2((sc)->sc_bt, (sc)->sc_bh,(reg))
  55 
  56 #define nvram2env_read_4(sc, reg)				\
  57 	bus_space_read_4((sc)->sc_bt, (sc)->sc_bh,(reg))
  58 
  59 #define nvram2env_write_1(sc, reg, val)			\
  60 	bus_space_write_1((sc)->sc_bt, (sc)->sc_bh,	\
  61 			 (reg), (val))
  62 
  63 #define nvram2env_write_2(sc, reg, val)			\
  64 	bus_space_write_2((sc)->sc_bt, (sc)->sc_bh,	\
  65 			 (reg), (val))
  66 
  67 #define nvram2env_write_4(sc, reg, val)			\
  68 	bus_space_write_4((sc)->sc_bt, (sc)->sc_bh,	\
  69 			 (reg), (val))
  70 
  71 struct nvram2env_softc {
  72 	bus_space_tag_t bst;
  73 	bus_space_handle_t bsh;
  74 	bus_addr_t addr;
  75 	int need_swap;
  76 	uint32_t sig;
  77 	uint32_t flags;
  78 #define NVRAM_FLAGS_NOCHECK	0x0001	/* Do not check(CRC or somthing else)*/
  79 #define NVRAM_FLAGS_GENERIC	0x0002	/* Format Generic, skip 4b and read */
  80 #define NVRAM_FLAGS_BROADCOM	0x0004	/* Format Broadcom, use struct nvram */
  81 #define NVRAM_FLAGS_UBOOT	0x0008	/* Format Generic, skip 4b of CRC and read */
  82 	uint32_t maxsize;
  83 	uint32_t crc;
  84 };
  85 
  86 static int	nvram2env_attach(device_t);
  87 static int	nvram2env_probe(device_t);
  88 
  89 #define NVRAM_MAX_SIZE 0x10000
  90 
  91 static void
  92 nvram2env_identify(driver_t * drv, device_t parent)
  93 {
  94 	int i, ivar;
  95 
  96 	for (i = 0; !resource_int_value("nvram", i, "base", &ivar); i++)
  97 		BUS_ADD_CHILD(parent, 0, "nvram2env", i);
  98 }
  99 
 100 static int
 101 nvram2env_probe(device_t dev)
 102 {
 103 	uint32_t i, ivar, sig;
 104 	struct nvram2env_softc * sc = device_get_softc(dev);
 105 	sc->bst = mips_bus_space_generic;
 106 
 107 	if (resource_int_value("nvram", device_get_unit(dev), "sig",
 108 	    &sc->sig) != 0 || sc->sig == 0)
 109 		sc->sig = 0x48534c46;
 110 
 111 	if (resource_int_value("nvram", device_get_unit(dev), "maxsize",
 112 	    &sc->maxsize) != 0 || sc->maxsize == 0)
 113 		sc->maxsize = NVRAM_MAX_SIZE;
 114 
 115 	if (resource_int_value("nvram", device_get_unit(dev), "flags", 
 116 	    &sc->flags) != 0 || sc->flags == 0)
 117 		sc->flags = NVRAM_FLAGS_GENERIC;
 118 
 119 
 120 	for (i = 0; i < 2; i ++)
 121 	{
 122 		if (resource_int_value("nvram", device_get_unit(dev), 
 123 			(!i)?"base":"fallbackbase", &ivar) != 0 ||
 124 		    ivar == 0)
 125 			continue;
 126 
 127 		sc->addr = MIPS_PHYS_TO_KSEG1(ivar);
 128 
 129 		if (bootverbose)
 130 			device_printf(dev, "base=0x%08x sig=0x%08x "
 131 			    "maxsize=0x%08x flags=0x%08x\n",
 132 			    sc->addr, sc->sig, sc->maxsize, sc->flags);
 133 
 134 		if (bus_space_map(sc->bst, sc->addr, sc->maxsize, 0,
 135 		    &sc->bsh) != 0)
 136 			continue;
 137 
 138 		sig = bus_space_read_4(sc->bst, sc->bsh, 0);
 139 		if ( sig == sc->sig /*FLSH*/)
 140 		{
 141 			device_printf(dev, "Found NVRAM at %#x\n", 
 142 			    (uint32_t)ivar);
 143 			sc->need_swap = 0;
 144 			goto unmap_done;
 145 		}
 146 		else if ( htole32(sig) == sc->sig /*HSLF*/)
 147 		{
 148 			device_printf(dev, "Found NVRAM at %#x\n", 
 149 			    (uint32_t)ivar);
 150 			sc->need_swap = 1;
 151 			goto unmap_done;
 152 		} else if (sc->flags & NVRAM_FLAGS_UBOOT) {
 153 			device_printf(dev, "Use NVRAM at %#x\n", 
 154 			    (uint32_t)ivar);
 155 			sc->crc = sig;
 156 			goto unmap_done;
 157 		}
 158 		bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
 159 	}
 160 	sc->bst = 0;
 161 	sc->bsh = 0;
 162 	sc->addr = 0;
 163 	return (ENXIO);
 164 
 165 unmap_done:
 166 	bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
 167 	device_set_desc(dev, "NVRAM to ENV pseudo-device");
 168 	return (BUS_PROBE_DEFAULT);
 169 
 170 }
 171 
 172 struct nvram {
 173 	u_int32_t sig;
 174 	u_int32_t size;
 175 	u_int32_t unknown1;
 176 	u_int32_t unknown2;
 177 	u_int32_t unknown3;
 178 	char data[];
 179 };
 180 
 181 static uint32_t read_4(struct nvram2env_softc * sc, int offset) 
 182 {
 183 	if (sc->need_swap) 
 184 		return (bswap32(bus_space_read_4(sc->bst, sc->bsh, offset)));
 185 	else
 186 		return (bus_space_read_4(sc->bst, sc->bsh, offset));
 187 }
 188 
 189 
 190 static int
 191 nvram2env_attach(device_t dev)
 192 {
 193 	struct nvram2env_softc * sc = device_get_softc(dev);
 194 	struct nvram * nv;
 195 	char *pair, *value, *assign;
 196 	uint32_t sig, size, i;
 197 
 198 	if (sc->bst == 0 || sc->addr == 0)
 199 		return (ENXIO);
 200 
 201 	if (bus_space_map(sc->bst, sc->addr, NVRAM_MAX_SIZE, 0,
 202 		&sc->bsh) != 0)
 203 		return (ENXIO);
 204 
 205 	sig  = read_4(sc, 0);
 206 	size = read_4(sc, 4);
 207 #if 1
 208 	if (bootverbose)
 209 		device_printf(dev, " size=0x%05x maxsize=0x%05x\n", size, sc->maxsize);
 210 #endif
 211 	size = (size > sc->maxsize)?sc->maxsize:size;
 212 
 213 
 214 	if (sig == sc->sig || (sc->flags & NVRAM_FLAGS_UBOOT))
 215 	{
 216 
 217 		/* align and shift size to 32bit size*/
 218 		size += 3;
 219 		size >>= 2;
 220 
 221 		nv = malloc(size<<2, M_DEVBUF, M_WAITOK | M_ZERO);
 222 		if (!nv)
 223 			return (ENOMEM);
 224 
 225 		for (i = 0; i < size; i ++)
 226 			((uint32_t *)nv)[i] = read_4(sc, i<<2);
 227 
 228 		if (sc->flags & NVRAM_FLAGS_BROADCOM) {
 229 			device_printf(dev, "sig = %#x\n",  nv->sig);
 230 			device_printf(dev, "size = %#x\n", nv->size);
 231 		}
 232 
 233 		if (!(sc->flags & NVRAM_FLAGS_NOCHECK)) {
 234 			/* TODO: need checksum verification */
 235 		}
 236 
 237 		if (sc->flags & NVRAM_FLAGS_GENERIC)
 238 			pair = (char*)nv+4;
 239 		if (sc->flags & NVRAM_FLAGS_UBOOT)
 240 			pair = (char*)nv+4;
 241 		else if (sc->flags & NVRAM_FLAGS_BROADCOM)
 242 			pair = (char*)nv+20;
 243 		else
 244 			pair = (char*)nv+4;
 245 
 246 		for ( ; 
 247 		    (u_int32_t)pair < ((u_int32_t)nv + size - 4); 
 248 		    pair = pair + strlen(pair) + 1 + strlen(value) + 1 ) {
 249 
 250 			if (pair && strlen(pair)) {
 251 
 252 #if 0
 253 				printf("ENV: %s\n", pair);
 254 #endif
 255 				/* hint.nvram.0. */
 256 				assign = strchr(pair,'=');
 257 				assign[0] = '\0';
 258 				value = assign+1;
 259 #if 1
 260 				if (bootverbose)
 261 					printf("ENV: %s=%s\n", pair, value);
 262 #endif
 263 				setenv(pair, value);
 264 
 265 				if (strcasecmp(pair, "WAN_MAC_ADDR") == 0) {
 266 					/* Alias for MAC address of eth0 */
 267 					if (bootverbose)
 268 						printf("ENV: aliasing "
 269 						    "WAN_MAC_ADDR to ethaddr"
 270 						    " = %s\n",  value);
 271 					setenv("ethaddr", value);
 272 				}
 273 				else if (strcasecmp(pair, "LAN_MAC_ADDR") == 0){
 274 					/* Alias for MAC address of eth1 */
 275 					if (bootverbose)
 276 						printf("ENV: aliasing "
 277 						    "LAN_MAC_ADDR to eth1addr"
 278 						    " = %s\n",  value);
 279 					setenv("eth1addr", value);
 280 				}
 281 
 282 				if (strcmp(pair, "bootverbose") == 0)
 283 					bootverbose = strtoul(value, 0, 0);
 284 				if (strcmp(pair, "boothowto"  ) == 0)
 285 					boothowto   = strtoul(value, 0, 0);
 286 			}
 287 			else
 288 				break;
 289 		}
 290 		free(nv, M_DEVBUF);
 291 	}
 292 
 293 	bus_space_unmap(sc->bst, sc->bsh, NVRAM_MAX_SIZE);
 294 
 295 	return (0);
 296 }
 297 
 298 static device_method_t nvram2env_methods[] = {
 299 	/* Device interface */
 300 	DEVMETHOD(device_identify, 	nvram2env_identify),
 301 	DEVMETHOD(device_probe,		nvram2env_probe),
 302 	DEVMETHOD(device_attach,	nvram2env_attach),
 303 	{0, 0},
 304 };
 305 
 306 static driver_t nvram2env_driver = {
 307 	"nvram2env",
 308 	nvram2env_methods,
 309 	sizeof(struct nvram2env_softc),
 310 };
 311 static devclass_t nvram2env_devclass;
 312 
 313 DRIVER_MODULE(nvram2env, nexus, nvram2env_driver, nvram2env_devclass, 0, 0);

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.