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

📄 netflash.c

📁 通过网络刷新flash的工具源代码.linux下使用的
💻 C
📖 第 1 页 / 共 4 页
字号:
	int rd, rc, tmpfd;	int delay;	int dochecksum, dokill, dokillpartial, doreboot, doftp;	int dopreserve, doversion, doremoveversion, dohardwareversion;	int devsize = 0, sgsize = 0;	struct fileblock_t *fb;#ifdef CONFIG_USER_NETFLASH_HMACMD5	char *hmacmd5key = NULL;#endif#if defined(CONFIG_USER_NETFLASH_WITH_CGI) && !defined(RECOVER_PROGRAM)	char options[64];	char *new_argv[10];#endif	rdev = "/dev/flash/image";	srvname = NULL;	filename = NULL;	console = NULL;	dochecksum = 1;	dokill = 1;	dokillpartial = 0;	doreboot = 1;	dolock = 0;	dounlock = 0;	delay = 0;	doftp = 0;	dothrow = 0;	dopreserve = 1;	preserveconfig = 0;	checkimage = 0;	dojffs2 = 0;	doremoveversion = 1;#ifdef CONFIG_USER_NETFLASH_VERSION	doversion = 1;	dohardwareversion = 1;#else	doversion = 0;	dohardwareversion = 0;#endif /*CONFIG_USER_NETFLASH_VERSION*/#ifdef CONFIG_USER_NETFLASH_DECOMPRESS	doinflate = 0;#endif#if defined(CONFIG_USER_NETFLASH_WITH_CGI) && !defined(RECOVER_PROGRAM)	if (argc == 2 && strncmp(argv[1], "cgi://", 6) == 0) {		char *pt;		char *sep;		int new_argc = 0;		docgi = 1;		dokillpartial = 1;		/* Our "command line" options come from stdin for cgi		 * Format of the command line is: cgi://dataname,optionsname		 */		pt = argv[1] + 6;		sep = strchr(pt, ',');		if (sep) {			int len = sep - pt;			if (len >= sizeof(cgi_data)) {				len = sizeof(cgi_data) - 1;			}			strncpy(cgi_data, pt, len);			cgi_data[len] = 0;			strncpy(cgi_options, sep + 1, sizeof(cgi_options));			cgi_options[sizeof(cgi_options) - 1] = 0;		} else {			exit_failed(BAD_CGI_FORMAT);		}		if ((file_length = cgi_load(cgi_data, cgi_options, options)) <= 0) {			exit_failed(BAD_CGI_DATA);		}		new_argv[new_argc++] = argv[0];		/* Parse the options */		pt = strtok(options, " \t");		while (pt) {			assert(new_argc < 10);			new_argv[new_argc++] = pt;			pt = strtok(0, " \t");		}		argc = new_argc;		argv = new_argv;	}#endif	while ((rc = getopt(argc, argv, CMD_LINE_OPTIONS)) > 0) {		switch (rc) {		case 'p':			preserve = 1;			stop_early = 1;			break;		case 's':			stop_early = 1;			break;		case 'S':			nostop_early = 1;			break;		case 'b':			doreboot = 0;			break;		case 'c':			console = optarg;			break;		case 'C':			checkimage = 1;			break;		case 'd':			delay = (atoi(optarg));			break;		case 'f':			doftp = 1;			break;		case 'F':			dopreserve = 0;			break;		case 'i': 			doversion = 0; 			break;		case 'H': 			dohardwareversion = 0; 			break;		case 'j':			dojffs2 = 1;			nostop_early = 1;			break;		case 'k':			dokill = 0;			break;		case 'K':			dokill = 1;			dokillpartial = 1;			break;		case 'l':			dolock++;			break;#ifdef CONFIG_USER_NETFLASH_HMACMD5		case 'm':			hmacmd5key = optarg;			break;#endif		case 'n':			/* No checksum implies no version */			dochecksum = doversion = dohardwareversion = doremoveversion = 0;			break;		case 'o':			offset = strtol(optarg, NULL, 0);			break;		case 'r':			rdev = optarg;			break;		case 't':			dothrow = 1;			break;		case 'u':			dounlock++;			break;		case 'v':			notice("version %s", version);			exit(0);#ifdef CONFIG_USER_NETFLASH_DECOMPRESS		case 'z':			doinflate = 1;			break;#endif#ifdef CONFIG_USER_NETFLASH_SETSRC		case 'I':			srcaddr = optarg;			break;#endif#ifdef CONFIG_USER_NETFLASH_WATCHDOG		case 'w':			watchdog = 0;			break;#endif		case 'h':		case '?':			usage(0);			break;		}	}	/*	 * for /dev/flash/image we want to stop early unless the user	 * has told us not to (-S).  This allows us to preserve logd info	 *	 * So we override the default of not stopping early for /dev/flash/image	 */	if (strcmp(rdev, "/dev/flash/image") == 0) {		if (nostop_early == 0)			stop_early = 1;	}	if ((nfd = fopen("/dev/null", "rw")) == NULL) {		error("open(/dev/null) failed: %s", strerror(errno));		exit_failed(NO_DEV_NULL);	}	if (!docgi) {		if (optind == (argc - 1)) {			srvname = NULL;			filename = argv[optind];		} else if (optind == (argc - 2)) {			srvname = argv[optind++];			filename = argv[optind];		} else {			usage(1);		}	}	if (delay > 0) {		/* sleep the required time */		notice("waiting %d seconds before updating flash...",delay);		sleep(delay);	}	/*	 *	Need to do any real FTP setup early, before killing processes	 *	(and this losing association with the controlling tty).	 */	if (doftp) {		if (ftpconnect(srvname)) {			error("ftpconnect failed");			exit_failed(FTP_CONNECT_FAIL);		}	}	if (dokill) {		if (dokillpartial)			kill_processes_partial();		else			kill_processes(console);	}	/*	 * Open the flash device and allocate a segment sized block.	 * This is the largest block we need to allocate, so we do	 * it first to try to avoid fragmentation effects.	 */	if (dopreserve && (strcmp(rdev, "/dev/flash/image") == 0))		preserveconfig = 1;	rd = open(rdev, O_RDWR);	if (rd < 0) {		error("open(%s) failed: %s", rdev, strerror(errno));		exit_failed(BAD_OPEN_FLASH);	}	if (stat(rdev, &stat_rdev) != 0) {		error("stat(%s) failed: %s", rdev, strerror(errno));		exit_failed(BAD_OPEN_FLASH);	} else if (S_ISBLK(stat_rdev.st_mode)) {#ifdef CONFIG_NFTL_RW		if (major(stat_rdev.st_rdev) == NFTL_MAJOR) {			unsigned long l;			program_segment = program_generic_segment;			preserveconfig = dolock = dounlock = 0;			if (ioctl(rd, BLKGETSIZE, &l) < 0) {				error("ioctl(BLKGETSIZE) failed, errno=%d",						errno);				exit_failed(BAD_OPEN_FLASH);			}			devsize = l*512; /* Sectors are always 512 bytes */			/* Use a larger sgsize for efficiency, but it			 * must divide evenly into devsize. */			for (sgsize = 512; sgsize < 64 * 1024; sgsize <<= 1)				if (devsize & sgsize)					break;		}#endif#ifdef CONFIG_IDE		if ((major(stat_rdev.st_rdev) == IDE0_MAJOR) ||		    (major(stat_rdev.st_rdev) == IDE1_MAJOR) ||		    (major(stat_rdev.st_rdev) == IDE2_MAJOR) ||		    (major(stat_rdev.st_rdev) == IDE3_MAJOR)) {			struct hd_geometry geo;			program_segment = program_generic_segment;			preserveconfig = dolock = dounlock = 0;			if (ioctl(rd, HDIO_GETGEO, &geo) < 0) {				error("ioctl(HDIO_GETGEO) failed, errno=%d",						errno);				exit_failed(BAD_OPEN_FLASH);			}			devsize = geo.heads*geo.cylinders*geo.sectors*512;			/* Use a larger sgsize for efficiency, but it			 * must divide evenly into devsize. */			for (sgsize = 512; sgsize < 64 * 1024; sgsize <<= 1)				if (devsize & sgsize)					break;		}#endif	}	if (!program_segment) {#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULES)		mtd_info_t mtd_info, rootfs_info;		program_segment = program_mtd_segment;		if (ioctl(rd, MEMGETINFO, &mtd_info) < 0) {			error("ioctl(MEMGETINFO) failed, errno=%d", errno);			exit_failed(BAD_OPEN_FLASH);		}		devsize = mtd_info.size;		sgsize = mtd_info.erasesize;		/*		 * NETtel/x86 boards that boot direct from INTEL FLASH also have a		 * boot sector at the top of the FLASH. When programming complete		 * images we need to not overwrite this.		 */		if (preserveconfig) {			if ((tmpfd = open("/dev/flash/rootfs", O_RDONLY)) > 0) {				if (ioctl(tmpfd, MEMGETINFO, &rootfs_info) >= 0) {					if (rootfs_info.size & 0x000fffff) {						devsize = devsize - (0x00100000 -								(rootfs_info.size & 0x000fffff));					}				}				close(tmpfd);			}		}#else		program_segment = program_blkmem_segment;		if (ioctl(rd, BMGETSIZEB, &devsize) != 0) {			error("ioctl(BMGETSIZEB) failed, errno=%d", errno);			exit_failed(BAD_OPEN_FLASH);		}		if (ioctl(rd, BMSGSIZE, &sgsize) != 0) {			error("ioctl(BMSGSIZE) failed, errno=%d", errno);			exit_failed(BAD_OPEN_FLASH);		}#endif	}  	if (offset < 0) {		error("offset is less than zero");		exit_failed(BAD_OFFSET);	}	if (offset >= devsize) {		error("offset is greater than device size (%d)", devsize);		exit_failed(BAD_OFFSET);	}	sgdata = malloc(sgsize);	if (!sgdata) {		error("Insufficient memory for image!");		exit_failed(NO_MEMORY);	}	if (checkimage) {		check_buf = malloc(sgsize);		if (!check_buf) {			error("Insufficient memory for image!");			exit_failed(NO_MEMORY);		}	}	/*	 * Fetch file into memory buffers. Exactly how depends on the exact	 * load method. Support for tftp, http and local file currently.	 */	if (!docgi) {		fileblocks = NULL;		file_offset = 0;		file_length = 0;		if (srvname) {			if (doftp)				ftpfetch(srvname, filename);			else				tftpfetch(srvname, filename);		} else if (filefetch(filename) < 0) {				error("failed to find %s", filename);				exit_failed(NO_IMAGE);		}	}	/*	 * Do some checks on the data received	 *    - starts at offset 0	 *    - length > 0	 *    - no holes	 *    - checksum	 */	if (fileblocks == NULL) {		error("failed to load new image");		exit_failed(NO_IMAGE);	}#ifndef CONFIG_USER_NETFLASH_CRYPTO	if (!dothrow)#endif		if (fileblocks->pos != 0) {			error("failed to load new image");			exit_failed(NO_IMAGE);		}	if (file_length == 0) {		error("failed to load new image");		exit_failed(NO_IMAGE);	}	for (fb = fileblocks; fb->next != NULL; fb = fb->next)		if (fb->pos + fb->length != fb->next->pos) {			error("failed to load new image");			exit_failed(NO_IMAGE);		}	if (!docgi) {		notice("got \"%s\", length=%ld", filename, file_length);	}#ifdef CONFIG_USER_NETFLASH_CRYPTO	check_crypto_signature();#endif#ifdef CONFIG_USER_NETFLASH_HMACMD5	if (hmacmd5key)		check_hmac_md5(hmacmd5key);	else#endif	if (dochecksum)		chksum();	/*	 * Check the version information.	 * Side effect: this also checks whether version information is present,	 * and if so, removes it, since it doesn't need to get written to flash.	 */	if (doversion || doremoveversion)		rc = check_vendor();#ifdef CONFIG_USER_NETFLASH_VERSION	if (doversion || dohardwareversion) {		switch (rc){		case 5:			error("VERSION - you are trying to load an "				"image that does not\n         "				"contain valid version information.");			exit_failed(NO_VERSION);		default:			break;		}	}	if (doversion) {		switch (rc){#ifndef CONFIG_USER_NETFLASH_VERSION_ALLOW_CURRENT		case 3:			error("VERSION - you are trying to upgrade "				"with the same firmware\n"				"         version that you already have.");			exit_failed(ALREADY_CURRENT);#endif /* !CONFIG_USER_NETFLASH_VERSION_ALLOW_CURRENT */#ifndef CONFIG_USER_NETFLASH_VERSION_ALLOW_OLDER		case 4:			error("VERSION - you are trying to upgrade "				"with an older version of\n"				"         the firmware.");			exit_failed(VERSION_OLDER);#endif /* !CONFIG_USER_NETFLASH_VERSION_ALLOW_OLDER */		case 6:			error("VERSION - you are trying to load an "				"image for a different language.");			exit_failed(BAD_LANGUAGE);		case 0:			default:			break;		}	}	if (dohardwareversion) {		switch (rc){		case 1:			error("VERSION - product name incorrect.");			exit_failed(WRONG_PRODUCT);		case 2:			error("VERSION - vendor name incorrect.");			exit_failed(WRONG_VENDOR);		case 0:			default:			break;		}	}#endif /*CONFIG_USER_NETFLASH_VERSION*/#ifdef CONFIG_USER_NETFLASH_DECOMPRESS	doinflate = check_decompression(doinflate);#else	image_length = file_length;#endif	/* Check image that we fetched will actually fit in the FLASH device. */	if (image_length > devsize - offset) {		error("image too large for FLASH device (size=%d)",			devsize - offset);			exit_failed(IMAGE_TOO_BIG);	}	if (dothrow) {		notice("the image is good.");		exit(IMAGE_GOOD);	}#if defined(CONFIG_USER_NETFLASH_WITH_CGI) && !defined(RECOVER_PROGRAM)	if (docgi) {		// let's let our parent know it's ok.		kill(getppid(),SIGUSR1);	}#endif	if (flashing_rootfs(rdev)) {		/*		 *	Our filesystem is live, so we MUST kill processes if we haven't		 *  done it already.		 */		notice("flashing root filesystem, kill is forced");		if (!dokill || dokillpartial) {			kill_processes(console);		}		/* We must reboot on this platform */		doreboot = 1;	}#ifdef CONFIG_PROP_LOGD_LOGD	log_upgrade();#endif#if defined(CONFIG_USER_MOUNT_UMOUNT) || defined(CONFIG_USER_BUSYBOX_UMOUNT)	if (doreboot) {#if defined(CONFIG_USER_FLATFSD_USE_FLASH_FS) && defined(CONFIG_PROP_LOGD_LOGD)		/* Log the reboot to /etc/config before it's umounted */		char	tmp[50];		sprintf(tmp, "/bin/logd reboot %d: %s", getpid(), basename(argv[0]));			system(tmp);#endif		umount_all();	}#endif#ifdef CONFIG_JFFS_FS	/* Stop the JFFS garbage collector */	killprocname("jffs_gcd", SIGSTOP);#endif#ifdef CONFIG_JFFS2_FS	/* Stop the JFFS2 garbage collector */	killprocname("jffs2_gcd_mtd1", SIGSTOP);#endif	/*	 * Program the FLASH device.	 */	fflush(stdout);	sleep(1);	notice("programming FLASH device %s", rdev);#ifndef TEST_NO_DEVICE	program_flash(rd, devsize, sgdata, sgsize, check_buf);#endif /* TEST_NO_DEVICE */	if (doreboot) {		/* Wait half a second */		usleep(500000);		raw_reboot(0xfee1dead, 672274793, 0x01234567);	}	return exitstatus;}static void exit_failed(int rc){#ifdef CONFIG_USER_NETFLASH_WATCHDOG	close(watchdog_fd);#endif	exit(rc);}/****************************************************************************/

⌨️ 快捷键说明

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