📄 flashimage.c
字号:
/* * Copyright (C) 2007 Jiong Zhao <gohigh@gmail.com> * * 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 *//* flashimage.c */#include <limits.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <stdint.h>#include <sys/ioctl.h>#include <sys/syscall.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <error.h>#include <time.h>#include <sys/types.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/reboot.h>#include <linux/reboot.h>#include <byteswap.h>#include "mtd.h"#define FPRINTF fprintf/* Define the machine's endian type. If we operate on Big Endian data, * then we use READ32_BE(X) and STORE32_BE(X). If we operate on Little * Endian data, then we should use READ32_LE(X) and STORE32_LE(X). */#define __BYTE_ORDER __LITTLE_ENDIAN // Host machine - i386 type.//#define __BYTE_ORDER __BIG_ENDIAN // Target machine - ARM type.#if __BYTE_ORDER == __BIG_ENDIAN // Program used on ARM type.#define STORE32_LE(X) bswap_32(X)#define READ32_LE(X) bswap_32(X)#define STORE32_BE(X) (X)#define READ32_BE(X) (X)#elif __BYTE_ORDER == __LITTLE_ENDIAN // Program used on i386 type.#define STORE32_LE(X) (X)#define READ32_LE(X) (X)#define STORE32_BE(X) bswap_32(X)#define READ32_BE(X) bswap_32(X)#else#error unkown endianness!#endifuint32_t crc32(uint32_t crc, char *buf, size_t len);/**********************************************************************/#define PAK_MAGIC 0x41435358 /* "XSCA" */#define PAK_VERSION 1#define PAK_MAX_LEN 0xB00000#define MAX_NAME_LEN 15#define MAX_PAK_IMAGES 5#define MAX_ARGS 8#define BUFSIZE (128 * 1024) /* 0x00020000 */#define HDBUFSIZE 512#define INIT_CRC 0xFFFFFFFFstruct img_header { uint32_t offset; /* image begin offset in this pack file. -1 end.*/ uint32_t len; /* length of pure file. */ uint32_t mtdofs; /* null if this is the last. */ uint32_t mtdno; /* in /proc/mtd: dev */ char mtdname[MAX_NAME_LEN+1]; /* in /proc/mtd: name */ char filename[MAX_NAME_LEN+1]; /* filename when packed (w/o path) */} img_header_t ; struct pak_header { uint32_t magic; /* "XSCA" */ uint32_t len; /* Length of file including header */ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ uint32_t icount; /* Total image file number. */ struct img_header img[MAX_PAK_IMAGES]; } pheader ;struct proc_mtd_table { char mtd[8]; uint32_t size; uint32_t erasesize; char name[20]; char devfile[20];} ptable[MAX_MTD_DEVICES];char hdbuf[HDBUFSIZE];char buf[BUFSIZE];int buflen;int quiet ;int unlocked;char *erase[MAX_ARGS];char *device;char *imgfile;/**********************************************************************//* The header occupis 256 bytes. The first image file is stored beginning *//* from this location. Only 5 image files can be stored together. */void usage(void) __attribute__ (( __noreturn__ ));int my_mtd_open(const char *mtd, int flags);int get_proc_mtdno(const char *name);int image_crc32_check(int imgfd){ uint32_t n = 0; uint32_t crc = INIT_CRC ; /* 0xFFFFFFFF, so no swap needed. */ // Get the packed file header (pheader) and check the CRC. while ((n = read(imgfd, buf, BUFSIZE))) { if (crc == INIT_CRC) { pheader = *(struct pak_header *)buf ; n -= offsetof(struct pak_header, icount); crc = crc32(crc, &buf[offsetof(struct pak_header, icount)], n); } else { crc = crc32(crc, buf, n); } } /* The magic number is a special case. It should always be a * little endian type */ if (READ32_LE(pheader.magic) != PAK_MAGIC) { if ( READ32_BE(pheader.magic) != PAK_MAGIC) { fprintf(stderr, "The file's type is incorrect.\n"); return 0; } else { fprintf(stderr, "=== WARNING: magic swapped. Should be an old image file.\n"); } } if (crc != READ32_BE(pheader.crc32)) { fprintf(stderr, "Current crc and crc in file header:%x, %x\n", crc, READ32_BE(pheader.crc32)); fprintf(stderr, "Packed file CRC check error.\n"); return 0; } ; lseek(imgfd, 0L, 0); return 1;}int show_imgfile_info(void){ int i; // we need list all the info in imgfile. fprintf(stderr, "\nThe packed file \"%s\" contains %d image(s) as bellow:\n", imgfile, READ32_BE(pheader.icount)); for (i=0; i < READ32_BE(pheader.icount); i++) { //fprintf(stderr, "The device %s has img in imgsfile:\n", device); fprintf(stderr, "----------------------------------\n"); fprintf(stderr, "Orignal image name: \"%s\"\n", pheader.img[i].filename); fprintf(stderr, "Image file length : %d\n", READ32_BE(pheader.img[i].len)); fprintf(stderr, "Name for this MTD : \"%s\"\n", pheader.img[i].mtdname); fprintf(stderr, "Offset in this MTD: 0x%08X\n", READ32_BE(pheader.img[i].mtdofs)); } return 0; } int check_device_In_imgfile(char *device, int show){ int mtdno, found = 0; int i ; // Check to see if 'device' has a image in the ImgsFile. // If there has one or more, we list the info of these imgs. if (!device) return 0; mtdno = -1 ; sscanf(device, "mtd%d", &mtdno); found = 0; for (i=0; i < READ32_BE(pheader.icount); i++) { if ((strcmp(device, pheader.img[i].mtdname)==0)||(mtdno == READ32_BE(pheader.img[i].mtdno))){ // we need only list this specified img info. if (found == 0) { found = 1; if (show){ fprintf(stderr, "The packed file \"%s\" contains images for the device %s :\n", imgfile, device); } else return 1; } if (show) { fprintf(stderr, "-------- Image %d --------------------\n",i+1); fprintf(stderr, "Orignal image name: \"%s\"\n", pheader.img[i].filename); fprintf(stderr, "Image file length : %d\n", READ32_BE(pheader.img[i].len)); fprintf(stderr, "Name for this MTD : \"%s\"\n", pheader.img[i].mtdname); fprintf(stderr, "Offset in this MTD: 0x%08X\n", READ32_BE(pheader.img[i].mtdofs)); } else return 1; } } if (found == 0) { fprintf(stderr, "The packed file \"%s\" does't contain image for device %s.\n", imgfile, device); exit(1); } return 1;}int image_mtd_check(int imgfd, const char *device){ int i, mtdno; char *devfile ; mtdno = -1 ; sscanf(device, "mtd%d", &mtdno); for (i=0; i < READ32_BE(pheader.icount); i++) { if ((strcmp(device, pheader.img[i].mtdname)==0)||(mtdno == READ32_BE(pheader.img[i].mtdno))){ // we need only list this specified img info. mtdno = READ32_BE(pheader.img[i].mtdno); if (mtdno == get_proc_mtdno(device)){ devfile = ptable[mtdno].devfile; fprintf(stderr, "device %s's devfile is: %s\n", device, devfile); /* ...... */ } } } return 1;}int my_mtd_check(char *device){ struct mtd_info_user mtdInfo; int fd; if (device == NULL) return 1; fd = my_mtd_open(device, O_RDWR|O_SYNC); if (fd < 0) { fprintf(stderr, "Could not open mtd device: %s\n",device); return 0; } if (ioctl(fd, MEMGETINFO, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", device); close(fd); return 0; } close(fd); return 1;}int mtd_unlock(const char *mtd){ int fd; struct mtd_info_user mtdInfo; struct erase_info_user mtdLockInfo; fd = my_mtd_open(mtd, O_RDWR | O_SYNC); if (fd < 0) { fprintf(stderr, "Could not open mtd device: %s\n", mtd); exit(1); } if (ioctl(fd, MEMGETINFO, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", mtd); close(fd); exit(1); } mtdLockInfo.start = 0; mtdLockInfo.length = mtdInfo.size ; if (ioctl(fd, MEMUNLOCK, &mtdLockInfo)) { close(fd); return 0; } close (fd); return 0;}int my_mtd_open(const char *device, int flags){ int mtdno; if (device==NULL) return (-1); if ((mtdno = get_proc_mtdno(device))<0) return (-1); return open(ptable[mtdno].devfile, flags);}int mtd_erase(const char *mtd){ int fd; struct mtd_info_user mtdInfo; struct erase_info_user mtdEraseInfo; fd = my_mtd_open(mtd, O_RDWR | O_SYNC); if (fd < 0) { fprintf(stderr, "Could not open mtd device: %s\n", mtd); exit(1); } if (ioctl(fd, MEMGETINFO, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", mtd); close(fd); exit(1); } mtdEraseInfo.length = mtdInfo.erasesize; for (mtdEraseInfo.start = 0 ; mtdEraseInfo.start < mtdInfo.size; mtdEraseInfo.start += mtdInfo.erasesize) { ioctl(fd, MEMUNLOCK, &mtdEraseInfo); if (ioctl(fd, MEMERASE, &mtdEraseInfo)) fprintf(stderr, "Failed to erase block on %s at 0x%x\n", mtd, mtdEraseInfo.start); } close(fd); return 0;}int my_mtd_write(int imgfd, int pt_id, int img_id){ int fd; char *device ; char *fname ; int mtdno; uint32_t res, rn, wr,rd,er; uint32_t mtdofs, offset; uint32_t mtdlen ; struct mtd_info_user mtdInfo ; struct erase_info_user mtdEraseInfo ; device = ptable[pt_id].mtd ; mtdno = get_proc_mtdno(device); offset = READ32_BE(pheader.img[img_id].offset); mtdofs = READ32_BE(pheader.img[img_id].mtdofs) ; mtdlen = READ32_BE(pheader.img[img_id].len); fname = pheader.img[img_id].filename; if ((mtdofs + mtdlen) > ptable[pt_id].size ) { fprintf(stderr, "Image too large to fit into the mtd device %s\n", device); exit(-1); } if (!quiet) { fprintf(stderr, "Writing %s to %s at offset 0x%08X with length %d", fname, device, mtdofs, mtdlen); fprintf(stderr, " [ ]"); } fd = my_mtd_open(device, O_RDWR|O_SYNC); if (fd < 0) { fprintf(stderr, "Could not open mtd device: %s\n", device); exit(-1); } if (ioctl(fd, MEMGETINFO, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", device); close(fd); exit(-1); } lseek(fd, mtdofs, 0); lseek(imgfd, offset, 0); rd = 0; wr = er = mtdofs ; rn = (mtdlen > sizeof(buf))? sizeof(buf):mtdlen; while (mtdlen>0) { if ((rd = read(imgfd, buf, rn)) != rn) { fprintf(stderr, "Failed reading packed file.\n"); exit(-1); } wr += rd ; /* need to erase the next block before writing data to it */ while (wr > er) { mtdEraseInfo.start = er ; mtdEraseInfo.length = mtdInfo.erasesize; if (!quiet) fprintf(stderr, "\b\b\b[e]"); /* erase the chunk */ if (ioctl (fd, MEMERASE, &mtdEraseInfo) < 0) { fprintf(stderr, "Erasing mtd device failed: %s\n", device); exit(1); } er += mtdInfo.erasesize; } if (!quiet) fprintf(stderr, "\b\b\b[w]"); if ((res = write(fd, buf, rn)) != rn) { if (res < 0) fprintf(stderr, "Error writing mtd device %s\n", device); else fprintf(stderr, "Insufficient space to write mtd device %s\n", device); exit(-1); } mtdlen -= rn; rn = (mtdlen > sizeof(buf))? sizeof(buf):mtdlen; } if (!quiet) fprintf(stderr, "\b\b\b\b\n"); close(fd); return 0;}/****************************************/int init_ptable(void){ FILE *fp; int ret ; int i, n = 0; char line[PATH_MAX]; char devfile[PATH_MAX]; char *p ; uint32_t kk, qq; char name[30]; char dev[30];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -