mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1057 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			1057 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From d673a23639860e21ef87c4c455018c4b6245868a Mon Sep 17 00:00:00 2001
 | |
| From: John Crispin <john@phrozen.org>
 | |
| Date: Wed, 3 Nov 2021 14:32:11 +0100
 | |
| Subject: [PATCH] tools: add realtek image building code
 | |
| 
 | |
| Signed-off-by: John Crispin <john@phrozen.org>
 | |
| ---
 | |
|  tools/Makefile              |   1 +
 | |
|  tools/rtk-tools/Makefile    |  50 ++++
 | |
|  tools/rtk-tools/src/apmib.h |  77 +++++++
 | |
|  tools/rtk-tools/src/cvimg.c | 443 ++++++++++++++++++++++++++++++++++++
 | |
|  tools/rtk-tools/src/mgbin.c | 429 ++++++++++++++++++++++++++++++++++
 | |
|  5 files changed, 1000 insertions(+)
 | |
|  create mode 100644 tools/rtk-tools/Makefile
 | |
|  create mode 100644 tools/rtk-tools/src/apmib.h
 | |
|  create mode 100644 tools/rtk-tools/src/cvimg.c
 | |
|  create mode 100644 tools/rtk-tools/src/mgbin.c
 | |
| 
 | |
| diff --git a/tools/Makefile b/tools/Makefile
 | |
| index ae3cc5dfd6..a2d49967e7 100644
 | |
| --- a/tools/Makefile
 | |
| +++ b/tools/Makefile
 | |
| @@ -36,6 +36,7 @@ tools-$(CONFIG_TARGET_tegra) += cbootimage cbootimage-configs
 | |
|  tools-$(CONFIG_USES_MINOR) += kernel2minor
 | |
|  tools-$(CONFIG_USE_SPARSE) += sparse
 | |
|  tools-$(CONFIG_USE_LLVM_BUILD) += llvm-bpf
 | |
| +tools-$(CONFIG_TARGET_rtkmipsel) += rtk-tools
 | |
|  
 | |
|  # builddir dependencies
 | |
|  $(curdir)/autoconf/compile := $(curdir)/m4/compile
 | |
| diff --git a/tools/rtk-tools/Makefile b/tools/rtk-tools/Makefile
 | |
| new file mode 100644
 | |
| index 0000000000..a7f79c04b6
 | |
| --- /dev/null
 | |
| +++ b/tools/rtk-tools/Makefile
 | |
| @@ -0,0 +1,50 @@
 | |
| +# 
 | |
| +# Copyright (C) 2006-2010 OpenWrt.org
 | |
| +#
 | |
| +# This is free software, licensed under the GNU General Public License v2.
 | |
| +# See /LICENSE for more information.
 | |
| +#
 | |
| +
 | |
| +include $(TOPDIR)/rules.mk
 | |
| +
 | |
| +PKG_NAME:=rtk-tools
 | |
| +PKG_VERSION:=0.1
 | |
| +
 | |
| +HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME}-$(PKG_VERSION)
 | |
| +HOST_CFLAGS += -DCOMPACT_FILENAME_BUFFER -DHOME_GATEWAY
 | |
| +
 | |
| +include $(INCLUDE_DIR)/host-build.mk
 | |
| +
 | |
| +define Host/Compile
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8196C src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8196c
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8196C src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8196c
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8196E src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8196e
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8196E src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8196e
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl819xd
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl819xd
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl819xdt
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl819xdt
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl89xxd
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8198c
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8954e
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8197f
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl89xxd
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8198c
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8954e
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_819XD src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8197f
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8881A src/cvimg.c -o $(HOST_BUILD_DIR)/cvimg-rtl8881a
 | |
| +	$(HOSTCC) $(HOST_CFLAGS) -DCONFIG_RTL_8881A src/mgbin.c -o $(HOST_BUILD_DIR)/mgbin-rtl8881a
 | |
| +endef
 | |
| +
 | |
| +define Host/Install
 | |
| +	$(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
 | |
| +	$(INSTALL_BIN) $(HOST_BUILD_DIR)/cvimg* $(STAGING_DIR_HOST)/bin/
 | |
| +	$(INSTALL_BIN) $(HOST_BUILD_DIR)/mgbin* $(STAGING_DIR_HOST)/bin/
 | |
| +endef
 | |
| +
 | |
| +define Host/Clean
 | |
| +	rm -f $(STAGING_DIR_HOST)/bin/cvimg*
 | |
| +	rm -f $(STAGING_DIR_HOST)/bin/mgbin*
 | |
| +endef
 | |
| +
 | |
| +$(eval $(call HostBuild))
 | |
| diff --git a/tools/rtk-tools/src/apmib.h b/tools/rtk-tools/src/apmib.h
 | |
| new file mode 100644
 | |
| index 0000000000..bf7257efa1
 | |
| --- /dev/null
 | |
| +++ b/tools/rtk-tools/src/apmib.h
 | |
| @@ -0,0 +1,77 @@
 | |
| +#ifndef __APMIB_H
 | |
| +#define __APMIB_H
 | |
| +
 | |
| +#ifndef WIN32
 | |
| +#define __PACK__        __attribute__ ((packed))
 | |
| +#else
 | |
| +#define __PACK__
 | |
| +#endif
 | |
| +
 | |
| +#define BOOT_HEADER         ((char *)"boot")
 | |
| +
 | |
| +#if defined(CONFIG_RTL_8196B)
 | |
| +#define ROOT_HEADER         ((char *)"r6br")
 | |
| +#elif defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8881A)
 | |
| +#define ROOT_HEADER         ((char *)"r6cr")
 | |
| +#else
 | |
| +#define ROOT_HEADER         ((char *)"root")
 | |
| +#endif //#if defined(CONFIG_RTL_8196B)
 | |
| +
 | |
| +#if defined(CONFIG_RTL_8196B)
 | |
| +#if (defined(HOME_GATEWAY) && defined(VPN_SUPPORT))
 | |
| +#define WEB_HEADER          ((char *)"w6bv")
 | |
| +#elif (defined(HOME_GATEWAY))
 | |
| +#define WEB_HEADER          ((char *)"w6bg")
 | |
| +#else
 | |
| +#define WEB_HEADER          ((char *)"w6ba")
 | |
| +#endif
 | |
| +#elif defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8881A)
 | |
| +#if (defined(HOME_GATEWAY) && defined(VPN_SUPPORT))
 | |
| +#define WEB_HEADER          ((char *)"w6cv")
 | |
| +#elif (defined(HOME_GATEWAY))
 | |
| +#define WEB_HEADER          ((char *)"w6cg")
 | |
| +#else
 | |
| +#define WEB_HEADER          ((char *)"w6ca")
 | |
| +#endif
 | |
| +#else
 | |
| +#if (defined(HOME_GATEWAY) && defined(VPN_SUPPORT))
 | |
| +#define WEB_HEADER          ((char *)"webv")
 | |
| +#elif (defined(HOME_GATEWAY))
 | |
| +#define WEB_HEADER          ((char *)"webg")
 | |
| +#else
 | |
| +#define WEB_HEADER          ((char *)"weba")
 | |
| +#endif
 | |
| +#endif //#if defined(CONFIG_RTL_8196B)
 | |
| +
 | |
| +#if defined(CONFIG_RTL_8196B)
 | |
| +#define FW_HEADER_WITH_ROOT ((char *)"cr6b")
 | |
| +#define FW_HEADER           ((char *)"cs6b")
 | |
| +#elif defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8881A)
 | |
| +#define FW_HEADER_WITH_ROOT ((char *)"cr6c")
 | |
| +#define FW_HEADER           ((char *)"cs6c")
 | |
| +#else
 | |
| +#define FW_HEADER_WITH_ROOT ((char *)"csro")
 | |
| +#define FW_HEADER           ((char *)"csys")
 | |
| +#endif //#if defined(CONFIG_RTL_8196B)
 | |
| +
 | |
| +#define ALL_HEADER          ((char *)"allp")
 | |
| +
 | |
| +#define HW_SETTING_OFFSET			0x6000
 | |
| +#define DEFAULT_SETTING_OFFSET		0x8000
 | |
| +#define CURRENT_SETTING_OFFSET		0xc000
 | |
| +
 | |
| +#define DWORD_SWAP(v) ( (((v&0xff)<<24)&0xff000000) | ((((v>>8)&0xff)<<16)&0xff0000) | \
 | |
| +				                ((((v>>16)&0xff)<<8)&0xff00) | (((v>>24)&0xff)&0xff) )
 | |
