Changeset 8444


Ignore:
Timestamp:
2007-08-20T18:12:24+02:00 (9 years ago)
Author:
nbd
Message:

cleanup mtd, implement jffs2write - one step closer to config preserving system upgrades

Location:
trunk/package/mtd
Files:
4 added
3 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/package/mtd/Makefile

    r6501 r8444  
    1111 
    1212PKG_NAME:=mtd 
    13 PKG_RELEASE:=5 
     13PKG_RELEASE:=6 
    1414 
    1515PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME) 
  • trunk/package/mtd/src/Makefile

    r6501 r8444  
    1 # $Id$ 
     1CC = gcc 
     2CFLAGS += -Wall 
    23 
    3 all: mtd 
    4  
    5 %.o: %.c 
    6         $(CC) -I. $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $^ 
    7  
    8 mtd: mtd.o 
    9         $(CC) -o $@ $^ 
    10  
     4mtd: mtd.o jffs2.o crc32.o 
    115clean: 
    12         rm -f *.o mtd 
     6        rm -f *.o jffs2  
  • trunk/package/mtd/src/mtd.c

    r8439 r8444  
    2929#include <stdio.h> 
    3030#include <stdint.h> 
     31#include <signal.h> 
    3132#include <sys/ioctl.h> 
    3233#include <sys/syscall.h> 
     
    4445#include <linux/reboot.h> 
    4546 
    46 #include "mtd.h" 
     47#include "mtd-api.h" 
    4748 
    4849#define TRX_MAGIC       0x30524448      /* "HDR0" */ 
     
    5152 
    5253#define DEBUG 
     54 
     55#define JFFS2_DEFAULT_DIR       "tmp" 
    5356 
    5457#define SYSTYPE_UNKNOWN     0 
     
    6467}; 
    6568 
    66 char buf[BUFSIZE]; 
    67 int buflen; 
     69static char buf[BUFSIZE]; 
     70static char *imagefile; 
     71static int buflen; 
    6872int quiet; 
    69  
    70 #ifdef target_brcm 
    71 int 
    72 image_check_brcm(int imagefd, const char *mtd) 
    73 { 
    74         struct trx_header *trx = (struct trx_header *) buf; 
    75         struct mtd_info_user mtdInfo; 
    76         int fd; 
    77  
    78         if (strcmp(mtd, "linux") != 0) 
    79                 return 1; 
    80          
    81         buflen = read(imagefd, buf, 32); 
    82         if (buflen < 32) { 
    83                 fprintf(stdout, "Could not get image header, file too small (%ld bytes)\n", buflen); 
    84                 return 0; 
    85         } 
    86  
    87         if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) { 
    88                 if (quiet < 2) { 
    89                         fprintf(stderr, "Bad trx header\n"); 
    90                         fprintf(stderr, "This is not the correct file format; refusing to flash.\n" 
    91                                         "Please specify the correct file or use -f to force.\n"); 
    92                 } 
    93                 return 0; 
    94         } 
    95  
    96         /* check if image fits to mtd device */ 
    97         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
    98         if(fd < 0) { 
    99                 fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    100                 exit(1); 
    101         } 
    102  
    103         if(ioctl(fd, MEMGETINFO, &mtdInfo)) { 
    104                 fprintf(stderr, "Could not get MTD device info from %s\n", mtd); 
    105                 exit(1); 
    106         } 
    107                  
    108         if(mtdInfo.size < trx->len) { 
    109                 fprintf(stderr, "Image too big for partition: %s\n", mtd); 
    110                 close(fd); 
    111                 return 0; 
    112         }        
    113          
    114         close(fd); 
    115         return 1; 
    116 } 
    117 #endif /* target_brcm */ 
    118  
    119 int 
    120 image_check(int imagefd, const char *mtd) 
    121 { 
    122         int fd, systype; 
    123         size_t count; 
    124         char *c; 
    125         FILE *f; 
    126  
    127 #ifdef target_brcm 
    128         return image_check_brcm(imagefd, mtd); 
    129 #endif 
    130 } 
    131  
    132 int mtd_check(char *mtd) 
    133 { 
    134         struct mtd_info_user mtdInfo; 
    135         int fd; 
    136  
    137         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
    138         if(fd < 0) { 
    139                 fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    140                 return 0; 
    141         } 
    142  
    143         if(ioctl(fd, MEMGETINFO, &mtdInfo)) { 
    144                 fprintf(stderr, "Could not get MTD device info from %s\n", mtd); 
    145                 close(fd); 
    146                 return 0; 
    147         } 
    148  
    149         close(fd); 
    150         return 1; 
    151 } 
    152  
    153 int 
    154 mtd_unlock(const char *mtd) 
    155 { 
    156         int fd; 
    157         struct mtd_info_user mtdInfo; 
    158         struct erase_info_user mtdLockInfo; 
    159  
    160         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
    161         if(fd < 0) { 
    162                 fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    163                 exit(1); 
    164         } 
    165  
    166         if(ioctl(fd, MEMGETINFO, &mtdInfo)) { 
    167                 fprintf(stderr, "Could not get MTD device info from %s\n", mtd); 
    168                 close(fd); 
    169                 exit(1); 
    170         } 
    171  
    172         mtdLockInfo.start = 0; 
    173         mtdLockInfo.length = mtdInfo.size; 
    174         if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) { 
    175                 close(fd); 
    176                 return 0; 
    177         } 
    178                  
    179         close(fd); 
    180         return 0; 
    181 } 
    182  
    183 int 
    184 mtd_open(const char *mtd, int flags) 
     73int mtdsize = 0; 
     74int erasesize = 0; 
     75 
     76int mtd_open(const char *mtd) 
    18577{ 
    18678        FILE *fp; 
     
    18880        int i; 
    18981        int ret; 
     82        int flags = O_RDWR | O_SYNC; 
    19083 
    19184        if ((fp = fopen("/proc/mtd", "r"))) { 
     
    207100} 
    208101 
    209 int 
    210 mtd_erase(const char *mtd) 
    211 { 
     102int mtd_check_open(const char *mtd) 
     103{ 
     104        struct mtd_info_user mtdInfo; 
    212105        int fd; 
    213         struct mtd_info_user mtdInfo; 
    214         struct erase_info_user mtdEraseInfo; 
    215  
    216         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
     106 
     107        fd = mtd_open(mtd); 
    217108        if(fd < 0) { 
    218109                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    219                 exit(1); 
     110                return 0; 
    220111        } 
    221112 
     
    223114                fprintf(stderr, "Could not get MTD device info from %s\n", mtd); 
    224115                close(fd); 
    225                 exit(1); 
    226         } 
    227  
    228         mtdEraseInfo.length = mtdInfo.erasesize; 
     116                return 0; 
     117        } 
     118        mtdsize = mtdInfo.size; 
     119        erasesize = mtdInfo.erasesize; 
     120 
     121        return fd; 
     122} 
     123 
     124int mtd_erase_block(int fd, int offset) 
     125{ 
     126        struct erase_info_user mtdEraseInfo; 
     127 
     128        mtdEraseInfo.start = offset; 
     129        mtdEraseInfo.length = erasesize; 
     130        ioctl(fd, MEMUNLOCK, &mtdEraseInfo); 
     131        if (ioctl (fd, MEMERASE, &mtdEraseInfo) < 0) { 
     132                fprintf(stderr, "Erasing mtd failed.\n"); 
     133                exit(1); 
     134        } 
     135} 
     136 
     137int mtd_write_buffer(int fd, char *buf, int offset, int length) 
     138{ 
     139        lseek(fd, offset, SEEK_SET); 
     140        write(fd, buf, length); 
     141} 
     142 
     143 
     144#ifdef target_brcm 
     145static int 
     146image_check_brcm(int imagefd, const char *mtd) 
     147{ 
     148        struct trx_header *trx = (struct trx_header *) buf; 
     149        int fd; 
     150 
     151        if (strcmp(mtd, "linux") != 0) 
     152                return 1; 
     153         
     154        buflen = read(imagefd, buf, 32); 
     155        if (buflen < 32) { 
     156                fprintf(stdout, "Could not get image header, file too small (%ld bytes)\n", buflen); 
     157                return 0; 
     158        } 
     159 
     160        if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) { 
     161                if (quiet < 2) { 
     162                        fprintf(stderr, "Bad trx header\n"); 
     163                        fprintf(stderr, "This is not the correct file format; refusing to flash.\n" 
     164                                        "Please specify the correct file or use -f to force.\n"); 
     165                } 
     166                return 0; 
     167        } 
     168 
     169        /* check if image fits to mtd device */ 
     170        fd = mtd_check_open(mtd); 
     171        if(fd < 0) { 
     172                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
     173                exit(1); 
     174        } 
     175 
     176        if(mtdsize < trx->len) { 
     177                fprintf(stderr, "Image too big for partition: %s\n", mtd); 
     178                close(fd); 
     179                return 0; 
     180        }        
     181         
     182        close(fd); 
     183        return 1; 
     184} 
     185#endif /* target_brcm */ 
     186 
     187static int 
     188image_check(int imagefd, const char *mtd) 
     189{ 
     190        int fd, systype; 
     191        size_t count; 
     192        char *c; 
     193        FILE *f; 
     194 
     195#ifdef target_brcm 
     196        return image_check_brcm(imagefd, mtd); 
     197#endif 
     198} 
     199 
     200static int mtd_check(const char *mtd) 
     201{ 
     202        int fd; 
     203 
     204        fd = mtd_check_open(mtd); 
     205        if (!fd) 
     206                return 0; 
     207 
     208        close(fd); 
     209        return 1; 
     210} 
     211 
     212static int 
     213mtd_unlock(const char *mtd) 
     214{ 
     215        int fd; 
     216        struct erase_info_user mtdLockInfo; 
     217 
     218        fd = mtd_check_open(mtd); 
     219        if(fd <= 0) { 
     220                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
     221                exit(1); 
     222        } 
     223 
     224        if (quiet < 2)  
     225                fprintf(stderr, "Unlocking %s ...\n", mtd); 
     226 
     227        mtdLockInfo.start = 0; 
     228        mtdLockInfo.length = mtdsize; 
     229        if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) { 
     230                close(fd); 
     231                return 0; 
     232        } 
     233                 
     234        close(fd); 
     235        return 0; 
     236} 
     237 
     238static int 
     239mtd_erase(const char *mtd) 
     240{ 
     241        int fd; 
     242        struct erase_info_user mtdEraseInfo; 
     243 
     244        if (quiet < 2) 
     245                fprintf(stderr, "Erasing %s ...\n", mtd); 
     246 
     247        fd = mtd_check_open(mtd); 
     248        if(fd <= 0) { 
     249                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
     250                exit(1); 
     251        } 
     252 
     253        mtdEraseInfo.length = erasesize; 
    229254 
    230255        for (mtdEraseInfo.start = 0; 
    231                  mtdEraseInfo.start < mtdInfo.size; 
    232                  mtdEraseInfo.start += mtdInfo.erasesize) { 
     256                 mtdEraseInfo.start < mtdsize; 
     257                 mtdEraseInfo.start += erasesize) { 
    233258                 
    234259                ioctl(fd, MEMUNLOCK, &mtdEraseInfo); 
     
    242267} 
    243268 
    244 int 
     269static int 
    245270mtd_refresh(const char *mtd) 
    246271{ 
    247272        int fd; 
    248273 
    249         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
    250         if(fd < 0) { 
     274        if (quiet < 2) 
     275                fprintf(stderr, "Refreshing mtd partition %s ... ", mtd); 
     276 
     277        fd = mtd_check_open(mtd); 
     278        if(fd <= 0) { 
    251279                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    252280                exit(1); 
    253281        } 
     282 
    254283        if (ioctl(fd, MTDREFRESH, NULL)) { 
    255284                fprintf(stderr, "Failed to refresh the MTD device\n"); 
     
    258287        } 
    259288        close(fd); 
     289 
     290        if (quiet < 2) 
     291                fprintf(stderr, "\n"); 
     292 
    260293        return 0; 
    261294} 
    262295 
    263 int 
     296static int 
    264297mtd_write(int imagefd, const char *mtd) 
    265298{ 
    266299        int fd, i, result; 
    267300        size_t r, w, e; 
    268         struct mtd_info_user mtdInfo; 
    269301        struct erase_info_user mtdEraseInfo; 
    270302        int ret = 0; 
    271303 
    272         fd = mtd_open(mtd, O_RDWR | O_SYNC); 
     304        fd = mtd_check_open(mtd); 
    273305        if(fd < 0) { 
    274306                fprintf(stderr, "Could not open mtd device: %s\n", mtd); 
    275307                exit(1); 
    276308        } 
    277  
    278         if(ioctl(fd, MEMGETINFO, &mtdInfo)) { 
    279                 fprintf(stderr, "Could not get MTD device info from %s\n", mtd); 
    280                 close(fd); 
    281                 exit(1); 
    282         } 
    283                  
     309                 
     310        if (quiet < 2) 
     311                fprintf(stderr, "Writing from %s to %s ... ", imagefile, mtd); 
     312 
    284313        r = w = e = 0; 
    285314        if (!quiet) 
     
    297326                /* need to erase the next block before writing data to it */ 
    298327                while (w > e) { 
    299                         mtdEraseInfo.start = e; 
    300                         mtdEraseInfo.length = mtdInfo.erasesize; 
    301  
    302328                        if (!quiet) 
    303329                                fprintf(stderr, "\b\b\b[e]"); 
     330 
     331                        mtd_erase_block(fd, e); 
     332 
    304333                        /* erase the chunk */ 
    305                         if (ioctl (fd,MEMERASE,&mtdEraseInfo) < 0) { 
    306                                 fprintf(stderr, "Erasing mtd failed: %s\n", mtd); 
    307                                 exit(1); 
    308                         } 
    309                         e += mtdInfo.erasesize; 
     334                        e += erasesize; 
    310335                } 
    311336                 
     
    328353                fprintf(stderr, "\b\b\b\b"); 
    329354 
     355        if (quiet < 2) 
     356                fprintf(stderr, "\n"); 
     357 
    330358        close(fd); 
    331359        return 0; 
    332360} 
    333361 
    334 void usage(void) 
     362static void usage(void) 
    335363{ 
    336364        fprintf(stderr, "Usage: mtd [<options> ...] <command> [<arguments> ...] <device>\n\n" 
     
    341369        "        erase                   erase all data on device\n" 
    342370        "        write <imagefile>|-     write <imagefile> (use - for stdin) to device\n" 
     371        "        jffs2write <file>       append <file> to the jffs2 partition on the device\n" 
    343372        "Following options are available:\n" 
    344373        "        -q                      quiet mode (once: no [w] on writing,\n" 
     
    346375        "        -r                      reboot after successful command\n" 
    347376        "        -f                      force write without trx checks\n" 
    348         "        -e <device>             erase <device> before executing the command\n\n" 
     377        "        -e <device>             erase <device> before executing the command\n" 
     378        "        -d <name>               directory for jffs2write, defaults to \"tmp\"\n" 
     379        "\n" 
    349380        "Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards\n" 
    350381        "         mtd -r write linux.trx linux\n\n"); 
     
    352383} 
    353384 
     385static void do_reboot(void) 
     386{ 
     387        fprintf(stderr, "Rebooting ...\n"); 
     388        fflush(stderr); 
     389 
     390        /* try regular reboot method first */ 
     391        system("/sbin/reboot"); 
     392        sleep(2); 
     393 
     394        /* if we're still alive at this point, force the kernel to reboot */ 
     395        syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL); 
     396} 
     397 
    354398int main (int argc, char **argv) 
    355399{ 
    356400        int ch, i, boot, unlock, imagefd, force, unlocked; 
    357         char *erase[MAX_ARGS], *device, *imagefile; 
     401        char *erase[MAX_ARGS], *device; 
     402        char *jffs2dir = JFFS2_DEFAULT_DIR; 
    358403        enum { 
    359404                CMD_ERASE, 
    360405                CMD_WRITE, 
    361406                CMD_UNLOCK, 
    362                 CMD_REFRESH 
     407                CMD_REFRESH, 
     408                CMD_JFFS2WRITE 
    363409        } cmd; 
    364410         
     
    369415        quiet = 0; 
    370416 
    371         while ((ch = getopt(argc, argv, "frqe:")) != -1) 
     417        while ((ch = getopt(argc, argv, "frqe:d:")) != -1) 
    372418                switch (ch) { 
    373419                        case 'f': 
     
    388434                                erase[i] = NULL; 
    389435                                break; 
    390                          
     436                        case 'd': 
     437                                jffs2dir = optarg; 
     438                                break; 
    391439                        case '?': 
    392440                        default: 
     
    435483                        } 
    436484                } 
     485        } else if ((strcmp(argv[0], "jffs2write") == 0) && (argc == 3)) { 
     486                cmd = CMD_JFFS2WRITE; 
     487                device = argv[2]; 
     488         
     489                imagefile = argv[1]; 
     490                if (!mtd_check(device)) { 
     491                        fprintf(stderr, "Can't open device for writing!\n"); 
     492                        exit(1); 
     493                } 
    437494        } else { 
    438495                usage(); 
     
    444501        unlocked = 0; 
    445502        while (erase[i] != NULL) { 
    446                 if (quiet < 2) 
    447                         fprintf(stderr, "Unlocking %s ...\n", erase[i]); 
    448503                mtd_unlock(erase[i]); 
    449                 if (quiet < 2) 
    450                         fprintf(stderr, "Erasing %s ...\n", erase[i]); 
    451504                mtd_erase(erase[i]); 
    452505                if (strcmp(erase[i], device) == 0) 
     
    455508        } 
    456509         
    457         if (!unlocked) { 
    458                 if (quiet < 2)  
    459                         fprintf(stderr, "Unlocking %s ...\n", device); 
    460                 mtd_unlock(device); 
    461         } 
    462510                 
    463511        switch (cmd) { 
    464512                case CMD_UNLOCK: 
     513                        if (!unlocked) 
     514                                mtd_unlock(device); 
    465515                        break; 
    466516                case CMD_ERASE: 
    467                         if (quiet < 2) 
    468                                 fprintf(stderr, "Erasing %s ...\n", device); 
     517                        if (!unlocked) 
     518                                mtd_unlock(device); 
    469519                        mtd_erase(device); 
    470520                        break; 
    471521                case CMD_WRITE: 
    472                         if (quiet < 2) 
    473                                 fprintf(stderr, "Writing from %s to %s ... ", imagefile, device); 
     522                        if (!unlocked) 
     523                                mtd_unlock(device); 
    474524                        mtd_write(imagefd, device); 
    475                         if (quiet < 2) 
    476                                 fprintf(stderr, "\n"); 
     525                        break; 
     526                case CMD_JFFS2WRITE: 
     527                        if (!unlocked) 
     528                                mtd_unlock(device); 
     529                        mtd_write_jffs2(device, imagefile, jffs2dir); 
    477530                        break; 
    478531                case CMD_REFRESH: 
    479                         if (quiet < 2) 
    480                                 fprintf(stderr, "Refreshing mtd partition %s ... "); 
    481532                        mtd_refresh(device); 
    482                         if (quiet < 2) 
    483                                 fprintf(stderr, "\n"); 
    484533                        break; 
    485534        } 
     
    487536        sync(); 
    488537         
    489         if (boot) { 
    490                 fprintf(stderr, "Rebooting ...\n"); 
    491                 fflush(stderr); 
    492                 syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL); 
    493         } 
     538        if (boot) 
     539                do_reboot(); 
     540 
    494541        return 0; 
    495542} 
Note: See TracChangeset for help on using the changeset viewer.