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