Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
programmer: Introduce programmer alias mechanism
Originally introduced in the downstream commit ba0827acee4da6740133345f43aae386923bbaad .
This was originally authored by David Hendricks so that the various flash peripheral in ChromeOS devices can be flashed. For example, flashrom -p ec -r ec.bin flashrom -p host -r host.bin
Note that this requires, `CONFIG_DEFAULT_PROGRAMMER=PROGRAMMER_INTERNAL make` to be defined as build-time.
BUG=b:148755493 BRANCH=none TEST=ran ./flashrom -p host --flash-name
Change-Id: I73766451cd8900a9e0fe08efc7a4d81b2a35ac8d Signed-off-by: Edward O'Callaghan quasisec@google.com --- M cli_classic.c M it85spi.c M linux_mtd.c M linux_spi.c M programmer.c M programmer.h 6 files changed, 98 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/71/38671/1
diff --git a/cli_classic.c b/cli_classic.c index 73cc417..d58562b 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -329,13 +329,51 @@ break; } } - if (prog == PROGRAMMER_INVALID) { + + for (i = 0; aliases[i].name; i++) { + name = aliases[i].name; + namelen = strlen(aliases[i].name); + + if (strncmp(optarg, name, namelen)) + continue; + + switch (optarg[namelen]) { + case ':': + pparam = strdup(optarg + namelen + 1); + if (!strlen(pparam)) { + free(pparam); + pparam = NULL; + } + break; + case '\0': + break; + default: + /* The continue refers to the for-loop. + * It is here to be able to + * differentiate between foo and foobar. + */ + continue; + } + + alias = &aliases[i]; + msg_gdbg("Programmer alias: "%s", parameter: " + " "%s",\n", alias->name, pparam); + break; + } + + if ((prog == PROGRAMMER_INVALID) && !alias) { fprintf(stderr, "Error: Unknown programmer "%s". Valid choices are:\n", optarg); list_programmers_linebreak(0, 80, 0); msg_ginfo(".\n"); cli_classic_abort_usage(NULL); } + + if ((prog != PROGRAMMER_INVALID) && alias) { + fprintf(stderr, "Error: Alias cannot be used " + "with programmer name.\n"); + cli_classic_abort_usage(NULL); + } break; case 'R': /* print_version() is always called during startup. */ diff --git a/it85spi.c b/it85spi.c index 5ce9193..47e2337 100644 --- a/it85spi.c +++ b/it85spi.c @@ -289,6 +289,9 @@ { int ret;
+ if (!programming_ec()) + return 1; + if (!(internal_buses_supported & BUS_FWH)) { msg_pdbg("%s():%d buses not support FWH\n", __func__, __LINE__); return 1; diff --git a/linux_mtd.c b/linux_mtd.c index d2df95e..bee7cc5 100644 --- a/linux_mtd.c +++ b/linux_mtd.c @@ -363,6 +363,9 @@ int dev_num = 0; int ret = 1;
+ if (!programming_host()) + return 1; + param = extract_programmer_param("dev"); if (param) { char *endptr; diff --git a/linux_spi.c b/linux_spi.c index aa73c18..221a36e 100644 --- a/linux_spi.c +++ b/linux_spi.c @@ -78,6 +78,14 @@ const uint8_t mode = SPI_MODE_0; const uint8_t bits = 8;
+ /* + * FIXME: There might be other programmers with flash memory (such as + * an EC) connected via SPI. For now we rely on the device's driver to + * distinguish it and assume generic SPI implies host. + */ + if (!programming_host()) + return 1; + p = extract_programmer_param("spispeed"); if (p && strlen(p)) { speed_hz = (uint32_t)strtoul(p, &endp, 10) * 1000; diff --git a/programmer.c b/programmer.c index f4b4384..ffad784 100644 --- a/programmer.c +++ b/programmer.c @@ -128,6 +128,13 @@ return 0; }
+struct programmer_alias aliases[] = { + { "ec", ALIAS_EC }, + { "host", ALIAS_HOST }, + { NULL }, +}; +struct programmer_alias *alias; + enum chipbustype get_buses_supported(void) { int i; diff --git a/programmer.h b/programmer.h index 3cf53b9..a7bd947 100644 --- a/programmer.h +++ b/programmer.h @@ -130,6 +130,44 @@ PROGRAMMER_INVALID /* This must always be the last entry. */ };
+enum alias_type { + ALIAS_NONE = 0, /* no alias (default) */ + ALIAS_EC, /* embedded controller */ + ALIAS_HOST, /* chipset / PCH / SoC / etc. */ +}; + +struct programmer_alias { + const char *name; + enum alias_type type; +}; + +extern struct programmer_alias *alias; +extern struct programmer_alias aliases[]; + +/** + * This function returns 'true' if current flashrom invocation is programming + * NONE. + */ +static inline int programming_none(void) { + return alias && (alias->type == ALIAS_NONE); +} + +/** + * This function returns 'true' if current flashrom invocation is programming + * the EC. + */ +static inline int programming_ec(void) { + return alias && (alias->type == ALIAS_EC); +} + +/** + * This function returns 'true' if current flashrom invocation is programming + * the HOST. + */ +static inline int programming_host(void) { + return alias && (alias->type == ALIAS_HOST); +} + enum programmer_type { PCI = 1, /* to detect uninitialized values */ USB,
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
This support is somewhat required for the introduction of cros_ec_*.c friends and certainly something we wish to have unified back into upstream.
I have cleaned up the alias mechanism locally a bit modulo this patch pending review: https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+...
Carl-Daniel Hailfinger has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
Wim Vervoorn has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
The host parameter is used by the vpd tool when it tries to read and write the vpd data using flashrom.
David Hendricks has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
This patch alone doesn't quite paint the full picture, I suspect others will be added to the chain.
The idea came about when ECs started appearing on different buses on different platforms - Some had an EC connected via LPC, some via I2C, and some on SPI. The problem was that `-p internal:bus=<lpc|i2c|spi>` became ambiguous and very cumbersome to use when trying to target ECs. Probing an EC could interfere with system operation so we wanted to bail out immediately when the probe function was called if we didn't actually intend to target an EC.
Similarly, this approach helped when host firmware ROMs started using linux_spi and linux_mtd programmer interfaces.
In both cases, this helps eliminate ambiguity (and potentially disruptive behavior) when flashrom is probing and obviates the need for every program and script that calls flashrom to have platform-specific logic to map component (host firmware ROM or EC) to programmer argument.
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
This patch alone doesn't quite paint the full picture, I suspect others will be added to the chain.
The idea came about when ECs started appearing on different buses on different platforms - Some had an EC connected via LPC, some via I2C, and some on SPI. The problem was that `-p internal:bus=<lpc|i2c|spi>` became ambiguous and very cumbersome to use when trying to target ECs. Probing an EC could interfere with system operation so we wanted to bail out immediately when the probe function was called if we didn't actually intend to target an EC.
Similarly, this approach helped when host firmware ROMs started using linux_spi and linux_mtd programmer interfaces.
In both cases, this helps eliminate ambiguity (and potentially disruptive behavior) when flashrom is probing and obviates the need for every program and script that calls flashrom to have platform-specific logic to map component (host firmware ROM or EC) to programmer argument.
Thanks David for the enriched background! That is super helpful as I could only surmise a limited understanding just by digging alone. As Carl I suppose is getting at - can we get away with not needing to upstream it or do you see this is something we definitely envision should to be part of the overall convergence effort? The answer now seems to be yes however I thought I would ask explicitly as some of this stuff is unclear if it should be rewritten or ported near verbatim or just dropped without knowing some context lost to history.
David Hendricks has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
Patch Set 1:
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
This patch alone doesn't quite paint the full picture, I suspect others will be added to the chain.
The idea came about when ECs started appearing on different buses on different platforms - Some had an EC connected via LPC, some via I2C, and some on SPI. The problem was that `-p internal:bus=<lpc|i2c|spi>` became ambiguous and very cumbersome to use when trying to target ECs. Probing an EC could interfere with system operation so we wanted to bail out immediately when the probe function was called if we didn't actually intend to target an EC.
Similarly, this approach helped when host firmware ROMs started using linux_spi and linux_mtd programmer interfaces.
In both cases, this helps eliminate ambiguity (and potentially disruptive behavior) when flashrom is probing and obviates the need for every program and script that calls flashrom to have platform-specific logic to map component (host firmware ROM or EC) to programmer argument.
Thanks David for the enriched background! That is super helpful as I could only surmise a limited understanding just by digging alone. As Carl I suppose is getting at - can we get away with not needing to upstream it or do you see this is something we definitely envision should to be part of the overall convergence effort? The answer now seems to be yes however I thought I would ask explicitly as some of this stuff is unclear if it should be rewritten or ported near verbatim or just dropped without knowing some context lost to history.
Sure thing! Personally I think the idea is useful upstream just to help users avoid certain EC pitfalls since many of our users are using laptops these days. It might also be nice to have `-p usb` or `-p serial` for external programmers as a convenient shorthand, though they might require some additional argument parsing for things like setting voltage correctly. I'm sure any addition to upstream syntax will be met with a fair bit of resistance/bikeshedding, though maybe it's not such a bad thing if the premise is at least accepted...
For better or worse I suspect it's already in several of places in the ChromeOS codebase including the `vpd` tool as Wim pointed out, factory scripts, update scripts, and test suites [2].
For the benefit of others in this thread, here is the original and a follow-up patch that uses it: [1] https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+... [2] https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+...
Carl-Daniel Hailfinger has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
Patch Set 1:
Patch Set 1:
Patch Set 1:
What does the patch do? The description only says that it's required for various ChromeOS devices and I would like to understand the background.
This patch alone doesn't quite paint the full picture, I suspect others will be added to the chain.
The idea came about when ECs started appearing on different buses on different platforms - Some had an EC connected via LPC, some via I2C, and some on SPI. The problem was that `-p internal:bus=<lpc|i2c|spi>` became ambiguous and very cumbersome to use when trying to target ECs. Probing an EC could interfere with system operation so we wanted to bail out immediately when the probe function was called if we didn't actually intend to target an EC.
Similarly, this approach helped when host firmware ROMs started using linux_spi and linux_mtd programmer interfaces.
In both cases, this helps eliminate ambiguity (and potentially disruptive behavior) when flashrom is probing and obviates the need for every program and script that calls flashrom to have platform-specific logic to map component (host firmware ROM or EC) to programmer argument.
Thanks David for the enriched background! That is super helpful as I could only surmise a limited understanding just by digging alone. As Carl I suppose is getting at - can we get away with not needing to upstream it or do you see this is something we definitely envision should to be part of the overall convergence effort? The answer now seems to be yes however I thought I would ask explicitly as some of this stuff is unclear if it should be rewritten or ported near verbatim or just dropped without knowing some context lost to history.
Sure thing! Personally I think the idea is useful upstream just to help users avoid certain EC pitfalls since many of our users are using laptops these days. It might also be nice to have `-p usb` or `-p serial` for external programmers as a convenient shorthand, though they might require some additional argument parsing for things like setting voltage correctly. I'm sure any addition to upstream syntax will be met with a fair bit of resistance/bikeshedding, though maybe it's not such a bad thing if the premise is at least accepted...
For better or worse I suspect it's already in several of places in the ChromeOS codebase including the `vpd` tool as Wim pointed out, factory scripts, update scripts, and test suites [2].
For the benefit of others in this thread, here is the original and a follow-up patch that uses it: [1] https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+... [2] https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+...
Thank you all so much for the explanation! The motivation behind the patch is now clear.
As you noticed, the programmer parameter bus=<whatever> is not fit for the purpose. Admittedly, that parameter was never designed to handle an EC vs. host selection, but for some cases, it was possible to use it for such a selection. The dummy programmer probably has the usage matching the purpose of bus= best.
Just to make sure I understand you correctly: You want to select which onboard flash chip is accessed by flashrom, and there may be multiple flash chips hanging off different masters. Do the following scenarios look complete to you? 1. Flash chip attached directly to the southbridge (Parallel, LPC, FWH, SPI) and we handle all hardware access inside flashrom. 2. Like 1, but the master accesses are abstracted by using Linux spidev. 3. Like 2, but the chip accesses are abstracted as well by using Linux MTD. 4. Like 1, but sometimes a dual chip setup is used and we may have to set which chip is active (e.g. in Dual BIOS setups), and sometimes a dual chip setup is only accessible as some opaque combined chip. 5. Flash chip attached to some master (Super I/O, EC, whatever) which performs implicit translation for all read accesses from the chipset, but writing and other commands have to be done by talking to the master directly and we handle all hardware access inside flashrom. 6. Like 5, but the implicit translation only covers part of the flash chip and all accesses from flashrom have to be done by talking to the master EC directly. 7. Like 6, but there is no implicit translation.
Scenario 1 is the classic internal case for flashrom. Scenario 2 is covered by linux_spi. Scenario 3 is covered by linux_mtd. Scenario 4 is covered by adding a programmer parameter to internal. Scenario 5 (it87) was added pretty early to flashrom after we had covered the classic case and is enabled implicity with internal. Scenario 6 is similar to current Intel southbridges with IFD, except that with Intel IFD there's no translation and we're prevented from accessing the whole chip in most cases. Scenario 7 without any chipset requirements is the easiest scenario because it is just a separate programmer (see satamv or others).
The scenarios above are made more complicated by the fact that some ECs require chipset setup to be accessible, and some ECs may really dislike the probe sequence for another EC. There may be combinations of 5+7 or 6+7 for two different flash chips hanging off the same master, but I have no idea if those really exist. Combinations of 7+7 exist (see nicintel_spi and nicintel_eeprom), and we have one driver for each part of the combination.
So overall, AFAICS the desire is to be able to specify "probe just the masters which may have access to the X" where X is "firmware for the main CPU", "VPD", or something else. You also do not want to have detailed hardware knowledge in the scripts calling flashrom, but rather inside flashrom.
Please help me correct any misunderstandings above. Maybe we can come up with a clean design which satisfies all of your needs.
David Hendricks has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Hi Carl-Daniel,
Just to make sure I understand you correctly: You want to select which onboard flash chip is accessed by flashrom, and there may be multiple flash chips hanging off different masters.
Correct.
Do the following scenarios look complete to you?
- Flash chip attached directly to the southbridge (Parallel, LPC, FWH, SPI) and we handle all hardware access inside flashrom.
- Like 1, but the master accesses are abstracted by using Linux spidev.
- Like 2, but the chip accesses are abstracted as well by using Linux MTD.
- Like 1, but sometimes a dual chip setup is used and we may have to set which chip is active (e.g. in Dual BIOS setups), and sometimes a dual chip setup is only accessible as some opaque combined chip.
- Flash chip attached to some master (Super I/O, EC, whatever) which performs implicit translation for all read accesses from the chipset, but writing and other commands have to be done by talking to the master directly and we handle all hardware access inside flashrom.
- Like 5, but the implicit translation only covers part of the flash chip and all accesses from flashrom have to be done by talking to the master EC directly.
- Like 6, but there is no implicit translation.
Scenario 1 is the classic internal case for flashrom. Scenario 2 is covered by linux_spi. Scenario 3 is covered by linux_mtd.
Right, but the idea here is to make it so the user says `-p host` instead of having to know which of the three options listed here would usually require (`-p internal:bus=<spi|i2c|lpc>`, '-p linux_spi`, `-p linux_mtd`). As you pointed out this makes it so that the hardware knowledge is inside flashrom, meaning that syntax sugar necessary to target the intended device is nicely abstracted from users, documentation, scripts, tests, daemons, etc.
Using Chromebooks as an example, there are now over 150 devices with hardware from all major vendors listed on their "developer information for Chrome OS devices" website. Flashrom is used on all of them, so keeping flashrom's syntax simple and consistent across all devices is very important.
The scenarios above are made more complicated by the fact that some ECs require chipset setup to be accessible, and some ECs may really dislike the probe sequence for another EC.
Yes, and it's better to avoid changing the hardware at all if it's not absolutely needed, for example setting the boot BIOS straps register. If something goes wrong in scenarios 5, 6, and 7 and a probe sequence leaves the master in a changed state, then the system might not boot until the power is cycled. And on a laptop that often means taking apart the whole thing and removing the battery.
So overall, AFAICS the desire is to be able to specify "probe just the masters which may have access to the X" where X is "firmware for the main CPU", "VPD", or something else. You also do not want to have detailed hardware knowledge in the scripts calling flashrom, but rather inside flashrom.
Exactly.
Please help me correct any misunderstandings above. Maybe we can come up with a clean design which satisfies all of your needs.
Great!
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1:
Patch Set 1:
Hi Carl-Daniel,
Just to make sure I understand you correctly: You want to select which onboard flash chip is accessed by flashrom, and there may be multiple flash chips hanging off different masters.
Correct.
Do the following scenarios look complete to you?
- Flash chip attached directly to the southbridge (Parallel, LPC, FWH, SPI) and we handle all hardware access inside flashrom.
- Like 1, but the master accesses are abstracted by using Linux spidev.
- Like 2, but the chip accesses are abstracted as well by using Linux MTD.
- Like 1, but sometimes a dual chip setup is used and we may have to set which chip is active (e.g. in Dual BIOS setups), and sometimes a dual chip setup is only accessible as some opaque combined chip.
- Flash chip attached to some master (Super I/O, EC, whatever) which performs implicit translation for all read accesses from the chipset, but writing and other commands have to be done by talking to the master directly and we handle all hardware access inside flashrom.
- Like 5, but the implicit translation only covers part of the flash chip and all accesses from flashrom have to be done by talking to the master EC directly.
- Like 6, but there is no implicit translation.
Scenario 1 is the classic internal case for flashrom. Scenario 2 is covered by linux_spi. Scenario 3 is covered by linux_mtd.
Right, but the idea here is to make it so the user says `-p host` instead of having to know which of the three options listed here would usually require (`-p internal:bus=<spi|i2c|lpc>`, '-p linux_spi`, `-p linux_mtd`). As you pointed out this makes it so that the hardware knowledge is inside flashrom, meaning that syntax sugar necessary to target the intended device is nicely abstracted from users, documentation, scripts, tests, daemons, etc.
Using Chromebooks as an example, there are now over 150 devices with hardware from all major vendors listed on their "developer information for Chrome OS devices" website. Flashrom is used on all of them, so keeping flashrom's syntax simple and consistent across all devices is very important.
The scenarios above are made more complicated by the fact that some ECs require chipset setup to be accessible, and some ECs may really dislike the probe sequence for another EC.
Yes, and it's better to avoid changing the hardware at all if it's not absolutely needed, for example setting the boot BIOS straps register. If something goes wrong in scenarios 5, 6, and 7 and a probe sequence leaves the master in a changed state, then the system might not boot until the power is cycled. And on a laptop that often means taking apart the whole thing and removing the battery.
So overall, AFAICS the desire is to be able to specify "probe just the masters which may have access to the X" where X is "firmware for the main CPU", "VPD", or something else. You also do not want to have detailed hardware knowledge in the scripts calling flashrom, but rather inside flashrom.
Exactly.
Please help me correct any misunderstandings above. Maybe we can come up with a clean design which satisfies all of your needs.
Great!
I wasn't too such that the next step is here and are there any specific actions I should be taking to keep this moving forwards in a direction?
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/38671 )
Change subject: programmer: Introduce programmer alias mechanism ......................................................................
Patch Set 1: Code-Review-2
I decided after much work down stream that this layer violates too much and doesn't lead to good places. A more well designed and maintainable solution is being devised downstream to allow something more in tune with upstreams well maintained control flow.
https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+... https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+...
Once I have dealt with our issues downstream I will potentially re-propose something for upstream for consideration.