blob: 6031444d49303d10a2f854fe003cfcb686798bc7 [file] [log] [blame]
/* Copyright (C) 2011-2012 Humax Co., Ltd. All rights reserved.
*
* Humax Co., Ltd. ("Humax") hereby provides permission, free of charge, to any
* person obtaining a copy of this source code, to use and redistribute this
* source code with or without modification subject to the following conditions:
*
* 1. Redistributions of this source code must retain the above copyright
* notice, permission notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* permission notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY HUMAX "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ACCURACY, COMPLETENESS,
* CURRENCY, AVAILABILITY, TITLE OR NON-INFRINGEMENT. IN NO EVENT HUMAX OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF OR OTHER DEALINGS IN THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusion contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of Humax.
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Humax’s software provided under a license
* other than the above license, without Humax's express prior written consent.
*/
/*******************************************************************/
/************************* File Description ************************/
/*******************************************************************/
/* File Name: $Workfile: hmx_uprade_nvram.c $
* Version: $Revision: 1.0 $
* Original Author: Yang Hyun Uk $
* Current Author: $Author: huyang@humaxdigital.com $
* Date: $Date: 2011.11.07
* File Description: Humax Upgrade APIs
* Module:
* Remarks:
*/
/**
* @defgroup NVRAM APIs for Upgrade Module
* @ingroup UPGRADE
*/
/**
* @author Hyunuk Yang(huyang@humaxdigital.com)
* @date 07 Nov 2011
*/
/*@{*/
/**
* @file hmx_upgrade_nvram.c
*/
/*******************************************************************/
/**************************** Header Files *************************/
/*******************************************************************/
/* Start Including Header Files */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hnvram_dlist.h"
#include "hmx_upgrade_nvram.h"
/* End Including Headers */
/*******************************************************************/
/****************************** define *****************************/
/*******************************************************************/
/* Start #define */
#define NVRAM_TYPE_LEN 1
#define NVRAM_RECORD_LENG_LEN 4
#define NVRAM_NAME_LENG_LEN 1
#define NVRAM_DATA_LENG_LEN 4
#define MAX_NAME_LEN (256)
#define MAX_DATA_LEN (256*1024)
#define MAX_FIELD_LEN (MAX_DATA_LEN+MAX_NAME_LEN*2)
#define NVRAM_TLV_TYPE_END 0x00
#define NVRAM_TLV_TYPE_ENV 0x01
#define get8bit(q) (unsigned char)((q)[0])
#define get32bit(q) (unsigned int)(((*(unsigned char *)(q)) << 24) | \
(*((unsigned char *)(q)+1) << 16) | \
(*((unsigned char *)(q)+2) << 8) | \
(*((unsigned char *)(q)+3)) )
#define DEBUG_ERR(...) fprintf(stderr, __VA_ARGS__)
#define DEBUG_INFO(...) fprintf(stderr, __VA_ARGS__)
#define UNUSED(x) (void)(x)
#define MAX_NVRAM_FILENAME_LENGTH 32
#define SEM_Get(x) (void)(x)
#define SEM_Release(x) (void)(x)
#define NVRAM_RO_OFFSET 0x0
#define NVRAM_RO_SIZE 0x00100000
#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
/* End #define */
/*******************************************************************/
/****************************** typedef ****************************/
/*******************************************************************/
/* Start typedef */
typedef struct NVRAM_EVNVAR_t {
dlist_hdr_t dlist_hdr;
unsigned int recLen;
unsigned char *name;
unsigned char nameLen;
unsigned char *value;
unsigned int valueLen;
} NVRAM_EVNVAR_T;
typedef struct HMX_NVRAM_MAP_t {
NVRAM_FIELD_T type;
unsigned char szFileName[MAX_NVRAM_FILENAME_LENGTH];
HMX_NVRAM_PARTITION_E storePartition;
unsigned int defaultSize;
} HMX_NVRAM_FIELD_INFO_T;
HMX_NVRAM_FIELD_INFO_T s_nvramFieldInfo[] = {
{NVRAM_FIELD_SYSTEM_ID, "SYSTEM_ID", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_SERIAL_NO, "SERIAL_NO", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_MAC_ADDR, "MAC_ADDR", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_HDCP_KEY, "HDCP_KEY", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_DTCP_KEY, "DTCP_KEY", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_1ST_SERIAL_NUMBER, "1ST_SERIAL_NUMBER", HMX_NVRAM_PARTITION_RO,
0},
{NVRAM_FIELD_2ND_SERIAL_NUMBER, "2ND_SERIAL_NUMBER", HMX_NVRAM_PARTITION_RO,
0},
{NVRAM_FIELD_GPN, "GPN", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_MAC_ADDR_MOCA, "MAC_ADDR_MOCA", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_MAC_ADDR_BT, "MAC_ADDR_BT", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_GOOGLE_SSL_PEM, "GOOGLE_SSL_PEM", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_GOOGLE_SSL_CRT, "GOOGLE_SSL_CRT", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_HW_VER, "HW_VER", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_LOADER_VERSION, "LOADER_VERSION", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_ACTIVATED_KERNEL_NUM, "ACTIVATED_KERNEL_NUM",
HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_MTD_TYPE_FOR_KERNEL, "MTD_TYPE_FOR_KERNEL",
HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_ACTIVATED_KERNEL_NAME, "ACTIVATED_KERNEL_NAME",
HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_EXTRA_KERNEL_OPT, "EXTRA_KERNEL_OPT", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_PLATFORM_NAME, "PLATFORM_NAME", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_PAIRED_DISK, "PAIRED_DISK", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_PARTITION_VER, "PARTITION_VER", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_MAC_ADDR_WIFI, "MAC_ADDR_WIFI", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_MAC_ADDR_WIFI2, "MAC_ADDR_WIFI2", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_MAC_ADDR_WAN, "MAC_ADDR_WAN", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_UITYPE, "UITYPE", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_LASER_CHANNEL, "LASER_CHANNEL", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_MAC_ADDR_PON, "MAC_ADDR_PON", HMX_NVRAM_PARTITION_RO, 0},
{NVRAM_FIELD_PRODUCTION_UNIT, "PRODUCTION_UNIT", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_BOOT_TARGET, "BOOT_TARGET", HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_ANDROID_ACTIVE_PARTITION, "ANDROID_ACTIVE_PARTITION",
HMX_NVRAM_PARTITION_RW, 0},
{NVRAM_FIELD_DUMMY, "DUMMY", HMX_NVRAM_PARTITION_RW, 0}
};
/* End typedef */
/*******************************************************************/
/************************ global variables *************************/
/*******************************************************************/
/* Start global variable */
static dlist_hdr_t s_nvram_envvars[HMX_NVRAM_PARTITION_MAX] = {
DLIST_INIT(s_nvram_envvars[0]),
DLIST_INIT(s_nvram_envvars[1]),
DLIST_INIT(s_nvram_envvars[2]),
};
static unsigned int s_nvram_offset[HMX_NVRAM_PARTITION_MAX] = {
NVRAM_RO_OFFSET,
NVRAM_RW_OFFSET,
RAW_FS_OFFSET
};
static unsigned int s_nvram_backup_offset[HMX_NVRAM_PARTITION_MAX] = {
0,
NVRAM_RWB_OFFSET,
0
};
static unsigned int s_nvram_size[HMX_NVRAM_PARTITION_MAX] = {
NVRAM_RO_SIZE,
NVRAM_RW_SIZE,
RAW_FS_SIZE
};
/* End global variable */
/*******************************************************************/
/************************ static variables *************************/
/*******************************************************************/
/* Start static variable */
static unsigned long s_nvramSema;
/* End static variable */
/*******************************************************************/
/************************ static funtions **************************/
/*******************************************************************/
/* *********************************************************************
* drv_NVRAM_Read(buffer,offset,length)
*
* Read data from the NVRAM device0
*
* Input parameters:
* buffer - destination buffer
* offset - offset of data to read
* length - number of bytes to read
*
* Return value:
* number of bytes read, or <0 if error occured
********************************************************************* */
static int drv_NVRAM_Read(unsigned char *buffer, unsigned int offset,
unsigned int length)
{
int ret = HMX_UPGRADE_NVRAM_Read(offset, buffer, length);
if (ret != 0) {
return ret;
}
return length;
}
/* *********************************************************************
* drv_NVRAM_Write(buffer,offset,length)
*
* Write data to the NVRAM device
*
* Input parameters:
* buffer - source buffer
* offset - offset of data to write
* length - number of bytes to write
*
* Return value:
* number of bytes written, or -1 if error occured
********************************************************************* */
static int drv_NVRAM_Write(const unsigned char *buffer, unsigned int offset,
unsigned int length)
{
int ret = HMX_UPGRADE_NVRAM_Write(offset, buffer, length);
if (ret != 0) {
return -1;
}
return length;
}
/* *********************************************************************
* HMX_NVRAM_FindEnv(name)
*
* Locate an environment variable in the in-memory list
*
* Input parameters:
* name - name of env var to find
*
* Return value:
* NVRAM_EVNVAR_T pointer, or NULL if not found
********************************************************************* */
static NVRAM_EVNVAR_T *drv_NVRAM_FindEnv(HMX_NVRAM_PARTITION_E partition,
const unsigned char *name)
{
dlist_hdr_t *entry;
NVRAM_EVNVAR_T *env;
DLIST_FOR_EACH(&s_nvram_envvars[partition], entry) {
env = (NVRAM_EVNVAR_T *) entry;
if (strcmp((char*)env->name, (char*)name) == 0)
break;
}
if (entry == &s_nvram_envvars[partition])
return NULL;
return (NVRAM_EVNVAR_T *) entry;
}
/* *********************************************************************
* HMX_NVRAM_ScanDir(idx,name,namelen,val,vallen)
*
* Enumerate environment variables. This routine locates
* the nth environment variable and copies its name and value
* to user buffers.
*
* The namelen and vallen variables must be preinitialized to
* the maximum size of the output buffer.
*
* Input parameters:
* idx - variable index to find (starting with zero)
* name,namelen - name buffer and length
* val,vallen - value buffer and length
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_ScanDir(HMX_NVRAM_PARTITION_E partition,
unsigned int idx, unsigned char *name,
unsigned int *namelen, unsigned char *val,
unsigned int *vallen)
{
dlist_hdr_t *entry;
NVRAM_EVNVAR_T *env;
DLIST_FOR_EACH(&s_nvram_envvars[partition], entry) {
if (idx == 0)
break;
idx--;
}
if (entry == &s_nvram_envvars[partition]) {
return DRV_ERR;
}
env = (NVRAM_EVNVAR_T *) entry;
if (name != NULL) {
strncpy((char*)name, (char*)env->name, env->nameLen);
name[env->nameLen] = 0;
}
*namelen = env->nameLen;
if (val != NULL) {
memcpy(val, env->value, env->valueLen);
}
*vallen = env->valueLen;
return DRV_OK;
}
/* *********************************************************************
* drv_NVRAM_Delete(name)
*
* Delete an environment variable
*
* Input parameters:
* name - environment variable to delete
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_Delete(HMX_NVRAM_PARTITION_E partition,
const unsigned char *name)
{
NVRAM_EVNVAR_T *env;
env = drv_NVRAM_FindEnv(partition, name);
if (env == NULL) {
return DRV_ERR;
}
dlist_del((dlist_hdr_t *) env);
free(env);
return DRV_OK;
}
/* *********************************************************************
* drv_NVRAM_GetEnv(name)
*
* Retrieve the value of an environment variable starting from an offset.
*
* Input parameters:
* partition - name of the nvram partition
* name - name of environment variable to find
* offset - relative offset to where the variable starts
* data - where to retrieve the value of the variable
* readLen - maximum length of the returned data
* pDataLen - the actual size of the data, may be smaller than readLen
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_GetEnv(HMX_NVRAM_PARTITION_E partition,
const unsigned char *name,
const unsigned int offset,
unsigned char *data,
unsigned int readLen,
unsigned int *pDataLen)
{
NVRAM_EVNVAR_T *env;
unsigned int len;
if (data == NULL)
return DRV_ERR_INVALID_PARAMETER;
memset(data, 0, readLen);
env = drv_NVRAM_FindEnv(partition, name);
if (env == NULL)
return DRV_ERR_INVALID_PARAMETER;
if (readLen > env->valueLen - offset)
len = env->valueLen - offset;
else
len = readLen;
memcpy(data, env->value+offset, len);
if (pDataLen != NULL)
*pDataLen = len;
return DRV_OK;
}
/* *********************************************************************
* drv_NVRAM_GetLength(name)
*
* Retrieve the value of an environment variable
*
* Input parameters:
* partition - the nvram partition for the environment variable
* name - name of environment variable to find
* pLen - pointer to where the length should be returned
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_GetLength(HMX_NVRAM_PARTITION_E partition,
const unsigned char *name,
unsigned int *pLen)
{
NVRAM_EVNVAR_T *env;
env = drv_NVRAM_FindEnv(partition, name);
if (env != NULL) {
*pLen = env->valueLen;
return DRV_OK;
}
return DRV_ERR_INVALID_PARAMETER;
}
/* *********************************************************************
* drv_NVRAM_SetEnv(name,value,flags)
*
* Set the value of an environment variable
*
* Input parameters:
* name - name of variable
* value - value of variable
* flags - flags for variable (ENV_FLG_xxx)
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_SetEnv(HMX_NVRAM_PARTITION_E partition,
const unsigned char *name,
const unsigned char *value,
unsigned int valueLen)
{
NVRAM_EVNVAR_T *env;
unsigned int namelen;
env = drv_NVRAM_FindEnv(partition, name);
if (env) {
dlist_del((dlist_hdr_t *) env);
free(env);
}
namelen = strlen((char*)name);
env = (NVRAM_EVNVAR_T*)
malloc(sizeof(NVRAM_EVNVAR_T) + namelen + 1 + valueLen);
if (!env) {
return DRV_ERR_OUTOFMEMORY;
}
env->name = (unsigned char *) (env+1);
env->value = env->name + namelen + 1;
env->nameLen = namelen;
env->valueLen = valueLen;
env->recLen = (NVRAM_NAME_LENG_LEN + namelen + NVRAM_DATA_LENG_LEN +
valueLen);
strncpy((char*)env->name, (char*)name, namelen);
env->name[namelen] = 0;
memcpy(env->value, value, valueLen);
dlist_add(&s_nvram_envvars[partition], (dlist_hdr_t *) env);
return DRV_OK;
}
/* *********************************************************************
* drv_NVRAM_LoadByAddress()
*
* Load the environment from the NVRAM device.
*
* Input parameters:
* partition - the name of the NVRAM partition
* address - the address to load from
* size - the size of nvram
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
static DRV_Error drv_NVRAM_LoadByAddress(HMX_NVRAM_PARTITION_E partition,
unsigned int address,
unsigned int size)
{
unsigned int nvram_size;
unsigned char *buffer;
unsigned char *ptr;
unsigned int recLen;
unsigned int recType;
unsigned int offset;
DRV_Error retval;
unsigned char fileName[MAX_NAME_LEN];
unsigned char nameLen;
unsigned int dataLen;
nvram_size = size;
buffer = (unsigned char*)malloc(MAX_FIELD_LEN);
if (buffer == NULL)
{
return DRV_ERR_OUTOFMEMORY;
}
ptr = buffer;
offset = 0;
retval = DRV_OK;
/* Read the record type and length */
if (drv_NVRAM_Read(ptr, offset+address, NVRAM_TYPE_LEN) != NVRAM_TYPE_LEN) {
retval = DRV_ERR_EXTERNAL_ERROR;
goto error;
}
while ((*ptr != NVRAM_TLV_TYPE_END) && (nvram_size > NVRAM_TYPE_LEN)) {
/* Adjust pointer for TLV type */
recType = get8bit(ptr);
nvram_size -= NVRAM_TYPE_LEN;
offset += NVRAM_TYPE_LEN;
if (recType != NVRAM_TLV_TYPE_ENV) {
retval = DRV_ERR_EVENT_INITIALIZATION;
goto error;
}
/* Read the record type and length - 16 bits, MSB first */
if (drv_NVRAM_Read(ptr, offset+address, NVRAM_RECORD_LENG_LEN) !=
NVRAM_RECORD_LENG_LEN) {
retval = DRV_ERR_EXTERNAL_ERROR;
goto error;
}
recLen = get32bit(ptr);
nvram_size -= NVRAM_RECORD_LENG_LEN;
offset += NVRAM_RECORD_LENG_LEN;
if (recLen > MAX_FIELD_LEN) {
retval = DRV_ERR_EVENT_INITIALIZATION;
goto error;
}
if (recLen > nvram_size) {
retval = DRV_ERR_EVENT_INITIALIZATION;
goto error; /* should not happen, bad NVRAM */
}
/* Read the TLV data */
if (drv_NVRAM_Read(ptr,offset+address,recLen) != (int)recLen) {
retval = DRV_ERR_EXTERNAL_ERROR;
goto error;
}
nameLen = get8bit(ptr);
ptr += NVRAM_NAME_LENG_LEN;
if (nameLen) {
memcpy(fileName, ptr, nameLen);
}
fileName[nameLen] = 0;
ptr += nameLen;
dataLen = get32bit(ptr);
ptr += NVRAM_DATA_LENG_LEN;
if (dataLen > MAX_DATA_LEN) {
retval = DRV_ERR_EVENT_INITIALIZATION;
goto error;
}
if (recLen != (NVRAM_NAME_LENG_LEN + nameLen + NVRAM_DATA_LENG_LEN +
dataLen)) {
retval = DRV_ERR_EVENT_INITIALIZATION;
goto error;
}
drv_NVRAM_SetEnv(partition, fileName, ptr, dataLen);
nvram_size -= (unsigned int)recLen;
offset += recLen;
/* Read the next record type */
ptr = buffer;
if (drv_NVRAM_Read(ptr,offset+address, NVRAM_TYPE_LEN) != NVRAM_TYPE_LEN) {
retval = DRV_ERR_EXTERNAL_ERROR;
goto error;
}
}
error:
free(buffer);
return retval;
}
static DRV_Error drv_NVRAM_Load(HMX_NVRAM_PARTITION_E partition)
{
DRV_Error drv_error;
drv_error = drv_NVRAM_LoadByAddress(partition, s_nvram_offset[partition],
s_nvram_size[partition]);
if (drv_error != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_Load] error(%d) loading partition (%d)\n", drv_error, partition);
if (s_nvram_backup_offset[partition] != 0) {
drv_error = drv_NVRAM_LoadByAddress(partition,
s_nvram_backup_offset[partition],
s_nvram_size[partition]);
if (drv_error != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_Load] error(%d) loading backup partition (%d)\n",
drv_error, partition);
} else {
DEBUG_INFO("[HMX_NVRAM_Load] load OK loading backup partition (%d)\n",
partition);
}
}
}
return drv_error;
}
/* *********************************************************************
* HMX_NVRAM_Save()
*
* Write the environment to the NVRAM device.
*
* Input parameters:
* nothing
*
* Return value:
* 0 if ok, else error code
********************************************************************* */
static DRV_Error drv_NVRAM_Save(HMX_NVRAM_PARTITION_E partition)
{
unsigned int nvram_size;
unsigned char *buffer;
unsigned char *buffer_end;
unsigned char *ptr;
dlist_hdr_t *entry;
NVRAM_EVNVAR_T *env;
unsigned char namelen;
unsigned int valuelen;
unsigned int recLen;
DRV_Error result;
nvram_size = s_nvram_size[partition];
buffer = (unsigned char*)malloc(nvram_size);
if (buffer == NULL) {
return DRV_ERR_OUTOFMEMORY;
}
buffer_end = buffer + nvram_size - 1;
ptr = buffer;
DLIST_FOR_EACH(&s_nvram_envvars[partition], entry) {
env = (NVRAM_EVNVAR_T *) entry;
namelen = env->nameLen;
valuelen = env->valueLen;
recLen = env->recLen;
if ((ptr + NVRAM_TYPE_LEN + NVRAM_RECORD_LENG_LEN + recLen) > buffer_end) {
/* One or more variables don't fit into the partition. Fail the write. */
free(buffer);
return DRV_ERR_OUTOFMEMORY;
}
*ptr++ = NVRAM_TLV_TYPE_ENV; /* TLV record type */
*ptr++ = (recLen>>24) & 0xFF; /* TLV record length */
*ptr++ = (recLen>>16) & 0xFF; /* TLV record length */
*ptr++ = (recLen>>8) & 0xFF; /* TLV record length */
*ptr++ = (recLen>>0) & 0xFF; /* TLV record length */
*ptr++ = (namelen>>0) & 0xFF; /* NAME record length */
memcpy(ptr, env->name, namelen); /* NAME record data */
ptr += namelen;
*ptr++ = (valuelen>>24) & 0xFF; /* VALUE record length */
*ptr++ = (valuelen>>16) & 0xFF; /* VALUE record length */
*ptr++ = (valuelen>>8) & 0xFF; /* VALUE record length */
*ptr++ = (valuelen>>0) & 0xFF; /* VALUE record length */
memcpy(ptr,env->value, valuelen);
ptr += valuelen;
}
*ptr++ = NVRAM_TLV_TYPE_END;
nvram_size = drv_NVRAM_Write(buffer,0+s_nvram_offset[partition],ptr-buffer);
if (s_nvram_backup_offset[partition] != 0) {
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 result;
}
static unsigned int NVRAM_SWAP32(unsigned int A)
{
return ((A << 24) | ((A << 8) & 0xFF0000) | ((A >> 8) & 0xFF00) |(A >> 24));
}
static DRV_Error drv_NVRAM_GetFieldInfo(const NVRAM_FIELD_T type,
HMX_NVRAM_PARTITION_E *pPartition,
unsigned char *pszFileName,
unsigned int *defaultSize)
{
int i;
SEM_Get(s_nvramSema);
for (i = 0; ; i++) {
if (NVRAM_FIELD_DUMMY == s_nvramFieldInfo[i].type)
break;
if (type != s_nvramFieldInfo[i].type)
continue;
strncpy((char*)pszFileName, (char*)(s_nvramFieldInfo[i].szFileName),
MAX_NVRAM_FILENAME_LENGTH);
*pPartition = s_nvramFieldInfo[i].storePartition;
*defaultSize = s_nvramFieldInfo[i].defaultSize;
SEM_Release(s_nvramSema);
return DRV_OK;
}
SEM_Release(s_nvramSema);
return DRV_ERR;
}
DRV_Error HMX_NVRAM_Init(const char *location)
{
HMX_UPGRADE_NVRAM_Init(location);
drv_NVRAM_Load(HMX_NVRAM_PARTITION_RO);
drv_NVRAM_Load(HMX_NVRAM_PARTITION_RW);
return DRV_OK;
}
DRV_Error HMX_NVRAM_Write(HMX_NVRAM_PARTITION_E partition,
const unsigned char *pName, unsigned int offset,
const unsigned char *pValue, unsigned int ulSize)
{
DRV_Error drv_error;
UNUSED(offset);
SEM_Get(s_nvramSema);
drv_error = drv_NVRAM_SetEnv(partition, pName, pValue, ulSize);
drv_error = drv_NVRAM_Save(partition);
SEM_Release(s_nvramSema);
return drv_error;
}
DRV_Error HMX_NVRAM_Read(HMX_NVRAM_PARTITION_E partition,
const unsigned char *pName, unsigned int offset,
unsigned char *pValue, unsigned int ulSize,
unsigned int *pLen)
{
DRV_Error drv_error;
if (pValue == NULL)
return DRV_ERR_INVALID_PARAMETER;
SEM_Get(s_nvramSema);
memset(pValue, 0, ulSize);
drv_error = drv_NVRAM_GetEnv(partition, pName, offset, pValue, ulSize, pLen);
SEM_Release(s_nvramSema);
return drv_error;
}
DRV_Error HMX_NVRAM_GetFieldAndSize(NVRAM_FIELD_T field, unsigned int offset,
void *data, int nDataSize, unsigned int *pDataSize)
{
DRV_Error errCode = DRV_ERR;
unsigned char szFileName[MAX_NVRAM_FILENAME_LENGTH];
HMX_NVRAM_PARTITION_E partition;
unsigned int defaultSize;
if (data == NULL || field == NVRAM_FIELD_DUMMY) {
return DRV_ERR_INVALID_PARAMETER;
}
errCode = drv_NVRAM_GetFieldInfo(field, &partition, szFileName, &defaultSize);
if (errCode != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_GetField] field(%d) error(%08X) : "
"HMX_NVRAM_GetFieldInfo\n", field, errCode);
return errCode;
}
switch (partition) {
case HMX_NVRAM_PARTITION_W_RAWFS :
break;
case HMX_NVRAM_PARTITION_RO :
case HMX_NVRAM_PARTITION_RW :
if (defaultSize == 0) {
errCode = HMX_NVRAM_Read(partition, szFileName, offset,
(unsigned char*)data, nDataSize, pDataSize);
if (errCode != DRV_OK) {
return errCode;
}
if (field == NVRAM_FIELD_SYSTEM_ID && errCode == 0) {
*((unsigned int*)data) = NVRAM_SWAP32((unsigned int)*(unsigned int*)data);
}
} else {
unsigned char *pBuf;
pBuf = (unsigned char*)malloc(defaultSize);
if (pBuf == NULL) {
DEBUG_ERR("[HMX_NVRAM_GetField] malloc\n");
return DRV_ERR_INITIALIZATION;
}
errCode = HMX_NVRAM_Read(partition, szFileName, 0, pBuf, defaultSize, pDataSize);
if (errCode != DRV_OK) {
memset(pBuf, 0, defaultSize);
}
memcpy(data, pBuf + offset, nDataSize);
free(pBuf);
}
break;
default :
DEBUG_ERR("[HMX_NVRAM_GetField] DI_ERR_INVALID_PARAM field(%d)-%s "
"error(%08X) : HMX_NVRAM_Write\n", field, szFileName, errCode);
return DRV_ERR_INVALID_PARAMETER;
}
return errCode;
}
DRV_Error HMX_NVRAM_GetField(NVRAM_FIELD_T field, unsigned int offset,
void *data, int nDataSize)
{
return HMX_NVRAM_GetFieldAndSize(field, offset, data, nDataSize, NULL);
}
DRV_Error HMX_NVRAM_SetField(NVRAM_FIELD_T field, unsigned int offset,
void *data, int nDataSize)
{
DRV_Error errCode = DRV_ERR;
unsigned char szFileName[MAX_NVRAM_FILENAME_LENGTH];
HMX_NVRAM_PARTITION_E partition;
unsigned int defaultSize;
unsigned int systemId;
if (data == NULL || field == NVRAM_FIELD_DUMMY) {
return DRV_ERR_INVALID_PARAMETER;
}
errCode = drv_NVRAM_GetFieldInfo(field, &partition, szFileName, &defaultSize);
if (errCode != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_SetField] error(%08X) : HMX_NVRAM_GetFieldInfo, "
"field (%d)\n", errCode, field);
return errCode;
}
switch (partition) {
case HMX_NVRAM_PARTITION_W_RAWFS :
return DRV_ERR_INVALID_PARAMETER;
case HMX_NVRAM_PARTITION_RO :
case HMX_NVRAM_PARTITION_RW :
if (defaultSize == 0) {
if (field == NVRAM_FIELD_SYSTEM_ID && errCode == 0) {
systemId = NVRAM_SWAP32((unsigned int)*(unsigned int*)data);
data = (void*)&systemId;
}
errCode = HMX_NVRAM_Write(partition, szFileName, 0,
(unsigned char*)data, nDataSize);
if (errCode != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_SetField] field(%d)-%s error(%08X) : "
"HMX_NVRAM_Write\n", field, szFileName, errCode);
return errCode;
}
} else {
unsigned char *pBuf;
pBuf = (unsigned char*)malloc(defaultSize);
if (pBuf == NULL) {
DEBUG_ERR("[HMX_NVRAM_SetField] malloc\n");
return DRV_ERR_INITIALIZATION;
}
errCode = HMX_NVRAM_Read(partition, szFileName, 0, pBuf, defaultSize, NULL);
if (errCode != DRV_OK) {
memset(pBuf, 0, defaultSize);
}
memcpy(pBuf + offset, data, nDataSize);
errCode = HMX_NVRAM_Write(partition, szFileName, 0, pBuf, defaultSize);
free(pBuf);
if (errCode != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_SetField] field(%d)-%s error(%08X) : "
"HMX_NVRAM_Write\n", field, szFileName, errCode);
return errCode;
}
}
break;
default :
DEBUG_ERR("[HMX_NVRAM_SetField] DI_ERR_INVALID_PARAM field(%d)-%s "
"error(%08X) : HMX_NVRAM_Write\n", field, szFileName, errCode);
return DRV_ERR_INVALID_PARAMETER;
}
return errCode;
}
DRV_Error HMX_NVRAM_GetLength(NVRAM_FIELD_T field, unsigned int *pLen)
{
DRV_Error errCode = DRV_ERR;
unsigned char szFileName[MAX_NVRAM_FILENAME_LENGTH];
HMX_NVRAM_PARTITION_E partition;
unsigned int defaultSize;
if (pLen == NULL) {
return DRV_ERR_INVALID_PARAMETER;
}
*pLen = 0;
errCode = drv_NVRAM_GetFieldInfo(field, &partition, szFileName, &defaultSize);
if (errCode != DRV_OK) {
DEBUG_ERR("[HMX_NVRAM_GetLength] error(%08X) : HMX_NVRAM_GetFieldInfo, "
"field (%d)\n", errCode, field);
return errCode;
}
errCode = drv_NVRAM_GetLength(partition, szFileName, pLen);
return DRV_OK;
}
DRV_Error HMX_NVRAM_Remove(HMX_NVRAM_PARTITION_E partition,
const unsigned char *pName)
{
DRV_Error result;
SEM_Get(s_nvramSema);
result = drv_NVRAM_Delete(partition, pName);
if (result == DRV_OK) {
result = drv_NVRAM_Save(partition);
}
SEM_Release(s_nvramSema);
return result;
}
DRV_Error HMX_NVRAM_Dump(unsigned char* pucBuffer, unsigned int uiLen, unsigned int uiAlign)
{
unsigned int uiIndex;
unsigned int skip;
skip = 1;
for (uiIndex=0 ; uiIndex<uiLen ; uiIndex++) {
if (uiAlign!=0 && (uiIndex%uiAlign)==0) {
if (skip == 0) {
printf("\n");
}
else
skip = 0;
}
printf("%02X ", *(pucBuffer+uiIndex));
}
printf("\n");
return DRV_OK;
}
void HMX_NVRAM_Print_Separator(void) {
printf("-------------------- "
"--------------------------------------------------\n");
}
DRV_Error HMX_NVRAM_Dir(void)
{
char name[80];
char *value;
int nameLen, valueLen;
int idx;
value = (char*)malloc(MAX_DATA_LEN);
if (value == NULL)
{
return DRV_ERR_OUTOFMEMORY;
}
SEM_Get(s_nvramSema);
printf("ROM Name Value\n");
HMX_NVRAM_Print_Separator();
for (idx=0;;idx++) {
if (drv_NVRAM_ScanDir(HMX_NVRAM_PARTITION_RO, idx, (unsigned char*)name, (unsigned int*)&nameLen, (unsigned char*)value, (unsigned int*)&valueLen) != DRV_OK)
break;
printf("%20s ", name);
(void)HMX_NVRAM_Dump((unsigned char*)value, valueLen, 16);
}
HMX_NVRAM_Print_Separator();
printf("\n");
printf("Variable Name Value\n");
HMX_NVRAM_Print_Separator();
for (idx=0;;idx++) {
if (drv_NVRAM_ScanDir(HMX_NVRAM_PARTITION_RW, idx, (unsigned char*)name, (unsigned int*)&nameLen, (unsigned char*)value, (unsigned int*)&valueLen) != DRV_OK)
break;
printf("%20s ", name);
(void)HMX_NVRAM_Dump((unsigned char*)value, valueLen, 16);
}
HMX_NVRAM_Print_Separator();
free(value);
SEM_Release(s_nvramSema);
return DRV_OK;
}
/*@}*/