nand.c revision 2779beecc7410f29102125e87e8174597acb2fe5
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful, 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details. 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/ 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu_file.h" 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "goldfish_nand_reg.h" 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "goldfish_nand.h" 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/tempfile.h" 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu_debug.h" 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/android.h" 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DEBUG 1 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG 21acbee3546b9a380a4eb33daef3dccfac87c56b0bXavier Ducrohet# define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 22acbee3546b9a380a4eb33daef3dccfac87c56b0bXavier Ducrohet# define D_ACTIVE VERBOSE_CHECK(init) 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define T(...) VERBOSE_PRINT(nand_limits,__VA_ARGS__) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define T_ACTIVE VERBOSE_CHECK(nand_limits) 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define D(...) ((void)0) 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define D_ACTIVE 0 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define T(...) ((void)0) 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define T_ACTIVE 0 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* lseek uses 64-bit offsets on Darwin. */ 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* prefer lseek64 on Linux */ 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __APPLE__ 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define llseek lseek 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__linux__) 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define llseek lseek64 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define XLOG xlog 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectxlog( const char* format, ... ) 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project va_list args; 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project va_start(args, format); 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "NAND: "); 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vfprintf(stderr, format, args); 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project va_end(args); 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/* Information on a single device/nand image used by the emulator 53c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct { 55c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije char* devname; /* name for this device (not null-terminated, use len below) */ 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t devname_len; 57c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint8_t* data; /* buffer for read/write actions to underlying image */ 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int fd; 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t flags; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t page_size; 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t extra_size; 62c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint32_t erase_size; /* size of the data buffer mentioned above */ 63c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint64_t max_size; /* Capacity limit for the image. The actual underlying 64c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * file may be smaller. */ 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} nand_dev; 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectnand_threshold android_nand_write_threshold; 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectnand_threshold android_nand_read_threshold; 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_NAND_THRESHOLD 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* update a threshold, return 1 if limit is hit, 0 otherwise */ 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectnand_threshold_update( nand_threshold* t, uint32_t len ) 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (t->counter < t->limit) { 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t avail = t->limit - t->counter; 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (avail > len) 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project avail = len; 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (t->counter == 0) { 82e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine T("%s: starting threshold counting to %lld", 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project __FUNCTION__, t->limit); 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t->counter += avail; 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (t->counter >= t->limit) { 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* threshold reach, send a signal to an external process */ 88e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine T( "%s: sending signal %d to pid %d !", 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project __FUNCTION__, t->signal, t->pid ); 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kill( t->pid, t->signal ); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAND_UPDATE_READ_THRESHOLD(len) \ 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_threshold_update( &android_nand_read_threshold, (uint32_t)(len) ) 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAND_UPDATE_WRITE_THRESHOLD(len) \ 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_threshold_update( &android_nand_write_threshold, (uint32_t)(len) ) 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !NAND_THRESHOLD */ 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAND_UPDATE_READ_THRESHOLD(len) \ 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do {} while (0) 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAND_UPDATE_WRITE_THRESHOLD(len) \ 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do {} while (0) 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !NAND_THRESHOLD */ 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic nand_dev *nand_devs = NULL; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t nand_dev_count = 0; 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 116c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/* The controller is the single access point for all NAND images currently 117c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * attached to the system. 118c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct { 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t base; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // register state 123c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint32_t dev; /* offset in nand_devs for the device that is 124c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * currently being accessed */ 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr_low; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr_high; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t transfer_size; 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t data; 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t result; 130c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} nand_dev_controller_state; 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 132c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/* update this everytime you change the nand_dev_controller_state structure 133c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * 1: initial version, saving only nand_dev_controller_state fields 134c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * 2: saving actual disk contents as well 135c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 136c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije#define NAND_DEV_STATE_SAVE_VERSION 2 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 138c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije#define QFIELD_STRUCT nand_dev_controller_state 139c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten ThijeQFIELD_BEGIN(nand_dev_controller_state_fields) 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(dev), 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(addr_low), 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(addr_high), 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(transfer_size), 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(data), 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project QFIELD_INT32(result), 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectQFIELD_END 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int do_read(int fd, void* buf, size_t size) 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = read(fd, buf, size); 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } while (ret < 0 && errno == EINTR); 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int do_write(int fd, const void* buf, size_t size) 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = write(fd, buf, size); 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } while (ret < 0 && errno == EINTR); 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 169c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije#define NAND_DEV_SAVE_DISK_BUF_SIZE 2048 170c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 171c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 172c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/** 173c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * Copies the current contents of a disk image into the snapshot file. 174c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * 175c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * TODO optimize this using some kind of copy-on-write mechanism for 176c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * unchanged disk sections. 177c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 178c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic void nand_dev_save_disk_state(QEMUFile *f, nand_dev *dev) 179c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 180c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int buf_size = NAND_DEV_SAVE_DISK_BUF_SIZE; 181c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint8_t buffer[NAND_DEV_SAVE_DISK_BUF_SIZE] = {0}; 182c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int ret; 183c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint64_t total_copied = 0; 184c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 185c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* Put the size up front, since otherwise we don't know how much to read 186c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * when restoring. 187c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 188c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije const uint64_t total_size = dev->max_size; 189c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_put_be64(f, total_size); 190c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 191c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* copy all data from the stream to the stored image */ 192c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = lseek(dev->fd, 0, SEEK_SET); 193c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret < 0) { 194c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s seek failed: %s\n", __FUNCTION__, strerror(errno)); 195c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_file_set_error(f); 196c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return; 197c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 198c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije do { 199c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = do_read(dev->fd, buffer, buf_size); 200c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret < 0) { 201c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s read failed: %s\n", __FUNCTION__, strerror(errno)); 202c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_file_set_error(f); 203c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return; 204c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 205c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_put_buffer(f, buffer, ret); 206c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 207c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije total_copied += ret; 208c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 209c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije while (ret == buf_size && total_copied < total_size); 210c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 211c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* The file may be smaller than the device size. Pad with 0xff (pattern for 212c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * erased data) until we have filled the snapshot buffer we declared earlier. 213c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * TODO avoid padding. Unfortunately, attempts to use the actual size of the 214c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * underlying image instead result in broken restores. This also happens 215c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * when limited padding is inserted so the image size is a multiple of 216c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * page_size or erase_size. 217c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 218c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije memset(buffer, 0xff, NAND_DEV_SAVE_DISK_BUF_SIZE); 219c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije while (total_copied < total_size) { 220c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* adjust buffer size for last part of the image */ 221c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (total_size - total_copied < buf_size) { 222c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije buf_size = total_size - total_copied; 223c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 224c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_put_buffer(f, buffer, buf_size); 225c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije total_copied += buf_size; 226c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 227c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 228c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 229c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 230c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/** 231c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * Saves the state of all disks managed by this controller to a snapshot file. 232c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 233c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic void nand_dev_save_disks(QEMUFile *f) 234c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 235c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int i; 236c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije for (i = 0; i < nand_dev_count; i++) { 237c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_save_disk_state(f, nand_devs + i); 238c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 239c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 240c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 241c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/** 242c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * Overwrites the contents of the disk image managed by this device with the 243c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * contents as they were at the point the snapshot was made. 244c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 245c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic int nand_dev_load_disk_state(QEMUFile *f, nand_dev *dev) 246c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 247c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int buf_size = NAND_DEV_SAVE_DISK_BUF_SIZE; 248c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint8_t buffer[NAND_DEV_SAVE_DISK_BUF_SIZE] = {0}; 249c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int ret; 250c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 251c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* number of bytes to restore */ 252c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint64_t total_size = qemu_get_be64(f); 253c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (total_size > dev->max_size) { 254c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s, restore failed: size required (%lld) exceeds device limit (%lld)\n", 255c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije __FUNCTION__, total_size, dev->max_size); 256c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return -EIO; 257c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 258c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 259c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* overwrite disk contents with snapshot contents */ 260c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije uint64_t next_offset = 0; 261c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije do { 262c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = lseek(dev->fd, 0, SEEK_SET); 263c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } while (ret < 0 && errno == EINTR); 264c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret < 0) { 265c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s seek failed: %s\n", __FUNCTION__, strerror(errno)); 266c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return -EIO; 267c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 268c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije while (next_offset < total_size) { 269c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* snapshot buffer may not be an exact multiple of buf_size 270c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * if necessary, adjust buffer size for last copy operation */ 271c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (total_size - next_offset < buf_size) { 272c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije buf_size = total_size - next_offset; 273c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 274c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 275c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = qemu_get_buffer(f, buffer, buf_size); 276c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret != buf_size) { 277c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s read failed: expected %d bytes but got %d\n", 278c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije __FUNCTION__, buf_size, ret); 279c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return -EIO; 280c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 281c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = do_write(dev->fd, buffer, buf_size); 282c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret != buf_size) { 283c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije XLOG("%s, write failed: %s\n", __FUNCTION__, strerror(errno)); 284c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return -EIO; 285c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 286c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 287c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije next_offset += buf_size; 288c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 289c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 290c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return 0; 291c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 292c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 293c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije/** 294c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * Restores the state of all disks managed by this driver from a snapshot file. 295c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 296c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic int nand_dev_load_disks(QEMUFile *f) 297c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 298c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int i, ret; 299c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije for (i = 0; i < nand_dev_count; i++) { 300c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije ret = nand_dev_load_disk_state(f, nand_devs + i); 301c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (ret) 302c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return ret; // abort on error 303c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije } 304c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 305c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return 0; 306c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 307c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 308c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic void nand_dev_controller_state_save(QEMUFile *f, void *opaque) 309c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 310c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state* s = opaque; 311c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 312c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije qemu_put_struct(f, nand_dev_controller_state_fields, s); 313c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 314c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije /* The guest will continue writing to the disk image after the state has 315c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * been saved. To guarantee that the state is identical after resume, save 316c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije * a copy of the current disk state in the snapshot. 317c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije */ 318c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_save_disks(f); 319c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 320c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 321c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijestatic int nand_dev_controller_state_load(QEMUFile *f, void *opaque, int version_id) 322c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije{ 323c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state* s = opaque; 324c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije int ret; 325c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 326c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if (version_id != NAND_DEV_STATE_SAVE_VERSION) 327c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return -1; 328c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 329c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if ((ret = qemu_get_struct(f, nand_dev_controller_state_fields, s))) 330c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return ret; 331c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if ((ret = nand_dev_load_disks(f))) 332c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return ret; 333c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 334c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return 0; 335c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije} 336c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije 3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t nand_dev_read_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t len = total_len; 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t read_len = dev->erase_size; 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int eof = 0; 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NAND_UPDATE_READ_THRESHOLD(total_len); 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lseek(dev->fd, addr, SEEK_SET); 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(len > 0) { 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(read_len < dev->erase_size) { 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(dev->data, 0xff, dev->erase_size); 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_len = dev->erase_size; 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project eof = 1; 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(len < read_len) 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_len = len; 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(!eof) { 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_len = do_read(dev->fd, dev->data, read_len); 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_memory_rw_debug(cpu_single_env, data, dev->data, read_len, 1); 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project data += read_len; 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= read_len; 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return total_len; 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t nand_dev_write_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t len = total_len; 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t write_len = dev->erase_size; 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NAND_UPDATE_WRITE_THRESHOLD(total_len); 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lseek(dev->fd, addr, SEEK_SET); 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(len > 0) { 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(len < write_len) 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project write_len = len; 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_memory_rw_debug(cpu_single_env, data, dev->data, write_len, 0); 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = do_write(dev->fd, dev->data, write_len); 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ret < write_len) { 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("nand_dev_write_file, write failed: %s\n", strerror(errno)); 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project data += write_len; 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= write_len; 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return total_len - len; 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t nand_dev_erase_file(nand_dev *dev, uint64_t addr, uint32_t total_len) 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t len = total_len; 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t write_len = dev->erase_size; 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lseek(dev->fd, addr, SEEK_SET); 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(dev->data, 0xff, dev->erase_size); 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(len > 0) { 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(len < write_len) 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project write_len = len; 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = do_write(dev->fd, dev->data, write_len); 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ret < write_len) { 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG( "nand_dev_write_file, write failed: %s\n", strerror(errno)); 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= write_len; 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return total_len - len; 4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this is a huge hack required to make the PowerPC emulator binary usable 4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * on Mac OS X. If you define this function as 'static', the emulated kernel 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * will panic when attempting to mount the /data partition. 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * worse, if you do *not* define the function as static on Linux-x86, the 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * emulated kernel will also panic !? 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * I still wonder if this is a compiler bug, or due to some nasty thing the 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * emulator does with CPU registers during execution of the translated code. 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !(defined __APPLE__ && defined __powerpc__) 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 422c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thijeuint32_t nand_dev_do_cmd(nand_dev_controller_state *s, uint32_t cmd) 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t size; 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t addr; 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev *dev; 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = s->addr_low | ((uint64_t)s->addr_high << 32); 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = s->transfer_size; 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(s->dev >= nand_dev_count) 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev = nand_devs + s->dev; 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(cmd) { 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_GET_DEV_NAME: 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(size > dev->devname_len) 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = dev->devname_len; 4384e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner cpu_memory_rw_debug(cpu_single_env, s->data, (uint8_t*)dev->devname, size, 1); 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return size; 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_READ: 441c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(addr >= dev->max_size) 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 443c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(size > dev->max_size - addr) 444c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije size = dev->max_size - addr; 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->fd >= 0) 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nand_dev_read_file(dev, s->data, addr, size); 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 1); 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return size; 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_WRITE: 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 452c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(addr >= dev->max_size) 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 454c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(size > dev->max_size - addr) 455c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije size = dev->max_size - addr; 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->fd >= 0) 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nand_dev_write_file(dev, s->data, addr, size); 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 0); 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return size; 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_ERASE: 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 463c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(addr >= dev->max_size) 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 465c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije if(size > dev->max_size - addr) 466c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije size = dev->max_size - addr; 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->fd >= 0) 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nand_dev_erase_file(dev, addr, size); 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(&dev->data[addr], 0xff, size); 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return size; 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_BLOCK_BAD_GET: // no bad block support 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_CMD_BLOCK_BAD_SET: 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->flags & NAND_DEV_FLAG_READ_ONLY) 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd); 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* I/O write */ 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void nand_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 486c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state *s = (nand_dev_controller_state *)opaque; 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (offset) { 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV: 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->dev = value; 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(s->dev >= nand_dev_count) { 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(cpu_single_env, "nand_dev_write: Bad dev %x\n", value); 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_ADDR_HIGH: 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->addr_high = value; 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_ADDR_LOW: 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->addr_low = value; 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_TRANSFER_SIZE: 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->transfer_size = value; 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DATA: 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->data = value; 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_COMMAND: 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->result = nand_dev_do_cmd(s, value); 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(cpu_single_env, "nand_dev_write: Bad offset %x\n", offset); 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* I/O read */ 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t nand_dev_read(void *opaque, target_phys_addr_t offset) 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 519c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state *s = (nand_dev_controller_state *)opaque; 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev *dev; 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (offset) { 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_VERSION: 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NAND_VERSION_CURRENT; 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_NUM_DEV: 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nand_dev_count; 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_RESULT: 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return s->result; 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(s->dev >= nand_dev_count) 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev = nand_devs + s->dev; 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (offset) { 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_FLAGS: 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dev->flags; 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_NAME_LEN: 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dev->devname_len; 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_PAGE_SIZE: 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dev->page_size; 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_EXTRA_SIZE: 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dev->extra_size; 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_ERASE_SIZE: 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dev->erase_size; 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_SIZE_LOW: 553c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return (uint32_t)dev->max_size; 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case NAND_DEV_SIZE_HIGH: 556c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije return (uint32_t)(dev->max_size >> 32); 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(cpu_single_env, "nand_dev_read: Bad offset %x\n", offset); 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUReadMemoryFunc *nand_dev_readfn[] = { 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_read, 5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_read, 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_read 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUWriteMemoryFunc *nand_dev_writefn[] = { 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_write, 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_write, 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_write 5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize the QFB device */ 5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid nand_dev_init(uint32_t base) 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int iomemtype; 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static int instance_id = 0; 581c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state *s; 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 583c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije s = (nand_dev_controller_state *)qemu_mallocz(sizeof(nand_dev_controller_state)); 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iomemtype = cpu_register_io_memory(nand_dev_readfn, nand_dev_writefn, s); 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_register_physical_memory(base, 0x00000fff, iomemtype); 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->base = base; 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register_savevm( "nand_dev", instance_id++, NAND_DEV_STATE_SAVE_VERSION, 589c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije nand_dev_controller_state_save, nand_dev_controller_state_load, s); 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int arg_match(const char *a, const char *b, size_t b_len) 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(*a && b_len--) { 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(*a++ != *b++) 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return b_len == 0; 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid nand_add_dev(const char *arg) 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t dev_size = 0; 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char *next_arg; 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char *value; 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t arg_len, value_len; 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev *new_devs, *dev; 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *devname = NULL; 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t devname_len = 0; 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *initfilename = NULL; 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *rwfilename = NULL; 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int initfd = -1; 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rwfd = -1; 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int read_only = 0; 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pad; 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ssize_t read_size; 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t page_size = 2048; 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t extra_size = 64; 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t erase_pages = 64; 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(arg) { 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next_arg = strchr(arg, ','); 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project value = strchr(arg, '='); 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(next_arg != NULL) { 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arg_len = next_arg - arg; 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next_arg++; 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(value >= next_arg) 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project value = NULL; 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arg_len = strlen(arg); 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(value != NULL) { 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size_t new_arg_len = value - arg; 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project value_len = arg_len - new_arg_len - 1; 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arg_len = new_arg_len; 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project value++; 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project value_len = 0; 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(devname == NULL) { 6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(value != NULL) 6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project devname_len = arg_len; 6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project devname = malloc(arg_len); 6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(devname == NULL) 6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out_of_memory; 6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(devname, arg, arg_len); 6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(value == NULL) { 6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(arg_match("readonly", arg, arg_len)) { 6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_only = 1; 6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("bad arg: %.*s\n", arg_len, arg); 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(arg_match("size", arg, arg_len)) { 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *ep; 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev_size = strtoull(value, &ep, 0); 6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ep != value + value_len) 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(arg_match("pagesize", arg, arg_len)) { 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *ep; 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project page_size = strtoul(value, &ep, 0); 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ep != value + value_len) 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(arg_match("extrasize", arg, arg_len)) { 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *ep; 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project extra_size = strtoul(value, &ep, 0); 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ep != value + value_len) 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(arg_match("erasepages", arg, arg_len)) { 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *ep; 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project erase_pages = strtoul(value, &ep, 0); 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ep != value + value_len) 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(arg_match("initfile", arg, arg_len)) { 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project initfilename = malloc(value_len + 1); 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(initfilename == NULL) 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out_of_memory; 6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(initfilename, value, value_len); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project initfilename[value_len] = '\0'; 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(arg_match("file", arg, arg_len)) { 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rwfilename = malloc(value_len + 1); 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(rwfilename == NULL) 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out_of_memory; 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(rwfilename, value, value_len); 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rwfilename[value_len] = '\0'; 6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad_arg_and_value; 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arg = next_arg; 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rwfilename == NULL) { 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* we create a temporary file to store everything */ 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TempFile* tmp = tempfile_create(); 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tmp == NULL) { 7112779beecc7410f29102125e87e8174597acb2fe5Raphael XLOG("could not create temp file for %.*s NAND disk image: %s\n", 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project devname_len, devname, strerror(errno)); 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rwfilename = (char*) tempfile_path(tmp); 7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (VERBOSE_CHECK(init)) 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename); 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(rwfilename) { 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR)); 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(rwfd < 0 && read_only) { 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("could not open file %s, %s\n", rwfilename, strerror(errno)); 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* this could be a writable temporary file. use atexit_close_fd to ensure 7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * that it is properly cleaned up at exit on Win32 7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!read_only) 7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project atexit_close_fd(rwfd); 7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(initfilename) { 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project initfd = open(initfilename, O_BINARY | O_RDONLY); 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(initfd < 0) { 7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("could not open file %s, %s\n", initfilename, strerror(errno)); 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev_size == 0) { 7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev_size = lseek(initfd, 0, SEEK_END); 7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lseek(initfd, 0, SEEK_SET); 7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1)); 7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(new_devs == NULL) 7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out_of_memory; 7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_devs = new_devs; 7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev = &new_devs[nand_dev_count]; 7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->page_size = page_size; 7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->extra_size = extra_size; 7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->erase_size = erase_pages * (page_size + extra_size); 7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pad = dev_size % dev->erase_size; 7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pad != 0) { 7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev_size += (dev->erase_size - pad); 757acbee3546b9a380a4eb33daef3dccfac87c56b0bXavier Ducrohet D("rounding devsize up to a full eraseunit, now %llx\n", dev_size); 7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->devname = devname; 7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->devname_len = devname_len; 761c51182e909275b7d89c1ed847eae40fdd8b6a33fOt ten Thije dev->max_size = dev_size; 7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->data = malloc(dev->erase_size); 7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(dev->data == NULL) 7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out_of_memory; 7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0; 7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (initfd >= 0) { 7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_size = do_read(initfd, dev->data, dev->erase_size); 7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(read_size < 0) { 7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("could not read file %s, %s\n", initfilename, strerror(errno)); 7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(do_write(rwfd, dev->data, read_size) != read_size) { 7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("could not write file %s, %s\n", initfilename, strerror(errno)); 7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } while(read_size == dev->erase_size); 7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project close(initfd); 7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dev->fd = rwfd; 7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nand_dev_count++; 7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectout_of_memory: 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("out of memory\n"); 7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad_arg_and_value: 7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value); 7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(1); 7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 796e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine#ifdef CONFIG_NAND_LIMITS 797e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 798e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkinestatic uint64_t 799e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkineparse_nand_rw_limit( const char* value ) 800e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine{ 801e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine char* end; 802e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine uint64_t val = strtoul( value, &end, 0 ); 803e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 804e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (end == value) { 805e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter value '%s': expecting unsigned integer", value ); 806e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 807e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 808e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 809e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine switch (end[0]) { 810e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine case 'K': val <<= 10; break; 811e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine case 'M': val <<= 20; break; 812e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine case 'G': val <<= 30; break; 813e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine case 0: break; 814e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine default: 815e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad read/write limit suffix: use K, M or G" ); 816e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 817e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 818e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine return val; 819e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine} 820e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 821e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkinevoid 822e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkineparse_nand_limits(char* limits) 823e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine{ 824e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine int pid = -1, signal = -1; 825e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine int64_t reads = 0, writes = 0; 826e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine char* item = limits; 827e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 828e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine /* parse over comma-separated items */ 829e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine while (item && *item) { 830e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine char* next = strchr(item, ','); 831e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine char* end; 832e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 833e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (next == NULL) { 834e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine next = item + strlen(item); 835e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } else { 836e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine *next++ = 0; 837e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 838e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 839e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if ( !memcmp(item, "pid=", 4) ) { 840e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine pid = strtol(item+4, &end, 10); 841e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (end == NULL || *end) { 842e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter, expecting pid=<number>, got '%s'", 843e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine item ); 844e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 845e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 846e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (pid <= 0) { 847e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter: process identifier must be > 0" ); 848e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 849e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 850e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 851e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else if ( !memcmp(item, "signal=", 7) ) { 852e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine signal = strtol(item+7,&end, 10); 853e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (end == NULL || *end) { 854e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter: expecting signal=<number>, got '%s'", 855e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine item ); 856e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 857e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 858e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (signal <= 0) { 859e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter: signal number must be > 0" ); 860e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 861e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 862e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 863e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else if ( !memcmp(item, "reads=", 6) ) { 864e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine reads = parse_nand_rw_limit(item+6); 865e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 866e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else if ( !memcmp(item, "writes=", 7) ) { 867e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine writes = parse_nand_rw_limit(item+7); 868e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 869e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else { 870e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter '%s' (see -help-nand-limits)", item ); 871e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 872e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 873e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine item = next; 874e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 875e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine if (pid < 0) { 876e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad paramater: missing pid=<number>" ); 877e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 878e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 879e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else if (signal < 0) { 880e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine derror( "bad parameter: missing signal=<number>" ); 881e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine exit(1); 882e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 883e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine else if (reads == 0 && writes == 0) { 884e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine dwarning( "no read or write limit specified. ignoring -nand-limits" ); 885e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } else { 886e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine nand_threshold* t; 887e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 888e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t = &android_nand_read_threshold; 889e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->pid = pid; 890e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->signal = signal; 891e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->counter = 0; 892e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->limit = reads; 893e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine 894e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t = &android_nand_write_threshold; 895e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->pid = pid; 896e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->signal = signal; 897e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->counter = 0; 898e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine t->limit = writes; 899e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine } 900e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine} 901e13168648d5947955e0fd4fbf396f891ae53921fVladimir Chtchetkine#endif /* CONFIG_NAND_LIMITS */ 902