summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atavia.c2
-rw-r--r--dummyflasher.c8
-rw-r--r--flashrom.c61
-rw-r--r--ichspi.c8
-rw-r--r--include/flash.h7
-rw-r--r--include/programmer.h9
-rw-r--r--internal.c4
-rw-r--r--it87spi.c2
-rw-r--r--parallel.c11
-rw-r--r--programmer.c7
-rw-r--r--sb600spi.c6
-rw-r--r--serprog.c33
-rw-r--r--wbsio_spi.c2
13 files changed, 119 insertions, 41 deletions
diff --git a/atavia.c b/atavia.c
index 66bca65ef..5cbe058f4 100644
--- a/atavia.c
+++ b/atavia.c
@@ -133,6 +133,7 @@ static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr ad
}
static const struct par_master lpc_master_atavia = {
+ .map_flash_region = atavia_map,
.chip_readb = atavia_chip_readb,
.chip_readw = fallback_chip_readw,
.chip_readl = fallback_chip_readl,
@@ -189,5 +190,4 @@ const struct programmer_entry programmer_atavia = {
.type = PCI,
.devs.dev = ata_via,
.init = atavia_init,
- .map_flash_region = atavia_map,
};
diff --git a/dummyflasher.c b/dummyflasher.c
index b2a41c6e2..ad734f08c 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -920,6 +920,8 @@ static int dummy_shutdown(void *data)
}
static const struct spi_master spi_master_dummyflasher = {
+ .map_flash_region = dummy_map,
+ .unmap_flash_region = dummy_unmap,
.features = SPI_MASTER_4BA,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_UNSPECIFIED,
@@ -932,6 +934,8 @@ static const struct spi_master spi_master_dummyflasher = {
};
static const struct par_master par_master_dummyflasher = {
+ .map_flash_region = dummy_map,
+ .unmap_flash_region = dummy_unmap,
.chip_readb = dummy_chip_readb,
.chip_readw = dummy_chip_readw,
.chip_readl = dummy_chip_readl,
@@ -943,6 +947,8 @@ static const struct par_master par_master_dummyflasher = {
};
static const struct opaque_master opaque_master_dummyflasher = {
+ .map_flash_region = dummy_map,
+ .unmap_flash_region = dummy_unmap,
.probe = probe_variable_size,
.read = dummy_opaque_read,
.write = dummy_opaque_write,
@@ -1424,6 +1430,4 @@ const struct programmer_entry programmer_dummy = {
/* FIXME */
.devs.note = "Dummy device, does nothing and logs all accesses\n",
.init = dummy_init,
- .map_flash_region = dummy_map,
- .unmap_flash_region = dummy_unmap,
};
diff --git a/flashrom.c b/flashrom.c
index f74b79a93..90899f059 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -203,27 +203,62 @@ int programmer_shutdown(void)
return ret;
}
-void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len)
+void *master_map_flash_region(const struct registered_master *mst,
+ const char *descr, uintptr_t phys_addr,
+ size_t len)
{
+ /* Check the bus master for a specialized map_flash_region; default to
+ * fallback if it does not specialize it
+ */
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len) = NULL;
+ if (mst->buses_supported & BUS_PROG)
+ map_flash_region = mst->opaque.map_flash_region;
+ else if (mst->buses_supported & BUS_SPI)
+ map_flash_region = mst->spi.map_flash_region;
+ else if (mst->buses_supported & BUS_NONSPI)
+ map_flash_region = mst->par.map_flash_region;
+
void *ret;
- if (programmer->map_flash_region)
- ret = programmer->map_flash_region(descr, phys_addr, len);
+ if (map_flash_region)
+ ret = map_flash_region(descr, phys_addr, len);
else
ret = fallback_map(descr, phys_addr, len);
msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
- __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
+ __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
return ret;
}
-void programmer_unmap_flash_region(void *virt_addr, size_t len)
+void master_unmap_flash_region(const struct registered_master *mst,
+ void *virt_addr, size_t len)
{
- if (programmer->unmap_flash_region)
- programmer->unmap_flash_region(virt_addr, len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len) = NULL;
+ if (mst->buses_supported & BUS_PROG)
+ unmap_flash_region = mst->opaque.unmap_flash_region;
+ else if (mst->buses_supported & BUS_SPI)
+ unmap_flash_region = mst->spi.unmap_flash_region;
+ else if (mst->buses_supported & BUS_NONSPI)
+ unmap_flash_region = mst->par.unmap_flash_region;
+
+ if (unmap_flash_region)
+ unmap_flash_region(virt_addr, len);
else
fallback_unmap(virt_addr, len);
msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
}
+static bool master_uses_physmap(const struct registered_master *mst)
+{
+#if CONFIG_INTERNAL == 1
+ if (mst->buses_supported & BUS_PROG)
+ return mst->opaque.map_flash_region == physmap;
+ else if (mst->buses_supported & BUS_SPI)
+ return mst->spi.map_flash_region == physmap;
+ else if (mst->buses_supported & BUS_NONSPI)
+ return mst->par.map_flash_region == physmap;
+#endif
+ return false;
+}
+
void programmer_delay(unsigned int usecs)
{
if (usecs > 0) {
@@ -647,13 +682,13 @@ unsigned int count_max_decode_exceedings(const struct flashctx *flash)
void unmap_flash(struct flashctx *flash)
{
if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
- programmer_unmap_flash_region((void *)flash->virtual_registers, flash->chip->total_size * 1024);
+ master_unmap_flash_region(flash->mst, (void *)flash->virtual_registers, flash->chip->total_size * 1024);
flash->physical_registers = 0;
flash->virtual_registers = (chipaddr)ERROR_PTR;
}
if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
- programmer_unmap_flash_region((void *)flash->virtual_memory, flash->chip->total_size * 1024);
+ master_unmap_flash_region(flash->mst, (void *)flash->virtual_memory, flash->chip->total_size * 1024);
flash->physical_memory = 0;
flash->virtual_memory = (chipaddr)ERROR_PTR;
}
@@ -673,7 +708,7 @@ int map_flash(struct flashctx *flash)
const chipsize_t size = flash->chip->total_size * 1024;
uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
- void *addr = programmer_map_flash_region(flash->chip->name, base, size);
+ void *addr = master_map_flash_region(flash->mst, flash->chip->name, base, size);
if (addr == ERROR_PTR) {
msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
flash->chip->name, PRIxPTR_WIDTH, base);
@@ -687,7 +722,7 @@ int map_flash(struct flashctx *flash)
* Ignore these problems for now and always report success. */
if (flash->chip->feature_bits & FEATURE_REGISTERMAP) {
base = 0xffffffff - size - 0x400000 + 1;
- addr = programmer_map_flash_region("flash chip registers", base, size);
+ addr = master_map_flash_region(flash->mst, "flash chip registers", base, size);
if (addr == ERROR_PTR) {
msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
flash->chip->name, PRIxPTR_WIDTH, base);
@@ -831,12 +866,10 @@ notfound:
msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) ", force ? "Assuming" : "Found",
flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp);
free(tmp);
-#if CONFIG_INTERNAL == 1
- if (programmer->map_flash_region == physmap)
+ if (master_uses_physmap(mst))
msg_cinfo("mapped at physical address 0x%0*" PRIxPTR ".\n",
PRIxPTR_WIDTH, flash->physical_memory);
else
-#endif
msg_cinfo("on %s.\n", programmer->name);
/* Flash registers may more likely not be mapped if the chip was forced.
diff --git a/ichspi.c b/ichspi.c
index fa15a953e..7e7967e07 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1773,6 +1773,8 @@ static const struct spi_master spi_master_ich7 = {
.max_data_write = 64,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
@@ -1783,6 +1785,8 @@ static const struct spi_master spi_master_ich9 = {
.max_data_write = 64,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
@@ -1790,6 +1794,8 @@ static const struct spi_master spi_master_ich9 = {
};
static const struct opaque_master opaque_master_ich_hwseq = {
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.max_data_read = 64,
.max_data_write = 64,
.probe = ich_hwseq_probe,
@@ -2199,6 +2205,8 @@ static const struct spi_master spi_master_via = {
.max_data_write = 16,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
diff --git a/include/flash.h b/include/flash.h
index 79aaa64a8..c696f64e9 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -55,8 +55,11 @@ typedef uintptr_t chipaddr;
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
int register_shutdown(int (*function) (void *data), void *data);
-void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len);
-void programmer_unmap_flash_region(void *virt_addr, size_t len);
+struct registered_master;
+void *master_map_flash_region(const struct registered_master *mast,
+ const char *descr, uintptr_t phys_addr, size_t len);
+void master_unmap_flash_region(const struct registered_master *mast,
+ void *virt_addr, size_t len);
void programmer_delay(unsigned int usecs);
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
diff --git a/include/programmer.h b/include/programmer.h
index 17abfd222..4b5bf92ac 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -50,9 +50,6 @@ struct programmer_entry {
int (*init) (const struct programmer_cfg *cfg);
- void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
- void (*unmap_flash_region) (void *virt_addr, size_t len);
-
void (*delay) (unsigned int usecs);
};
@@ -309,6 +306,8 @@ struct spi_master {
int (*multicommand)(const struct flashctx *flash, struct spi_command *cmds);
/* Optimized functions for this master */
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len);
int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write_256)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
int (*write_aai)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
@@ -399,6 +398,8 @@ int wbsio_check_for_spi(void);
/* opaque.c */
struct opaque_master {
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len);
int max_data_read;
int max_data_write;
/* Specific functions for this master */
@@ -424,6 +425,8 @@ int register_opaque_master(const struct opaque_master *mst, void *data);
/* parallel.c */
struct par_master {
+ void *(*map_flash_region) (const char *descr, uintptr_t phys_addr, size_t len);
+ void (*unmap_flash_region) (void *virt_addr, size_t len);
void (*chip_writeb) (const struct flashctx *flash, uint8_t val, chipaddr addr);
void (*chip_writew) (const struct flashctx *flash, uint16_t val, chipaddr addr);
void (*chip_writel) (const struct flashctx *flash, uint32_t val, chipaddr addr);
diff --git a/internal.c b/internal.c
index 2558cdefd..8c834e2c5 100644
--- a/internal.c
+++ b/internal.c
@@ -107,6 +107,8 @@ static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
}
static const struct par_master par_master_internal = {
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.chip_readb = internal_chip_readb,
.chip_readw = internal_chip_readw,
.chip_readl = internal_chip_readl,
@@ -347,6 +349,4 @@ const struct programmer_entry programmer_internal = {
.type = OTHER,
.devs.note = NULL,
.init = internal_init,
- .map_flash_region = physmap,
- .unmap_flash_region = physunmap,
};
diff --git a/it87spi.c b/it87spi.c
index 85da1507b..5acaea691 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -315,6 +315,8 @@ static const struct spi_master spi_master_it87xx = {
.max_data_write = MAX_DATA_UNSPECIFIED,
.command = it8716f_spi_send_command,
.multicommand = default_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = it8716f_spi_chip_read,
.write_256 = it8716f_spi_chip_write_256,
.write_aai = spi_chip_write_1,
diff --git a/parallel.c b/parallel.c
index 9001fe80f..e635088a0 100644
--- a/parallel.c
+++ b/parallel.c
@@ -76,6 +76,17 @@ int register_par_master(const struct par_master *mst,
}
}
+ /* Bus masters supporting FWH/LPC cannot use fallback_map(), distinct
+ * mappings are needed to support chips with FEATURE_REGISTERMAP
+ */
+ if ((buses & (BUS_FWH | BUS_LPC)) && !mst->map_flash_region) {
+ msg_perr("%s called with incomplete master definition. "
+ "FWH/LPC masters must provide memory mappings. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
if (!mst->chip_writeb || !mst->chip_writew || !mst->chip_writel ||
!mst->chip_writen || !mst->chip_readb || !mst->chip_readw ||
!mst->chip_readl || !mst->chip_readn) {
diff --git a/programmer.c b/programmer.c
index 2b960e6a0..939d8c2d7 100644
--- a/programmer.c
+++ b/programmer.c
@@ -20,7 +20,12 @@
/* Fallback map() for programmers which don't need special handling */
void *fallback_map(const char *descr, uintptr_t phys_addr, size_t len)
{
- /* FIXME: Should return phys_addr. */
+ /* A result of NULL causes mapped addresses to be chip physical
+ * addresses, assuming only a single region is mapped (the entire flash
+ * space). Chips with a second region (like a register map) require a
+ * real memory mapping to distinguish the different ranges. Those chips
+ * are FWH/LPC, so the bus master provides a real mapping.
+ */
return NULL;
}
diff --git a/sb600spi.c b/sb600spi.c
index 8b02b51d2..6020145b2 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -600,6 +600,8 @@ static const struct spi_master spi_master_sb600 = {
.max_data_write = FIFO_SIZE_OLD - 3,
.command = sb600_spi_send_command,
.multicommand = default_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
@@ -612,6 +614,8 @@ static const struct spi_master spi_master_yangtze = {
.max_data_write = FIFO_SIZE_YANGTZE - 3,
.command = spi100_spi_send_command,
.multicommand = default_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
@@ -624,6 +628,8 @@ static const struct spi_master spi_master_promontory = {
.max_data_write = FIFO_SIZE_YANGTZE - 3,
.command = spi100_spi_send_command,
.multicommand = default_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = promontory_read_memmapped,
.write_256 = default_spi_write_256,
.write_aai = default_spi_write_aai,
diff --git a/serprog.c b/serprog.c
index 12d15d74c..a3a3db3e5 100644
--- a/serprog.c
+++ b/serprog.c
@@ -438,7 +438,23 @@ static int serprog_shutdown(void *data)
return 0;
}
+static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
+{
+ /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
+ * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
+ * the hardware observes a subset of the address bits only). Combined with the standard mapping of
+ * flashrom this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
+ * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
+ if ((phys_addr & 0xFF000000) == 0xFF000000) {
+ return (void*)phys_addr;
+ }
+ msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
+ descr, len, PRIxPTR_WIDTH, phys_addr);
+ return NULL;
+}
+
static struct spi_master spi_master_serprog = {
+ .map_flash_region = serprog_map,
.features = SPI_MASTER_4BA,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_WRITE_UNLIMITED,
@@ -553,6 +569,7 @@ static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf,
}
static const struct par_master par_master_serprog = {
+ .map_flash_region = serprog_map,
.chip_readb = serprog_chip_readb,
.chip_readw = fallback_chip_readw,
.chip_readl = fallback_chip_readl,
@@ -945,27 +962,11 @@ static void serprog_delay(unsigned int usecs)
sp_prev_was_write = 0;
}
-static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len)
-{
- /* Serprog transmits 24 bits only and assumes the underlying implementation handles any remaining bits
- * correctly (usually setting them to one either in software (for FWH/LPC) or relying on the fact that
- * the hardware observes a subset of the address bits only). Combined with the standard mapping of
- * flashrom this creates a 16 MB-wide window just below the 4 GB boundary where serprog can operate (as
- * needed for non-SPI chips). Below we make sure that the requested range is within this window. */
- if ((phys_addr & 0xFF000000) == 0xFF000000) {
- return (void*)phys_addr;
- }
- msg_pwarn(MSGHEADER "requested mapping %s is incompatible: 0x%zx bytes at 0x%0*" PRIxPTR ".\n",
- descr, len, PRIxPTR_WIDTH, phys_addr);
- return NULL;
-}
-
const struct programmer_entry programmer_serprog = {
.name = "serprog",
.type = OTHER,
/* FIXME */
.devs.note = "All programmer devices speaking the serprog protocol\n",
.init = serprog_init,
- .map_flash_region = serprog_map,
.delay = serprog_delay,
};
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 95ca1e99f..661ecbb11 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -187,6 +187,8 @@ static const struct spi_master spi_master_wbsio = {
.max_data_write = MAX_DATA_UNSPECIFIED,
.command = wbsio_spi_send_command,
.multicommand = default_spi_send_multicommand,
+ .map_flash_region = physmap,
+ .unmap_flash_region = physunmap,
.read = wbsio_spi_read,
.write_256 = spi_chip_write_1,
.write_aai = spi_chip_write_1,