tree: Bring tree into a re-enterent state
This is a rather large change that has been attempted before in,
`commit 63b92f99a9d43dd637bcce564cd372be3c81c5d8`
and quickly reverted in,
`commit ac1d25c100bcd37075ec4b674a16f54edcd31d94`
This was again tried later in,
`commit bcae375630ea8a9bfd3645700451209fb98b66eb`
however had to be reverted in
`commit 65eb881cf669fff21c6da4302762abaac3bf105a`.
The problem was largely to do with how the old alias mechanism was
implemented in,
`commit ba0827acee4da6740133345f43aae386923bbaad`.
and all the laying violations of cros_ec. These combined with other
tree misc divergences caused significant problems trying to adopt the
upstreams cleaner re-enterent state management control flow structures.
Since we have now removed the poorly implemented aliasing mechanism
and boxed down the cros_ec laying violations to only a small section
of flashrom.c we can proceed to finally bring about a convergence with
upstreams control-flow structure. This then entirely aligns our tree
with upstreams control flow at its core.
Drivers are then split into three main types:
i ) opaque,
ii ) par &&,
iii) spi.
where each type has a struct-typed state machine heap allocation
registered into `registered_masters`. The three pointer types are
collected together into an anon-union within the flashctx core
structure. This flashctx structure is largely passed around via the
entire life-time of the program and therefore accessable via most
functions. Each of the three driver types also contain an abstract heap
allocation untyped with `void *` called `data` that allows each driver
to maintain its own internal state machine as it sees fit in a
re-enterent fashion. This bounded life-time of internal state machines
for each driver allows each driver to be reasoned about as a monadic
unit of work and therefore the control flow to be linear across the
three. As for the differences between the types, spi being the obvious
one for SPI buses, opaque being for drivers that wrap other underlying
mechanisms such as a char driver provided by the kernel. The last driver
type 'par` is a little special parallel one that is infrequently used. A
caller can determine which pointer to use via bifurcating upon the buses
state within the flashctx and therefore picking the correct pointer type
from the anon-union.
We have to squash in many changes together to make this an atomic switch
over as things become hard to debug doing these changes bit by bit.
Squash in;
flashrom.c: Make all par_master chip ops re-enterent
register_par_master() should no longer need to be a singleton state and
instead use the internal state machine to register all par_masters just
as upstream does. Only dummyflasher is used for the purposes of
chromiumos afaik.
Squash in;
programmer.h: unwind b/171755805 hack
cli_classic.c: fixes for register_spi_master
opaque.c: Make opaque masters re-enterent
cli_classic.c: Align with upstream count_max_decode_exceedings()
kill buses_supported global
spi.c, tree: Make spi_master re-enterent
take bitbang_spi.c verbatim from upstream.
BUG=b:170440733,b:165100282
BRANCH=none
TEST=builds, confirm 'ec:type=fp' functions, many DUT's spot checked.
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Change-Id: I29d757e86099344591f833361628fa48ccb01565
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+/2512924
Commit-Queue: Edward O'Callaghan <quasisec@chromium.org>
Tested-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Sam McNally <sammc@chromium.org>
diff --git a/programmer.c b/programmer.c
index 97132f5..8c5946d 100644
--- a/programmer.c
+++ b/programmer.c
@@ -24,19 +24,6 @@
*/
enum ich_chipset g_ich_generation = CHIPSET_ICH_UNKNOWN;
-static const struct par_master par_master_none = {
- .chip_readb = noop_chip_readb,
- .chip_readw = fallback_chip_readw,
- .chip_readl = fallback_chip_readl,
- .chip_readn = fallback_chip_readn,
- .chip_writeb = noop_chip_writeb,
- .chip_writew = fallback_chip_writew,
- .chip_writel = fallback_chip_writel,
- .chip_writen = fallback_chip_writen,
-};
-
-const struct par_master *par_master = &par_master_none;
-
/* No-op shutdown() for programmers which don't need special handling */
int noop_shutdown(void)
{
@@ -114,10 +101,22 @@
return;
}
-void register_par_master(const struct par_master *pgm, const enum chipbustype buses)
+int register_par_master(const struct par_master *mst,
+ const enum chipbustype buses)
{
- par_master = pgm;
- buses_supported |= buses;
+ struct registered_master rmst;
+ 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) {
+ msg_perr("%s called with incomplete master definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+ rmst.buses_supported = buses;
+ rmst.par = *mst;
+ return register_master(&rmst);
}
/* The limit of 4 is totally arbitrary. */