blob: d01f8b267eab50433b35341fd6db47757a9998c5 [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_flash.c $
* Version: $Revision: 1.0 $
* Original Author: Yang Hyun Uk $
* Current Author: $Author: huyang@humaxdigital.com $
* Date: $Date: 2011.09.30
* File Description: Humax Upgrade APIs
* Module:
* Remarks:
*/
/**
* @defgroup UPGRADE_FLASH Flashing APIs for Upgrade Module
* @ingroup UPGRADE
*
*/
/**
* @author Hyunuk Yang(huyang@humaxdigital.com)
* @date 30 Sept 2011
*/
/*@{*/
/**
* @file hmx_upgrade_flash.c
*/
/*******************************************************************/
/**************************** Header Files *************************/
/*******************************************************************/
/* Start Including Header Files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <mtd/mtd-user.h>
/* End Including Headers */
/*******************************************************************/
/****************************** define *****************************/
/*******************************************************************/
/* Start #define */
#define HNVRAM_PARTITION_DEFAULT "/dev/mtd/hnvram"
/* End #define */
/*******************************************************************/
/****************************** typedef ****************************/
/*******************************************************************/
/* Start typedef */
/* End typedef */
/*******************************************************************/
/************************ global variables *************************/
/*******************************************************************/
/* Start global variable */
int libupgrade_verbose = 1;
/* End global variable */
/*******************************************************************/
/************************ static variables *************************/
/*******************************************************************/
/* Start static variable */
static const char *hnvram_partition = HNVRAM_PARTITION_DEFAULT;
/* End static variable */
/*******************************************************************/
/************************ static funtions **************************/
/*******************************************************************/
void HMX_UPGRADE_NVRAM_Init(const char * location)
{
if (location == NULL) {
hnvram_partition = HNVRAM_PARTITION_DEFAULT;
} else {
hnvram_partition = location;
}
}
const char* HMX_UPGRADE_NVRAM_Get_Partition_Path(void)
{
return hnvram_partition;
}
int HMX_UPGRADE_NVRAM_Write(unsigned long offset, const unsigned char * data,
unsigned int size )
{
int ret;
void *buf;
char *rpath;
char *p;
int fd_nvram;
if (libupgrade_verbose) printf("[%s] offset %08lx, size %d, data = %02x\n",
__FUNCTION__, offset, size, data[0] );
buf = malloc(size);
if (!buf) {
perror("malloc");
return -1;
}
rpath = realpath(hnvram_partition, NULL);
if (!rpath) {
perror("realpath");
free(buf);
return -1;
}
fd_nvram = open(rpath, (O_RDWR | O_SYNC));
if (fd_nvram < 0) {
ret = -1;
perror(rpath);
goto out_free;
}
ret = lseek(fd_nvram, offset, SEEK_SET);
if (ret < 0) {
perror("lseek");
goto out_close;
}
ret = read(fd_nvram, buf, size);
if (ret < 0) {
perror("read");
goto out_close;
}
/* Only write to flash if data is different from what is already there. */
if ((unsigned int)ret == size && !memcmp(data, buf, size)) {
ret = 0;
goto out_close;
}
ret = lseek(fd_nvram, offset, SEEK_SET);
if (ret < 0) {
perror("lseek");
goto out_close;
}
ret = write(fd_nvram, data, size);
if (ret < 0) {
perror("write");
goto out_close;
}
/*
* If hnvram is on MMC partition, we cannot flush the partition.
* Instead, we need to flush the entire MMC device.
* For example, GFCH100 hnvram partition is at /dev/mmcblk0p1,
* so we need to flush /dev/mmcblk0.
*/
p = strstr(rpath, "mmcblk");
if (p) {
p = strchr(p + 6, 'p');
if (p) {
*p = '\0';
close(fd_nvram);
fd_nvram = open(rpath, (O_RDWR | O_SYNC));
if (fd_nvram < 0) {
ret = -1;
perror(rpath);
goto out_free;
}
}
}
/*
* BLKFLSBUF will fail if we are writing to a file (-f) instead of a device
* If realpath is under /dev, then we are writing to a device and can proceed
*/
if (strncmp(rpath, "/dev/", 5) == 0) {
/*
* Writes to /dev/mtdblockX are cached indefinitely until the last file
* descriptor is closed. Flush this cache after writing. The user depends on
* data being physically written to flash when this function returns.
* Requires CAP_SYS_ADMIN.
*/
ret = ioctl(fd_nvram, BLKFLSBUF, 0);
if (ret < 0) {
perror("ioctl(hnvram, BLKFLSBUF, 0)");
goto out_close;
}
}
ret = 0;
out_close:
close(fd_nvram);
out_free:
free(rpath);
free(buf);
return ret;
}
int HMX_UPGRADE_NVRAM_Read(unsigned long offset, unsigned char * data,
unsigned int size )
{
char *rpath;
int fd_nvram;
int ret;
if (libupgrade_verbose) printf("[%s] offset %08lx, size %d, data = %02x\n",
__FUNCTION__, offset, size, data[0] );
rpath = realpath(hnvram_partition, NULL);
if (!rpath) {
perror("realpath");
return -1;
}
fd_nvram = open(rpath, (O_RDWR | O_SYNC));
if (fd_nvram < 0) {
ret = -1;
perror(rpath);
goto out_free;
}
ret = lseek(fd_nvram, offset, SEEK_SET);
if (ret < 0) {
perror("lseek");
goto out_close;
}
ret = read(fd_nvram, data, size);
if (ret < 0) {
perror("read");
goto out_close;
}
ret = 0;
out_close:
close(fd_nvram);
out_free:
free(rpath);
return ret;
}
/*@}*/