static unsigned long host_block_write(block_dev_desc_t *block_dev, unsigned long start, lbaint_t blkcnt, const void *buffer) { int dev = block_dev->dev; struct host_block_dev *host_dev = find_host_device(dev); if (os_lseek(host_dev->fd, start * host_dev->blk_dev.blksz, OS_SEEK_SET) == -1) { printf("ERROR: Invalid position\n"); return -1; } ssize_t len = os_write(host_dev->fd, buffer, blkcnt * host_dev->blk_dev.blksz); if (len >= 0) return len / host_dev->blk_dev.blksz; return -1; }
long sandbox_fs_write_at(const char *filename, unsigned long pos, void *buffer, unsigned long towrite) { ssize_t size; int fd, ret; fd = os_open(filename, OS_O_RDWR | OS_O_CREAT); if (fd < 0) return fd; ret = os_lseek(fd, pos, OS_SEEK_SET); if (ret == -1) { os_close(fd); return ret; } size = os_write(fd, buffer, towrite); os_close(fd); return size; }
static int server_readdir( u8 *p ) { const char* name; u32 fsize = 0, d; int fd; char separator[ 2 ] = { PLATFORM_PATH_SEPARATOR, 0 }; log_msg( "server_readdir: request handler starting\n" ); if( remotefs_readdir_read_request( p, &d ) == ELUARPC_ERR ) { log_msg( "server_readdir: unable to read request\n" ); return SERVER_ERR; } log_msg( "server_readdir: DIR = %08X\n", d ); os_readdir( d, &name ); if( name ) { // Need to compute size now // Get real filename server_fullname[ 0 ] = server_fullname[ PLATFORM_MAX_FNAME_LEN ] = 0; strncpy( server_fullname, server_basedir, PLATFORM_MAX_FNAME_LEN ); if( name && strlen( name ) > 0 ) { if( server_fullname[ strlen( server_fullname ) - 1 ] != PLATFORM_PATH_SEPARATOR ) strncat( server_fullname, separator, PLATFORM_MAX_FNAME_LEN ); strncat( server_fullname, name, PLATFORM_MAX_FNAME_LEN ); } fd = os_open( server_fullname, RFS_OPEN_FLAG_RDONLY, 0 ); if( fd ) { fsize = os_lseek( fd, 0, RFS_LSEEK_END ); os_close( fd ); } else { log_msg( "server_readdir: unable to open file %s\n", server_fullname ); name = NULL; } } log_msg( "server_readdir: OS response is fname = %s, fsize = %u\n", name, ( unsigned )fsize ); remotefs_readdir_write_response( p, name, fsize, 0 ); return SERVER_OK; }
long sandbox_fs_read_at(const char *filename, unsigned long pos, void *buffer, unsigned long maxsize) { ssize_t size; int fd, ret; fd = os_open(filename, OS_O_RDONLY); if (fd < 0) return fd; ret = os_lseek(fd, pos, OS_SEEK_SET); if (ret == -1) { os_close(fd); return ret; } if (!maxsize) maxsize = os_get_filesize(filename); size = os_read(fd, buffer, maxsize); os_close(fd); return size; }
int host_dev_bind(int dev, char *filename) { struct host_block_dev *host_dev = find_host_device(dev); if (!host_dev) return -1; if (host_dev->blk_dev.priv) { os_close(host_dev->fd); host_dev->blk_dev.priv = NULL; } if (host_dev->filename) free(host_dev->filename); if (filename && *filename) { host_dev->filename = strdup(filename); } else { host_dev->filename = NULL; return 0; } host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); if (host_dev->fd == -1) { printf("Failed to access host backing file '%s'\n", host_dev->filename); return 1; } block_dev_desc_t *blk_dev = &host_dev->blk_dev; blk_dev->if_type = IF_TYPE_HOST; blk_dev->priv = host_dev; blk_dev->blksz = 512; blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; blk_dev->block_read = host_block_read; blk_dev->block_write = host_block_write; blk_dev->dev = dev; blk_dev->part_type = PART_TYPE_UNKNOWN; init_part(blk_dev); return 0; }
int sandbox_fs_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize, loff_t *actread) { loff_t size; int fd, ret; fd = os_open(filename, OS_O_RDONLY); if (fd < 0) return fd; ret = os_lseek(fd, pos, OS_SEEK_SET); if (ret == -1) { os_close(fd); return ret; } if (!maxsize) { ret = os_get_filesize(filename, &size); if (ret) { os_close(fd); return ret; } maxsize = size; } size = os_read(fd, buffer, maxsize); os_close(fd); if (size < 0) { ret = -1; } else { ret = 0; *actread = size; } return ret; }
static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, const void *rxp, void *txp, unsigned long flags) { struct sandbox_spi_flash *sbsf = dev_get_priv(dev); const uint8_t *rx = rxp; uint8_t *tx = txp; uint cnt, pos = 0; int bytes = bitlen / 8; int ret; debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, sandbox_sf_state_name(sbsf->state), bytes); if ((flags & SPI_XFER_BEGIN)) sandbox_sf_cs_activate(dev); if (sbsf->state == SF_CMD) { /* Figure out the initial state */ ret = sandbox_sf_process_cmd(sbsf, rx, tx); if (ret) return ret; ++pos; } /* Process the remaining data */ while (pos < bytes) { switch (sbsf->state) { case SF_ID: { u8 id; debug(" id: off:%u tx:", sbsf->off); if (sbsf->off < IDCODE_LEN) { /* Extract correct byte from ID 0x00aabbcc */ id = sbsf->data->jedec >> (8 * (IDCODE_LEN - 1 - sbsf->off)); } else { id = 0; } debug("%d %02x\n", sbsf->off, id); tx[pos++] = id; ++sbsf->off; break; } case SF_ADDR: debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, rx[pos]); if (sbsf->addr_bytes++ < SF_ADDR_LEN) sbsf->off = (sbsf->off << 8) | rx[pos]; debug("addr:%06x\n", sbsf->off); if (tx) sandbox_spi_tristate(&tx[pos], 1); pos++; /* See if we're done processing */ if (sbsf->addr_bytes < SF_ADDR_LEN + sbsf->pad_addr_bytes) break; /* Next state! */ if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { puts("sandbox_sf: os_lseek() failed"); return -EIO; } switch (sbsf->cmd) { case CMD_READ_ARRAY_FAST: case CMD_READ_ARRAY_SLOW: sbsf->state = SF_READ; break; case CMD_PAGE_PROGRAM: sbsf->state = SF_WRITE; break; default: /* assume erase state ... */ sbsf->state = SF_ERASE; goto case_sf_erase; } debug(" cmd: transition to %s state\n", sandbox_sf_state_name(sbsf->state)); break; case SF_READ: /* * XXX: need to handle exotic behavior: * - reading past end of device */ cnt = bytes - pos; debug(" tx: read(%u)\n", cnt); assert(tx); ret = os_read(sbsf->fd, tx + pos, cnt); if (ret < 0) { puts("sandbox_sf: os_read() failed\n"); return -EIO; } pos += ret; break; case SF_READ_STATUS: debug(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status, cnt); pos += cnt; break; case SF_READ_STATUS1: debug(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status >> 8, cnt); pos += cnt; break; case SF_WRITE_STATUS: debug(" write status: %#x (ignored)\n", rx[pos]); pos = bytes; break; case SF_WRITE: /* * XXX: need to handle exotic behavior: * - unaligned addresses * - more than a page (256) worth of data * - reading past end of device */ if (!(sbsf->status & STAT_WEL)) { puts("sandbox_sf: write enable not set before write\n"); goto done; } cnt = bytes - pos; debug(" rx: write(%u)\n", cnt); if (tx) sandbox_spi_tristate(&tx[pos], cnt); ret = os_write(sbsf->fd, rx + pos, cnt); if (ret < 0) { puts("sandbox_spi: os_write() failed\n"); return -EIO; } pos += ret; sbsf->status &= ~STAT_WEL; break; case SF_ERASE: case_sf_erase: { if (!(sbsf->status & STAT_WEL)) { puts("sandbox_sf: write enable not set before erase\n"); goto done; } /* verify address is aligned */ if (sbsf->off & (sbsf->erase_size - 1)) { debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", sbsf->cmd, sbsf->erase_size, sbsf->off); sbsf->status &= ~STAT_WEL; goto done; } debug(" sector erase addr: %u, size: %u\n", sbsf->off, sbsf->erase_size); cnt = bytes - pos; if (tx) sandbox_spi_tristate(&tx[pos], cnt); pos += cnt; /* * TODO([email protected]): latch WIP in status, and * delay before clearing it ? */ ret = sandbox_erase_part(sbsf, sbsf->erase_size); sbsf->status &= ~STAT_WEL; if (ret) { debug("sandbox_sf: Erase failed\n"); goto done; } goto done; } default: debug(" ??? no idea what to do ???\n"); goto done; }
static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx, uint bytes) { struct sandbox_spi_flash *sbsf = priv; uint cnt, pos = 0; int ret; debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, sandbox_sf_state_name(sbsf->state), bytes); if (sbsf->state == SF_CMD) { /* Figure out the initial state */ if (sandbox_sf_process_cmd(sbsf, rx, tx)) return 1; ++pos; } /* Process the remaining data */ while (pos < bytes) { switch (sbsf->state) { case SF_ID: { u8 id; debug(" id: off:%u tx:", sbsf->off); if (sbsf->off < IDCODE_LEN) id = sbsf->data->idcode[sbsf->off]; else id = 0; debug("%02x\n", id); tx[pos++] = id; ++sbsf->off; break; } case SF_ADDR: debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, rx[pos]); if (sbsf->addr_bytes++ < SF_ADDR_LEN) sbsf->off = (sbsf->off << 8) | rx[pos]; debug("addr:%06x\n", sbsf->off); sandbox_spi_tristate(&tx[pos++], 1); /* See if we're done processing */ if (sbsf->addr_bytes < SF_ADDR_LEN + sbsf->pad_addr_bytes) break; /* Next state! */ if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { puts("sandbox_sf: os_lseek() failed"); return 1; } switch (sbsf->cmd) { case CMD_READ_ARRAY_FAST: case CMD_READ_ARRAY_SLOW: sbsf->state = SF_READ; break; case CMD_PAGE_PROGRAM: sbsf->state = SF_WRITE; break; default: /* assume erase state ... */ sbsf->state = SF_ERASE; goto case_sf_erase; } debug(" cmd: transition to %s state\n", sandbox_sf_state_name(sbsf->state)); break; case SF_READ: /* * XXX: need to handle exotic behavior: * - reading past end of device */ cnt = bytes - pos; debug(" tx: read(%u)\n", cnt); ret = os_read(sbsf->fd, tx + pos, cnt); if (ret < 0) { puts("sandbox_spi: os_read() failed\n"); return 1; } pos += ret; break; case SF_READ_STATUS: debug(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status, cnt); pos += cnt; break; case SF_READ_STATUS1: debug(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status >> 8, cnt); pos += cnt; break; case SF_WRITE: /* * XXX: need to handle exotic behavior: * - unaligned addresses * - more than a page (256) worth of data * - reading past end of device */ if (!(sbsf->status & STAT_WEL)) { puts("sandbox_sf: write enable not set before write\n"); goto done; } cnt = bytes - pos; debug(" rx: write(%u)\n", cnt); sandbox_spi_tristate(&tx[pos], cnt); ret = os_write(sbsf->fd, rx + pos, cnt); if (ret < 0) { puts("sandbox_spi: os_write() failed\n"); return 1; } pos += ret; sbsf->status &= ~STAT_WEL; break; case SF_ERASE: case_sf_erase: { const struct sandbox_spi_flash_erase_commands * erase_cmd = sbsf->cmd_data; if (!(sbsf->status & STAT_WEL)) { puts("sandbox_sf: write enable not set before erase\n"); goto done; } /* verify address is aligned */ if (sbsf->off & (erase_cmd->size - 1)) { debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", erase_cmd->cmd, erase_cmd->size, sbsf->off); sbsf->status &= ~STAT_WEL; goto done; } debug(" sector erase addr: %u\n", sbsf->off); cnt = bytes - pos; sandbox_spi_tristate(&tx[pos], cnt); pos += cnt; /* * TODO([email protected]): latch WIP in status, and * delay before clearing it ? */ ret = sandbox_erase_part(sbsf, erase_cmd->size); sbsf->status &= ~STAT_WEL; if (ret) { debug("sandbox_sf: Erase failed\n"); goto done; } goto done; } default: debug(" ??? no idea what to do ???\n"); goto done; } } done: return pos == bytes ? 0 : 1; }
int host_dev_bind(int devnum, char *filename) { struct host_block_dev *host_dev; struct udevice *dev; char dev_name[20], *str, *fname; int ret, fd; /* Remove and unbind the old device, if any */ ret = blk_get_device(IF_TYPE_HOST, devnum, &dev); if (ret == 0) { ret = device_remove(dev); if (ret) return ret; ret = device_unbind(dev); if (ret) return ret; } else if (ret != -ENODEV) { return ret; } if (!filename) return 0; snprintf(dev_name, sizeof(dev_name), "host%d", devnum); str = strdup(dev_name); if (!str) return -ENOMEM; fname = strdup(filename); if (!fname) { free(str); return -ENOMEM; } fd = os_open(filename, OS_O_RDWR); if (fd == -1) { printf("Failed to access host backing file '%s'\n", filename); ret = -ENOENT; goto err; } ret = blk_create_device(gd->dm_root, "sandbox_host_blk", str, IF_TYPE_HOST, devnum, 512, os_lseek(fd, 0, OS_SEEK_END), &dev); if (ret) goto err_file; ret = device_probe(dev); if (ret) { device_unbind(dev); goto err_file; } host_dev = dev_get_priv(dev); host_dev->fd = fd; host_dev->filename = fname; return blk_prepare_device(dev); err_file: os_close(fd); err: free(fname); free(str); return ret; }