Author: adrian
Date: Mon May 23 03:51:15 2016
New Revision: 300446
URL: https://svnweb.freebsd.org/changeset/base/300446

Log:
  [nvram2env] fix nvram2env to scan all of memory, not 1/4th
  
  The variable "size" stores number of words (4bytes). But the loop over
  memory uses size as number of bytes to scan memory. As result it fetches
  only 1/4th of memory.
  
  This patch solves this problem and nvram2env fetches all NVRAM variables.
  
  Test plan:
  
  Pre-requisites: any MIPS board with ASCII-based NVRAM mapped into memory
  
  * Add "device nvram2env" into kernel configuration
  * Specify hints: base is mandatory (according to nvram2env(4))
  
  hint.nvram.0.base=0x1c7f8000 (it's valid address for Asus RT-N53 with
  flags = 0x4)
  
  * Build & load kernel with bootverbose
  
  Actual result: only part of nvram variables are found
  Expected result: all variables are found
  
  Submitted by: Michael Zhilin <miz...@gmail.com>
  Differential Revision:        https://reviews.freebsd.org/D6466

Modified:
  head/sys/dev/nvram2env/nvram2env.c

Modified: head/sys/dev/nvram2env/nvram2env.c
==============================================================================
--- head/sys/dev/nvram2env/nvram2env.c  Mon May 23 03:47:44 2016        
(r300445)
+++ head/sys/dev/nvram2env/nvram2env.c  Mon May 23 03:51:15 2016        
(r300446)
@@ -193,10 +193,12 @@ static uint32_t read_4(struct nvram2env_
 static int
 nvram2env_attach(device_t dev)
 {
-       struct nvram2env_softc * sc = device_get_softc(dev);
-       struct nvram * nv;
+       struct nvram2env_softc  *sc;
+       struct nvram            *nv;
        char *pair, *value, *assign;
-       uint32_t sig, size, i;
+       uint32_t sig, size, i, *tmp;
+
+       sc = device_get_softc(dev);
 
        if (sc->bst == 0 || sc->addr == 0)
                return (ENXIO);
@@ -217,16 +219,22 @@ nvram2env_attach(device_t dev)
        if (sig == sc->sig || (sc->flags & NVRAM_FLAGS_UBOOT))
        {
 
-               /* align and shift size to 32bit size*/
+               /* align size to 32bit size*/
                size += 3;
-               size >>= 2;
+               size &= ~3;
 
-               nv = malloc(size<<2, M_DEVBUF, M_WAITOK | M_ZERO);
+               nv = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
                if (!nv)
                        return (ENOMEM);
+               /* set tmp pointer to begin of NVRAM */
+               tmp = (uint32_t *) nv;
 
-               for (i = 0; i < size; i ++)
-                       ((uint32_t *)nv)[i] = read_4(sc, i<<2);
+               /* use read_4 to swap bytes if it's required */
+               for (i = 0; i < size; i += 4) {
+                       *tmp = read_4(sc, i);
+                       tmp++;
+               }
+               /* now tmp pointer is end of NVRAM */
 
                if (sc->flags & NVRAM_FLAGS_BROADCOM) {
                        device_printf(dev, "sig = %#x\n",  nv->sig);
@@ -246,49 +254,47 @@ nvram2env_attach(device_t dev)
                else
                        pair = (char*)nv+4;
 
-               for ( ; 
-                   (u_int32_t)pair < ((u_int32_t)nv + size - 4); 
-                   pair = pair + strlen(pair) + 1 + strlen(value) + 1 ) {
+               /* iterate over buffer till end. tmp points to end of NVRAM */
+               for ( ; pair < (char*)tmp; 
+                   pair += strlen(pair) + strlen(value) + 2 ) {
 
-                       if (pair && strlen(pair)) {
+                       if (!pair || (strlen(pair) == 0))
+                               break;
 
-#if 0
-                               printf("ENV: %s\n", pair);
-#endif
-                               /* hint.nvram.0. */
-                               assign = strchr(pair,'=');
-                               assign[0] = '\0';
-                               value = assign+1;
+                       /* hint.nvram.0. */
+                       assign = strchr(pair,'=');
+                       assign[0] = '\0';
+                       value = assign+1;
 #if 1
-                               if (bootverbose)
-                                       printf("ENV: %s=%s\n", pair, value);
+                       if (bootverbose)
+                               printf("ENV: %s=%s\n", pair, value);
+#else
+                       printf("ENV: %s\n", pair);
 #endif
-                               kern_setenv(pair, value);
+                       kern_setenv(pair, value);
 
-                               if (strcasecmp(pair, "WAN_MAC_ADDR") == 0) {
-                                       /* Alias for MAC address of eth0 */
-                                       if (bootverbose)
-                                               printf("ENV: aliasing "
-                                                   "WAN_MAC_ADDR to ethaddr"
-                                                   " = %s\n",  value);
-                                       kern_setenv("ethaddr", value);
-                               }
-                               else if (strcasecmp(pair, "LAN_MAC_ADDR") == 0){
-                                       /* Alias for MAC address of eth1 */
-                                       if (bootverbose)
-                                               printf("ENV: aliasing "
-                                                   "LAN_MAC_ADDR to eth1addr"
-                                                   " = %s\n",  value);
-                                       kern_setenv("eth1addr", value);
-                               }
-
-                               if (strcmp(pair, "bootverbose") == 0)
-                                       bootverbose = strtoul(value, 0, 0);
-                               if (strcmp(pair, "boothowto"  ) == 0)
-                                       boothowto   = strtoul(value, 0, 0);
+                       if (strcasecmp(pair, "WAN_MAC_ADDR") == 0) {
+                               /* Alias for MAC address of eth0 */
+                               if (bootverbose)
+                                       printf("ENV: aliasing "
+                                           "WAN_MAC_ADDR to ethaddr"
+                                           " = %s\n",  value);
+                               kern_setenv("ethaddr", value);
                        }
-                       else
-                               break;
+                       else if (strcasecmp(pair, "LAN_MAC_ADDR") == 0){
+                               /* Alias for MAC address of eth1 */
+                               if (bootverbose)
+                                       printf("ENV: aliasing "
+                                           "LAN_MAC_ADDR to eth1addr"
+                                           " = %s\n",  value);
+                               kern_setenv("eth1addr", value);
+                       }
+
+                       if (strcmp(pair, "bootverbose") == 0)
+                               bootverbose = strtoul(value, 0, 0);
+                       if (strcmp(pair, "boothowto"  ) == 0)
+                               boothowto   = strtoul(value, 0, 0);
+
                }
                free(nv, M_DEVBUF);
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to