nand.c revision 2779beecc7410f29102125e87e8174597acb2fe5
1/* Copyright (C) 2007-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12#include "qemu_file.h" 13#include "goldfish_nand_reg.h" 14#include "goldfish_nand.h" 15#include "android/utils/tempfile.h" 16#include "qemu_debug.h" 17#include "android/android.h" 18 19#define DEBUG 1 20#if DEBUG 21# define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 22# define D_ACTIVE VERBOSE_CHECK(init) 23# define T(...) VERBOSE_PRINT(nand_limits,__VA_ARGS__) 24# define T_ACTIVE VERBOSE_CHECK(nand_limits) 25#else 26# define D(...) ((void)0) 27# define D_ACTIVE 0 28# define T(...) ((void)0) 29# define T_ACTIVE 0 30#endif 31 32/* lseek uses 64-bit offsets on Darwin. */ 33/* prefer lseek64 on Linux */ 34#ifdef __APPLE__ 35# define llseek lseek 36#elif defined(__linux__) 37# define llseek lseek64 38#endif 39 40#define XLOG xlog 41 42static void 43xlog( const char* format, ... ) 44{ 45 va_list args; 46 va_start(args, format); 47 fprintf(stderr, "NAND: "); 48 vfprintf(stderr, format, args); 49 va_end(args); 50} 51 52/* Information on a single device/nand image used by the emulator 53 */ 54typedef struct { 55 char* devname; /* name for this device (not null-terminated, use len below) */ 56 size_t devname_len; 57 uint8_t* data; /* buffer for read/write actions to underlying image */ 58 int fd; 59 uint32_t flags; 60 uint32_t page_size; 61 uint32_t extra_size; 62 uint32_t erase_size; /* size of the data buffer mentioned above */ 63 uint64_t max_size; /* Capacity limit for the image. The actual underlying 64 * file may be smaller. */ 65} nand_dev; 66 67nand_threshold android_nand_write_threshold; 68nand_threshold android_nand_read_threshold; 69 70#ifdef CONFIG_NAND_THRESHOLD 71 72/* update a threshold, return 1 if limit is hit, 0 otherwise */ 73static void 74nand_threshold_update( nand_threshold* t, uint32_t len ) 75{ 76 if (t->counter < t->limit) { 77 uint64_t avail = t->limit - t->counter; 78 if (avail > len) 79 avail = len; 80 81 if (t->counter == 0) { 82 T("%s: starting threshold counting to %lld", 83 __FUNCTION__, t->limit); 84 } 85 t->counter += avail; 86 if (t->counter >= t->limit) { 87 /* threshold reach, send a signal to an external process */ 88 T( "%s: sending signal %d to pid %d !", 89 __FUNCTION__, t->signal, t->pid ); 90 91 kill( t->pid, t->signal ); 92 } 93 } 94 return; 95} 96 97#define NAND_UPDATE_READ_THRESHOLD(len) \ 98 nand_threshold_update( &android_nand_read_threshold, (uint32_t)(len) ) 99 100#define NAND_UPDATE_WRITE_THRESHOLD(len) \ 101 nand_threshold_update( &android_nand_write_threshold, (uint32_t)(len) ) 102 103#else /* !NAND_THRESHOLD */ 104 105#define NAND_UPDATE_READ_THRESHOLD(len) \ 106 do {} while (0) 107 108#define NAND_UPDATE_WRITE_THRESHOLD(len) \ 109 do {} while (0) 110 111#endif /* !NAND_THRESHOLD */ 112 113static nand_dev *nand_devs = NULL; 114static uint32_t nand_dev_count = 0; 115 116/* The controller is the single access point for all NAND images currently 117 * attached to the system. 118 */ 119typedef struct { 120 uint32_t base; 121 122 // register state 123 uint32_t dev; /* offset in nand_devs for the device that is 124 * currently being accessed */ 125 uint32_t addr_low; 126 uint32_t addr_high; 127 uint32_t transfer_size; 128 uint32_t data; 129 uint32_t result; 130} nand_dev_controller_state; 131 132/* update this everytime you change the nand_dev_controller_state structure 133 * 1: initial version, saving only nand_dev_controller_state fields 134 * 2: saving actual disk contents as well 135 */ 136#define NAND_DEV_STATE_SAVE_VERSION 2 137 138#define QFIELD_STRUCT nand_dev_controller_state 139QFIELD_BEGIN(nand_dev_controller_state_fields) 140 QFIELD_INT32(dev), 141 QFIELD_INT32(addr_low), 142 QFIELD_INT32(addr_high), 143 QFIELD_INT32(transfer_size), 144 QFIELD_INT32(data), 145 QFIELD_INT32(result), 146QFIELD_END 147 148 149static int do_read(int fd, void* buf, size_t size) 150{ 151 int ret; 152 do { 153 ret = read(fd, buf, size); 154 } while (ret < 0 && errno == EINTR); 155 156 return ret; 157} 158 159static int do_write(int fd, const void* buf, size_t size) 160{ 161 int ret; 162 do { 163 ret = write(fd, buf, size); 164 } while (ret < 0 && errno == EINTR); 165 166 return ret; 167} 168 169#define NAND_DEV_SAVE_DISK_BUF_SIZE 2048 170 171 172/** 173 * Copies the current contents of a disk image into the snapshot file. 174 * 175 * TODO optimize this using some kind of copy-on-write mechanism for 176 * unchanged disk sections. 177 */ 178static void nand_dev_save_disk_state(QEMUFile *f, nand_dev *dev) 179{ 180 int buf_size = NAND_DEV_SAVE_DISK_BUF_SIZE; 181 uint8_t buffer[NAND_DEV_SAVE_DISK_BUF_SIZE] = {0}; 182 int ret; 183 uint64_t total_copied = 0; 184 185 /* Put the size up front, since otherwise we don't know how much to read 186 * when restoring. 187 */ 188 const uint64_t total_size = dev->max_size; 189 qemu_put_be64(f, total_size); 190 191 /* copy all data from the stream to the stored image */ 192 ret = lseek(dev->fd, 0, SEEK_SET); 193 if (ret < 0) { 194 XLOG("%s seek failed: %s\n", __FUNCTION__, strerror(errno)); 195 qemu_file_set_error(f); 196 return; 197 } 198 do { 199 ret = do_read(dev->fd, buffer, buf_size); 200 if (ret < 0) { 201 XLOG("%s read failed: %s\n", __FUNCTION__, strerror(errno)); 202 qemu_file_set_error(f); 203 return; 204 } 205 qemu_put_buffer(f, buffer, ret); 206 207 total_copied += ret; 208 } 209 while (ret == buf_size && total_copied < total_size); 210 211 /* The file may be smaller than the device size. Pad with 0xff (pattern for 212 * erased data) until we have filled the snapshot buffer we declared earlier. 213 * TODO avoid padding. Unfortunately, attempts to use the actual size of the 214 * underlying image instead result in broken restores. This also happens 215 * when limited padding is inserted so the image size is a multiple of 216 * page_size or erase_size. 217 */ 218 memset(buffer, 0xff, NAND_DEV_SAVE_DISK_BUF_SIZE); 219 while (total_copied < total_size) { 220 /* adjust buffer size for last part of the image */ 221 if (total_size - total_copied < buf_size) { 222 buf_size = total_size - total_copied; 223 } 224 qemu_put_buffer(f, buffer, buf_size); 225 total_copied += buf_size; 226 } 227} 228 229 230/** 231 * Saves the state of all disks managed by this controller to a snapshot file. 232 */ 233static void nand_dev_save_disks(QEMUFile *f) 234{ 235 int i; 236 for (i = 0; i < nand_dev_count; i++) { 237 nand_dev_save_disk_state(f, nand_devs + i); 238 } 239} 240 241/** 242 * Overwrites the contents of the disk image managed by this device with the 243 * contents as they were at the point the snapshot was made. 244 */ 245static int nand_dev_load_disk_state(QEMUFile *f, nand_dev *dev) 246{ 247 int buf_size = NAND_DEV_SAVE_DISK_BUF_SIZE; 248 uint8_t buffer[NAND_DEV_SAVE_DISK_BUF_SIZE] = {0}; 249 int ret; 250 251 /* number of bytes to restore */ 252 uint64_t total_size = qemu_get_be64(f); 253 if (total_size > dev->max_size) { 254 XLOG("%s, restore failed: size required (%lld) exceeds device limit (%lld)\n", 255 __FUNCTION__, total_size, dev->max_size); 256 return -EIO; 257 } 258 259 /* overwrite disk contents with snapshot contents */ 260 uint64_t next_offset = 0; 261 do { 262 ret = lseek(dev->fd, 0, SEEK_SET); 263 } while (ret < 0 && errno == EINTR); 264 if (ret < 0) { 265 XLOG("%s seek failed: %s\n", __FUNCTION__, strerror(errno)); 266 return -EIO; 267 } 268 while (next_offset < total_size) { 269 /* snapshot buffer may not be an exact multiple of buf_size 270 * if necessary, adjust buffer size for last copy operation */ 271 if (total_size - next_offset < buf_size) { 272 buf_size = total_size - next_offset; 273 } 274 275 ret = qemu_get_buffer(f, buffer, buf_size); 276 if (ret != buf_size) { 277 XLOG("%s read failed: expected %d bytes but got %d\n", 278 __FUNCTION__, buf_size, ret); 279 return -EIO; 280 } 281 ret = do_write(dev->fd, buffer, buf_size); 282 if (ret != buf_size) { 283 XLOG("%s, write failed: %s\n", __FUNCTION__, strerror(errno)); 284 return -EIO; 285 } 286 287 next_offset += buf_size; 288 } 289 290 return 0; 291} 292 293/** 294 * Restores the state of all disks managed by this driver from a snapshot file. 295 */ 296static int nand_dev_load_disks(QEMUFile *f) 297{ 298 int i, ret; 299 for (i = 0; i < nand_dev_count; i++) { 300 ret = nand_dev_load_disk_state(f, nand_devs + i); 301 if (ret) 302 return ret; // abort on error 303 } 304 305 return 0; 306} 307 308static void nand_dev_controller_state_save(QEMUFile *f, void *opaque) 309{ 310 nand_dev_controller_state* s = opaque; 311 312 qemu_put_struct(f, nand_dev_controller_state_fields, s); 313 314 /* The guest will continue writing to the disk image after the state has 315 * been saved. To guarantee that the state is identical after resume, save 316 * a copy of the current disk state in the snapshot. 317 */ 318 nand_dev_save_disks(f); 319} 320 321static int nand_dev_controller_state_load(QEMUFile *f, void *opaque, int version_id) 322{ 323 nand_dev_controller_state* s = opaque; 324 int ret; 325 326 if (version_id != NAND_DEV_STATE_SAVE_VERSION) 327 return -1; 328 329 if ((ret = qemu_get_struct(f, nand_dev_controller_state_fields, s))) 330 return ret; 331 if ((ret = nand_dev_load_disks(f))) 332 return ret; 333 334 return 0; 335} 336 337static uint32_t nand_dev_read_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) 338{ 339 uint32_t len = total_len; 340 size_t read_len = dev->erase_size; 341 int eof = 0; 342 343 NAND_UPDATE_READ_THRESHOLD(total_len); 344 345 lseek(dev->fd, addr, SEEK_SET); 346 while(len > 0) { 347 if(read_len < dev->erase_size) { 348 memset(dev->data, 0xff, dev->erase_size); 349 read_len = dev->erase_size; 350 eof = 1; 351 } 352 if(len < read_len) 353 read_len = len; 354 if(!eof) { 355 read_len = do_read(dev->fd, dev->data, read_len); 356 } 357 cpu_memory_rw_debug(cpu_single_env, data, dev->data, read_len, 1); 358 data += read_len; 359 len -= read_len; 360 } 361 return total_len; 362} 363 364static uint32_t nand_dev_write_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) 365{ 366 uint32_t len = total_len; 367 size_t write_len = dev->erase_size; 368 int ret; 369 370 NAND_UPDATE_WRITE_THRESHOLD(total_len); 371 372 lseek(dev->fd, addr, SEEK_SET); 373 while(len > 0) { 374 if(len < write_len) 375 write_len = len; 376 cpu_memory_rw_debug(cpu_single_env, data, dev->data, write_len, 0); 377 ret = do_write(dev->fd, dev->data, write_len); 378 if(ret < write_len) { 379 XLOG("nand_dev_write_file, write failed: %s\n", strerror(errno)); 380 break; 381 } 382 data += write_len; 383 len -= write_len; 384 } 385 return total_len - len; 386} 387 388static uint32_t nand_dev_erase_file(nand_dev *dev, uint64_t addr, uint32_t total_len) 389{ 390 uint32_t len = total_len; 391 size_t write_len = dev->erase_size; 392 int ret; 393 394 lseek(dev->fd, addr, SEEK_SET); 395 memset(dev->data, 0xff, dev->erase_size); 396 while(len > 0) { 397 if(len < write_len) 398 write_len = len; 399 ret = do_write(dev->fd, dev->data, write_len); 400 if(ret < write_len) { 401 XLOG( "nand_dev_write_file, write failed: %s\n", strerror(errno)); 402 break; 403 } 404 len -= write_len; 405 } 406 return total_len - len; 407} 408 409/* this is a huge hack required to make the PowerPC emulator binary usable 410 * on Mac OS X. If you define this function as 'static', the emulated kernel 411 * will panic when attempting to mount the /data partition. 412 * 413 * worse, if you do *not* define the function as static on Linux-x86, the 414 * emulated kernel will also panic !? 415 * 416 * I still wonder if this is a compiler bug, or due to some nasty thing the 417 * emulator does with CPU registers during execution of the translated code. 418 */ 419#if !(defined __APPLE__ && defined __powerpc__) 420static 421#endif 422uint32_t nand_dev_do_cmd(nand_dev_controller_state *s, uint32_t cmd) 423{ 424 uint32_t size; 425 uint64_t addr; 426 nand_dev *dev; 427 428 addr = s->addr_low | ((uint64_t)s->addr_high << 32); 429 size = s->transfer_size; 430 if(s->dev >= nand_dev_count) 431 return 0; 432 dev = nand_devs + s->dev; 433 434 switch(cmd) { 435 case NAND_CMD_GET_DEV_NAME: 436 if(size > dev->devname_len) 437 size = dev->devname_len; 438 cpu_memory_rw_debug(cpu_single_env, s->data, (uint8_t*)dev->devname, size, 1); 439 return size; 440 case NAND_CMD_READ: 441 if(addr >= dev->max_size) 442 return 0; 443 if(size > dev->max_size - addr) 444 size = dev->max_size - addr; 445 if(dev->fd >= 0) 446 return nand_dev_read_file(dev, s->data, addr, size); 447 cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 1); 448 return size; 449 case NAND_CMD_WRITE: 450 if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 451 return 0; 452 if(addr >= dev->max_size) 453 return 0; 454 if(size > dev->max_size - addr) 455 size = dev->max_size - addr; 456 if(dev->fd >= 0) 457 return nand_dev_write_file(dev, s->data, addr, size); 458 cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 0); 459 return size; 460 case NAND_CMD_ERASE: 461 if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 462 return 0; 463 if(addr >= dev->max_size) 464 return 0; 465 if(size > dev->max_size - addr) 466 size = dev->max_size - addr; 467 if(dev->fd >= 0) 468 return nand_dev_erase_file(dev, addr, size); 469 memset(&dev->data[addr], 0xff, size); 470 return size; 471 case NAND_CMD_BLOCK_BAD_GET: // no bad block support 472 return 0; 473 case NAND_CMD_BLOCK_BAD_SET: 474 if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 475 return 0; 476 return 0; 477 default: 478 cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd); 479 return 0; 480 } 481} 482 483/* I/O write */ 484static void nand_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) 485{ 486 nand_dev_controller_state *s = (nand_dev_controller_state *)opaque; 487 488 switch (offset) { 489 case NAND_DEV: 490 s->dev = value; 491 if(s->dev >= nand_dev_count) { 492 cpu_abort(cpu_single_env, "nand_dev_write: Bad dev %x\n", value); 493 } 494 break; 495 case NAND_ADDR_HIGH: 496 s->addr_high = value; 497 break; 498 case NAND_ADDR_LOW: 499 s->addr_low = value; 500 break; 501 case NAND_TRANSFER_SIZE: 502 s->transfer_size = value; 503 break; 504 case NAND_DATA: 505 s->data = value; 506 break; 507 case NAND_COMMAND: 508 s->result = nand_dev_do_cmd(s, value); 509 break; 510 default: 511 cpu_abort(cpu_single_env, "nand_dev_write: Bad offset %x\n", offset); 512 break; 513 } 514} 515 516/* I/O read */ 517static uint32_t nand_dev_read(void *opaque, target_phys_addr_t offset) 518{ 519 nand_dev_controller_state *s = (nand_dev_controller_state *)opaque; 520 nand_dev *dev; 521 522 switch (offset) { 523 case NAND_VERSION: 524 return NAND_VERSION_CURRENT; 525 case NAND_NUM_DEV: 526 return nand_dev_count; 527 case NAND_RESULT: 528 return s->result; 529 } 530 531 if(s->dev >= nand_dev_count) 532 return 0; 533 534 dev = nand_devs + s->dev; 535 536 switch (offset) { 537 case NAND_DEV_FLAGS: 538 return dev->flags; 539 540 case NAND_DEV_NAME_LEN: 541 return dev->devname_len; 542 543 case NAND_DEV_PAGE_SIZE: 544 return dev->page_size; 545 546 case NAND_DEV_EXTRA_SIZE: 547 return dev->extra_size; 548 549 case NAND_DEV_ERASE_SIZE: 550 return dev->erase_size; 551 552 case NAND_DEV_SIZE_LOW: 553 return (uint32_t)dev->max_size; 554 555 case NAND_DEV_SIZE_HIGH: 556 return (uint32_t)(dev->max_size >> 32); 557 558 default: 559 cpu_abort(cpu_single_env, "nand_dev_read: Bad offset %x\n", offset); 560 return 0; 561 } 562} 563 564static CPUReadMemoryFunc *nand_dev_readfn[] = { 565 nand_dev_read, 566 nand_dev_read, 567 nand_dev_read 568}; 569 570static CPUWriteMemoryFunc *nand_dev_writefn[] = { 571 nand_dev_write, 572 nand_dev_write, 573 nand_dev_write 574}; 575 576/* initialize the QFB device */ 577void nand_dev_init(uint32_t base) 578{ 579 int iomemtype; 580 static int instance_id = 0; 581 nand_dev_controller_state *s; 582 583 s = (nand_dev_controller_state *)qemu_mallocz(sizeof(nand_dev_controller_state)); 584 iomemtype = cpu_register_io_memory(nand_dev_readfn, nand_dev_writefn, s); 585 cpu_register_physical_memory(base, 0x00000fff, iomemtype); 586 s->base = base; 587 588 register_savevm( "nand_dev", instance_id++, NAND_DEV_STATE_SAVE_VERSION, 589 nand_dev_controller_state_save, nand_dev_controller_state_load, s); 590} 591 592static int arg_match(const char *a, const char *b, size_t b_len) 593{ 594 while(*a && b_len--) { 595 if(*a++ != *b++) 596 return 0; 597 } 598 return b_len == 0; 599} 600 601void nand_add_dev(const char *arg) 602{ 603 uint64_t dev_size = 0; 604 const char *next_arg; 605 const char *value; 606 size_t arg_len, value_len; 607 nand_dev *new_devs, *dev; 608 char *devname = NULL; 609 size_t devname_len = 0; 610 char *initfilename = NULL; 611 char *rwfilename = NULL; 612 int initfd = -1; 613 int rwfd = -1; 614 int read_only = 0; 615 int pad; 616 ssize_t read_size; 617 uint32_t page_size = 2048; 618 uint32_t extra_size = 64; 619 uint32_t erase_pages = 64; 620 621 while(arg) { 622 next_arg = strchr(arg, ','); 623 value = strchr(arg, '='); 624 if(next_arg != NULL) { 625 arg_len = next_arg - arg; 626 next_arg++; 627 if(value >= next_arg) 628 value = NULL; 629 } 630 else 631 arg_len = strlen(arg); 632 if(value != NULL) { 633 size_t new_arg_len = value - arg; 634 value_len = arg_len - new_arg_len - 1; 635 arg_len = new_arg_len; 636 value++; 637 } 638 else 639 value_len = 0; 640 641 if(devname == NULL) { 642 if(value != NULL) 643 goto bad_arg_and_value; 644 devname_len = arg_len; 645 devname = malloc(arg_len); 646 if(devname == NULL) 647 goto out_of_memory; 648 memcpy(devname, arg, arg_len); 649 } 650 else if(value == NULL) { 651 if(arg_match("readonly", arg, arg_len)) { 652 read_only = 1; 653 } 654 else { 655 XLOG("bad arg: %.*s\n", arg_len, arg); 656 exit(1); 657 } 658 } 659 else { 660 if(arg_match("size", arg, arg_len)) { 661 char *ep; 662 dev_size = strtoull(value, &ep, 0); 663 if(ep != value + value_len) 664 goto bad_arg_and_value; 665 } 666 else if(arg_match("pagesize", arg, arg_len)) { 667 char *ep; 668 page_size = strtoul(value, &ep, 0); 669 if(ep != value + value_len) 670 goto bad_arg_and_value; 671 } 672 else if(arg_match("extrasize", arg, arg_len)) { 673 char *ep; 674 extra_size = strtoul(value, &ep, 0); 675 if(ep != value + value_len) 676 goto bad_arg_and_value; 677 } 678 else if(arg_match("erasepages", arg, arg_len)) { 679 char *ep; 680 erase_pages = strtoul(value, &ep, 0); 681 if(ep != value + value_len) 682 goto bad_arg_and_value; 683 } 684 else if(arg_match("initfile", arg, arg_len)) { 685 initfilename = malloc(value_len + 1); 686 if(initfilename == NULL) 687 goto out_of_memory; 688 memcpy(initfilename, value, value_len); 689 initfilename[value_len] = '\0'; 690 } 691 else if(arg_match("file", arg, arg_len)) { 692 rwfilename = malloc(value_len + 1); 693 if(rwfilename == NULL) 694 goto out_of_memory; 695 memcpy(rwfilename, value, value_len); 696 rwfilename[value_len] = '\0'; 697 } 698 else { 699 goto bad_arg_and_value; 700 } 701 } 702 703 arg = next_arg; 704 } 705 706 if (rwfilename == NULL) { 707 /* we create a temporary file to store everything */ 708 TempFile* tmp = tempfile_create(); 709 710 if (tmp == NULL) { 711 XLOG("could not create temp file for %.*s NAND disk image: %s\n", 712 devname_len, devname, strerror(errno)); 713 exit(1); 714 } 715 rwfilename = (char*) tempfile_path(tmp); 716 if (VERBOSE_CHECK(init)) 717 dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename); 718 } 719 720 if(rwfilename) { 721 rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR)); 722 if(rwfd < 0 && read_only) { 723 XLOG("could not open file %s, %s\n", rwfilename, strerror(errno)); 724 exit(1); 725 } 726 /* this could be a writable temporary file. use atexit_close_fd to ensure 727 * that it is properly cleaned up at exit on Win32 728 */ 729 if (!read_only) 730 atexit_close_fd(rwfd); 731 } 732 733 if(initfilename) { 734 initfd = open(initfilename, O_BINARY | O_RDONLY); 735 if(initfd < 0) { 736 XLOG("could not open file %s, %s\n", initfilename, strerror(errno)); 737 exit(1); 738 } 739 if(dev_size == 0) { 740 dev_size = lseek(initfd, 0, SEEK_END); 741 lseek(initfd, 0, SEEK_SET); 742 } 743 } 744 745 new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1)); 746 if(new_devs == NULL) 747 goto out_of_memory; 748 nand_devs = new_devs; 749 dev = &new_devs[nand_dev_count]; 750 751 dev->page_size = page_size; 752 dev->extra_size = extra_size; 753 dev->erase_size = erase_pages * (page_size + extra_size); 754 pad = dev_size % dev->erase_size; 755 if (pad != 0) { 756 dev_size += (dev->erase_size - pad); 757 D("rounding devsize up to a full eraseunit, now %llx\n", dev_size); 758 } 759 dev->devname = devname; 760 dev->devname_len = devname_len; 761 dev->max_size = dev_size; 762 dev->data = malloc(dev->erase_size); 763 if(dev->data == NULL) 764 goto out_of_memory; 765 dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0; 766 767 if (initfd >= 0) { 768 do { 769 read_size = do_read(initfd, dev->data, dev->erase_size); 770 if(read_size < 0) { 771 XLOG("could not read file %s, %s\n", initfilename, strerror(errno)); 772 exit(1); 773 } 774 if(do_write(rwfd, dev->data, read_size) != read_size) { 775 XLOG("could not write file %s, %s\n", initfilename, strerror(errno)); 776 exit(1); 777 } 778 } while(read_size == dev->erase_size); 779 close(initfd); 780 } 781 dev->fd = rwfd; 782 783 nand_dev_count++; 784 785 return; 786 787out_of_memory: 788 XLOG("out of memory\n"); 789 exit(1); 790 791bad_arg_and_value: 792 XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value); 793 exit(1); 794} 795 796#ifdef CONFIG_NAND_LIMITS 797 798static uint64_t 799parse_nand_rw_limit( const char* value ) 800{ 801 char* end; 802 uint64_t val = strtoul( value, &end, 0 ); 803 804 if (end == value) { 805 derror( "bad parameter value '%s': expecting unsigned integer", value ); 806 exit(1); 807 } 808 809 switch (end[0]) { 810 case 'K': val <<= 10; break; 811 case 'M': val <<= 20; break; 812 case 'G': val <<= 30; break; 813 case 0: break; 814 default: 815 derror( "bad read/write limit suffix: use K, M or G" ); 816 exit(1); 817 } 818 return val; 819} 820 821void 822parse_nand_limits(char* limits) 823{ 824 int pid = -1, signal = -1; 825 int64_t reads = 0, writes = 0; 826 char* item = limits; 827 828 /* parse over comma-separated items */ 829 while (item && *item) { 830 char* next = strchr(item, ','); 831 char* end; 832 833 if (next == NULL) { 834 next = item + strlen(item); 835 } else { 836 *next++ = 0; 837 } 838 839 if ( !memcmp(item, "pid=", 4) ) { 840 pid = strtol(item+4, &end, 10); 841 if (end == NULL || *end) { 842 derror( "bad parameter, expecting pid=<number>, got '%s'", 843 item ); 844 exit(1); 845 } 846 if (pid <= 0) { 847 derror( "bad parameter: process identifier must be > 0" ); 848 exit(1); 849 } 850 } 851 else if ( !memcmp(item, "signal=", 7) ) { 852 signal = strtol(item+7,&end, 10); 853 if (end == NULL || *end) { 854 derror( "bad parameter: expecting signal=<number>, got '%s'", 855 item ); 856 exit(1); 857 } 858 if (signal <= 0) { 859 derror( "bad parameter: signal number must be > 0" ); 860 exit(1); 861 } 862 } 863 else if ( !memcmp(item, "reads=", 6) ) { 864 reads = parse_nand_rw_limit(item+6); 865 } 866 else if ( !memcmp(item, "writes=", 7) ) { 867 writes = parse_nand_rw_limit(item+7); 868 } 869 else { 870 derror( "bad parameter '%s' (see -help-nand-limits)", item ); 871 exit(1); 872 } 873 item = next; 874 } 875 if (pid < 0) { 876 derror( "bad paramater: missing pid=<number>" ); 877 exit(1); 878 } 879 else if (signal < 0) { 880 derror( "bad parameter: missing signal=<number>" ); 881 exit(1); 882 } 883 else if (reads == 0 && writes == 0) { 884 dwarning( "no read or write limit specified. ignoring -nand-limits" ); 885 } else { 886 nand_threshold* t; 887 888 t = &android_nand_read_threshold; 889 t->pid = pid; 890 t->signal = signal; 891 t->counter = 0; 892 t->limit = reads; 893 894 t = &android_nand_write_threshold; 895 t->pid = pid; 896 t->signal = signal; 897 t->counter = 0; 898 t->limit = writes; 899 } 900} 901#endif /* CONFIG_NAND_LIMITS */ 902