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