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