⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auto_update.c

📁 U-BOOT,著名的Bootloader程序
💻 C
字号:
/* * (C) Copyright 2003-2004 * Gary Jennejohn, DENX Software Engineering, gj@denx.de. * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <command.h>#include <image.h>#include <asm/byteorder.h>#if defined(CFG_NAND_LEGACY)#include <linux/mtd/nand_legacy.h>#endif#include <fat.h>#include <part.h>#include "auto_update.h"#ifdef CONFIG_AUTO_UPDATE#if !defined(CONFIG_CMD_FAT)#error "must define CONFIG_CMD_FAT"#endifextern au_image_t au_image[];extern int N_AU_IMAGES;/* where to load files into memory */#define LOAD_ADDR ((unsigned char *)0x100000)#define MAX_LOADSZ 0x1c00000/* externals */extern int fat_register_device(block_dev_desc_t *, int);extern int file_fat_detectfs(void);extern long file_fat_read(const char *, void *, unsigned long);long do_fat_read (const char *filename, void *buffer,		  unsigned long maxsize, int dols);extern int flash_sect_erase(ulong, ulong);extern int flash_sect_protect (int, ulong, ulong);extern int flash_write (char *, ulong, ulong);#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)/* references to names in cmd_nand.c */#define NANDRW_READ	0x01#define NANDRW_WRITE	0x00#define NANDRW_JFFS2	0x02#define NANDRW_JFFS2_SKIP	0x04extern struct nand_chip nand_dev_desc[];extern int nand_legacy_rw(struct nand_chip* nand, int cmd,			  size_t start, size_t len,			  size_t * retlen, u_char * buf);extern int nand_legacy_erase(struct nand_chip* nand, size_t ofs,			     size_t len, int clean);#endifextern block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];int au_check_cksum_valid(int i, long nbytes){	image_header_t *hdr;	hdr = (image_header_t *)LOAD_ADDR;#if defined(CONFIG_FIT)	if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {		puts ("Non legacy image format not supported\n");		return -1;	}#endif	if ((au_image[i].type == AU_FIRMWARE) &&	    (au_image[i].size != image_get_data_size (hdr))) {		printf ("Image %s has wrong size\n", au_image[i].name);		return -1;	}	if (nbytes != (image_get_image_size (hdr))) {		printf ("Image %s bad total SIZE\n", au_image[i].name);		return -1;	}	/* check the data CRC */	if (!image_check_dcrc (hdr)) {		printf ("Image %s bad data checksum\n", au_image[i].name);		return -1;	}	return 0;}int au_check_header_valid(int i, long nbytes){	image_header_t *hdr;	unsigned long checksum;	hdr = (image_header_t *)LOAD_ADDR;#if defined(CONFIG_FIT)	if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {		puts ("Non legacy image format not supported\n");		return -1;	}#endif	/* check the easy ones first */	if (nbytes < image_get_header_size ()) {		printf ("Image %s bad header SIZE\n", au_image[i].name);		return -1;	}	if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) {		printf ("Image %s bad MAGIC or ARCH\n", au_image[i].name);		return -1;	}	if (!image_check_hcrc (hdr)) {		printf ("Image %s bad header checksum\n", au_image[i].name);		return -1;	}	/* check the type - could do this all in one gigantic if() */	if (((au_image[i].type & AU_TYPEMASK) == AU_FIRMWARE) &&	    !image_check_type (hdr, IH_TYPE_FIRMWARE)) {		printf ("Image %s wrong type\n", au_image[i].name);		return -1;	}	if (((au_image[i].type & AU_TYPEMASK) == AU_SCRIPT) &&	    !image_check_type (hdr, IH_TYPE_SCRIPT)) {		printf ("Image %s wrong type\n", au_image[i].name);		return -1;	}	/* recycle checksum */	checksum = image_get_data_size (hdr);	return 0;}int au_do_update(int i, long sz){	image_header_t *hdr;	char *addr;	long start, end;	int off, rc;	uint nbytes;	int k;#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)	int total;#endif	hdr = (image_header_t *)LOAD_ADDR;#if defined(CONFIG_FIT)	if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {		puts ("Non legacy image format not supported\n");		return -1;	}#endif	switch (au_image[i].type & AU_TYPEMASK) {	case AU_SCRIPT:		printf("Executing script %s\n", au_image[i].name);		/* execute a script */		if (image_check_type (hdr, IH_TYPE_SCRIPT)) {			addr = (char *)((char *)hdr + image_get_header_size ());			/* stick a NULL at the end of the script, otherwise */			/* parse_string_outer() runs off the end. */			addr[image_get_data_size (hdr)] = 0;			addr += 8;			/*			 * Replace cr/lf with ;			 */			k = 0;			while (addr[k] != 0) {				if ((addr[k] == 10) || (addr[k] == 13)) {					addr[k] = ';';				}				k++;			}			run_command(addr, 0);			return 0;		}		break;	case AU_FIRMWARE:	case AU_NOR:	case AU_NAND:		start = au_image[i].start;		end = au_image[i].start + au_image[i].size - 1;		/*		 * do not update firmware when image is already in flash.		 */		if (au_image[i].type == AU_FIRMWARE) {			char *orig = (char*)start;			char *new  = (char *)((char *)hdr +					      image_get_header_size ());			nbytes = image_get_data_size (hdr);			while (--nbytes) {				if (*orig++ != *new++) {					break;				}			}			if (!nbytes) {				printf ("Skipping firmware update - "					"images are identical\n");				break;			}		}		/* unprotect the address range */		if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) ||		    (au_image[i].type == AU_FIRMWARE)) {			flash_sect_protect (0, start, end);		}		/*		 * erase the address range.		 */		if (au_image[i].type != AU_NAND) {			printf ("Updating NOR FLASH with image %s\n",				au_image[i].name);			debug ("flash_sect_erase(%lx, %lx);\n", start, end);			flash_sect_erase (start, end);		} else {#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)			printf ("Updating NAND FLASH with image %s\n",				au_image[i].name);			debug ("nand_legacy_erase(%lx, %lx);\n", start, end);			rc = nand_legacy_erase (nand_dev_desc, start,						end - start + 1, 0);			debug ("nand_legacy_erase returned %x\n", rc);#endif		}		udelay(10000);		/* strip the header - except for the kernel and ramdisk */		if (au_image[i].type != AU_FIRMWARE) {			addr = (char *)hdr;			off = image_get_header_size ();			nbytes = image_get_image_size (hdr);		} else {			addr = (char *)((char *)hdr + image_get_header_size ());			off = 0;			nbytes = image_get_data_size (hdr);		}		/*		 * copy the data from RAM to FLASH		 */		if (au_image[i].type != AU_NAND) {			debug ("flash_write(%p, %lx, %x)\n",			       addr, start, nbytes);			rc = flash_write ((char *)addr, start,					  (nbytes + 1) & ~1);		} else {#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)			debug ("nand_legacy_rw(%p, %lx, %x)\n",			       addr, start, nbytes);			rc = nand_legacy_rw (nand_dev_desc,					     NANDRW_WRITE | NANDRW_JFFS2,					     start, nbytes, (size_t *)&total,					     (uchar *)addr);			debug ("nand_legacy_rw: ret=%x total=%d nbytes=%d\n",			       rc, total, nbytes);#else			rc = -1;#endif		}		if (rc != 0) {			printf ("Flashing failed due to error %d\n", rc);			return -1;		}		/*		 * check the dcrc of the copy		 */		if (au_image[i].type != AU_NAND) {			rc = crc32 (0, (uchar *)(start + off),				    image_get_data_size (hdr));		} else {#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)			rc = nand_legacy_rw (nand_dev_desc,					     NANDRW_READ | NANDRW_JFFS2 |					     NANDRW_JFFS2_SKIP,					     start, nbytes, (size_t *)&total,					     (uchar *)addr);			rc = crc32 (0, (uchar *)(addr + off),				    image_get_data_size (hdr));#endif		}		if (rc != image_get_dcrc (hdr)) {			printf ("Image %s Bad Data Checksum After COPY\n",				au_image[i].name);			return -1;		}		/* protect the address range */		/* this assumes that ONLY the firmware is protected! */		if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) ||		    (au_image[i].type == AU_FIRMWARE)) {			flash_sect_protect (1, start, end);		}		break;	default:		printf("Wrong image type selected!\n");	}	return 0;}static void process_macros (const char *input, char *output){	char c, prev;	const char *varname_start = NULL;	int inputcnt  = strlen (input);	int outputcnt = CFG_CBSIZE;	int state = 0;	/* 0 = waiting for '$'	*/			/* 1 = waiting for '(' or '{' */			/* 2 = waiting for ')' or '}' */			/* 3 = waiting for '''  */#ifdef DEBUG_PARSER	char *output_start = output;	printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n",		strlen(input), input);#endif	prev = '\0';			/* previous character */	while (inputcnt && outputcnt) {	    c = *input++;	    inputcnt--;	    if (state != 3) {	    /* remove one level of escape characters */	    if ((c == '\\') && (prev != '\\')) {		if (inputcnt-- == 0)			break;		prev = c;		c = *input++;	    }	    }	    switch (state) {	    case 0:			/* Waiting for (unescaped) $ */		if ((c == '\'') && (prev != '\\')) {			state = 3;			break;		}		if ((c == '$') && (prev != '\\')) {			state++;		} else {			*(output++) = c;			outputcnt--;		}		break;	    case 1:			/* Waiting for ( */		if (c == '(' || c == '{') {			state++;			varname_start = input;		} else {			state = 0;			*(output++) = '$';			outputcnt--;			if (outputcnt) {				*(output++) = c;				outputcnt--;			}		}		break;	    case 2:			/* Waiting for )	*/		if (c == ')' || c == '}') {			int i;			char envname[CFG_CBSIZE], *envval;			/* Varname # of chars */			int envcnt = input - varname_start - 1;			/* Get the varname */			for (i = 0; i < envcnt; i++) {				envname[i] = varname_start[i];			}			envname[i] = 0;			/* Get its value */			envval = getenv (envname);			/* Copy into the line if it exists */			if (envval != NULL)				while ((*envval) && outputcnt) {					*(output++) = *(envval++);					outputcnt--;				}			/* Look for another '$' */			state = 0;		}		break;	    case 3:			/* Waiting for '	*/		if ((c == '\'') && (prev != '\\')) {			state = 0;		} else {			*(output++) = c;			outputcnt--;		}		break;	    }	    prev = c;	}	if (outputcnt)		*output = 0;#ifdef DEBUG_PARSER	printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",		strlen (output_start), output_start);#endif}/* * this is called from board_init() after the hardware has been set up * and is usable. That seems like a good time to do this. * Right now the return value is ignored. */int do_auto_update(void){	block_dev_desc_t *stor_dev = NULL;	long sz;	int i, res, cnt, old_ctrlc, got_ctrlc;	char buffer[32];	char str[80];	int n;	if  (ide_dev_desc[0].type != DEV_TYPE_UNKNOWN) {		stor_dev = get_dev ("ide", 0);		if (stor_dev == NULL) {			debug ("ide: unknown device\n");			return -1;		}	}	if (fat_register_device (stor_dev, 1) != 0) {		debug ("Unable to register ide disk 0:1\n");		return -1;	}	/*	 * Check if magic file is present	 */	if ((n = do_fat_read (AU_MAGIC_FILE, buffer,			      sizeof(buffer), LS_NO)) <= 0) {		debug ("No auto_update magic file (n=%d)\n", n);		return -1;	}#ifdef CONFIG_AUTO_UPDATE_SHOW	board_auto_update_show (1);#endif	puts("\nAutoUpdate Disk detected! Trying to update system...\n");	/* make sure that we see CTRL-C and save the old state */	old_ctrlc = disable_ctrlc (0);	/* just loop thru all the possible files */	for (i = 0; i < N_AU_IMAGES; i++) {		/*		 * Try to expand the environment var in the fname		 */		process_macros (au_image[i].name, str);		strcpy (au_image[i].name, str);		printf("Reading %s ...", au_image[i].name);		/* just read the header */		sz = do_fat_read (au_image[i].name, LOAD_ADDR,				  image_get_header_size (), LS_NO);		debug ("read %s sz %ld hdr %d\n",			au_image[i].name, sz, image_get_header_size ());		if (sz <= 0 || sz < image_get_header_size ()) {			puts(" not found\n");			continue;		}		if (au_check_header_valid (i, sz) < 0) {			puts(" header not valid\n");			continue;		}		sz = do_fat_read (au_image[i].name, LOAD_ADDR,				  MAX_LOADSZ, LS_NO);		debug ("read %s sz %ld hdr %d\n",			au_image[i].name, sz, image_get_header_size ());		if (sz <= 0 || sz <= image_get_header_size ()) {			puts(" not found\n");			continue;		}		if (au_check_cksum_valid (i, sz) < 0) {			puts(" checksum not valid\n");			continue;		}		puts(" done\n");		do {			res = au_do_update (i, sz);			/* let the user break out of the loop */			if (ctrlc() || had_ctrlc ()) {				clear_ctrlc ();				if (res < 0)					got_ctrlc = 1;				break;			}			cnt++;		} while (res < 0);	}	/* restore the old state */	disable_ctrlc (old_ctrlc);	puts("AutoUpdate finished\n\n");#ifdef CONFIG_AUTO_UPDATE_SHOW	board_auto_update_show (0);#endif	return 0;}int auto_update(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){	do_auto_update();	return 0;}U_BOOT_CMD(	autoupd,	1,	1,	auto_update,	"autoupd - Automatically update images\n",	NULL);#endif /* CONFIG_AUTO_UPDATE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -