diff options
-rw-r--r-- | include/programmer.h | 8 | ||||
-rw-r--r-- | include/writeprotect.h | 3 | ||||
-rw-r--r-- | libflashrom.c | 18 | ||||
-rw-r--r-- | writeprotect.c | 37 |
4 files changed, 53 insertions, 13 deletions
diff --git a/include/programmer.h b/include/programmer.h index 5fb06260e..eaf4a983e 100644 --- a/include/programmer.h +++ b/include/programmer.h @@ -402,6 +402,14 @@ struct opaque_master { int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); int (*write) (struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int (*erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen); + /* + * Callbacks for accessing flash registers. An opaque programmer must + * provide these functions for writeprotect operations to be available, + * unless it provides custom wp operations instead. + */ + int (*read_register)(const struct flashctx *flash, enum flash_reg reg, uint8_t *value); + int (*write_register)(const struct flashctx *flash, enum flash_reg reg, uint8_t value); + /* Callbacks for overiding default writeprotect operations with custom ones. */ enum flashrom_wp_result (*wp_write_cfg)(struct flashctx *, const struct flashrom_wp_cfg *); enum flashrom_wp_result (*wp_read_cfg)(struct flashrom_wp_cfg *, struct flashctx *); enum flashrom_wp_result (*wp_get_ranges)(struct flashrom_wp_ranges **, struct flashctx *); diff --git a/include/writeprotect.h b/include/writeprotect.h index e27403dcf..12926c4d3 100644 --- a/include/writeprotect.h +++ b/include/writeprotect.h @@ -86,4 +86,7 @@ enum flashrom_wp_result wp_read_cfg(struct flashrom_wp_cfg *, struct flashrom_fl /* Get a list of protection ranges supported by the chip */ enum flashrom_wp_result wp_get_available_ranges(struct flashrom_wp_ranges **, struct flashrom_flashctx *); +/* Checks if writeprotect functions can be used with the current flash/programmer */ +bool wp_operations_available(struct flashrom_flashctx *); + #endif /* !__WRITEPROTECT_H__ */ diff --git a/libflashrom.c b/libflashrom.c index 0c6613e94..3e28938c9 100644 --- a/libflashrom.c +++ b/libflashrom.c @@ -470,34 +470,34 @@ void flashrom_wp_get_range(size_t *start, size_t *len, const struct flashrom_wp_ enum flashrom_wp_result flashrom_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg) { - if (flash->mst->buses_supported & BUS_SPI) - return wp_write_cfg(flash, cfg); - if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_write_cfg) return flash->mst->opaque.wp_write_cfg(flash, cfg); + if (wp_operations_available(flash)) + return wp_write_cfg(flash, cfg); + return FLASHROM_WP_ERR_OTHER; } enum flashrom_wp_result flashrom_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash) { - if (flash->mst->buses_supported & BUS_SPI) - return wp_read_cfg(cfg, flash); - if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_read_cfg) return flash->mst->opaque.wp_read_cfg(cfg, flash); + if (wp_operations_available(flash)) + return wp_read_cfg(cfg, flash); + return FLASHROM_WP_ERR_OTHER; } enum flashrom_wp_result flashrom_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashrom_flashctx *flash) { - if (flash->mst->buses_supported & BUS_SPI) - return wp_get_available_ranges(list, flash); - if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_get_ranges) return flash->mst->opaque.wp_get_ranges(list, flash); + if (wp_operations_available(flash)) + return wp_get_available_ranges(list, flash); + return FLASHROM_WP_ERR_OTHER; } diff --git a/writeprotect.c b/writeprotect.c index 60d8ead1e..57d0f9bd6 100644 --- a/writeprotect.c +++ b/writeprotect.c @@ -23,13 +23,33 @@ #include "libflashrom.h" #include "chipdrivers.h" #include "writeprotect.h" +#include "programmer.h" + +/* + * Allow specialisation in opaque masters, such as ichspi hwseq, to r/w to status registers. + */ +static int wp_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t value) +{ + if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.write_register) { + return flash->mst->opaque.write_register(flash, reg, value); + } + return spi_write_register(flash, reg, value); +} + +static int wp_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value) +{ + if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.read_register) { + return flash->mst->opaque.read_register(flash, reg, value); + } + return spi_read_register(flash, reg, value); +} /** Read and extract a single bit from the chip's registers */ static enum flashrom_wp_result read_bit(uint8_t *value, bool *present, struct flashctx *flash, struct reg_bit_info bit) { *present = bit.reg != INVALID_REG; if (*present) { - if (spi_read_register(flash, bit.reg, value)) + if (wp_read_register(flash, bit.reg, value)) return FLASHROM_WP_ERR_READ_FAILED; *value = (*value >> bit.bit_index) & 1; } else { @@ -126,12 +146,12 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b continue; uint8_t value; - if (spi_read_register(flash, reg, &value)) + if (wp_read_register(flash, reg, &value)) return FLASHROM_WP_ERR_READ_FAILED; value = (value & ~write_masks[reg]) | (reg_values[reg] & write_masks[reg]); - if (spi_write_register(flash, reg, value)) + if (wp_write_register(flash, reg, value)) return FLASHROM_WP_ERR_WRITE_FAILED; } @@ -141,7 +161,7 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b continue; uint8_t value; - if (spi_read_register(flash, reg, &value)) + if (wp_read_register(flash, reg, &value)) return FLASHROM_WP_ERR_READ_FAILED; uint8_t actual = value & write_masks[reg]; @@ -407,6 +427,15 @@ static bool chip_supported(struct flashctx *flash) return (flash->chip != NULL) && (flash->chip->decode_range != NULL); } + +bool wp_operations_available(struct flashrom_flashctx *flash) +{ + return (flash->mst->buses_supported & BUS_SPI) || + ((flash->mst->buses_supported & BUS_PROG) && + flash->mst->opaque.read_register && + flash->mst->opaque.write_register); +} + enum flashrom_wp_result wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash) { struct wp_bits bits; |