00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 #include <stdlib.h>
00155 #include <stdio.h>
00156 #include <string.h>
00157 #include <unistd.h>
00158 #include <fcntl.h>
00159 #include <errno.h>
00160 #include <syslog.h>
00161 #include <sys/ioctl.h>
00162 #include <linux/version.h>
00163 #if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 8)
00164 #if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 19)
00165 #include <linux/compiler.h>
00166 #endif
00167 #include <mtd/mtd-user.h>
00168 #else
00169 #include <linux/mtd/mtd.h>
00170 #endif
00171 #ifdef USE_FWINFO_AREA
00172 #include <fwinfo.h>
00173 #endif
00174
00175
00176
00177 #define EMPTYMAGIC 0xffffffff
00178 #define PARAMMAGIC_PRIMARY 0xbeefcace
00179 #define PARAMMAGIC_BACKUP 0xdeadbabe
00180
00181 #define MAX_PARAM_NAME_LEN 0xff
00182 #define MAX_RECORD_LEN 0xffff
00183
00184 #define ERR_NO_MAGIC -3
00185 #define ERR_END_OF_PARAMS -2
00186 #define ERR_OTHER -1
00187 #define NO_ERROR 0
00188
00189 #define NAND_NOR_COMPATIBILITY_MODE (1)
00190
00191
00192 #define ROUND_UP(len, pagesize) ((((len) - 1) & ~((pagesize) - 1)) + (pagesize))
00193
00194 #define BLOCK_START(offset, blocksize) (((offset) & ((blocksize) -1)) == 0)
00195
00196 #define BLOCK_ADDR(offset, blocksize) ((offset) & ~((blocksize) -1))
00197
00198 static const char *dev = "/dev/part/rescue";
00199
00200 const char usage[] =
00201 "Usage: bootblocktool [options] command\n"
00202 "Options:\n"
00203 " -backup Makes all subsequent parameters pertain to the backup block\n"
00204 " -nocgi Disable CGI detection\n"
00205 " -d device The device to use\n"
00206 " -err Set exit status != 0 on parameter errors\n"
00207 "Commands:\n"
00208 " -x name1 name2 ... ; get\n"
00209 " -c name:name2:name3 ; get/check\n"
00210 " -a name1 value1 name2 value2 ... ; set\n"
00211 " -w name=value:name2=value2 ; set\n"
00212 " -l ; list parameters\n"
00213 " -lenv ; list parameters in setenv format\n"
00214 ;
00215
00216 const char HTML_END[] = " ";
00217
00218
00219
00220 #ifdef DEBUG
00221 #define D(x) x
00222 #define close(x) printf("close\n"); close(x)
00223
00224 int open_dbg(const char* name, int type)
00225 {
00226 printf("open(%s, %i)\n", name, type);
00227 return open(name, type);
00228 }
00229 #define open(name, type) open_dbg(name, type)
00230
00231 int lseek_dbg(int f, long offset, int whence)
00232 {
00233 int res;
00234
00235
00236 res = lseek(f, offset, whence);
00237 printf(" seek to %li %i result: %i %s\n", offset, whence,
00238 res, res!=offset?"!!!!":"");
00239
00240 return res;
00241
00242 }
00243 #define lseek(f, offset, whence) lseek_dbg(f, offset, whence)
00244 #else
00245 #define D(x)
00246 #endif
00247
00248
00249
00250 typedef enum {SCRIPT, NAMEVALUE } Toutput_type;
00251
00252
00253
00254 static void printUsage(void);
00255 static void die(const char *);
00256
00257 static void listParams(Toutput_type output_type);
00258
00259 static int readParam(const char *name, char **value, int *firstfree);
00260 static int writeParam(const char *name, const char *value);
00261
00262 static int writeMagic(int file, int *offset);
00263
00264 static int readParamAt(int f, int offset,
00265 char **name, int *nameLen,
00266 char **value, int *valueLen,
00267 int *totlen);
00268 static int writeParamAt(int f, int offset, const char *name,
00269 const char *value);
00270
00271 static void skipBadBlocks(int fd, int *offset);
00272
00273 static int getChipParams(void);
00274
00275 static int setFlashParams(void);
00276
00277
00278
00279
00280
00281 static int useHTML = 0;
00282 static int setExitErr = 0;
00283 static int exitStat = 0;
00284
00285 static int PARAMMAGIC = PARAMMAGIC_PRIMARY;
00286
00287 static int FlashOffset;
00288 static int FlashEnd;
00289
00290 static int nandFlash = 0;
00291
00292 static unsigned int blockSize;
00293 static unsigned int pageSize;
00294
00295
00296
00297 int
00298 main(int argc, char **argv)
00299 {
00300 int dummy;
00301 const char *method;
00302
00303 argc--;
00304 argv++;
00305
00306 if (argc > 0 && !strcmp(*argv, "-nocgi"))
00307 {
00308 argc--;
00309 argv++;
00310 }
00311 else if ((method = getenv("REQUEST_METHOD")))
00312 {
00313 useHTML = 1;
00314 printf("Content-type: text/plain\r\n\r\n");
00315 }
00316 #if 0
00317 if (useHTML)
00318 {
00319 printf("<HTML><BODY>\n");
00320 printf("<pre>\n");
00321 }
00322 #endif
00323 if (argc > 0 && !strcmp(*argv, "-err"))
00324 {
00325 setExitErr = 1;
00326 argc--;
00327 argv++;
00328 }
00329 if (argc < 1)
00330 {
00331 printUsage();
00332 }
00333
00334 openlog("bootblocktool", LOG_PID, LOG_USER);
00335
00336 if (setFlashParams() < 0)
00337 return 1;
00338
00339 while (argc)
00340 {
00341
00342
00343
00344 if (!strcmp("-backup", *argv))
00345 {
00346 argc--;
00347 argv++;
00348 PARAMMAGIC = PARAMMAGIC_BACKUP;
00349 if (setFlashParams() < 0)
00350 return 1;
00351 }
00352 else if (!strcmp("-x", *argv))
00353 {
00354 argc--;
00355 argv++;
00356 if (argc < 1) {
00357 printUsage();
00358 }
00359
00360 while (argc > 0)
00361 {
00362
00363 char *value = 0;
00364 if (!readParam(*argv, &value, &dummy))
00365 {
00366
00367 printf("%s\n", value);
00368 free(value);
00369 }
00370 else
00371 {
00372 fprintf(stderr, "Warning: Parameter %s not found.\n", *argv);
00373 exitStat = 1;
00374 }
00375 argc--;
00376 argv++;
00377 }
00378 }
00379 else if (!strcmp("-l", *argv))
00380 {
00381 argc--;
00382 argv++;
00383
00384 listParams(NAMEVALUE);
00385 }
00386 else if (!strcmp("-lenv", *argv))
00387 {
00388 argc--;
00389 argv++;
00390
00391 listParams(SCRIPT);
00392 }
00393 else if (!strcmp("-a", *argv))
00394 {
00395 argc--;
00396 argv++;
00397 if (argc < 1) {
00398 printUsage();
00399 }
00400
00401 while (argc > 1)
00402 {
00403 if (writeParam(argv[0], argv[1]))
00404 {
00405 fprintf(stderr, "Warning: Parameter %s already exists.\n", argv[0]);
00406 exitStat = 1;
00407 }
00408 argc -= 2;
00409 argv += 2;
00410 }
00411 }
00412 else if (!strcmp("-d", *argv))
00413 {
00414
00415 dev = argv[1];
00416 D(printf("New device set: \"%s\"\n", dev));
00417 argv += 2;
00418 argc -= 2;
00419
00420 if (setFlashParams() < 0)
00421 return 1;
00422 }
00423 else if (!strcmp("-c", *argv))
00424 {
00425
00426 char *name;
00427 char *sep;
00428
00429 argc--;
00430 argv++;
00431 if (argc < 1) {
00432 printUsage();
00433 }
00434 name = *argv;
00435 sep = strchr(*argv, ':');
00436
00437
00438 while (name != NULL && *name != '\0')
00439 {
00440
00441 char *value = 0;
00442 if (sep != NULL)
00443 {
00444 *sep = '\0';
00445 sep++;
00446 }
00447
00448 if (!readParam(name, &value, &dummy))
00449 {
00450
00451 if (name != *argv)
00452 {
00453 printf(" ");
00454 }
00455 printf("%s", value);
00456 free(value);
00457 }
00458 else
00459 {
00460 fprintf(stderr, "Warning: Parameter %s not found.\n", name);
00461 printf("Warning: Parameter %s not found.\n", name);
00462 exitStat = 1;
00463 }
00464 name = sep;
00465 if (sep)
00466 {
00467 sep = strchr(sep, ':');
00468 }
00469 }
00470 argc--;
00471 argv++;
00472 }
00473 else if (!strcmp("-w", *argv))
00474 {
00475
00476 char *name;
00477 char *value;
00478 char *sep = NULL;
00479
00480 argc--;
00481 argv++;
00482 if (argc < 1) {
00483 printUsage();
00484 }
00485 name = *argv;
00486 value = strchr(name, '=');
00487 sep = strchr(name, ':');
00488 if (value)
00489 {
00490 if (sep && sep < value)
00491 {
00492 value = NULL;
00493 }
00494 else
00495 {
00496 *value = '\0';
00497 value++;
00498 }
00499 }
00500 if (sep)
00501 {
00502 *sep = '\0';
00503 sep++;
00504 }
00505
00506 printf("-w: %s\n", name);
00507
00508
00509 while (name != NULL && *name != '\0')
00510 {
00511 if (value)
00512 {
00513 if (writeParam(name, value))
00514 {
00515 fprintf(stderr, "Warning: Parameter %s already exists.\n", name);
00516 exitStat = 1;
00517 }
00518 }
00519 else
00520 {
00521 fprintf(stderr, "Warning: Parameter %s submitted without value.\n", name);
00522 exitStat = 1;
00523 }
00524 name = sep;
00525 if (name)
00526 {
00527 value = strchr(name, '=');
00528 sep = strchr(name, ':');
00529 if (value)
00530 {
00531 if (sep && sep < value)
00532 {
00533 value = NULL;
00534 }
00535 else
00536 {
00537 *value = '\0';
00538 value++;
00539 }
00540 }
00541 if (sep)
00542 {
00543 *sep = '\0';
00544 sep++;
00545 }
00546 }
00547 }
00548 argc--;
00549 argv++;
00550 }
00551 else
00552 {
00553 printUsage();
00554 }
00555 }
00556 if (useHTML)
00557 {
00558 printf(HTML_END);
00559 }
00560 closelog();
00561
00562 if (setExitErr)
00563 return exitStat;
00564 return NO_ERROR;
00565 }
00566
00567
00568
00569 static void
00570 printUsage(void)
00571 {
00572 if (useHTML)
00573 {
00574 printf(usage);
00575 }
00576 else
00577 {
00578 fprintf(stderr, usage);
00579 }
00580 exit(1);
00581 }
00582
00583
00584
00585 static void
00586 die(const char *err)
00587 {
00588 if (useHTML)
00589 {
00590 printf("Error: %s\n", err);
00591 printf(HTML_END);
00592 exit(1);
00593 }
00594 else
00595 {
00596 fprintf(stderr, "Error: %s\n", err);
00597 exit(1);
00598 }
00599 }
00600
00601
00602
00603 static int
00604 writeParam(const char *name, const char *value)
00605 {
00606 int offset;
00607 int f;
00608 int readerr;
00609
00610 D(printf("writeParam: %s=%s\n", name, value));
00611
00612 if (strlen(name) > MAX_PARAM_NAME_LEN)
00613 {
00614 syslog(LOG_ERR, "Parameter name too long! %m");
00615 die("Parameter name too long!\n");
00616 }
00617
00618
00619
00620
00621 readerr = readParam(name, 0, &offset);
00622 if (!readerr)
00623 {
00624
00625 return ERR_OTHER;
00626 }
00627
00628 if ((f = open(dev, O_WRONLY )) == -1)
00629 {
00630 syslog(LOG_ERR, "Couldn't open bootblock device! %m");
00631 die("Couldn't open device!\n");
00632 }
00633
00634
00635
00636 if (readerr == ERR_NO_MAGIC)
00637 {
00638 if (writeMagic(f, &offset) < 0)
00639 {
00640 close(f);
00641 die("Error writing magic!\n");
00642 }
00643 }
00644
00645 if (writeParamAt(f, offset, name, value) < 0)
00646 {
00647 close(f);
00648 die("Error writing parameters!\n");
00649 }
00650 syslog(LOG_NOTICE, "Wrote new parameter: %s=%s\n", name, value);
00651 close(f);
00652 return NO_ERROR;
00653 }
00654
00655
00656
00657 static void
00658 listParams(Toutput_type output_type)
00659 {
00660 int offset = FlashOffset;
00661 int f;
00662 char *parname;
00663 char *parvalue;
00664 int namelen;
00665 int valuelen;
00666 int totlen;
00667 unsigned long magic = 0;
00668
00669 if ((f = open(dev, O_RDONLY)) == -1)
00670 {
00671 syslog(LOG_ERR, "Couldn't open bootblock device! %m");
00672 die("Couldn't open bootblock device!\n");
00673 }
00674
00675
00676 if (nandFlash)
00677 skipBadBlocks(f, &offset);
00678
00679
00680
00681 if (lseek(f, offset, SEEK_SET) < 0)
00682 {
00683 int err_saved = errno;
00684
00685 perror("lseek");
00686 syslog(LOG_ERR, "lseek() failed. %s", strerror(err_saved));
00687 fprintf(stderr, "bootblocktool[%d]: seek failed.\n", getpid());
00688 close(f);
00689 return;
00690 }
00691
00692 read(f, &magic, sizeof(magic));
00693
00694 if (magic == EMPTYMAGIC)
00695 {
00696
00697 D(printf("EMPTYMAGIC!\n"));
00698 close(f);
00699 return;
00700 }
00701
00702 if (magic != PARAMMAGIC)
00703 {
00704 syslog(LOG_ERR, "Wrong magic number found when trying to read parameter.");
00705 printf("ERROR: Wrong MAGIC for bootparams in listParams!\n");
00706 close(f);
00707 return;
00708 }
00709
00710
00711
00712 offset += nandFlash ? pageSize : sizeof(magic);
00713
00714
00715 for (;;)
00716 {
00717
00718 if (offset >= FlashEnd)
00719 {
00720 close(f);
00721 return;
00722 }
00723
00724
00725 if (nandFlash && BLOCK_START(offset, blockSize))
00726 skipBadBlocks(f, &offset);
00727
00728 int ret = readParamAt(f, offset, &parname, &namelen,
00729 &parvalue, &valuelen, &totlen);
00730 if (ret == ERR_END_OF_PARAMS)
00731 {
00732
00733 close(f);
00734 return;
00735 }
00736 else if (ret)
00737 {
00738 close(f);
00739 printf("ERROR: Unknown error when reading bootblock in listParams!\n");
00740 return;
00741 }
00742 else
00743 {
00744
00745 switch (output_type)
00746 {
00747 case NAMEVALUE:
00748 printf("%s=%s\n", parname, parvalue);
00749 break;
00750 case SCRIPT:
00751 printf("setenv %s \"%s\"\n", parname, parvalue);
00752 break;
00753 }
00754 free (parname);
00755 free (parvalue);
00756
00757
00758 offset += nandFlash ? ROUND_UP(totlen, pageSize) : totlen;
00759 }
00760 }
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 static int
00772 readParam(const char *name, char **value, int *firstfree)
00773 {
00774 int offset = FlashOffset;
00775 int f;
00776 char *parname;
00777 char *parvalue;
00778 int namelen;
00779 int valuelen;
00780 int totlen;
00781 unsigned long magic = 0;
00782 D(printf("readParam: '%s' \n", name));
00783
00784 if ((f = open(dev, O_RDONLY)) == -1)
00785 {
00786 syslog(LOG_ERR, "Couldn't open bootblock device! %m");
00787 die("Couldn't open bootblock device!\n");
00788 }
00789
00790
00791 if (nandFlash)
00792 skipBadBlocks(f, &offset);
00793
00794
00795
00796 if (lseek(f, offset, SEEK_SET) < 0)
00797 {
00798 int err_saved = errno;
00799
00800 perror("lseek");
00801 close(f);
00802 syslog(LOG_ERR, "lseek() failed. %s", strerror(err_saved));
00803 die("bootblocktoo: seek failed.\n");
00804 }
00805 read(f, &magic, sizeof(magic));
00806
00807 if (magic == EMPTYMAGIC)
00808 {
00809
00810 close(f);
00811 *firstfree = offset;
00812 return ERR_NO_MAGIC;
00813 }
00814
00815 if (magic != PARAMMAGIC)
00816 {
00817 close(f);
00818 syslog(LOG_ERR, "Wrong magic number found when trying to read parameter.");
00819 die("Wrong MAGIC for bootparams in readParam!\n");
00820 }
00821
00822
00823
00824 offset += nandFlash ? pageSize : sizeof(magic);
00825
00826
00827
00828 for (;;)
00829 {
00830
00831 if (nandFlash && BLOCK_START(offset, blockSize))
00832 skipBadBlocks(f, &offset);
00833
00834 int ret = readParamAt(f, offset, &parname, &namelen,
00835 &parvalue, &valuelen, &totlen);
00836 if (ret == ERR_END_OF_PARAMS)
00837 {
00838
00839 close(f);
00840 *firstfree = offset;
00841 return ERR_OTHER;
00842 }
00843 else if (ret == ERR_OTHER)
00844 {
00845 close(f);
00846 die("Unknown error when reading bootblock in readParam!\n");
00847 }
00848 else if (!strcmp(parname, name))
00849 {
00850
00851 free (parname);
00852 if (value)
00853 *value = parvalue;
00854 else
00855 free (parvalue);
00856 close(f);
00857 return NO_ERROR;
00858 }
00859 else
00860 {
00861 free (parname);
00862 free (parvalue);
00863
00864 offset += nandFlash ? ROUND_UP(totlen, pageSize) : totlen;
00865 }
00866 }
00867 }
00868
00869
00870
00871
00872
00873
00874
00875 static int
00876 readParamAt(int f, int offset, char **name, int *nameLen,
00877 char **value, int *valueLen, int *totlen)
00878 {
00879 unsigned int totallen;
00880 unsigned char buf[2];
00881 D(printf("readParamAt: %i\n", offset));
00882
00883
00884 if (offset >= FlashEnd)
00885 return ERR_END_OF_PARAMS;
00886
00887
00888 if (lseek(f, offset, SEEK_SET) < 0)
00889 {
00890 syslog(LOG_ERR, "Could not read parameter! lseek() failed! %m");
00891 D(printf("lseek failed\n"));
00892
00893 return ERR_OTHER;
00894 }
00895
00896
00897 if (read(f, buf, 2) != 2)
00898 {
00899 return ERR_OTHER;
00900 }
00901 totallen = buf[0] + (buf[1] << 8);
00902 D(printf(" totallen: %i \n", totallen));
00903 if (totallen == 0xffff)
00904 {
00905 return ERR_END_OF_PARAMS;
00906 }
00907 if (read(f, buf, 1) != 1)
00908 {
00909 return ERR_OTHER;
00910 }
00911 *nameLen = (int)buf[0];
00912 D(printf(" nameLen: %i \n", *nameLen));
00913
00914 if (!(*name = (char *)malloc(*nameLen + 1)))
00915 return ERR_OTHER;
00916 if (read(f, *name, *nameLen) != *nameLen)
00917 {
00918 free (*name);
00919 return ERR_OTHER;
00920 }
00921 (*name)[*nameLen] = '\0';
00922 D(printf(" *name: %s \n", *name));
00923 *valueLen = totallen - 3 - *nameLen;
00924
00925 if (!(*value = (char *)malloc(*valueLen + 1)))
00926 {
00927 free(*name);
00928 return ERR_OTHER;
00929 }
00930
00931 if (read(f, *value, *valueLen) != *valueLen)
00932 {
00933 free(*name);
00934 free(*value);
00935 return ERR_OTHER;
00936 }
00937 (*value)[*valueLen] = 0;
00938 *totlen = totallen;
00939 return 0;
00940 }
00941
00942
00943
00944
00945
00946 static int
00947 writeParamAt(int f, int offset, const char *name, const char *value)
00948 {
00949 int bufsize;
00950 unsigned char *buf;
00951 int valuelen;
00952 int namelen;
00953 int totlen;
00954 D(printf("writeParamAt: %i'%s'='%s' \n", offset, name, value));
00955 valuelen = strlen(value);
00956 namelen = strlen(name);
00957 totlen = 3 + namelen + valuelen;
00958
00959
00960
00961
00962 bufsize = nandFlash ? ROUND_UP(totlen, pageSize) : totlen;
00963 D(printf("buffer size %d\n", bufsize));
00964
00965 if (totlen >= MAX_RECORD_LEN ||
00966 !(buf = (unsigned char *)malloc(bufsize)) ||
00967 offset + bufsize >= FlashEnd)
00968 {
00969 return ERR_OTHER;
00970 }
00971
00972
00973
00974
00975
00976
00977
00978 if (nandFlash) {
00979 if ((offset & ~(blockSize - 1)) !=
00980 ((offset + bufsize) & ~(blockSize - 1)))
00981 {
00982 D(printf("parameter won't fit!\n"));
00983 D(printf("offset = 0x%x, bufsize = 0x%x, "
00984 "offsetpage = 0x%x, offset+bufpage = 0x%x\n",
00985 offset, bufsize, offset & ~(blockSize -1),
00986 (offset + bufsize) & ~(blockSize-1)));
00987 return ERR_OTHER;
00988 }
00989 }
00990
00991 if (nandFlash)
00992 memset(buf, 0xff, bufsize);
00993
00994 buf[0] = (totlen & 0x00ff) >> 0;
00995 buf[1] = (totlen & 0xff00) >> 8;
00996 buf[2] = (namelen & 0x00ff) >> 0;
00997 memcpy(buf + 3, name, namelen);
00998 memcpy(buf + 3 + namelen, value, valuelen);
00999
01000 if (lseek(f, offset, SEEK_SET) < 0)
01001 {
01002 int err_saved = errno;
01003
01004 D(perror("lseek");
01005 printf("lseek failed\n");
01006 );
01007 syslog(LOG_ERR, "Could not write parameter! lseek() failed! %s", strerror(err_saved));
01008 goto error;
01009 }
01010
01011
01012
01013 if (write(f, buf, bufsize) != bufsize)
01014 {
01015 int err_saved = errno;
01016
01017 D(perror("write ");
01018 printf("write failed\n");
01019 );
01020 syslog(LOG_ERR, "Could not write parameter! write() failed! %s", strerror(err_saved));
01021 goto error;
01022 }
01023
01024 free(buf);
01025 return NO_ERROR;
01026
01027 error:
01028 free(buf);
01029 return ERR_OTHER;
01030 }
01031
01032
01033
01034
01035
01036 static int
01037 writeMagic(int file, int *offset)
01038 {
01039 int bufsize;
01040 unsigned char *buf;
01041 unsigned long magic = PARAMMAGIC;
01042
01043 D(printf("writeMagic at %i \n", *offset));
01044
01045 bufsize = nandFlash ? pageSize : sizeof(magic);
01046 if (!(buf = (unsigned char *)malloc(bufsize)))
01047 {
01048 return ERR_OTHER;
01049 }
01050
01051 if (nandFlash)
01052 memset(buf, 0xff, bufsize);
01053
01054 memcpy(buf, &magic, sizeof(magic));
01055
01056 if (lseek(file, *offset, SEEK_SET) < 0)
01057 {
01058 int err_saved = errno;
01059
01060 D(perror("lseek");
01061 printf("lseek failed\n");
01062 );
01063 syslog(LOG_ERR, "Could not write magic number! lseek() failed! %s", strerror(err_saved));
01064 goto error;
01065 }
01066
01067
01068 if (write(file, buf, bufsize) != bufsize)
01069 {
01070 int err_saved = errno;
01071
01072 D(perror("write");
01073 printf("write failed\n"););
01074 syslog(LOG_ERR, "Could not write magic number! write() failed! %s", strerror(err_saved));
01075 goto error;
01076 }
01077
01078 (*offset) += bufsize;
01079
01080 free(buf);
01081
01082 return NO_ERROR;
01083
01084 error:
01085 free(buf);
01086 return ERR_OTHER;
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096 static int
01097 getChipParams(void)
01098 {
01099 int fd;
01100 struct mtd_info_user mtdInfo;
01101
01102 if ((fd = open(dev, O_RDONLY)) < 0)
01103 {
01104 syslog(LOG_ERR, "Couldn't open bootblock device! %m");
01105 die("Couldn't open bootblock device!\n");
01106 }
01107
01108
01109
01110 #if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0)
01111
01112 if ((ioctl(fd, MEMGETINFO, &mtdInfo)) < 0)
01113 {
01114 close(fd);
01115 syslog(LOG_ERR, "Couldn't get chip parameters! %m");
01116 die("Couldn't get chip parameters!\n");
01117 }
01118
01119 nandFlash = (mtdInfo.type == MTD_NANDFLASH);
01120 blockSize = mtdInfo.erasesize;
01121 #if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 18)
01122 pageSize = mtdInfo.writesize;
01123 #else
01124 pageSize = mtdInfo.oobblock;
01125 #endif
01126
01127 #else
01128
01129 nandFlash = blockSize = pageSize = 0;
01130
01131 #endif
01132
01133 D(printf("Flash type %s, blocksize %d, pagesize %d\n",
01134 nandFlash ? "NAND" : "NOR", blockSize, pageSize));
01135
01136 #if !defined(MEMGETBADBLOCK)
01137 if (nandFlash)
01138 {
01139 syslog(LOG_ERR, "NAND flash bad block detection "
01140 "not supported in this kernel version! %m");
01141 die("NAND flash bad block detection not supported in this kernel version\n");
01142 }
01143 #endif
01144
01145 close(fd);
01146
01147 return 0;
01148 }
01149
01150
01151
01152
01153
01154 static void
01155 skipBadBlocks(int fd, int *offset)
01156 {
01157 #if defined(MEMGETBADBLOCK)
01158 int blockbad = 1;
01159
01160 loff_t loffset = *offset;
01161
01162 while (blockbad && loffset < FlashEnd)
01163 {
01164 if ((blockbad = ioctl(fd, MEMGETBADBLOCK, &loffset)) < 0)
01165 {
01166 close(fd);
01167 syslog(LOG_ERR, "Couldn't determine block status! %m");
01168 die("Couldn't determine block status!\n");
01169 }
01170 if (blockbad)
01171 loffset += blockSize;
01172 }
01173
01174 *offset = loffset;
01175 if (loffset >= FlashEnd)
01176 {
01177 close(fd);
01178 syslog(LOG_ERR, "Ran out of good blocks!");
01179 die("Ran out of good blocks!\n");
01180 }
01181
01182 #else
01183
01184
01185
01186
01187 #endif
01188 }
01189
01190
01191
01192
01193
01194
01195 static int
01196 setFlashParams(void)
01197 {
01198
01199 #if !defined(USE_FWINFO_AREA) || NAND_NOR_COMPATIBILITY_MODE
01200
01201
01202
01203 if (PARAMMAGIC == PARAMMAGIC_PRIMARY) {
01204 FlashOffset = 0xc000;
01205 FlashEnd = 0x10000;
01206 } else {
01207 FlashOffset = 0x10000;
01208 FlashEnd = 0x14000;
01209 }
01210
01211 #else
01212
01213 struct fwinfo fwinfo;
01214
01215 if (read_flash_fwinfo(dev, &fwinfo) < 0)
01216 return -1;
01217
01218 FlashOffset = fwinfo.bootblkpar_flash_addr;
01219 FlashEnd = fwinfo.bootblkpar_flash_end;
01220
01221 #endif
01222
01223 if (getChipParams() < 0)
01224 return -1;
01225
01226 return 0;
01227 }
01228
01229