Add infrastructure to probe per bus
Add some infrastructure around per-bus probing functions. Each function
is provided a private parameter, e.g. the expected length of an ID. This
will allow us to implement probing functions that are only called as of-
ten as necessary. The results will be stored in the `registered_master`
structure, to be compared to database entries later.
The probe_buses() wrapper can be used for chip entries, and allows us to
transition the existing probing functions one by one. Once all functions
have been ported, probe_flash() can be adapted as well and the wrapper
will become obsolete.
Change-Id: I6e82b6d61df50234096ac39acab58a4014203933
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/74899
diff --git a/flashprog.c b/flashprog.c
index 0ab20cb..cf697fb 100644
--- a/flashprog.c
+++ b/flashprog.c
@@ -180,6 +180,15 @@
int i = --shutdown_fn_count;
ret |= shutdown_fn[i].func(shutdown_fn[i].data);
}
+
+ int i;
+ for (i = 0; i < registered_master_count; ++i) {
+ struct found_id *found_id, *next;
+ for (found_id = registered_masters[i].found_ids; found_id; found_id = next) {
+ next = found_id->next;
+ free(found_id);
+ }
+ }
registered_master_count = 0;
return ret;
@@ -619,6 +628,88 @@
return 0;
}
+static void probe_bus(struct registered_master *const mst, const enum id_type type)
+{
+ struct found_id **next_ptr;
+ unsigned int i;
+
+ if (mst->probed)
+ return;
+
+ next_ptr = &mst->found_ids;
+ for (i = 0; i < mst->probing.probe_count; ++i) {
+ if (type && type != mst->probing.probes[i].type)
+ continue;
+
+ *next_ptr = mst->probing.probes[i].run(&mst->probing.probes[i], &mst->common);
+
+ /* walk to end in case multiple IDs were found in a single call */
+ while (*next_ptr)
+ next_ptr = &(*next_ptr)->next;
+ }
+
+ mst->probed = true;
+}
+
+static bool chip_on_bus(struct registered_master *const mst, const struct flashprog_chip *const chip)
+{
+ static const char *const id_names[] = {
+ [ID_82802AB] = "82802AB",
+ [ID_EN29LV640B] = "EN29LV640B",
+ [ID_JEDEC] = "JEDEC",
+ [ID_JEDEC_29GL] = "JEDEC_29GL",
+ [ID_OPAQUE] = "OPAQUE",
+ [ID_SPI_AT25F] = "SPI_AT25F",
+ [ID_SPI_RDID] = "SPI_RDID",
+ [ID_SPI_RDID4] = "SPI_RDID4",
+ [ID_SPI_REMS] = "SPI_REMS",
+ [ID_SPI_RES1] = "SPI_RES1",
+ [ID_SPI_RES2] = "SPI_RES2",
+ [ID_SPI_RES3] = "SPI_RES3",
+ [ID_SPI_SFDP] = "SPI_SFDP",
+ [ID_SPI_ST95] = "SPI_ST95",
+ [ID_W29EE011] = "W29EE011",
+ [ID_EDI] = "EDI",
+ };
+
+ if (chip_to_probe) {
+ /* If we are looking for a particular chip,
+ limit the probing functions to its type. */
+ probe_bus(mst, chip->id.type);
+ } else {
+ probe_bus(mst, 0);
+ }
+
+ struct found_id *found_id;
+ for (found_id = mst->found_ids; found_id; found_id = found_id->next) {
+ if (found_id->info.id.type != chip->id.type)
+ continue;
+
+ if (found_id->info.id.type < ARRAY_SIZE(id_names))
+ msg_cdbg("%s: id1 0x%02x, id2 0x%02x ",
+ id_names[found_id->info.id.type],
+ found_id->info.id.id1, found_id->info.id.id2);
+
+ if (mst->probing.match(chip, &found_id->info))
+ break;
+ }
+
+ msg_cdbg("\n");
+ return !!found_id;
+}
+
+/* wrapper that's used until all probing functions are ported to per-bus probing */
+int probe_buses(struct flashctx *const flash)
+{
+ int i;
+ for (i = 0; i < registered_master_count; ++i) {
+ if (flash->mst.common == ®istered_masters[i].common &&
+ chip_on_bus(®istered_masters[i], flash->chip))
+ return 1;
+ }
+ return 0;
+}
+
int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force)
{
const struct flashchip *chip;
diff --git a/helpers.c b/helpers.c
index 5f2b02d..b892c20 100644
--- a/helpers.c
+++ b/helpers.c
@@ -20,6 +20,26 @@
#include <string.h>
#include "flash.h"
+/* Check if raw data is all 0 or all 1. */
+bool flashprog_no_data(const void *const raw_data, const size_t len)
+{
+ const uint8_t *const raw_end = (const uint8_t *)raw_data + len;
+ const uint8_t patterns[] = { 0x00, 0xff };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(patterns); ++i) {
+ const uint8_t *raw_ptr;
+ for (raw_ptr = raw_data; raw_ptr < raw_end; ++raw_ptr) {
+ if (*raw_ptr != patterns[i])
+ break;
+ }
+ if (raw_ptr == raw_end)
+ return true;
+ }
+
+ return false;
+}
+
int flashprog_read_chunked(struct flashctx *const flash, uint8_t *dst, unsigned int start, unsigned int len,
unsigned int chunksize, readfunc_t *const read)
{
diff --git a/include/chipdrivers/probing.h b/include/chipdrivers/probing.h
index 7563f74..fefca3c 100644
--- a/include/chipdrivers/probing.h
+++ b/include/chipdrivers/probing.h
@@ -17,6 +17,7 @@
#ifndef __PROBING_H__
#define __PROBING_H__ 1
+#include <stddef.h>
#include <stdint.h>
enum id_type {
@@ -47,9 +48,43 @@
* Identification code.
*/
struct id_info {
- uint32_t manufacture;
- uint32_t model;
+ union {
+ uint32_t manufacture;
+ uint32_t id1;
+ };
+ union {
+ uint32_t model;
+ uint32_t id2;
+ };
enum id_type type;
};
+struct id_info_ext {
+ struct id_info id;
+ void *ext;
+};
+
+struct found_id {
+ struct found_id *next;
+ struct id_info_ext info;
+};
+
+struct flashprog_chip;
+struct master_common;
+
+struct bus_probe {
+ enum id_type type;
+ struct found_id *(*run)(const struct bus_probe *, const struct master_common *);
+ void *arg;
+};
+
+struct bus_probing {
+ unsigned int probe_count;
+ const struct bus_probe *probes;
+ bool (*match)(const struct flashprog_chip *, const struct id_info_ext *);
+};
+
+struct flashprog_flashctx;
+int probe_buses(struct flashprog_flashctx *);
+
#endif /* !__PROBING_H__ */
diff --git a/include/flash.h b/include/flash.h
index 60e35d0..c4d9040 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -243,7 +243,8 @@
PREPARE_FULL,
};
-struct flashchip {
+#define flashchip flashprog_chip
+struct flashprog_chip {
const char *vendor;
const char *name;
@@ -505,6 +506,7 @@
void print_supported_wiki(void);
/* helpers.c */
+bool flashprog_no_data(const void *raw_data, size_t);
int flashprog_read_chunked(struct flashctx *, uint8_t *dst, unsigned int start, unsigned int len, unsigned int chunksize, readfunc_t *);
uint32_t address_to_bits(uint32_t addr);
unsigned int bitcount(unsigned long a);
diff --git a/include/programmer.h b/include/programmer.h
index 5cef491..46b50f1 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -474,6 +474,11 @@
struct registered_master {
size_t max_rom_decode;
enum chipbustype buses_supported;
+
+ struct bus_probing probing;
+ struct found_id *found_ids;
+ bool probed;
+
union {
struct master_common common;
struct par_master par;
diff --git a/opaque.c b/opaque.c
index eacc09f..f03b70a 100644
--- a/opaque.c
+++ b/opaque.c
@@ -48,7 +48,7 @@
int register_opaque_master(const struct opaque_master *mst, void *data)
{
- struct registered_master rmst;
+ struct registered_master rmst = { 0 };
if (mst->shutdown) {
if (register_shutdown(mst->shutdown, data)) {
diff --git a/parallel.c b/parallel.c
index abed345..5746862 100644
--- a/parallel.c
+++ b/parallel.c
@@ -66,7 +66,7 @@
int register_par_master(const struct par_master *mst, const enum chipbustype buses,
const size_t max_rom_decode, void *data)
{
- struct registered_master rmst;
+ struct registered_master rmst = { 0 };
if (mst->shutdown) {
if (register_shutdown(mst->shutdown, data)) {
diff --git a/spi.c b/spi.c
index 9f8fb89..6f77e5c 100644
--- a/spi.c
+++ b/spi.c
@@ -163,7 +163,7 @@
int register_spi_master(const struct spi_master *mst, size_t max_rom_decode, void *data)
{
- struct registered_master rmst;
+ struct registered_master rmst = { 0 };
if (mst->shutdown) {
if (register_shutdown(mst->shutdown, data)) {