static void scsi_mode_sense6(uint8_t *block, uint8_t in_len) { uint8_t response[4]; if (state == USB_MS_SCSI_STATE_PARSE) { state = USB_MS_SCSI_STATE_DATA_OUT; /* terminate if fail to verify */ if (scsi_verify_cdb6(block, in_len)) return; /* response exceeds allocation length */ if (block[4] < sizeof(response)) return scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_INVALID_FIELD_IN_CDB); memset(response, 0, sizeof(response)); /* set WP bit if necessary */ response[2] = spi_flash_check_protect(0, CONFIG_SPI_FLASH_SIZE) ? (1 << 7) : 0; memcpy_usbram(ms_ep_tx, (uint8_t *) response, sizeof(response)); btable_ep[USB_EP_MS_TX].tx_count = sizeof(response); } else if (state == USB_MS_SCSI_STATE_DATA_OUT) state = USB_MS_SCSI_STATE_REPLY; return scsi_sense_code(SCSI_SENSE_NO_SENSE, SCSI_SENSE_CODE_NONE); }
/** * Return flash protect state flags from the physical layer. * * This should only be called by flash_get_protect(). * * Uses the EC_FLASH_PROTECT_* flags from ec_commands.h */ uint32_t flash_physical_get_protect_flags(void) { uint32_t flags = 0; if (spi_flash_check_protect(CONFIG_WP_STORAGE_OFF, CONFIG_WP_STORAGE_SIZE)) { flags |= EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW; } if (entire_flash_locked) flags |= EC_FLASH_PROTECT_ALL_NOW; return flags; }
/** * Read physical write protect setting for a flash bank. * * @param bank Bank index to check. * @return non-zero if bank is protected until reboot. */ int flash_physical_get_protect(int bank) { return spi_flash_check_protect(bank * CONFIG_FLASH_BANK_SIZE, CONFIG_FLASH_BANK_SIZE); }
/* * Required by SPC-4. */ static void scsi_write10(uint8_t *block, uint8_t in_len) { int rv; int write_len; if (state == USB_MS_SCSI_STATE_PARSE) { state = USB_MS_SCSI_STATE_DATA_IN; /* terminate if fail to verify */ if (scsi_verify_cdb10(block, in_len)) return; /* RELADR bit not supported */ if (block[1] & 0x1) return scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_INVALID_FIELD_IN_CDB); buffer = 0; offset = SCSI_BLOCK_SIZE_BYTES * (block[2] << 24 | block[3] << 16 | block[4] << 8 | block[5]); bytes = SCSI_BLOCK_SIZE_BYTES * (block[7] << 8 | block[8]); /* Chip has protection */ if (spi_flash_check_protect(offset, bytes)) return scsi_sense_code(SCSI_SENSE_DATA_PROTECT, SCSI_SENSE_CODE_WRITE_PROTECTED); /* Wait for any previous operation to complete */ rv = spi_flash_wait(); if (rv == EC_ERROR_TIMEOUT) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_TIMEOUT); rv = spi_flash_erase(offset, bytes); /* invalid address */ if (rv == EC_ERROR_INVAL) return scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_LBA_OUT_OF_RANGE); else if (rv != EC_SUCCESS) return scsi_sense_code(SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_UNRECOVERED_READ_ERROR); } else if (state == USB_MS_SCSI_STATE_DATA_IN) { /* write whatever was received */ write_len = MIN(bytes, btable_ep[USB_EP_MS_RX].rx_count & 0x3ff); ASSERT(write_len <= SPI_FLASH_MAX_WRITE_SIZE); #if CONFIG_USB_MS_BUFFER_SIZE != USB_MS_PACKET_SIZE /* perform write only when local buffer is over full */ if (buffer + write_len > CONFIG_USB_MS_BUFFER_SIZE) { /* Wait for previous operation to complete */ rv = spi_flash_wait(); if (rv == EC_ERROR_TIMEOUT) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_TIMEOUT); rv = spi_flash_write(offset, CONFIG_USB_MS_BUFFER_SIZE, temp_buf); if (rv == EC_ERROR_INVAL) return scsi_sense_code( SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_LBA_OUT_OF_RANGE); else if (rv != EC_SUCCESS) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_UNRECOVERED_READ_ERROR); offset += buffer; bytes -= buffer; buffer = 0; } /* copy data to local buffer */ memcpy(temp_buf + buffer, (uint8_t *) ms_ep_rx, write_len); buffer += write_len; /* on last write */ if (bytes == buffer) { /* Wait for previous operation to complete */ rv = spi_flash_wait(); if (rv == EC_ERROR_TIMEOUT) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_TIMEOUT); rv = spi_flash_write(offset, buffer, temp_buf); if (rv == EC_ERROR_INVAL) return scsi_sense_code( SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_LBA_OUT_OF_RANGE); else if (rv == EC_ERROR_ACCESS_DENIED) return scsi_sense_code(SCSI_SENSE_DATA_PROTECT, SCSI_SENSE_CODE_WRITE_PROTECTED); else if (rv != EC_SUCCESS) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_UNRECOVERED_READ_ERROR); /* Wait for last write to complete */ rv = spi_flash_wait(); if (rv == EC_ERROR_TIMEOUT) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_TIMEOUT); offset += buffer; bytes -= buffer; buffer = 0; /* received too much data */ } else if (bytes < buffer) return scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_LBA_OUT_OF_RANGE); #else memcpy(temp_buf, (uint8_t *) ms_ep_rx, write_len); /* Wait for previous operation to complete */ rv = spi_flash_wait(); if (rv == EC_ERROR_TIMEOUT) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_TIMEOUT); rv = spi_flash_write(offset, write_len, temp_buf); if (rv == EC_ERROR_INVAL) return scsi_sense_code( SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_LBA_OUT_OF_RANGE); else if (rv == EC_ERROR_ACCESS_DENIED) return scsi_sense_code(SCSI_SENSE_DATA_PROTECT, SCSI_SENSE_CODE_WRITE_PROTECTED); else if (rv != EC_SUCCESS) return scsi_sense_code( SCSI_SENSE_HARDWARE_ERROR, SCSI_SENSE_CODE_UNRECOVERED_READ_ERROR); offset += write_len; bytes -= write_len; #endif /* nothing left to write */ if (!bytes) state = USB_MS_SCSI_STATE_REPLY; } return scsi_sense_code(SCSI_SENSE_NO_SENSE, SCSI_SENSE_CODE_NONE); }