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