s32 DI_Config_Load(struct dipConfigState *cfg) { s32 fd, ret; #ifdef DEBUG svc_write("DIP: Config_Load(): Loading config file "); svc_write(__dip_cfg_filename); svc_write("\n"); #endif /* Open config file */ fd = os_open(__dip_cfg_filename, ISFS_OPEN_READ); #ifdef DEBUG svc_write("DIP: Config_Load(): Config file "); svc_write(fd < 0 ? "NOT found\n" : "found\n"); #endif if (fd < 0) return fd; /* Read config */ ret = os_read(fd, cfg, sizeof(struct dipConfigState)); if (ret == sizeof(struct dipConfigState)) { if (cfg->mode == MODE_FRAG) { s32 ret2; /* Read frag list */ memset(&fraglist_data, 0, sizeof(fraglist_data)); if (cfg->frag_size > sizeof(fraglist_data)) { ret2 = -1; } else { ret2 = os_read(fd, &fraglist_data, cfg->frag_size); } if (ret2 != cfg->frag_size) ret = -1; } } else if (ret >= 0) ret = -1; /* Close config */ os_close(fd); /* Delete config file */ __Config_Delete(__dip_cfg_filename); #ifdef DEBUG if (ret < 0) svc_write("DIP: Config_Load(): Config file has unexpected size!!!\n"); #endif return ret; }
ssize_t os_read_no_block(int fd, void *buf, size_t count) { const int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); return os_read(fd, buf, count); }
static unsigned long host_block_read(struct udevice *dev, unsigned long start, lbaint_t blkcnt, void *buffer) { struct host_block_dev *host_dev = dev_get_priv(dev); struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #else static unsigned long host_block_read(struct blk_desc *block_dev, unsigned long start, lbaint_t blkcnt, void *buffer) { int dev = block_dev->devnum; struct host_block_dev *host_dev = find_host_device(dev); if (!host_dev) return -1; #endif if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { printf("ERROR: Invalid block %lx\n", start); return -1; } ssize_t len = os_read(host_dev->fd, buffer, blkcnt * block_dev->blksz); if (len >= 0) return len / block_dev->blksz; return -1; }
/* * Simple wrapper around os_read that passes any previously processed * data to os->writer and then discards it to make room in * the buffer, while ensuring at least MAX_HEADER_SIZE bytes remain. * Returns the number of new data bytes in the buffer. */ static int getter_section(const char **text, void *cookie) { output_section_t *os = cookie; size_t prevconsumed; if (os->consumed < os->len) goto done; if (os->len == sizeof(os->buf)) { if (os->consumed <= MAX_HEADER_SIZE) goto done; if (os->in_section) { os->writer(os->name, os->content_type, os->buf, os->consumed - MAX_HEADER_SIZE, os->pos - os->len); } os_discard(os, os->consumed - MAX_HEADER_SIZE); os->consumed = MAX_HEADER_SIZE; } if (os_read(os) <= 0) return 0; done: prevconsumed = os->consumed; os->consumed = os->len; *text = os->buf + prevconsumed; return os->consumed - prevconsumed; }
void req_echo_str(FILE *fp, int fd, const struct sockaddr *destaddr, socklen_t addrlen) { char sbuf[MAXLINE], rbuf[MAXLINE]; int n; struct sockaddr reply_addr; socklen_t len; os_connect(fd, destaddr, addrlen); while (fgets(sbuf, MAXLINE, fp) != NULL) { //printf("[send]: %s", sbuf); os_write(fd, sbuf, strlen(sbuf)); len = addrlen; n = os_read(fd, rbuf, MAXLINE); #if 0 if (len != addrlen || memcmp(destaddr, &reply_addr, addrlen) != 0) { printf("packet not for us\n"); continue; } #endif rbuf[n] = 0; fputs(rbuf, stdout); } }
static void tiger_tree_fd(OS_FD fd, OFF_T len, OFF_T pos, OFF_T block_size, char *digest) { static char tiger_buffer[BLOCK_SIZE+1]; if(block_size == BLOCK_SIZE){ OFF_T length = (len - pos > BLOCK_SIZE) ? BLOCK_SIZE : len - pos; char *s = tiger_buffer+1; size_t toread = length; char *curs = s; while (toread!=0){ int max_nread = toread; /* HASH_BUFFER_LEN > toread ? toread : HASH_BUFFER_LEN; */ ssize_t nread = os_read (fd, curs, max_nread); if(nread <= 0) { unix_error(errno, "tiger_safe_fd: Read", Nothing); } curs += nread; toread -= nread; } tiger_hash(0, s, length, digest); } else { if(pos+block_size/2 >=len){ tiger_tree_fd(fd, len, pos, block_size/2, digest); } else { char digests_prefixed[1+DIGEST_LEN * 2]; char *digests = digests_prefixed+1; tiger_tree_fd(fd, len, pos, block_size/2, digests); tiger_tree_fd(fd, len, pos+block_size/2, block_size/2, digests+DIGEST_LEN); tiger_hash(1,digests, 2*DIGEST_LEN, digest); } } }
/* Fill a given buffer with the given block in volume. */ int volume_readinbuf(volume * vol,void* buf, long block) { UInt16 blksize_bits; ASSERT( block < vol->maxblocks); blksize_bits = vol->blksize_bits; block += vol->startblock; if( os_seek(vol->os_fd, block, blksize_bits) == block) if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits)) return 0; return -1; }
bool system_identifier_read(system_identifier_t *system_id) { os_read(system_id->os, sizeof(system_id->os)); system_serial_read(system_id->system, sizeof(system_id->system)); chassis_serial_read(system_id->chassis, sizeof(system_id->chassis)); baseboard_serial_read(system_id->baseboard, sizeof(system_id->baseboard)); unsigned char mac[6]; mac_read(mac, sizeof(mac)); sha1_calc(mac, sizeof(mac), system_id->mac, sizeof(system_id->mac)); return true; }
/* * Read into buffer until a newline is found. * Note: searches any existing data in the buffer, so discard * any previously processed data before calling. * Returns offset of newline, or 0 if buffer is full before found. */ static ssize_t os_getline(output_section_t *os) { size_t len = 0; char *p; for (;;) { p = memchr(os->buf + len, '\n', os->len - len); if (p) return p - os->buf + 1; len = os->len; if (os_read(os) <= 0) return 0; } }
bool module_file_has_module_header(const char *filename) { bool res = false; struct mach_header hdr; file_t fd = os_open(filename, OS_OPEN_READ); if (fd == INVALID_FILE) return false; if (os_read(fd, &hdr, sizeof(hdr)) == sizeof(hdr) && is_macho_header((app_pc)&hdr, sizeof(hdr))) res = true; os_close(fd); return res; }
static int server_read( u8 *p ) { int fd; u32 count; log_msg( "server_read: request handler starting\n" ); if( remotefs_read_read_request( p, &fd, &count ) == ELUARPC_ERR ) { log_msg( "server_read: unable to read request\n" ); return SERVER_ERR; } log_msg( "server_read: fd = %d, count = %u\n", fd, ( unsigned )count ); count = ( u32 )os_read( fd, p + ELUARPC_READ_BUF_OFFSET, count ); log_msg( "server_read: OS response is %u\n", ( unsigned )count ); remotefs_read_write_response( p, count ); return SERVER_OK; }
static unsigned long host_block_read(int dev, unsigned long start, lbaint_t blkcnt, void *buffer) { struct host_block_dev *host_dev = find_host_device(dev); if (!host_dev) return -1; 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_read(host_dev->fd, buffer, blkcnt * host_dev->blk_dev.blksz); if (len >= 0) return len / host_dev->blk_dev.blksz; return -1; }
/* Read a file into memory and return a pointer to it */ static int read_file(struct unit_test_state *uts, const char *fname, ulong *addrp) { int buf_size = 100000; ulong addr = 0; int size, fd; char *buf; buf = map_sysmem(addr, 0); ut_assert(buf != NULL); fd = os_open(fname, OS_O_RDONLY); ut_assert(fd >= 0); size = os_read(fd, buf, buf_size); ut_assert(size >= 0); ut_assert(size < buf_size); os_close(fd); *addrp = addr; return 0; }
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 sandbox_read_fdt_from_file(void) { struct sandbox_state *state = state_get_current(); const char *fname = state->fdt_fname; void *blob; loff_t size; int err; int fd; blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0); if (!state->fdt_fname) { err = fdt_create_empty_tree(blob, 256); if (!err) goto done; printf("Unable to create empty FDT: %s\n", fdt_strerror(err)); return -EINVAL; } err = os_get_filesize(fname, &size); if (err < 0) { printf("Failed to file FDT file '%s'\n", fname); return err; } fd = os_open(fname, OS_O_RDONLY); if (fd < 0) { printf("Failed to open FDT file '%s'\n", fname); return -EACCES; } if (os_read(fd, blob, size) != size) { os_close(fd); return -EIO; } os_close(fd); done: gd->fdt_blob = blob; return 0; }
s32 FFS_Config_Load(struct ffsConfigState *cfg) { s32 fd, ret; #ifdef DEBUG svc_write("DIP: Config_Load(): Loading config file "); svc_write(__ffs_cfg_filename); svc_write("\n"); #endif /* Open config file */ fd = os_open(__ffs_cfg_filename, ISFS_OPEN_READ); #ifdef DEBUG svc_write("DIP: Config_Load(): Config file "); svc_write(fd < 0 ? "NOT found\n" : "found\n"); #endif if (fd < 0) return fd; /* Read config */ ret = os_read(fd, cfg, sizeof(struct ffsConfigState)); if (ret != sizeof(struct ffsConfigState)) { #ifdef DEBUG svc_write("DIP: Config_Load(): Config file has unexpected size!!!\n"); #endif ret = -1; } /* Close config */ os_close(fd); /* Delete config file */ __Config_Delete(__ffs_cfg_filename); return ret; }
static int state_read_file(struct sandbox_state *state, const char *fname) { loff_t size; int ret; int fd; ret = os_get_filesize(fname, &size); if (ret < 0) { printf("Cannot find sandbox state file '%s'\n", fname); return ret; } state->state_fdt = os_malloc(size); if (!state->state_fdt) { puts("No memory to read sandbox state\n"); return -ENOMEM; } fd = os_open(fname, OS_O_RDONLY); if (fd < 0) { printf("Cannot open sandbox state file '%s'\n", fname); ret = -EPERM; goto err_open; } if (os_read(fd, state->state_fdt, size) != size) { printf("Cannot read sandbox state file '%s'\n", fname); ret = -EIO; goto err_read; } os_close(fd); return 0; err_read: os_close(fd); err_open: os_free(state->state_fdt); state->state_fdt = NULL; return ret; }
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; }
int main(int argc, char *argv[]) { int listenfd; int connfd; int on = 1; struct sockaddr_in serv_addr, cli_addr; socklen_t cli_len; int client_fd[FD_SETSIZE];/* each for every client */ fd_set allset; /* save interested descriptors */ fd_set rdset; /* select on this set */ int maxfd; int max_indx; /* max index in client_fd[] array */ int i, n; int nready; char buf[MAXLINE]; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "socket error: %s\n", strerror(errno)); exit(1); } os_setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_PORT); if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { fprintf(stderr, "bind error: %s\n", strerror(errno)); exit(1); } if (listen(listenfd, LISTEN_QUEUE) < 0) { fprintf(stderr, "listern error: %s\n", strerror(errno)); exit(1); } for (i=0; i < FD_SETSIZE; i++) client_fd[i] = -1; FD_ZERO(&allset); FD_SET(listenfd, &allset); maxfd = listenfd; max_indx = 0; for (; ;) { rdset = allset; nready = os_select(maxfd + 1, &rdset, NULL, NULL, NULL); /* select will modify rdset once return */ /* task 1: listen... accept new connection */ if(FD_ISSET(listenfd, &rdset)) { cli_len = sizeof(cli_addr); connfd = os_accept(listenfd, (struct sockaddr *)&cli_addr, &cli_len); for (i=0; i < FD_SETSIZE; i++) { /* a new client coming, select a useable fd */ if (client_fd[i] == -1) { client_fd[i] = connfd; maxfd = (connfd > maxfd) ? connfd : maxfd; break; } } FD_SET(connfd, &allset); if (i > max_indx) max_indx = i; if (--nready <= 0) continue; /* no more readable descriptors */ } /* task 2: deal with all clients' data */ for (i=0; i < maxfd; i++) { if (client_fd[i] == -1) continue; if (FD_ISSET(client_fd[i], &rdset)) { if ((n = os_read(client_fd[i], buf, MAXLINE)) == 0) { close(client_fd[i]); FD_CLR(client_fd[i], &allset); client_fd[i] = -1; } else { #ifdef DEBUG os_write(fileno(stdout), buf, n); #endif os_write(client_fd[i], buf, n); } } if (--nready <= 0) break; /* no more readable descriptors */ } #if 0 cli_len = sizeof(cli_addr); if ((connfd = accept(listenfd, (struct sockaddr *)&cli_addr, &cli_len)) < 0) { if (errno == EINTR) continue; else os_err_sys("accept error"); } if ((childpid = fork()) == 0) { close(listenfd); echo_string(connfd); exit(1); } close(connfd); #endif } return 0; }
s32 FFS_Read(s32 fd, void *d, s32 len) { return os_read(fd, d, len); }
int cgi_extract_sections(output_buffer_function *writer) { int content_length; const char *p; char *boundary; int boundary_length; int match; output_section_t os; p = getenv("REQUEST_METHOD"); if (!p || strcmp(p, "POST") != 0) { syslog(LOG_WARNING, "cgi_filefetch not POST"); return(CGIPARSE_ERR_FORMAT); } p = getenv("CONTENT_LENGTH"); if (!p || ((content_length = atoi(p)) == 0)) { syslog(LOG_WARNING, "cgi_filefetch bad content length"); return(CGIPARSE_ERR_DATA); } p = getenv("CONTENT_TYPE"); if (!p || strncmp(p, MULTIPART_FORM_DATA, sizeof(MULTIPART_FORM_DATA) - 1) != 0) { syslog(LOG_WARNING, "cgi_filefetch not type: %s", MULTIPART_FORM_DATA); return(CGIPARSE_ERR_DATA); } /* Now search for boundary=XXX */ p = strstr(p, "boundary="); if (!p) { syslog(LOG_WARNING, "cgi_filefetch bad or missing boundary specification"); return(CGIPARSE_ERR_DATA); } p = strchr(p, '=') + 1; debug("Got boundary=[%s]\n", p); /* Now search for --<boundary> * Note that we don't search for \r\n--<boundary> since * sometimes?? the first \r\n is missing */ boundary_length = strlen(p) + 2; boundary = alloca(boundary_length + 1); sprintf(boundary, "--%s", p); os.timeout = 0; os.len = 0; os.pos = 0; os.consumed = 0; os.in_section = 0; os.writer = writer; set_nonblock(0); /* Now iterate through each item separated by the boundary */ while ((match = KMP(boundary, boundary_length, getter_section, &os)) >= 0) { debug("Found match at %d\n", match - boundary_length); /* Flush all the bytes up until the match. */ os.consumed = os.len - (os.pos - match); if (os.in_section) { /* We have been outputting this section. Back up by the boundary length * (plus 2 for the \r\n) and flush the buffer */ debug("reached end of section, match=%d, os.len=%d, os.pos=%d, boundary_length=%d\n", match, (int)os.len, (int)os.pos, boundary_length); assert(os.consumed >= boundary_length + 2); os.writer(os.name, os.content_type, os.buf, os.consumed - boundary_length - 2, os.pos - os.len); } os_discard(&os, os.consumed); os.consumed = 0; while (os.len < 2) if (os_read(&os) <= 0) goto err; char ch1 = os.buf[0]; char ch2 = os.buf[1]; os_discard(&os, 2); if (ch1 == '\r' && ch2 == '\n') { /* we are at a boundary, so process this section */ if (process_section(&os) <= 0) goto err; } else if (ch1 == '-' && ch2 == '-') { debug("This is the last section\n"); return CGIPARSE_ERR_NONE; } else { debug("Warning: Ignoring section with unknown terminator: '%c%c'\n", ch1, ch2); } os.pos = os.len; } err: if (os.timeout) { return CGIPARSE_ERR_TIMEDOUT; } else { return CGIPARSE_ERR_DATA; } }
bool memquery_iterator_next(memquery_iter_t *iter) { maps_iter_t *mi = (maps_iter_t *) &iter->internal; char perm[16]; char *line; int len; app_pc prev_start = iter->vm_start; ASSERT((iter->may_alloc && OWN_MUTEX(&maps_iter_buf_lock)) || (!iter->may_alloc && OWN_MUTEX(&memory_info_buf_lock))); if (mi->newline == NULL) { mi->bufwant = BUFSIZE-1; mi->bufread = os_read(mi->maps, mi->buf, mi->bufwant); ASSERT(mi->bufread <= mi->bufwant); LOG(GLOBAL, LOG_VMAREAS, 6, "get_memory_info_from_os: bytes read %d/want %d\n", mi->bufread, mi->bufwant); if (mi->bufread <= 0) return false; mi->buf[mi->bufread] = '\0'; mi->newline = strchr(mi->buf, '\n'); line = mi->buf; } else { line = mi->newline + 1; mi->newline = strchr(line, '\n'); if (mi->newline == NULL) { /* FIXME clean up: factor out repetitive code */ /* shift 1st part of line to start of buf, then read in rest */ /* the memory for the processed part can be reused */ mi->bufwant = line - mi->buf; ASSERT(mi->bufwant <= mi->bufread); len = mi->bufread - mi->bufwant; /* what is left from last time */ /* since strings may overlap, should use memmove, not strncpy */ /* FIXME corner case: if len == 0, nothing to move */ memmove(mi->buf, line, len); mi->bufread = os_read(mi->maps, mi->buf+len, mi->bufwant); ASSERT(mi->bufread <= mi->bufwant); if (mi->bufread <= 0) return false; mi->bufread += len; /* bufread is total in buf */ mi->buf[mi->bufread] = '\0'; mi->newline = strchr(mi->buf, '\n'); line = mi->buf; } } LOG(GLOBAL, LOG_VMAREAS, 6, "\nget_memory_info_from_os: newline=[%s]\n", mi->newline ? mi->newline : "(null)"); /* Buffer is big enough to hold at least one line: if not, the file changed * underneath us after we hit the end. Just bail. */ if (mi->newline == NULL) return false; *mi->newline = '\0'; LOG(GLOBAL, LOG_VMAREAS, 6, "\nget_memory_info_from_os: line=[%s]\n", line); mi->comment_buffer[0]='\0'; len = sscanf(line, #ifdef IA32_ON_IA64 MAPS_LINE_FORMAT8, /* cross-compiling! */ #else sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8, #endif (unsigned long*)&iter->vm_start, (unsigned long*)&iter->vm_end, perm, (unsigned long*)&iter->offset, &iter->inode, mi->comment_buffer); if (iter->vm_start == iter->vm_end) { /* i#366 & i#599: Merge an empty regions caused by stack guard pages * into the stack region if the stack region is less than one page away. * Otherwise skip it. Some Linux kernels (2.6.32 has been observed) * have empty entries for the stack guard page. We drop the permissions * on the guard page, because Linux always insists that it has rwxp * perms, no matter how we change the protections. The actual stack * region has the perms we expect. * XXX: We could get more accurate info if we looked at * /proc/self/smaps, which has a Size: 4k line for these "empty" * regions. */ app_pc empty_start = iter->vm_start; bool r; LOG(GLOBAL, LOG_VMAREAS, 2, "maps_iterator_next: skipping or merging empty region 0x%08x\n", iter->vm_start); /* don't trigger the maps-file-changed check. * slight risk of a race where we'll pass back earlier/overlapping * region: we'll live with it. */ iter->vm_start = NULL; r = memquery_iterator_next(iter); /* We could check to see if we're combining with the [stack] section, * but that doesn't work if there are multiple stacks or the stack is * split into multiple maps entries, so we merge any empty region within * one page of the next region. */ if (empty_start <= iter->vm_start && iter->vm_start <= empty_start + PAGE_SIZE) { /* Merge regions if the next region was zero or one page away. */ iter->vm_start = empty_start; } return r; } if (iter->vm_start <= prev_start) { /* the maps file has expanded underneath us (presumably due to our * own committing while iterating): skip ahead */ LOG(GLOBAL, LOG_VMAREAS, 2, "maps_iterator_next: maps file changed: skipping 0x%08x\n", prev_start); iter->vm_start = prev_start; return memquery_iterator_next(iter); } if (len<6) mi->comment_buffer[0]='\0'; iter->prot = permstr_to_memprot(perm); #ifdef ANDROID /* i#1861: the Android kernel supports custom comments which can't merge */ if (iter->comment[0] != '\0') iter->prot |= MEMPROT_HAS_COMMENT; #endif return true; }
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; }
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_flash_bulk(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buff, int len) { struct sandbox_flash_plat *plat = dev_get_platdata(dev); struct sandbox_flash_priv *priv = dev_get_priv(dev); int ep = usb_pipeendpoint(pipe); struct umass_bbb_cbw *cbw = buff; debug("%s: dev=%s, pipe=%lx, ep=%x, len=%x, phase=%d\n", __func__, dev->name, pipe, ep, len, priv->phase); switch (ep) { case SANDBOX_FLASH_EP_OUT: switch (priv->phase) { case PHASE_START: priv->alloc_len = 0; priv->read_len = 0; if (priv->error || len != UMASS_BBB_CBW_SIZE || cbw->dCBWSignature != CBWSIGNATURE) goto err; if ((cbw->bCBWFlags & CBWFLAGS_SBZ) || cbw->bCBWLUN != 0) goto err; if (cbw->bCDBLength < 1 || cbw->bCDBLength >= 0x10) goto err; priv->transfer_len = cbw->dCBWDataTransferLength; priv->tag = cbw->dCBWTag; return handle_ufi_command(plat, priv, cbw->CBWCDB, cbw->bCDBLength); case PHASE_DATA: debug("data out\n"); break; default: break; } case SANDBOX_FLASH_EP_IN: switch (priv->phase) { case PHASE_DATA: debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n", len, priv->alloc_len, priv->read_len); if (priv->read_len) { ulong bytes_read; bytes_read = os_read(priv->fd, buff, len); if (bytes_read != len) return -EIO; priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; if (!priv->read_len) priv->phase = PHASE_STATUS; } else { if (priv->alloc_len && len > priv->alloc_len) len = priv->alloc_len; memcpy(buff, priv->buff, len); priv->phase = PHASE_STATUS; } return len; case PHASE_STATUS: debug("status in, len=%x\n", len); if (len > sizeof(priv->status)) len = sizeof(priv->status); memcpy(buff, &priv->status, len); priv->phase = PHASE_START; return len; default: break; } } err: priv->error = true; debug("%s: Detected transfer error\n", __func__); return 0; }