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