| /* 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; |
| } |
| |
| |
| /*@}*/ |