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