summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward O'Callaghan <quasisec@google.com>2021-10-28 10:53:18 +1100
committerCommit Bot <commit-bot@chromium.org>2021-11-18 23:04:40 +0000
commit483dff64346fd30224df5b66bf76124aeea7bb12 (patch)
tree75bbc6a98a66fcb0a5e7a688237496675a89c2e1
parent4200cb21c7f6c79dacee511400c88994bca5cf7f (diff)
downloadvboot-483dff64346fd30224df5b66bf76124aeea7bb12.tar.gz
vboot_reference/futility: Port W path to using libflashrom
Use libflashrom API over sub-processing the flashrom CLI. Squash in, vboot_reference/futility: Use image layout as fallback Use the layout encoding within the image as the fallback if we cannot read it from ROM. Also cleanup error paths while here. BUG=b:203715651 BRANCH=none TEST=cros deploy to nocturne and ran: `/usr/sbin/chromeos-firmwareupdate --mode=recovery --wp=1`. && `$ cros_run_unit_tests --board nocturne --packages vboot_reference`. Cq-Depend: chromium:3249690, chromium:3281062, chromium:3288610 Signed-off-by: Edward O'Callaghan <quasisec@google.com> Change-Id: I892aec510d8023abd42a07cbb036be79bc8b4498 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3247852 Tested-by: Edward O'Callaghan <quasisec@chromium.org> Auto-Submit: Edward O'Callaghan <quasisec@chromium.org> Commit-Queue: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Sam McNally <sammc@chromium.org>
-rw-r--r--Makefile4
-rw-r--r--futility/updater_utils.c147
2 files changed, 121 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index 7d074b42..0435936c 100644
--- a/Makefile
+++ b/Makefile
@@ -305,6 +305,8 @@ ifneq (${HAVE_LIBZIP},)
LIBZIP_LIBS := $(shell ${PKG_CONFIG} --libs libzip)
endif
+FLASHROM_LIBS := $(shell ${PKG_CONFIG} --libs flashrom)
+
# Determine QEMU architecture needed, if any
ifeq (${ARCH},${HOST_ARCH})
# Same architecture; no need for QEMU
@@ -1044,7 +1046,7 @@ signing_install: $(if ${SDK_BUILD},\
futil: ${FUTIL_BIN}
# FUTIL_LIBS is shared by FUTIL_BIN and TEST_FUTIL_BINS.
-FUTIL_LIBS = ${CRYPTO_LIBS} ${LIBZIP_LIBS}
+FUTIL_LIBS = ${CRYPTO_LIBS} ${LIBZIP_LIBS} ${FLASHROM_LIBS}
${FUTIL_BIN}: LDLIBS += ${FUTIL_LIBS}
${FUTIL_BIN}: ${FUTIL_OBJS} ${UTILLIB} ${FWLIB}
diff --git a/futility/updater_utils.c b/futility/updater_utils.c
index 51936a52..039788a2 100644
--- a/futility/updater_utils.c
+++ b/futility/updater_utils.c
@@ -9,11 +9,14 @@
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <string.h>
#include <unistd.h>
#if defined (__FreeBSD__) || defined(__OpenBSD__)
#include <sys/wait.h>
#endif
+#include <libflashrom.h>
+
#include "2common.h"
#include "crossystem.h"
#include "host_misc.h"
@@ -25,7 +28,6 @@
enum flashrom_ops {
FLASHROM_READ,
- FLASHROM_WRITE,
FLASHROM_WP_STATUS,
};
@@ -565,11 +567,6 @@ static int host_flashrom(enum flashrom_ops op, const char *image_path,
assert(image_path);
break;
- case FLASHROM_WRITE:
- op_cmd = "-w";
- assert(image_path);
- break;
-
case FLASHROM_WP_STATUS:
op_cmd = "--wp-status";
assert(image_path == NULL);
@@ -587,7 +584,7 @@ static int host_flashrom(enum flashrom_ops op, const char *image_path,
if (!extra)
extra = "";
- /* TODO(hungte) In future we should link with flashrom directly. */
+ /* TODO(b/203715651): link with flashrom directly. */
ASPRINTF(&command, "flashrom %s %s -p %s %s %s %s %s", op_cmd,
image_path, programmer, dash_i, section_name, extra,
postfix);
@@ -618,6 +615,119 @@ static int host_flashrom(enum flashrom_ops op, const char *image_path,
return r;
}
+static int flashrom_print_cb(enum flashrom_log_level level, const char *fmt,
+ va_list ap)
+{
+ int ret = 0;
+ enum flashrom_log_level verbose_screen = FLASHROM_MSG_INFO;
+ FILE *output_type = (level < verbose_screen) ? stderr : stdout;
+
+ if (level > verbose_screen)
+ return ret;
+
+#define COLOUR_RESET "\033[0;m"
+#define MAGENTA_TEXT "\033[35;1m"
+
+ if (level != FLASHROM_MSG_SPEW)
+ fprintf(output_type, MAGENTA_TEXT);
+
+ ret = vfprintf(output_type, fmt, ap);
+ /* msg_*spew often happens inside chip accessors
+ * in possibly time-critical operations.
+ * Don't slow them down by flushing.
+ */
+ if (level != FLASHROM_MSG_SPEW) {
+ fprintf(output_type, COLOUR_RESET);
+ fflush(output_type);
+ }
+
+ return ret;
+}
+
+static char *flashrom_extract_params(const char *str, char **prog, char **params)
+{
+ char *tmp = strdup(str);
+ *prog = strtok(tmp, ":");
+ *params = strtok(NULL, "");
+ return tmp;
+}
+
+static int host_flashrom_write(const struct firmware_image *image,
+ const char *region,
+ const struct firmware_image *diff_image)
+{
+ int r = 0;
+ size_t len = 0;
+
+ char *programmer, *params;
+ char *tmp = flashrom_extract_params(image->programmer, &programmer, &params);
+
+ struct flashrom_programmer *prog = NULL;
+ struct flashrom_flashctx *flashctx = NULL;
+ struct flashrom_layout *layout = NULL;
+
+ flashrom_set_log_callback((flashrom_log_callback *)&flashrom_print_cb);
+
+ r |= flashrom_init(1);
+ r |= flashrom_programmer_init(&prog, programmer, params);
+ r |= flashrom_flash_probe(&flashctx, prog, NULL);
+
+ len = flashrom_flash_getsize(flashctx);
+ if (len == 0) {
+ ERROR("zero sized flash detected\n");
+ r = -1;
+ goto err_cleanup;
+ }
+
+ if (diff_image) {
+ if (diff_image->size != image->size) {
+ ERROR("diff_image->size != image->size");
+ r = -1;
+ goto err_cleanup;
+ }
+ }
+
+ if (region) {
+ r = flashrom_layout_read_fmap_from_buffer(
+ &layout, flashctx, (const uint8_t *)image->data,
+ image->size);
+ if (r > 0) {
+ WARN("could not read fmap from image, r=%d, "
+ "falling back to read from rom\n", r);
+ r = flashrom_layout_read_fmap_from_rom(
+ &layout, flashctx, 0, len);
+ if (r > 0) {
+ ERROR("could not read fmap from rom, r=%d\n", r);
+ r = -1;
+ goto err_cleanup;
+ }
+ }
+ // empty region causes seg fault in API.
+ r |= flashrom_layout_include_region(layout, region);
+ if (r > 0) {
+ ERROR("could not include region = '%s'\n", region);
+ r = -1;
+ goto err_cleanup;
+ }
+ }
+
+ flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, true);
+ flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true);
+ if (diff_image) /* equiv --noverify --flash-contents=diff_image at cli */
+ flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, false);
+
+ r |= flashrom_image_write(flashctx, image->data, image->size,
+ diff_image ? diff_image->data : NULL);
+
+err_cleanup:
+ r |= flashrom_programmer_shutdown(prog);
+ flashrom_layout_release(layout);
+ flashrom_flash_release(flashctx);
+ free(tmp);
+
+ return r;
+}
+
/* Helper function to return write protection status via given programmer. */
enum wp_state host_get_wp(const char *programmer)
{
@@ -673,28 +783,7 @@ int write_system_firmware(const struct firmware_image *image,
struct tempfile *tempfiles,
int verbosity)
{
- const char *tmp_path = get_firmware_image_temp_file(image, tempfiles);
- const char *tmp_diff = NULL;
-
- const char *programmer = image->programmer;
- char *extra = NULL;
- int r;
-
- if (!tmp_path)
- return -1;
-
- if (diff_image) {
- tmp_diff = get_firmware_image_temp_file(
- diff_image, tempfiles);
- if (!tmp_diff)
- return -1;
- ASPRINTF(&extra, "--noverify --flash-contents=%s", tmp_diff);
- }
-
- r = host_flashrom(FLASHROM_WRITE, tmp_path, programmer, verbosity,
- section_name, extra);
- free(extra);
- return r;
+ return host_flashrom_write(image, section_name, diff_image);
}
/* Helper function to configure all properties. */