| +
 | |
| +#define WORD_SWAP(v) ((unsigned short)(((v>>8)&0xff) | ((v<<8)&0xff00)))
 | |
| +
 | |
| +#define SIGNATURE_LEN           4
 | |
| +
 | |
| +typedef struct img_header {
 | |
| +    unsigned char signature[SIGNATURE_LEN];
 | |
| +    unsigned int startAddr;
 | |
| +    unsigned int burnAddr;
 | |
| +    unsigned int len;
 | |
| +}__PACK__ IMG_HEADER_T, *IMG_HEADER_Tp;
 | |
| +
 | |
| +#endif
 | |
| diff --git a/tools/rtk-tools/src/cvimg.c b/tools/rtk-tools/src/cvimg.c
 | |
| new file mode 100644
 | |
| index 0000000000..de681d803e
 | |
| --- /dev/null
 | |
| +++ b/tools/rtk-tools/src/cvimg.c
 | |
| @@ -0,0 +1,443 @@
 | |
| +/*
 | |
| + *      Tool to convert ELF image to be the AP downloadable binary
 | |
| + *
 | |
| + *      Authors: David Hsu	<davidhsu@realtek.com.tw>
 | |
| + *
 | |
| + *      $Id: cvimg.c,v 1.4 2009/06/12 07:10:44 michael Exp $
 | |
| + *
 | |
| + */
 | |
| +
 | |
| +#include <stdlib.h>
 | |
| +#include <stdio.h>
 | |
| +#include <sys/types.h>
 | |
| +#include <sys/stat.h>
 | |
| +#include <fcntl.h>
 | |
| +#include <unistd.h>
 | |
| +#include <stdlib.h>
 | |
| +#include <string.h>
 | |
| +#undef HOME_GATEWAY
 | |
| +#define HOME_GATEWAY
 | |
| +#define RTK_4K_CHKSUM_FIX
 | |
| +
 | |
| +#include "apmib.h"
 | |
| +
 | |
| +/* 32-bit ELF base types. */
 | |
| +typedef unsigned int	Elf32_Addr;
 | |
| +typedef unsigned short	Elf32_Half;
 | |
| +typedef unsigned int	Elf32_Off;
 | |
| +typedef unsigned int	Elf32_Word;
 | |
| +
 | |
| +#define EI_NIDENT	16
 | |
| +
 | |
| +typedef struct elf32_hdr{
 | |
| +  unsigned char	e_ident[EI_NIDENT];
 | |
| +  Elf32_Half	e_type;
 | |
| +  Elf32_Half	e_machine;
 | |
| +  Elf32_Word	e_version;
 | |
| +  Elf32_Addr	e_entry;  /* Entry point */
 | |
| +  Elf32_Off	e_phoff;
 | |
| +  Elf32_Off	e_shoff;
 | |
| +  Elf32_Word	e_flags;
 | |
| +  Elf32_Half	e_ehsize;
 | |
| +  Elf32_Half	e_phentsize;
 | |
| +  Elf32_Half	e_phnum;
 | |
| +  Elf32_Half	e_shentsize;
 | |
| +  Elf32_Half	e_shnum;
 | |
| +  Elf32_Half	e_shstrndx;
 | |
| +} Elf32_Ehdr;
 | |
| +
 | |
| +#define DEFAULT_START_ADDR	0x80500000
 | |
| +#define DEFAULT_BASE_ADDR	0x80000000
 | |
| +
 | |
| +static unsigned short calculateChecksum(char *buf, int len);
 | |
| +
 | |
| +/////////////////////////////////////////////////////////
 | |
| +static unsigned int calculate_long_checksum(unsigned int *buf, int len)
 | |
| +{
 | |
| +	int i, j;
 | |
| +	unsigned int sum=0, tmp;
 | |
| +
 | |
| +	j = len/4;
 | |
| +
 | |
| +	for (i=0; i<j; buf++, i++) {
 | |
| +		tmp = *buf;
 | |
| +		sum += DWORD_SWAP(tmp);
 | |
| +	}
 | |
| +	return ~sum+1;
 | |
| +}
 | |
