Large hnvram value fixes (up to 64k).

Bug fixes discovered while testing prowl hnvram with large values.
  a) halve the size of the RW partition to match the size of the
     RWB (backup) partition.  nudge offsets so that the locations
     stay the same within the overall layout.
  b) explicitly fail when exceeding the storage available
     in a partition.
  c) fix a use-after-free

Change-Id: Id7f7c13d5d29aa09243f1e0b7920322167123c4f
diff --git a/libupgrade/hmx_upgrade_nvram.c b/libupgrade/hmx_upgrade_nvram.c
index fc1a52a..315c5e3 100644
--- a/libupgrade/hmx_upgrade_nvram.c
+++ b/libupgrade/hmx_upgrade_nvram.c
@@ -107,9 +107,15 @@
 
 #define NVRAM_RO_OFFSET         0x0
 #define NVRAM_RO_SIZE           0x00100000
-#define NVRAM_RW_OFFSET ( NVRAM_RO_OFFSET + NVRAM_RO_SIZE )
-#define NVRAM_RW_SIZE           0x00040000
-#define NVRAM_RWB_OFFSET        ( NVRAM_RW_OFFSET + NVRAM_RW_SIZE)
+#define NVRAM_RW_OFFSET         ( NVRAM_RO_OFFSET + NVRAM_RO_SIZE )
+/*
+ * Halve the size of the RW partition, so that it matches the
+ * size of the RW backup.  Add unused reserved space to ensure
+ * that the offsets remain consistent.
+ */
+#define NVRAM_RW_SIZE           0x00020000
+#define NVRAM_RESERVED_SIZE     0x00020000
+#define NVRAM_RWB_OFFSET        ( NVRAM_RW_OFFSET + NVRAM_RW_SIZE + NVRAM_RESERVED_SIZE)
 #define NVRAM_RWB_SIZE          0x00020000
 #define RAW_FS_OFFSET           ( NVRAM_RWB_OFFSET + NVRAM_RWB_SIZE)
 #define RAW_FS_SIZE             0x00020000
@@ -668,6 +674,7 @@
   unsigned char namelen;
   unsigned int valuelen;
   unsigned int recLen;
+  DRV_Error result;
 
   nvram_size = s_nvram_size[partition];
   buffer = malloc(nvram_size);
@@ -686,7 +693,8 @@
     recLen = env->recLen;
 
     if ((ptr + NVRAM_TYPE_LEN + NVRAM_RECORD_LENG_LEN + recLen) > buffer_end) {
-      break;
+      /* One or more variables don't fit into the partition. Fail the write. */
+      return DRV_ERR_OUTOFMEMORY;
     }
 
     *ptr++ = NVRAM_TLV_TYPE_ENV;        /* TLV record type */
@@ -718,10 +726,11 @@
     drv_NVRAM_Write(buffer,0+s_nvram_backup_offset[partition],ptr-buffer);
   }
 
+  result = (nvram_size == (unsigned int)(ptr-buffer)) ? DRV_OK :
+      DRV_ERR_EXTERNAL_ERROR;
   free(buffer);
 
-  return (nvram_size == (unsigned int)(ptr-buffer)) ? DRV_OK :
-      DRV_ERR_EXTERNAL_ERROR;
+  return result;
 }
 
 static unsigned int NVRAM_SWAP32(unsigned int A)