1/*- 2 * Copyright (C) 2009-2012 Semihalf 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/errno.h> 31#include <sys/ioctl.h> 32#include <sys/types.h> 33 34#include <dev/nand/nandsim.h> 35 36#include <ctype.h> 37#include <fcntl.h> 38#include <stdio.h> 39#include <string.h> 40#include <stdlib.h> 41#include <sysexits.h> 42#include <unistd.h> 43 44#include "nandsim_cfgparse.h" 45 46#define warn(fmt, args...) do { \ 47 printf("WARNING: " fmt "\n", ##args); } while (0) 48 49#define error(fmt, args...) do { \ 50 printf("ERROR: " fmt "\n", ##args); } while (0) 51 52#define MSG_MANDATORYKEYMISSING "mandatory key \"%s\" value belonging to " \ 53 "section \"%s\" is missing!\n" 54 55#define DEBUG 56#undef DEBUG 57 58#ifdef DEBUG 59#define debug(fmt, args...) do { \ 60 printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0) 61#else 62#define debug(fmt, args...) do {} while(0) 63#endif 64 65#define STRBUFSIZ 2000 66 67/* Macros extracts type and type size */ 68#define TYPE(x) ((x) & 0xf8) 69#define SIZE(x) (((x) & 0x07)) 70 71/* Erase/Prog/Read time max and min values */ 72#define DELAYTIME_MIN 10000 73#define DELAYTIME_MAX 10000000 74 75/* Structure holding configuration for controller. */ 76static struct sim_ctrl ctrl_conf; 77/* Structure holding configuration for chip. */ 78static struct sim_chip chip_conf; 79 80static struct nandsim_key nandsim_ctrl_keys[] = { 81 {"num_cs", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num_cs, 0}, 82 {"ctrl_num", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num, 0}, 83 84 {"ecc_layout", 1, VALUE_UINTARRAY | SIZE_16, 85 (void *)&ctrl_conf.ecc_layout, MAX_ECC_BYTES}, 86 87 {"filename", 0, VALUE_STRING, 88 (void *)&ctrl_conf.filename, FILENAME_SIZE}, 89 90 {"ecc", 0, VALUE_BOOL, (void *)&ctrl_conf.ecc, 0}, 91 {NULL, 0, 0, NULL, 0}, 92}; 93 94static struct nandsim_key nandsim_chip_keys[] = { 95 {"chip_cs", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.num, 0}, 96 {"chip_ctrl", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.ctrl_num, 97 0}, 98 {"device_id", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.device_id, 99 0}, 100 {"manufacturer_id", 1, VALUE_UINT | SIZE_8, 101 (void *)&chip_conf.manufact_id, 0}, 102 {"model", 0, VALUE_STRING, (void *)&chip_conf.device_model, 103 DEV_MODEL_STR_SIZE}, 104 {"manufacturer", 0, VALUE_STRING, (void *)&chip_conf.manufacturer, 105 MAN_STR_SIZE}, 106 {"page_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.page_size, 107 0}, 108 {"oob_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.oob_size, 109 0}, 110 {"pages_per_block", 1, VALUE_UINT | SIZE_32, 111 (void *)&chip_conf.pgs_per_blk, 0}, 112 {"blocks_per_lun", 1, VALUE_UINT | SIZE_32, 113 (void *)&chip_conf.blks_per_lun, 0}, 114 {"luns", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.luns, 0}, 115 {"column_addr_cycle", 1,VALUE_UINT | SIZE_8, 116 (void *)&chip_conf.col_addr_cycles, 0}, 117 {"row_addr_cycle", 1, VALUE_UINT | SIZE_8, 118 (void *)&chip_conf.row_addr_cycles, 0}, 119 {"program_time", 0, VALUE_UINT | SIZE_32, 120 (void *)&chip_conf.prog_time, 0}, 121 {"erase_time", 0, VALUE_UINT | SIZE_32, 122 (void *)&chip_conf.erase_time, 0}, 123 {"read_time", 0, VALUE_UINT | SIZE_32, 124 (void *)&chip_conf.read_time, 0}, 125 {"width", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.width, 0}, 126 {"wear_out", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.wear_level, 127 0}, 128 {"bad_block_map", 0, VALUE_UINTARRAY | SIZE_32, 129 (void *)&chip_conf.bad_block_map, MAX_BAD_BLOCKS}, 130 {NULL, 0, 0, NULL, 0}, 131}; 132 133static struct nandsim_section sections[] = { 134 {"ctrl", (struct nandsim_key *)&nandsim_ctrl_keys}, 135 {"chip", (struct nandsim_key *)&nandsim_chip_keys}, 136 {NULL, NULL}, 137}; 138 139static uint8_t logoutputtoint(char *, int *); 140static uint8_t validate_chips(struct sim_chip *, int, struct sim_ctrl *, int); 141static uint8_t validate_ctrls(struct sim_ctrl *, int); 142static int configure_sim(const char *, struct rcfile *); 143static int create_ctrls(struct rcfile *, struct sim_ctrl **, int *); 144static int create_chips(struct rcfile *, struct sim_chip **, int *); 145static void destroy_ctrls(struct sim_ctrl *); 146static void destroy_chips(struct sim_chip *); 147static int validate_section_config(struct rcfile *, const char *, int); 148 149int 150convert_argint(char *arg, int *value) 151{ 152 153 if (arg == NULL || value == NULL) 154 return (EINVAL); 155 156 errno = 0; 157 *value = (int)strtol(arg, NULL, 0); 158 if (*value == 0 && errno != 0) { 159 error("Cannot convert to number argument \'%s\'", arg); 160 return (EINVAL); 161 } 162 return (0); 163} 164 165int 166convert_arguint(char *arg, unsigned int *value) 167{ 168 169 if (arg == NULL || value == NULL) 170 return (EINVAL); 171 172 errno = 0; 173 *value = (unsigned int)strtol(arg, NULL, 0); 174 if (*value == 0 && errno != 0) { 175 error("Cannot convert to number argument \'%s\'", arg); 176 return (EINVAL); 177 } 178 return (0); 179} 180 181/* Parse given ',' separated list of bytes into buffer. */ 182int 183parse_intarray(char *array, int **buffer) 184{ 185 char *tmp, *tmpstr, *origstr; 186 unsigned int currbufp = 0, i; 187 unsigned int count = 0, from = 0, to = 0; 188 189 /* Remove square braces */ 190 if (array[0] == '[') 191 array ++; 192 if (array[strlen(array)-1] == ']') 193 array[strlen(array)-1] = ','; 194 195 from = strlen(array); 196 origstr = (char *)malloc(sizeof(char) * from); 197 strcpy(origstr, array); 198 199 tmpstr = (char *)strtok(array, ","); 200 /* First loop checks for how big int array we need to allocate */ 201 while (tmpstr != NULL) { 202 errno = 0; 203 if ((tmp = strchr(tmpstr, '-')) != NULL) { 204 *tmp = ' '; 205 if (convert_arguint(tmpstr, &from) || 206 convert_arguint(tmp, &to)) { 207 free(origstr); 208 return (EINVAL); 209 } 210 211 count += to - from + 1; 212 } else { 213 if (convert_arguint(tmpstr, &from)) { 214 free(origstr); 215 return (EINVAL); 216 } 217 count++; 218 } 219 tmpstr = (char *)strtok(NULL, ","); 220 } 221 222 if (count == 0) 223 goto out; 224 225 /* Allocate buffer of ints */ 226 tmpstr = (char *)strtok(origstr, ","); 227 *buffer = malloc(count * sizeof(int)); 228 229 /* Second loop is just inserting converted values into int array */ 230 while (tmpstr != NULL) { 231 errno = 0; 232 if ((tmp = strchr(tmpstr, '-')) != NULL) { 233 *tmp = ' '; 234 from = strtol(tmpstr, NULL, 0); 235 to = strtol(tmp, NULL, 0); 236 tmpstr = strtok(NULL, ","); 237 for (i = from; i <= to; i ++) 238 (*buffer)[currbufp++] = i; 239 continue; 240 } 241 errno = 0; 242 from = (int)strtol(tmpstr, NULL, 0); 243 (*buffer)[currbufp++] = from; 244 tmpstr = (char *)strtok(NULL, ","); 245 } 246out: 247 free(origstr); 248 return (count); 249} 250 251/* Convert logoutput strings literals into appropriate ints. */ 252static uint8_t 253logoutputtoint(char *logoutput, int *output) 254{ 255 int out; 256 257 if (strcmp(logoutput, "file") == 0) 258 out = NANDSIM_OUTPUT_FILE; 259 260 else if (strcmp(logoutput, "console") == 0) 261 out = NANDSIM_OUTPUT_CONSOLE; 262 263 else if (strcmp(logoutput, "ram") == 0) 264 out = NANDSIM_OUTPUT_RAM; 265 266 else if (strcmp(logoutput, "none") == 0) 267 out = NANDSIM_OUTPUT_NONE; 268 else 269 out = -1; 270 271 *output = out; 272 273 if (out == -1) 274 return (EINVAL); 275 else 276 return (0); 277} 278 279static int 280configure_sim(const char *devfname, struct rcfile *f) 281{ 282 struct sim_param sim_conf; 283 char buf[255]; 284 int err, tmpv, fd; 285 286 err = rc_getint(f, "sim", 0, "log_level", &tmpv); 287 288 if (tmpv < 0 || tmpv > 255 || err) { 289 error("Bad log level specified (%d)\n", tmpv); 290 return (ENOTSUP); 291 } else 292 sim_conf.log_level = tmpv; 293 294 rc_getstring(f, "sim", 0, "log_output", 255, (char *)&buf); 295 296 tmpv = -1; 297 err = logoutputtoint((char *)&buf, &tmpv); 298 if (err) { 299 error("Log output specified in config file does not seem to " 300 "be valid (%s)!", (char *)&buf); 301 return (ENOTSUP); 302 } 303 304 sim_conf.log_output = tmpv; 305 306 fd = open(devfname, O_RDWR); 307 if (fd == -1) { 308 error("could not open simulator device file (%s)!", 309 devfname); 310 return (EX_OSFILE); 311 } 312 313 err = ioctl(fd, NANDSIM_SIM_PARAM, &sim_conf); 314 if (err) { 315 error("simulator parameters could not be modified: %s", 316 strerror(errno)); 317 close(fd); 318 return (ENXIO); 319 } 320 321 close(fd); 322 return (EX_OK); 323} 324 325static int 326create_ctrls(struct rcfile *f, struct sim_ctrl **ctrls, int *cnt) 327{ 328 int count, i; 329 struct sim_ctrl *ctrlsptr; 330 331 count = rc_getsectionscount(f, "ctrl"); 332 if (count > MAX_SIM_DEV) { 333 error("Too many CTRL sections specified(%d)", count); 334 return (ENOTSUP); 335 } else if (count == 0) { 336 error("No ctrl sections specified"); 337 return (ENOENT); 338 } 339 340 ctrlsptr = (struct sim_ctrl *)malloc(sizeof(struct sim_ctrl) * count); 341 if (ctrlsptr == NULL) { 342 error("Could not allocate memory for ctrl configuration"); 343 return (ENOMEM); 344 } 345 346 for (i = 0; i < count; i++) { 347 bzero((void *)&ctrl_conf, sizeof(ctrl_conf)); 348 349 /* 350 * ECC layout have to end up with 0xffff, so 351 * we're filling buffer with 0xff. If ecc_layout is 352 * defined in config file, values will be overridden. 353 */ 354 memset((void *)&ctrl_conf.ecc_layout, 0xff, 355 sizeof(ctrl_conf.ecc_layout)); 356 357 if (validate_section_config(f, "ctrl", i) != 0) { 358 free(ctrlsptr); 359 return (EINVAL); 360 } 361 362 if (parse_section(f, "ctrl", i) != 0) { 363 free(ctrlsptr); 364 return (EINVAL); 365 } 366 367 memcpy(&ctrlsptr[i], &ctrl_conf, sizeof(ctrl_conf)); 368 /* Try to create ctrl with config parsed */ 369 debug("NUM=%d\nNUM_CS=%d\nECC=%d\nFILENAME=%s\nECC_LAYOUT[0]" 370 "=%d\nECC_LAYOUT[1]=%d\n\n", 371 ctrlsptr[i].num, ctrlsptr[i].num_cs, ctrlsptr[i].ecc, 372 ctrlsptr[i].filename, ctrlsptr[i].ecc_layout[0], 373 ctrlsptr[i].ecc_layout[1]); 374 } 375 *cnt = count; 376 *ctrls = ctrlsptr; 377 return (0); 378} 379 380static void 381destroy_ctrls(struct sim_ctrl *ctrls) 382{ 383 384 free(ctrls); 385} 386 387static int 388create_chips(struct rcfile *f, struct sim_chip **chips, int *cnt) 389{ 390 struct sim_chip *chipsptr; 391 int count, i; 392 393 count = rc_getsectionscount(f, "chip"); 394 if (count > (MAX_CTRL_CS * MAX_SIM_DEV)) { 395 error("Too many chip sections specified(%d)", count); 396 return (ENOTSUP); 397 } else if (count == 0) { 398 error("No chip sections specified"); 399 return (ENOENT); 400 } 401 402 chipsptr = (struct sim_chip *)malloc(sizeof(struct sim_chip) * count); 403 if (chipsptr == NULL) { 404 error("Could not allocate memory for chip configuration"); 405 return (ENOMEM); 406 } 407 408 for (i = 0; i < count; i++) { 409 bzero((void *)&chip_conf, sizeof(chip_conf)); 410 411 /* 412 * Bad block map have to end up with 0xffff, so 413 * we're filling array with 0xff. If bad block map is 414 * defined in config file, values will be overridden. 415 */ 416 memset((void *)&chip_conf.bad_block_map, 0xff, 417 sizeof(chip_conf.bad_block_map)); 418 419 if (validate_section_config(f, "chip", i) != 0) { 420 free(chipsptr); 421 return (EINVAL); 422 } 423 424 if (parse_section(f, "chip", i) != 0) { 425 free(chipsptr); 426 return (EINVAL); 427 } 428 429 memcpy(&chipsptr[i], &chip_conf, sizeof(chip_conf)); 430 431 /* Try to create chip with config parsed */ 432 debug("CHIP:\nNUM=%d\nCTRL_NUM=%d\nDEVID=%d\nMANID=%d\n" 433 "PAGE_SZ=%d\nOOBSZ=%d\nREAD_T=%d\nDEVMODEL=%s\n" 434 "MAN=%s\nCOLADDRCYCLES=%d\nROWADDRCYCLES=%d\nCHWIDTH=%d\n" 435 "PGS/BLK=%d\nBLK/LUN=%d\nLUNS=%d\nERR_RATIO=%d\n" 436 "WEARLEVEL=%d\nISWP=%d\n\n\n\n", 437 chipsptr[i].num, chipsptr[i].ctrl_num, 438 chipsptr[i].device_id, chipsptr[i].manufact_id, 439 chipsptr[i].page_size, chipsptr[i].oob_size, 440 chipsptr[i].read_time, chipsptr[i].device_model, 441 chipsptr[i].manufacturer, chipsptr[i].col_addr_cycles, 442 chipsptr[i].row_addr_cycles, chipsptr[i].width, 443 chipsptr[i].pgs_per_blk, chipsptr[i].blks_per_lun, 444 chipsptr[i].luns, chipsptr[i].error_ratio, 445 chipsptr[i].wear_level, chipsptr[i].is_wp); 446 } 447 *cnt = count; 448 *chips = chipsptr; 449 return (0); 450} 451 452static void 453destroy_chips(struct sim_chip *chips) 454{ 455 456 free(chips); 457} 458 459int 460parse_config(char *cfgfname, const char *devfname) 461{ 462 int err = 0, fd; 463 unsigned int chipsectionscnt, ctrlsectionscnt, i; 464 struct rcfile *f; 465 struct sim_chip *chips; 466 struct sim_ctrl *ctrls; 467 468 err = rc_open(cfgfname, "r", &f); 469 if (err) { 470 error("could not open configuration file (%s)", cfgfname); 471 return (EX_NOINPUT); 472 } 473 474 /* First, try to configure simulator itself. */ 475 if (configure_sim(devfname, f) != EX_OK) { 476 rc_close(f); 477 return (EINVAL); 478 } 479 480 debug("SIM CONFIGURED!\n"); 481 /* Then create controllers' configs */ 482 if (create_ctrls(f, &ctrls, &ctrlsectionscnt) != 0) { 483 rc_close(f); 484 return (ENXIO); 485 } 486 debug("CTRLS CONFIG READ!\n"); 487 488 /* Then create chips' configs */ 489 if (create_chips(f, &chips, &chipsectionscnt) != 0) { 490 destroy_ctrls(ctrls); 491 rc_close(f); 492 return (ENXIO); 493 } 494 debug("CHIPS CONFIG READ!\n"); 495 496 if (validate_ctrls(ctrls, ctrlsectionscnt) != 0) { 497 destroy_ctrls(ctrls); 498 destroy_chips(chips); 499 rc_close(f); 500 return (EX_SOFTWARE); 501 } 502 if (validate_chips(chips, chipsectionscnt, ctrls, 503 ctrlsectionscnt) != 0) { 504 destroy_ctrls(ctrls); 505 destroy_chips(chips); 506 rc_close(f); 507 return (EX_SOFTWARE); 508 } 509 510 /* Open device */ 511 fd = open(devfname, O_RDWR); 512 if (fd == -1) { 513 error("could not open simulator device file (%s)!", 514 devfname); 515 rc_close(f); 516 destroy_chips(chips); 517 destroy_ctrls(ctrls); 518 return (EX_OSFILE); 519 } 520 521 debug("SIM CONFIG STARTED!\n"); 522 523 /* At this stage, both ctrls' and chips' configs should be valid */ 524 for (i = 0; i < ctrlsectionscnt; i++) { 525 err = ioctl(fd, NANDSIM_CREATE_CTRL, &ctrls[i]); 526 if (err) { 527 if (err == EEXIST) 528 error("Controller#%d already created\n", 529 ctrls[i].num); 530 else if (err == EINVAL) 531 error("Incorrect controler number (%d)\n", 532 ctrls[i].num); 533 else 534 error("Could not created controller#%d\n", 535 ctrls[i].num); 536 /* Errors during controller creation stops parsing */ 537 close(fd); 538 rc_close(f); 539 destroy_ctrls(ctrls); 540 destroy_chips(chips); 541 return (ENXIO); 542 } 543 debug("CTRL#%d CONFIG STARTED!\n", i); 544 } 545 546 for (i = 0; i < chipsectionscnt; i++) { 547 err = ioctl(fd, NANDSIM_CREATE_CHIP, &chips[i]); 548 if (err) { 549 if (err == EEXIST) 550 error("Chip#%d for controller#%d already " 551 "created\n", chips[i].num, 552 chips[i].ctrl_num); 553 else if (err == EINVAL) 554 error("Incorrect chip number (%d:%d)\n", 555 chips[i].num, chips[i].ctrl_num); 556 else 557 error("Could not create chip (%d:%d)\n", 558 chips[i].num, chips[i].ctrl_num); 559 error("Could not start chip#%d\n", i); 560 destroy_chips(chips); 561 destroy_ctrls(ctrls); 562 close(fd); 563 rc_close(f); 564 return (ENXIO); 565 } 566 } 567 debug("CHIPS CONFIG STARTED!\n"); 568 569 close(fd); 570 rc_close(f); 571 destroy_chips(chips); 572 destroy_ctrls(ctrls); 573 return (0); 574} 575 576/* 577 * Function tries to get appropriate value for given key, convert it to 578 * array of ints (of given size), and perform all the necessary checks and 579 * conversions. 580 */ 581static int 582get_argument_intarray(const char *sect_name, int sectno, 583 struct nandsim_key *key, struct rcfile *f) 584{ 585 char strbuf[STRBUFSIZ]; 586 int *intbuf; 587 int getres; 588 uint32_t cnt, i = 0; 589 590 getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ, 591 (char *)&strbuf); 592 593 if (getres != 0) { 594 if (key->mandatory != 0) { 595 error(MSG_MANDATORYKEYMISSING, key->keyname, 596 sect_name); 597 return (EINVAL); 598 } else 599 /* Non-mandatory key, not present -- skip */ 600 return (0); 601 } 602 cnt = parse_intarray((char *)&strbuf, &intbuf); 603 cnt = (cnt <= key->maxlength) ? cnt : key->maxlength; 604 605 for (i = 0; i < cnt; i++) { 606 if (SIZE(key->valuetype) == SIZE_8) 607 *((uint8_t *)(key->field) + i) = 608 (uint8_t)intbuf[i]; 609 else if (SIZE(key->valuetype) == SIZE_16) 610 *((uint16_t *)(key->field) + i) = 611 (uint16_t)intbuf[i]; 612 else 613 *((uint32_t *)(key->field) + i) = 614 (uint32_t)intbuf[i]; 615 } 616 free(intbuf); 617 return (0); 618} 619 620/* 621 * Function tries to get appropriate value for given key, convert it to 622 * int of certain length. 623 */ 624static int 625get_argument_int(const char *sect_name, int sectno, struct nandsim_key *key, 626 struct rcfile *f) 627{ 628 int getres; 629 uint32_t val; 630 631 getres = rc_getint(f, sect_name, sectno, key->keyname, &val); 632 if (getres != 0) { 633 634 if (key->mandatory != 0) { 635 error(MSG_MANDATORYKEYMISSING, key->keyname, 636 sect_name); 637 638 return (EINVAL); 639 } else 640 /* Non-mandatory key, not present -- skip */ 641 return (0); 642 } 643 if (SIZE(key->valuetype) == SIZE_8) 644 *(uint8_t *)(key->field) = (uint8_t)val; 645 else if (SIZE(key->valuetype) == SIZE_16) 646 *(uint16_t *)(key->field) = (uint16_t)val; 647 else 648 *(uint32_t *)(key->field) = (uint32_t)val; 649 return (0); 650} 651 652/* Function tries to get string value for given key */ 653static int 654get_argument_string(const char *sect_name, int sectno, 655 struct nandsim_key *key, struct rcfile *f) 656{ 657 char strbuf[STRBUFSIZ]; 658 int getres; 659 660 getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ, 661 strbuf); 662 663 if (getres != 0) { 664 if (key->mandatory != 0) { 665 error(MSG_MANDATORYKEYMISSING, key->keyname, 666 sect_name); 667 return (1); 668 } else 669 /* Non-mandatory key, not present -- skip */ 670 return (0); 671 } 672 strncpy(key->field, (char *)&strbuf, (size_t)(key->maxlength - 1)); 673 return (0); 674} 675 676/* Function tries to get on/off value for given key */ 677static int 678get_argument_bool(const char *sect_name, int sectno, struct nandsim_key *key, 679 struct rcfile *f) 680{ 681 int getres, val; 682 683 getres = rc_getbool(f, sect_name, sectno, key->keyname, &val); 684 if (getres != 0) { 685 if (key->mandatory != 0) { 686 error(MSG_MANDATORYKEYMISSING, key->keyname, 687 sect_name); 688 return (1); 689 } else 690 /* Non-mandatory key, not present -- skip */ 691 return (0); 692 } 693 *(uint8_t *)key->field = (uint8_t)val; 694 return (0); 695} 696 697int 698parse_section(struct rcfile *f, const char *sect_name, int sectno) 699{ 700 struct nandsim_key *key; 701 struct nandsim_section *sect = (struct nandsim_section *)§ions; 702 int getres = 0; 703 704 while (1) { 705 if (sect == NULL) 706 return (EINVAL); 707 708 if (strcmp(sect->name, sect_name) == 0) 709 break; 710 else 711 sect++; 712 } 713 key = sect->keys; 714 do { 715 debug("->Section: %s, Key: %s, type: %d, size: %d", 716 sect_name, key->keyname, TYPE(key->valuetype), 717 SIZE(key->valuetype)/2); 718 719 switch (TYPE(key->valuetype)) { 720 case VALUE_UINT: 721 /* Single int value */ 722 getres = get_argument_int(sect_name, sectno, key, f); 723 724 if (getres != 0) 725 return (getres); 726 727 break; 728 case VALUE_UINTARRAY: 729 /* Array of ints */ 730 getres = get_argument_intarray(sect_name, 731 sectno, key, f); 732 733 if (getres != 0) 734 return (getres); 735 736 break; 737 case VALUE_STRING: 738 /* Array of chars */ 739 getres = get_argument_string(sect_name, sectno, key, 740 f); 741 742 if (getres != 0) 743 return (getres); 744 745 break; 746 case VALUE_BOOL: 747 /* Boolean value (true/false/on/off/yes/no) */ 748 getres = get_argument_bool(sect_name, sectno, key, 749 f); 750 751 if (getres != 0) 752 return (getres); 753 754 break; 755 } 756 } while ((++key)->keyname != NULL); 757 758 return (0); 759} 760 761static uint8_t 762validate_chips(struct sim_chip *chips, int chipcnt, 763 struct sim_ctrl *ctrls, int ctrlcnt) 764{ 765 int cchipcnt, i, width, j, id, max; 766 767 cchipcnt = chipcnt; 768 for (chipcnt -= 1; chipcnt >= 0; chipcnt--) { 769 if (chips[chipcnt].num >= MAX_CTRL_CS) { 770 error("chip no. too high (%d)!!\n", 771 chips[chipcnt].num); 772 return (EINVAL); 773 } 774 775 if (chips[chipcnt].ctrl_num >= MAX_SIM_DEV) { 776 error("controller no. too high (%d)!!\n", 777 chips[chipcnt].ctrl_num); 778 return (EINVAL); 779 } 780 781 if (chips[chipcnt].width != 8 && 782 chips[chipcnt].width != 16) { 783 error("invalid width:%d for chip#%d", 784 chips[chipcnt].width, chips[chipcnt].num); 785 return (EINVAL); 786 } 787 788 /* Check if page size is > 512 and if its power of 2 */ 789 if (chips[chipcnt].page_size < 512 || 790 (chips[chipcnt].page_size & 791 (chips[chipcnt].page_size - 1)) != 0) { 792 error("invalid page size:%d for chip#%d at ctrl#%d!!" 793 "\n", chips[chipcnt].page_size, 794 chips[chipcnt].num, 795 chips[chipcnt].ctrl_num); 796 return (EINVAL); 797 } 798 799 /* Check if controller no. ctrl_num is configured */ 800 for (i = 0, id = -1; i < ctrlcnt && id == -1; i++) 801 if (ctrls[i].num == chips[chipcnt].ctrl_num) 802 id = i; 803 804 if (i == ctrlcnt && id == -1) { 805 error("Missing configuration for controller %d" 806 " (at least one chip is connected to it)", 807 chips[chipcnt].ctrl_num); 808 return (EINVAL); 809 } else { 810 /* 811 * Controller is configured -> check oob_size 812 * validity 813 */ 814 i = 0; 815 max = ctrls[id].ecc_layout[0]; 816 while (i < MAX_ECC_BYTES && 817 ctrls[id].ecc_layout[i] != 0xffff) { 818 819 if (ctrls[id].ecc_layout[i] > max) 820 max = ctrls[id].ecc_layout[i]; 821 i++; 822 } 823 824 if (chips[chipcnt].oob_size < (unsigned)i) { 825 error("OOB size for chip#%d at ctrl#%d is " 826 "smaller than ecc layout length!", 827 chips[chipcnt].num, 828 chips[chipcnt].ctrl_num); 829 exit(EINVAL); 830 } 831 832 if (chips[chipcnt].oob_size < (unsigned)max) { 833 error("OOB size for chip#%d at ctrl#%d is " 834 "smaller than maximal ecc position in " 835 "defined layout!", chips[chipcnt].num, 836 chips[chipcnt].ctrl_num); 837 exit(EINVAL); 838 } 839 840 841 } 842 843 if ((chips[chipcnt].erase_time < DELAYTIME_MIN || 844 chips[chipcnt].erase_time > DELAYTIME_MAX) && 845 chips[chipcnt].erase_time != 0) { 846 error("Invalid erase time value for chip#%d at " 847 "ctrl#%d", 848 chips[chipcnt].num, 849 chips[chipcnt].ctrl_num); 850 return (EINVAL); 851 } 852 853 if ((chips[chipcnt].prog_time < DELAYTIME_MIN || 854 chips[chipcnt].prog_time > DELAYTIME_MAX) && 855 chips[chipcnt].prog_time != 0) { 856 error("Invalid prog time value for chip#%d at " 857 "ctr#%d!", 858 chips[chipcnt].num, 859 chips[chipcnt].ctrl_num); 860 return (EINVAL); 861 } 862 863 if ((chips[chipcnt].read_time < DELAYTIME_MIN || 864 chips[chipcnt].read_time > DELAYTIME_MAX) && 865 chips[chipcnt].read_time != 0) { 866 error("Invalid read time value for chip#%d at " 867 "ctrl#%d!", 868 chips[chipcnt].num, 869 chips[chipcnt].ctrl_num); 870 return (EINVAL); 871 } 872 } 873 /* Check if chips attached to the same controller, have same width */ 874 for (i = 0; i < ctrlcnt; i++) { 875 width = -1; 876 for (j = 0; j < cchipcnt; j++) { 877 if (chips[j].ctrl_num == i) { 878 if (width == -1) { 879 width = chips[j].width; 880 } else { 881 if (width != chips[j].width) { 882 error("Chips attached to " 883 "ctrl#%d have different " 884 "widths!\n", i); 885 return (EINVAL); 886 } 887 } 888 } 889 } 890 } 891 892 return (0); 893} 894 895static uint8_t 896validate_ctrls(struct sim_ctrl *ctrl, int ctrlcnt) 897{ 898 for (ctrlcnt -= 1; ctrlcnt >= 0; ctrlcnt--) { 899 if (ctrl[ctrlcnt].num > MAX_SIM_DEV) { 900 error("Controller no. too high (%d)!!\n", 901 ctrl[ctrlcnt].num); 902 return (EINVAL); 903 } 904 if (ctrl[ctrlcnt].num_cs > MAX_CTRL_CS) { 905 error("Too many CS (%d)!!\n", ctrl[ctrlcnt].num_cs); 906 return (EINVAL); 907 } 908 if (ctrl[ctrlcnt].ecc != 0 && ctrl[ctrlcnt].ecc != 1) { 909 error("ECC is set to neither 0 nor 1 !\n"); 910 return (EINVAL); 911 } 912 } 913 914 return (0); 915} 916 917static int validate_section_config(struct rcfile *f, const char *sect_name, 918 int sectno) 919{ 920 struct nandsim_key *key; 921 struct nandsim_section *sect; 922 char **keys_tbl; 923 int i, match; 924 925 for (match = 0, sect = (struct nandsim_section *)§ions; 926 sect != NULL; sect++) { 927 if (strcmp(sect->name, sect_name) == 0) { 928 match = 1; 929 break; 930 } 931 } 932 933 if (match == 0) 934 return (EINVAL); 935 936 keys_tbl = rc_getkeys(f, sect_name, sectno); 937 if (keys_tbl == NULL) 938 return (ENOMEM); 939 940 for (i = 0; keys_tbl[i] != NULL; i++) { 941 key = sect->keys; 942 match = 0; 943 do { 944 if (strcmp(keys_tbl[i], key->keyname) == 0) { 945 match = 1; 946 break; 947 } 948 } while ((++key)->keyname != NULL); 949 950 if (match == 0) { 951 error("Invalid key in config file: %s\n", keys_tbl[i]); 952 free(keys_tbl); 953 return (EINVAL); 954 } 955 } 956 957 free(keys_tbl); 958 return (0); 959} 960