| +
 | |
| +unsigned int extractStartAddr(char *filename)
 | |
| +{
 | |
| +    int fh;
 | |
| +    Elf32_Ehdr hdr;
 | |
| +    char *buf;
 | |
| +    
 | |
| +    buf = (char *)&hdr;
 | |
| +    fh = open(filename, O_RDONLY);
 | |
| +	if ( fh == -1 ) {
 | |
| +		printf("Open input file error2!\n");
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	lseek(fh, 0L, SEEK_SET);
 | |
| +	if ( read(fh, buf, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) {
 | |
| +		printf("Read file error2!\n");
 | |
| +		close(fh);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	close(fh);
 | |
| +	
 | |
| +	return(hdr.e_entry);
 | |
| +}
 | |
| +
 | |
| +void printf_usage(void)
 | |
| +{
 | |
| +    printf("Version: 1.1\n");
 | |
| +    printf("Usage: cvimg <option> input-filename output-filename start-addr burn-addr [signature]\n");
 | |
| +    printf("<option>: root|linux|boot|all|vmlinux|vmlinuxhdr|signature\n");
 | |
| +    printf("[signature]: user-specified signature (4 characters)\n");
 | |
| +}
 | |
| +
 | |
| +#ifdef RTK_4K_CHKSUM_FIX
 | |
| +#define JFFS2_ENDMARK_LEN 4
 | |
| +static int rtk_fix_4k_chk(char *inputFile,char *outFile)
 | |
| +{
 | |
| +	struct stat status;
 | |
| +	char *buf;
 | |
| +	int fh, size;
 | |
| +	IMG_HEADER_Tp pHeader;
 | |
| +	unsigned short checksum=0;
 | |
| +	int old_linx_len=0;
 | |
| +	
 | |
| +	if ( stat(inputFile, &status) < 0 ) {
 | |
| +		printf("Can't stat file! [%s]\n", inputFile );
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	
 | |
| +	//decide output size , current , stat+(checksum)	
 | |
| +	size= status.st_size ;	
 | |
| +
 | |
| +	buf = malloc(size);
 | |
| +	if (buf == NULL) {
 | |
| +		printf("Malloc buffer failed!\n");
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	memset(buf, '\0', size);
 | |
| +
 | |
| +	pHeader = (IMG_HEADER_Tp)buf;
 | |
| +	
 | |
| +	fh = open(inputFile, O_RDONLY);
 | |
| +	if ( fh == -1 ) {
 | |
| +		printf("Open input file error!\n");
 | |
| +		free( pHeader );
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	lseek(fh, 0L, SEEK_SET);
 | |
| +
 | |
| +	if ( read(fh, buf, status.st_size) != status.st_size) {
 | |
| +		printf("Read file error!\n");
 | |
| +		close(fh);
 | |
| +		free(pHeader);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	close(fh);
 | |
| +
 | |
| +	//update  len(not include jffs2 endmark)
 | |
| +	old_linx_len = DWORD_SWAP(pHeader->len);
 | |
| +	//printf("old_linx_len = %8x\n !!",old_linx_len);
 | |
| +	pHeader->len = DWORD_SWAP((size-sizeof(IMG_HEADER_T)-JFFS2_ENDMARK_LEN));
 | |
| +
 | |
| +	//erase old chksum
 | |
| +	//printf("old_cksum = %8x\n !!",*((unsigned short *)&buf[sizeof(IMG_HEADER_T)+old_linx_len-sizeof(checksum)]));
 | |
| +	*((unsigned short *)&buf[sizeof(IMG_HEADER_T)+old_linx_len-sizeof(checksum)]) = 0;
 | |
| +
 | |
| +	//add new chksum		
 | |
| +	checksum = WORD_SWAP(calculateChecksum(buf+sizeof(IMG_HEADER_T), (size-sizeof(IMG_HEADER_T)-JFFS2_ENDMARK_LEN)));
 | |
| +	//*((unsigned short *)&buf[status.st_size]) = checksum;
 | |
| +	*((unsigned short *)&buf[sizeof(IMG_HEADER_T)+old_linx_len-sizeof(checksum)]) = checksum;
 | |
| +
 | |
| +	//write to new file	
 | |
| +	fh = open(outFile, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU); //mark_88
 | |
| +	if ( fh == -1 ) {
 | |
| +		printf("Create output file error! [%s]\n", outFile);
 | |
| +		free(pHeader);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	write(fh, pHeader, size);
 | |
| +	close(fh);
 | |
| +	chmod(outFile, DEFFILEMODE);	
 | |
| +	
 | |
| +	printf("Generate 4k alignment image(with jffs2 end mark)successfully, length=%d, checksum=0x%x\n", (int)DWORD_SWAP(pHeader->len), checksum);
 | |
| +
 | |
| +	free(pHeader);
 | |
| +
 | |
| +	return 0;	
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +int main(int argc, char** argv)
 | |
| +{
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +	const char *inFile = NULL, *outFile = NULL;
 | |
| +#else
 | |
| +	char inFile[80]={0}, outFile[80]={0};
 | |
| +#endif
 | |
| +	int fh, size;
 | |
| +	struct stat status;
 | |
| +	char *buf;
 | |
| +	IMG_HEADER_Tp pHeader;
 | |
| +	unsigned int startAddr;
 | |
| +	unsigned int burnAddr;
 | |
| +	unsigned short checksum=0;
 | |
| +	int is_vmlinux = 0;
 | |
| +	int is_vmlinuxhdr = 0;
 | |
| +    int is_signature = 0;
 | |
| +	unsigned int lchecksum, padding_len=0;
 | |
| +	unsigned int start_addr=0;		
 | |
| +
 | |
| +	if (argc == 4 && !strcmp(argv[1], "size_chk")) {
 | |
| +		unsigned int total_size;
 | |
| +
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +		inFile = argv[2];
 | |
| +#else
 | |
| +		sscanf(argv[2], "%s", inFile);
 | |
| +#endif
 | |
| +		sscanf(argv[3], "%x", &startAddr);
 | |
| +		if ( stat(inFile, &status) < 0 ) {
 | |
| +			printf("Can't stat file! [%s]\n", inFile );
 | |
| +			exit(1);
 | |
| +		}
 | |
| +		printf("==============================================\n");
 | |
| +		printf("Summary ==>\n");
 | |
| +		printf("Image loading  addr          :0x%x\n", (int)startAddr);
 | |
| +		printf("Image decompress end addr    :0x%x\n", ((unsigned int)DEFAULT_BASE_ADDR)+(unsigned int)status.st_size);
 | |
| +
 | |
| +		total_size = startAddr - ((unsigned int)DEFAULT_BASE_ADDR);
 | |
| +
 | |
| +		if (status.st_size > (int)total_size)
 | |
| +		{
 | |
| +			printf("Error!!!! : Kernel image decompress will overwirte load image\n");
 | |
| +			exit(1);
 | |
| +		}
 | |
| +		else
 | |
| +			printf("Available size               :0x%08x\n",
 | |
| +					 (unsigned int)(total_size - status.st_size));
 | |
| +
 | |
| +		exit(0);
 | |
| +	}
 | |
| +
 | |
| +#ifdef CONFIG_RTL_FLASH_MAPPING_ENABLE
 | |
| +	if (argc == 3 && !strcmp(argv[1], "flash_size_chk")) {
 | |
| +		unsigned int total_size;
 | |
| +
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +		inFile = argv[2];
 | |
| +#else
 | |
| +		sscanf(argv[2], "%s", inFile);
 | |
| +#endif
 | |
| +		if ( stat(inFile, &status) < 0 ) {
 | |
| +			printf("Can't stat file! [%s]\n", inFile );
 | |
| +			exit(1);
 | |
| +		}
 | |
| +		printf("==============================================\n");
 | |
| +		printf("Summary ==>\n");
 | |
| +		printf("Image flash start  addr          :0x%x\n", (unsigned int)CODE_IMAGE_OFFSET);
 | |
| +		printf("Image flash end addr             :0x%x\n", (unsigned int)CODE_IMAGE_OFFSET+(unsigned int)status.st_size);
 | |
| +
 | |
| +#ifdef CONFIG_RTL_802_1X_CLIENT_SUPPORT
 | |
| +		total_size = ROOT_IMAGE_OFFSET - CODE_IMAGE_OFFSET - CERT_SIZE;	// To reserve CERT_SIZE for 802.1x wlan client mode to store 802.1x certs
 | |
| +#else
 | |
| +		total_size = ROOT_IMAGE_OFFSET - CODE_IMAGE_OFFSET;
 | |
| +#endif
 | |
| +
 | |
| +		if (status.st_size > (int)total_size)
 | |
| +		{
 | |
| +			printf("Error!!!! : Kernel image too big will overwirte rootfs image, cur size(%d), available size(%d).\n",(int)status.st_size, total_size);
 | |
| +			exit(1);
 | |
| +		}
 | |
| +		else
 | |
| +			printf("Available size               :0x%08x\n",
 | |
| +					 (unsigned int)(total_size - status.st_size));
 | |
| +
 | |
| +		exit(0);
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
| +#ifdef RTK_4K_CHKSUM_FIX
 | |
| +	if (argc == 4 && !strcmp(argv[1], "fix_chksum"))
 | |
| +	{
 | |
| +	    rtk_fix_4k_chk(argv[2],argv[3]);
 | |
| +	    return 0;
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
| +	if (argc == 4 && !strcmp(argv[1], "vmlinux"))
 | |
| +		is_vmlinux = 1;
 | |
| +
 | |
| +    if (argc == 5 && !strcmp(argv[1], "vmlinuxhdr")) {
 | |
| +		is_vmlinuxhdr = 1;
 | |
| +		start_addr = extractStartAddr(argv[4]);
 | |
| +	}
 | |
| +
 | |
| +	if (!strcmp(argv[1], "signature")) {
 | |
| +		is_signature = 1;
 | |
| +		if (argc != 7) {
 | |
| +		    printf_usage();
 | |
| +		    exit(1);
 | |
| +		}
 | |
| +	}
 | |
| +		
 | |
| +	// parse input arguments
 | |
| +	if ( argc != 6 && !is_vmlinux && !is_vmlinuxhdr && !is_signature) {
 | |
| +	    printf_usage();
 | |
| +		exit(1);
 | |
| +	}
 | |
| +
 | |
| +
 | |
| +
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +	inFile = argv[2];
 | |
| +	outFile = argv[3];
 | |
| +#else
 | |
| +	sscanf(argv[2], "%s", inFile);
 | |
| +	sscanf(argv[3], "%s", outFile);
 | |
| +#endif
 | |
| +
 | |
| +	if ((!is_vmlinux) && (!is_vmlinuxhdr)) {
 | |
| +		sscanf(argv[4], "%x", &startAddr);
 | |
| +		sscanf(argv[5], "%x", &burnAddr);
 | |
| +	}
 | |
| +	// check input file and allocate buffer
 | |
| +	if ( stat(inFile, &status) < 0 ) {
 | |
| +		printf("Can't stat file! [%s]\n", inFile );
 | |
| +		exit(1);
 | |
| +	}
 | |
| +
 | |
| +	if (is_vmlinuxhdr) {
 | |
| +		size = status.st_size + sizeof(padding_len) + sizeof(lchecksum) + sizeof(start_addr);
 | |
| +		padding_len = 4 - (size%4);	
 | |
| +		size += padding_len;
 | |
| +	}
 | |
| +	else if (!is_vmlinux) {
 | |
| +		size = status.st_size + sizeof(IMG_HEADER_T) + sizeof(checksum);
 | |
| +		if (size%2)
 | |
| +			size++; // pad
 | |
| +	}
 | |
| +	else {
 | |
| +		size = status.st_size + sizeof(padding_len) + sizeof(lchecksum);
 | |
| +		padding_len = 4 - (size%4);	
 | |
| +		size += padding_len;
 | |
| +	}
 | |
| +
 | |
| +	buf = malloc(size);
 | |
| +	if (buf == NULL) {
 | |
| +		printf("Malloc buffer failed!\n");
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	memset(buf, '\0', size);
 | |
| +	pHeader = (IMG_HEADER_Tp)buf;
 | |
| +
 | |
| +    if (is_vmlinuxhdr)
 | |
| +        buf += 8; // skip padding-length field and start-address field
 | |
| +	else if (!is_vmlinux)
 | |
| +		buf += sizeof(IMG_HEADER_T);
 | |
| +	else
 | |
| +		buf += 4; // skip padding-length field
 | |
| +
 | |
| +	// Read data and generate header
 | |
| +	fh = open(inFile, O_RDONLY);
 | |
| +	if ( fh == -1 ) {
 | |
| +		printf("Open input file error!\n");
 | |
| +		free( pHeader );
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	lseek(fh, 0L, SEEK_SET);
 | |
| +	if ( read(fh, buf, status.st_size) != status.st_size) {
 | |
| +		printf("Read file error!\n");
 | |
| +		close(fh);
 | |
| +		free(pHeader);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	close(fh);
 | |
| +
 | |
| +	if (is_vmlinuxhdr) {
 | |
| +		*((unsigned int *)pHeader) = DWORD_SWAP(padding_len);
 | |
| +		*((unsigned int *)((char *)pHeader+4)) = start_addr;
 | |
| +		lchecksum = DWORD_SWAP(calculate_long_checksum((unsigned int *)buf, size-12));
 | |
| +		memcpy(&buf[size-12], &lchecksum, 4);		
 | |
| +	}
 | |
| +	else if (!is_vmlinux) {
 | |
| +		if( !strcmp("root", argv[1]))
 | |
| +			memcpy(pHeader->signature, ROOT_HEADER, SIGNATURE_LEN);
 | |
| +		else if ( !strcmp("boot", argv[1]))
 | |
| +			memcpy(pHeader->signature, BOOT_HEADER, SIGNATURE_LEN);
 | |
| +		else if ( !strcmp("linux", argv[1]))
 | |
| +			memcpy(pHeader->signature, FW_HEADER, SIGNATURE_LEN);
 | |
| +		else if ( !strcmp("linux-ro", argv[1]))
 | |
| +			memcpy(pHeader->signature, FW_HEADER_WITH_ROOT, SIGNATURE_LEN);
 | |
| +		else if ( !strcmp("signature", argv[1]))
 | |
| +			memcpy(pHeader->signature, argv[6], SIGNATURE_LEN);
 | |
| +		else{
 | |
| +			printf("not supported signature\n");
 | |
| +			exit(1);
 | |
| +		}
 | |
| +		pHeader->len = DWORD_SWAP((size-sizeof(IMG_HEADER_T)));
 | |
| +		pHeader->startAddr = DWORD_SWAP(startAddr);
 | |
| +		pHeader->burnAddr = DWORD_SWAP(burnAddr);
 | |
| +
 | |
| +		if( !strcmp("root", argv[1])) {
 | |
| +			#define SIZE_OF_SQFS_SUPER_BLOCK 640		
 | |
| +			unsigned int fs_len;
 | |
| +			fs_len = DWORD_SWAP((size-sizeof(IMG_HEADER_T) - sizeof(checksum)- SIZE_OF_SQFS_SUPER_BLOCK));
 | |
| +			memcpy(buf + 8, &fs_len, 4);	
 | |
| +		}		
 | |
| +		
 | |
| +		checksum = WORD_SWAP(calculateChecksum(buf, status.st_size));
 | |
| +		*((unsigned short *)&buf[size-sizeof(IMG_HEADER_T)-sizeof(checksum)]) = checksum;
 | |
| +	}
 | |
| +	else { // is_vmlinux=1
 | |
| +		*((unsigned int *)pHeader) = DWORD_SWAP(padding_len);
 | |
| +		lchecksum = DWORD_SWAP(calculate_long_checksum((unsigned int *)buf, size-8));
 | |
| +		memcpy(&buf[size-8], &lchecksum, 4);		
 | |
| +	}
 | |
| +	
 | |
| +	// Write image to output file
 | |
| +	fh = open(outFile, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU); //mark_88
 | |
| +	if ( fh == -1 ) {
 | |
| +		printf("Create output file error! [%s]\n", outFile);
 | |
| +		free(pHeader);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +	write(fh, pHeader, size);
 | |
| +	close(fh);
 | |
| +	chmod(outFile, DEFFILEMODE);
 | |
| +	
 | |
| +	if (is_vmlinuxhdr)
 | |
| +	    printf("Generate image successfully, length=%d, checksum=0x%x, padding=%d, start address=0x%08x\n", size-12-padding_len, lchecksum, padding_len, DWORD_SWAP(start_addr));
 | |
| +	else if (!is_vmlinux)
 | |
| +		printf("Generate image successfully, length=%d, checksum=0x%x\n", (int)DWORD_SWAP(pHeader->len), checksum);
 | |
| +	else
 | |
| +		printf("Generate image successfully, length=%d, checksum=0x%x, padding=%d\n", size-8-padding_len, lchecksum, padding_len);
 | |
| +
 | |
| +	free(pHeader);
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static unsigned short calculateChecksum(char *buf, int len)
 | |
| +{
 | |
| +	int i, j;
 | |
| +	unsigned short sum=0, tmp;
 | |
| +
 | |
| +	j = (len/2)*2;
 | |
| +
 | |
| +	for (i=0; i<j; i+=2) {
 | |
| +		tmp = *((unsigned short *)(buf + i));
 | |
| +		sum += WORD_SWAP(tmp);
 | |
| +	}
 | |
| +
 | |
| +	if ( len % 2 ) {
 | |
| +		tmp = buf[len-1];
 | |
| +		sum += WORD_SWAP(tmp);
 | |
| +	}
 | |
| +	return ~sum+1;
 | |
| +}
 | |
| diff --git a/tools/rtk-tools/src/mgbin.c b/tools/rtk-tools/src/mgbin.c
 | |
| new file mode 100644
 | |
| index 0000000000..411c86aaae
 | |
| --- /dev/null
 | |
| +++ b/tools/rtk-tools/src/mgbin.c
 | |
| @@ -0,0 +1,429 @@
 | |
| +/*
 | |
| + *      utility to merge all binary into one image
 | |
| + *
 | |
| + *      Authors: David Hsu	<davidhsu@realtek.com.tw>
 | |
| + *
 | |
| + *      $Id: mgbin.c,v 1.7 2008/11/25 15:09:22 bradhuang Exp $
 | |
| + *
 | |
| + */
 | |
| +#include <string.h>
 | |
| +#include <stdio.h>
 | |
| +#include <sys/types.h>
 | |
| +#include <sys/stat.h>
 | |
| +#include <fcntl.h>
 | |
| +#include <stdlib.h>
 | |
| +#include <sys/types.h>
 | |
| +#ifdef WIN32
 | |
| +	#include <io.h>
 | |
| +#else
 | |
| +	#include <unistd.h>
 | |
| +#endif
 | |
| +#define __mips__
 | |
| +
 | |
| +#include "apmib.h"
 | |
| +
 | |
| +//#define DEBUG_PRINT	printf
 | |
| +#define DEBUG_PRINT(...)  do {} while(0)
 | |
| +
 | |
| +/////////////////////////////////////////////////////////////////////////////
 | |
| +/* Input file type */
 | |
| +typedef enum { BOOT_CODE=0, CONFIG, WEB_PAGES, SYS, ROOT, ALL, INVALID_FILE=-1 } TYPE_T;
 | |
| +
 | |
| +typedef struct _sector {
 | |
| +	TYPE_T type;
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +	const char *filename;
 | |
| +#else
 | |
| +	char filename[80];
 | |
| +#endif
 | |
| +	unsigned long offset;
 | |
| +	unsigned long size;
 | |
| +	int with_header;
 | |
| +} SECTOR_T;
 | |
| +
 | |
| +/////////////////////////////////////////////////////////////////////////////
 | |
| +static char *copyright="Copyright (c) Realtek Semiconductor Corp., 2007. All Rights Reserved.";
 | |
| +static char *version="1.0";
 | |
| +
 | |
| +static SECTOR_T sector[ROOT+1];
 | |
| +static int no_hw_config=0;
 | |
| +
 | |
| +#define BYTE_SWAP(word) (((word >> 8) &0xff) | ((((unsigned char)word)<<8)&0xff00) )
 | |
| +
 | |
| +/////////////////////////////////////////////////////////////////////////////
 | |
| +static TYPE_T checkInputFile(char *filename, int *pWith_header)
 | |
| +{
 | |
| +	int fh;
 | |
| +	char signature[6];
 | |
| +
 | |
| +#ifdef WIN32
 | |
| +	fh = open(filename, O_RDONLY|O_BINARY);
 | |
| +#else
 | |
| +	fh = open(filename, O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 | |
| +#endif
 | |
| +	if ( fh == -1 )
 | |
| +		return INVALID_FILE;
 | |
| +
 | |
| +	lseek(fh, 0, SEEK_SET);
 | |
| +
 | |
| +	if ( read(fh, signature, sizeof(signature)) != sizeof(signature)) {
 | |
| +		close(fh);
 | |
| +		return INVALID_FILE;
 | |
| +	}
 | |
| +	close(fh);
 | |
| +
 | |
| +	*pWith_header = 1;
 | |
| +	if ( !memcmp(signature, BOOT_HEADER, 4))
 | |
| +		return BOOT_CODE;
 | |
| +	else if ( !memcmp(signature, WEB_HEADER, 3) )
 | |
| +		return WEB_PAGES;
 | |
| +
 | |
| +	else if ( !memcmp(signature, FW_HEADER, 4) || 
 | |
| +			!memcmp(signature, FW_HEADER_WITH_ROOT, 4))
 | |
| +		return SYS;
 | |
| +
 | |
| +	else if ( !memcmp(signature, ROOT_HEADER, 4) )
 | |
| +		return ROOT;
 | |
| +	
 | |
| +	else if ( !memcmp(signature, "h", 1) || !memcmp(signature, "COMPHS", 6))
 | |
| +		return CONFIG;
 | |
| +	else if ( !memcmp(signature, "6G", 2) || !memcmp(signature, "6A", 2) || !memcmp(signature, "6g", 2) || !memcmp(signature, "6a", 2) || !memcmp(signature, "COMPDS", 6)) {
 | |
| +		no_hw_config = 1;
 | |
| +		return CONFIG;	
 | |
| +	}
 | |
| +	else if ( !memcmp(signature, "\x0b\xf0\x00\x02", 4)) {
 | |
| +		*pWith_header = 0;
 | |
| +		return BOOT_CODE;
 | |
| +	}
 | |
| +	return INVALID_FILE;
 | |
| +}
 | |
| +
 | |
| +////////////////////////////////////////////////////////////////////////////////
 | |
| +static void showHelp(void)
 | |
| +{
 | |
| +	printf("\nRTL865x utility to merge binary.\n");
 | |
| +	printf("%s Ver %s.\n\n", copyright, version);
 | |
| +	printf("usage: mgbin [-s] [-c] [-a] -o outputfile bootcode config webpages linux root\n");
 | |
| +	printf("	-s : do byte swap\n");
 | |
| +	printf("	-c : cascade. May use this option to merge image for web upload\n");
 | |
| +	printf("	-a : add all tag in header\n");
 | |
| +	
 | |
| +}
 | |
| +
 | |
| +
 | |
| +////////////////////////////////////////////////////////////////////////////////
 | |
| +static void do_byteswap(unsigned char *buf, int len)
 | |
| +{
 | |
| +	unsigned short wVal, *ptr;
 | |
| +	int i=0;
 | |
| +
 | |
| +	while (len > 0) {
 | |
| +		len -= 2;
 | |
| +		ptr = (unsigned short *)&buf[2*i];
 | |
| +		wVal = *ptr;
 | |
| +		*ptr = BYTE_SWAP( wVal );
 | |
| +		i++;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static unsigned short calculateChecksum(char *buf, int len, unsigned short oldv)
 | |
| +{
 | |
| +	int i, j;
 | |
| +	unsigned short sum=oldv, tmp;
 | |
| +
 | |
| +	j = (len/2)*2;
 | |
| +
 | |
| +	for (i=0; i<j; i+=2) {
 | |
| +		tmp = *((unsigned short *)(buf + i));
 | |
| +		sum += WORD_SWAP(tmp);
 | |
| +	}
 | |
| +
 | |
| +	if ( len % 2 ) {
 | |
| +		tmp = buf[len-1];
 | |
| +		sum += WORD_SWAP(tmp);
 | |
| +	}
 | |
| +	return sum;
 | |
| +}
 | |
| +
 | |
| +////////////////////////////////////////////////////////////////////////////////
 | |
| +int main(int argc, char** argv)
 | |
| +{
 | |
| +	int argNum=1;
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +	const char *outFile = NULL;
 | |
| +#else
 | |
| +	char outFile[80]={0};
 | |
| +#endif
 | |
| +	TYPE_T type;
 | |
| +	int mask=0, fh_out, fh_in, len, i, total=0;
 | |
| +	unsigned char *buf, *buf1;
 | |
| +	struct stat sbuf;
 | |
| +	int byteswap=0, cascade=0, last_idx=-1, is_all=0;
 | |
| +	int offset=0, with_header;
 | |
| +	IMG_HEADER_Tp pHeader;
 | |
| +	unsigned long burnAddr=0;
 | |
| +	IMG_HEADER_T allHeader;
 | |
| +	unsigned short checksum=0;
 | |
| +		
 | |
| +	memset(§or, 0, sizeof(sector));
 | |
| +
 | |
| +	while (argNum < argc) {
 | |
| +		if ( !strcmp(argv[argNum], "-o") ) {
 | |
| +			if (++argNum >= argc)
 | |
| +				break;
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +			outFile = argv[argNum];
 | |
| +#else
 | |
| +			sscanf(argv[argNum], "%s", outFile);
 | |
| +#endif
 | |
| +		}
 | |
| +		else if ( !strcmp(argv[argNum], "-s") ) {
 | |
| +			byteswap = 1;
 | |
| +		}
 | |
| +		else if ( !strcmp(argv[argNum], "-c") ) {
 | |
| +			cascade = 1;
 | |
| +		}
 | |
| +		else if ( !strcmp(argv[argNum], "-a") ) {
 | |
| +			is_all = 1;
 | |
| +			memset(&allHeader, '\0', sizeof(IMG_HEADER_T));
 | |
| +			memcpy(allHeader.signature, ALL_HEADER, SIGNATURE_LEN);			
 | |
| +		}
 | |
| +#if 0
 | |
| +		else if ( !strcmp(argv[argNum], "-a2") ) {
 | |
| +			is_all = 1;
 | |
| +			memset(&allHeader, '\0', sizeof(IMG_HEADER_T));
 | |
| +			memcpy(allHeader.signature, ALL_HEADER2, SIGNATURE_LEN);			
 | |
| +		}						
 | |
| +#endif
 | |
| +		else {
 | |
| +			if (is_all) {
 | |
| +				if ((argNum+1) < argc) {
 | |
| +					printf("argument error, only input file could be specified!\n");
 | |
| +					return -1;					
 | |
| +				}				
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +				sector[0].filename = argv[argNum];
 | |
| +#else
 | |
| +				strcpy(sector[0].filename,argv[argNum]);				
 | |
| +#endif
 | |
| +				sector[0].type=ALL;
 | |
| +				sector[0].with_header=0;
 | |
| +				mask |= (1 << ALL);
 | |
| +		}
 | |
| +		else {
 | |
| +			type=checkInputFile(argv[argNum], &with_header);
 | |
| +			DEBUG_PRINT("filename=%s, type=%d\n", argv[argNum], type);			
 | |
| +			if (type == INVALID_FILE) {
 | |
| +				printf("\nInvalid input file %s!!\n", argv[argNum]);
 | |
| +				showHelp();
 | |
| +				exit(1);
 | |
| +			}
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +			sector[type].filename = argv[argNum];
 | |
| +#else
 | |
| +			strcpy(sector[type].filename, argv[argNum]);
 | |
| +#endif
 | |
| +			sector[type].with_header = with_header;
 | |
| +			sector[type].type = type;
 | |
| +			mask |= (1 << type);
 | |
| +			}
 | |
| +		}
 | |
| +		argNum++;
 | |
| +	}
 | |
| +
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +	if( outFile == NULL )
 | |
| +#else
 | |
| +	if (!outFile[0]) 
 | |
| +#endif
 | |
| +	{
 | |
| +		printf("No output file specified!\n");
 | |
| +		showHelp();
 | |
| +		exit(1);
 | |
| +	}
 | |
| +
 | |
| +	if (mask == 0) {
 | |
| +		printf("No valid input image found!\n");
 | |
| +		exit(1);
 | |
| +	}
 | |
| +
 | |
| +	// Create output file
 | |
| +#ifdef WIN32
 | |
| +	_chmod(outFile, S_IREAD|S_IWRITE);
 | |
| +	fh_out = open(outFile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY);
 | |
| +#else
 | |
| +	chmod(outFile, S_IREAD|S_IWRITE);
 | |
| +	fh_out = open(outFile, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU);//mark_88
 | |
| +#endif
 | |
| +	if (fh_out == -1) {
 | |
| +		printf("Create output file %s error!\n", outFile);
 | |
| +		exit(1);
 | |
| +	}
 | |
| +
 | |
| +	if (is_all) {
 | |
| +		write(fh_out, &allHeader, sizeof(allHeader));
 | |
| +		total += sizeof(allHeader);
 | |
| +		printf("\nGenerate ");
 | |
| +	}
 | |
| +	else
 | |
| +	printf("\nMerge ");
 | |
| +
 | |
| +	for (i=BOOT_CODE; i<=ROOT ; i++) {
 | |
| +#ifdef COMPACT_FILENAME_BUFFER
 | |
| +		if (sector[i].filename) 
 | |
| +#else
 | |
| +		if (sector[i].filename[0]) 
 | |
| +#endif
 | |
| +		{
 | |
| +			if ( stat(sector[i].filename, &sbuf) != 0 ) {
 | |
| +				printf("Stat file %s error!\n", sector[i].filename);
 | |
| +				exit(1);
 | |
| +			}
 | |
| +			buf = malloc(sbuf.st_size+1);
 | |
| +			if (buf == NULL) {
 | |
| +				printf("allocate buffer failed %d!\n", (int)sbuf.st_size);
 | |
| +				exit(1);
 | |
| +			}
 | |
| +#ifdef WIN32
 | |
| +			fh_in = open(sector[i].filename, O_RDONLY|O_BINARY);
 | |
| +#else
 | |
| +			fh_in = open(sector[i].filename, O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 | |
| +#endif
 | |
| +			if (fh_in < 0) {
 | |
| +				printf("Open file %s error!\n", sector[i].filename);
 | |
| +				close(fh_out);
 | |
| +				exit(1);
 | |
| +			}
 | |
| +
 | |
| +			switch(sector[i].type) {
 | |
| +			case BOOT_CODE:
 | |
| +				printf("BOOT-CODE ");
 | |
| +				break;
 | |
| +			case CONFIG:
 | |
| +				printf("CONFIG-DATA(%s) ", (no_hw_config ? "no-hw" : "all"));
 | |
| +				break;
 | |
| +			case WEB_PAGES:
 | |
| +				printf("WEB-PAGES ");
 | |
| +				break;
 | |
| +			case SYS:
 | |
| +				printf("LINUX ");
 | |
| +				break;
 | |
| +			case ROOT:
 | |
| +				printf("ROOT ");
 | |
| +				break;
 | |
| +			case ALL:
 | |
| +				printf("ALL ");
 | |
| +				break;				
 | |
| +			case INVALID_FILE:
 | |
| +				break;
 | |
| +			}
 | |
| +
 | |
| +			if (read(fh_in, buf, sbuf.st_size) != sbuf.st_size) {
 | |
| +				printf("Read file %s error!\n", sector[i].filename);
 | |
| +				close(fh_in);
 | |
| +				close(fh_out);
 | |
| +				free(buf);
 | |
| +				exit(1);
 | |
| +			}
 | |
| +
 | |
| +			if (is_all) 
 | |
| +				checksum = calculateChecksum((char *)buf, sbuf.st_size, checksum);			
 | |
| +			else {
 | |
| +			if (sector[i].with_header) {
 | |
| +				if (sector[i].type == CONFIG) {
 | |
| +					if (no_hw_config == 0)
 | |
| +						burnAddr = HW_SETTING_OFFSET;
 | |
| +					else
 | |
| +						burnAddr = DEFAULT_SETTING_OFFSET;
 | |
| +				}
 | |
| +				else {
 | |
| +					pHeader = (IMG_HEADER_Tp)buf;
 | |
| +					burnAddr = DWORD_SWAP(pHeader->burnAddr);
 | |
| +				}
 | |
| +			}
 | |
| +			else 
 | |
| +				burnAddr = 0;			
 | |
| +
 | |
| +			if (byteswap) {
 | |
| +				if (sbuf.st_size % 2) {
 | |
| +					buf[sbuf.st_size] = '\0';
 | |
| +					sbuf.st_size++;
 | |
| +				}
 | |
| +				do_byteswap(buf, sbuf.st_size);
 | |
| +			}
 | |
| +			
 | |
| +			// try to append 0 if necessary
 | |
| +			if (!cascade && last_idx!=-1 && sector[i].with_header) {
 | |
| +				if ((sector[last_idx].offset+sector[last_idx].size) < burnAddr) {
 | |
| +					len = burnAddr - (sector[last_idx].offset+sector[last_idx].size);
 | |
| +					buf1 = calloc(len, 1);
 | |
| +					if (buf1 == NULL) {
 | |
| +						printf("allocate buffer failed %d!\n", len);
 | |
| +						exit(1);
 | |
| +					}
 | |
| +					write(fh_out, buf1, len);	// pad 0
 | |
| +					
 | |
| +					free(buf1);
 | |
| +					total += len;
 | |
| +//				printf("pad size=%d, last_idx=%d, burnAddr=%d\n", len, last_idx, burnAddr);			
 | |
| +				}				
 | |
| +			}			
 | |
| +
 | |
| +			// skip header if necessary
 | |
| +			if (!cascade && sector[i].with_header &&
 | |
| +					((sector[i].type == ROOT) || (sector[i].type == BOOT_CODE))) {
 | |
| +				offset = sizeof(IMG_HEADER_T);
 | |
| +//				sbuf.st_size -= sizeof(IMG_HEADER_T);
 | |
| +			}
 | |
| +			else
 | |
| +				offset = 0;
 | |
| +			}			
 | |
| +
 | |
| +//		printf("write offset=%d, size=%d\n", offset, 	sbuf.st_size);
 | |
| +			if ( write(fh_out, buf + offset , sbuf.st_size-offset) != sbuf.st_size-offset) {
 | |
| +				printf("Write output file %s error!\n", outFile);
 | |
| +				close(fh_in);
 | |
| +				close(fh_out);
 | |
| +				free(buf);
 | |
| +				exit(1);
 | |
| +			}
 | |
| +			close(fh_in);
 | |
| +			if (burnAddr > 0)
 | |
| +				sector[i].offset = burnAddr;
 | |
| +			else
 | |
| +				sector[i].offset = total;
 | |
| +			sector[i].size = sbuf.st_size-offset;
 | |
| +
 | |
| +//	printf("section[%d], offset=%d, size=%d\n", i, sector[i].offset, sector[i].size);
 | |
| +			
 | |
| +			total += sbuf.st_size;
 | |
| +			free(buf);
 | |
| +			last_idx = i;
 | |
| +			if (is_all)
 | |
| +				break;			
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
| +	if (is_all) {
 | |
| +		allHeader.len = DWORD_SWAP((total+2));
 | |
| +		checksum = calculateChecksum((char *)&allHeader, sizeof(allHeader), checksum);		
 | |
| +		checksum = WORD_SWAP((~checksum+1));
 | |
| +		write(fh_out, &checksum, 2);
 | |
| +		lseek(fh_out, 0, SEEK_SET);
 | |
| +		allHeader.len = DWORD_SWAP((total+2));
 | |
| +//		allHeader.startAddr = DWORD_SWAP(image_num);
 | |
| +		write(fh_out, &allHeader, sizeof(allHeader));		
 | |
| +		total += (2 + sizeof(allHeader));
 | |
| +	}
 | |
| +	close(fh_out);
 | |
| +
 | |
| +#ifdef WIN32
 | |
| +	_chmod(outFile, S_IREAD);
 | |
| +#else
 | |
| +	chmod(outFile, DEFFILEMODE);
 | |
| +#endif
 | |
| +
 | |
| +	printf("=> %s ok, size=%d.\n", outFile, total);
 | |
| +	exit(0);
 | |
| +}
 | |
| +
 | |
| -- 
 | |
| 2.25.1
 | |
| 
 | 
