• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
xlog(const char * format,...)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
nand_threshold_update(nand_threshold * t,uint32_t len)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)
QFIELD_INT32(dev)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 */
do_write(int fd,const void * buf,size_t size)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 */
do_lseek(int fd,off_t offset,int whence)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 */
do_ftruncate(int fd,size_t size)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  */
nand_dev_save_disk_state(QEMUFile * f,nand_dev * dev)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  */
nand_dev_save_disks(QEMUFile * f)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  */
nand_dev_load_disk_state(QEMUFile * f,nand_dev * dev)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  */
nand_dev_load_disks(QEMUFile * f)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 
nand_dev_controller_state_save(QEMUFile * f,void * opaque)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 
nand_dev_controller_state_load(QEMUFile * f,void * opaque,int version_id)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 
nand_dev_read_file(nand_dev * dev,uint32_t data,uint64_t addr,uint32_t total_len)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 
nand_dev_write_file(nand_dev * dev,uint32_t data,uint64_t addr,uint32_t total_len)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 
nand_dev_erase_file(nand_dev * dev,uint64_t addr,uint32_t total_len)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
nand_dev_do_cmd(nand_dev_controller_state * s,uint32_t cmd)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 */
nand_dev_write(void * opaque,target_phys_addr_t offset,uint32_t value)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 */
nand_dev_read(void * opaque,target_phys_addr_t offset)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 */
nand_dev_init(uint32_t base)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 
arg_match(const char * a,const char * b,size_t b_len)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 
nand_add_dev(const char * arg)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         rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR));
799         if(rwfd < 0) {
800             XLOG("could not open file %s, %s\n", rwfilename, strerror(errno));
801             exit(1);
802         }
803         /* this could be a writable temporary file. use atexit_close_fd to ensure
804          * that it is properly cleaned up at exit on Win32
805          */
806         if (!read_only)
807             atexit_close_fd(rwfd);
808     }
809 
810     if(initfilename) {
811         initfd = open(initfilename, O_BINARY | O_RDONLY);
812         if(initfd < 0) {
813             XLOG("could not open file %s, %s\n", initfilename, strerror(errno));
814             exit(1);
815         }
816         if(dev_size == 0) {
817             dev_size = do_lseek(initfd, 0, SEEK_END);
818             do_lseek(initfd, 0, SEEK_SET);
819         }
820     }
821 
822     new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1));
823     if(new_devs == NULL)
824         goto out_of_memory;
825     nand_devs = new_devs;
826     dev = &new_devs[nand_dev_count];
827 
828     dev->page_size = page_size;
829     dev->extra_size = extra_size;
830     dev->erase_size = erase_pages * (page_size + extra_size);
831     pad = dev_size % dev->erase_size;
832     if (pad != 0) {
833         dev_size += (dev->erase_size - pad);
834         D("rounding devsize up to a full eraseunit, now %llx\n", dev_size);
835     }
836     dev->devname = devname;
837     dev->devname_len = devname_len;
838     dev->max_size = dev_size;
839     dev->data = malloc(dev->erase_size);
840     if(dev->data == NULL)
841         goto out_of_memory;
842     dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0;
843 #ifdef TARGET_I386
844     dev->flags |= NAND_DEV_FLAG_BATCH_CAP;
845 #endif
846 
847     if (initfd >= 0) {
848         do {
849             read_size = do_read(initfd, dev->data, dev->erase_size);
850             if(read_size < 0) {
851                 XLOG("could not read file %s, %s\n", initfilename, strerror(errno));
852                 exit(1);
853             }
854             if(do_write(rwfd, dev->data, read_size) != read_size) {
855                 XLOG("could not write file %s, %s\n", rwfilename, strerror(errno));
856                 exit(1);
857             }
858         } while(read_size == dev->erase_size);
859         close(initfd);
860     }
861     dev->fd = rwfd;
862 
863     nand_dev_count++;
864 
865     return;
866 
867 out_of_memory:
868     XLOG("out of memory\n");
869     exit(1);
870 
871 bad_arg_and_value:
872     XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value);
873     exit(1);
874 }
875 
876 #ifdef CONFIG_NAND_LIMITS
877 
878 static uint64_t
parse_nand_rw_limit(const char * value)879 parse_nand_rw_limit( const char*  value )
880 {
881     char*     end;
882     uint64_t  val = strtoul( value, &end, 0 );
883 
884     if (end == value) {
885         derror( "bad parameter value '%s': expecting unsigned integer", value );
886         exit(1);
887     }
888 
889     switch (end[0]) {
890         case 'K':  val <<= 10; break;
891         case 'M':  val <<= 20; break;
892         case 'G':  val <<= 30; break;
893         case 0: break;
894         default:
895             derror( "bad read/write limit suffix: use K, M or G" );
896             exit(1);
897     }
898     return val;
899 }
900 
901 void
parse_nand_limits(char * limits)902 parse_nand_limits(char*  limits)
903 {
904     int      pid = -1, signal = -1;
905     int64_t  reads = 0, writes = 0;
906     char*    item = limits;
907 
908     /* parse over comma-separated items */
909     while (item && *item) {
910         char*  next = strchr(item, ',');
911         char*  end;
912 
913         if (next == NULL) {
914             next = item + strlen(item);
915         } else {
916             *next++ = 0;
917         }
918 
919         if ( !memcmp(item, "pid=", 4) ) {
920             pid = strtol(item+4, &end, 10);
921             if (end == NULL || *end) {
922                 derror( "bad parameter, expecting pid=<number>, got '%s'",
923                         item );
924                 exit(1);
925             }
926             if (pid <= 0) {
927                 derror( "bad parameter: process identifier must be > 0" );
928                 exit(1);
929             }
930         }
931         else if ( !memcmp(item, "signal=", 7) ) {
932             signal = strtol(item+7,&end, 10);
933             if (end == NULL || *end) {
934                 derror( "bad parameter: expecting signal=<number>, got '%s'",
935                         item );
936                 exit(1);
937             }
938             if (signal <= 0) {
939                 derror( "bad parameter: signal number must be > 0" );
940                 exit(1);
941             }
942         }
943         else if ( !memcmp(item, "reads=", 6) ) {
944             reads = parse_nand_rw_limit(item+6);
945         }
946         else if ( !memcmp(item, "writes=", 7) ) {
947             writes = parse_nand_rw_limit(item+7);
948         }
949         else {
950             derror( "bad parameter '%s' (see -help-nand-limits)", item );
951             exit(1);
952         }
953         item = next;
954     }
955     if (pid < 0) {
956         derror( "bad paramater: missing pid=<number>" );
957         exit(1);
958     }
959     else if (signal < 0) {
960         derror( "bad parameter: missing signal=<number>" );
961         exit(1);
962     }
963     else if (reads == 0 && writes == 0) {
964         dwarning( "no read or write limit specified. ignoring -nand-limits" );
965     } else {
966         nand_threshold*  t;
967 
968         t  = &android_nand_read_threshold;
969         t->pid     = pid;
970         t->signal  = signal;
971         t->counter = 0;
972         t->limit   = reads;
973 
974         t  = &android_nand_write_threshold;
975         t->pid     = pid;
976         t->signal  = signal;
977         t->counter = 0;
978         t->limit   = writes;
979     }
980 }
981 #endif /* CONFIG_NAND_LIMITS */
982