summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/programmer.h8
-rw-r--r--include/writeprotect.h3
-rw-r--r--libflashrom.c18
-rw-r--r--writeprotect.c37
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;