From f0af257a9b333b27d6ed9540ffbbb5cf4e20ba12 Mon Sep 17 00:00:00 2001 From: Edward O'Callaghan Date: Thu, 10 Feb 2022 11:23:08 +1100 Subject: vboot_ref: Reshuffle parallel flashrom impl Bring sub-process and libflashrom wrapper implementations under the common host/lib path to later be reconciled. The WP implementation is left separated out due to the lack of a libflashrom WP implementation which creates circular dependencies for the moment. BUG=b:207808292 BRANCH=none TEST=none Signed-off-by: Edward O'Callaghan Change-Id: Ic759c4e9828778a0ef1443b163224aef2c7cba54 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3461093 Reviewed-by: Nikolai Artemiev Auto-Submit: Edward O'Callaghan Tested-by: Edward O'Callaghan Commit-Queue: Edward O'Callaghan --- Makefile | 4 +- futility/flashrom_drv.c | 227 -------------------------------------------- futility/flashrom_wp_drv.c | 50 ++++++++++ futility/updater_utils.h | 7 -- host/lib/flashrom_drv.c | 190 ++++++++++++++++++++++++++++++++++++ host/lib/include/flashrom.h | 6 ++ 6 files changed, 249 insertions(+), 235 deletions(-) delete mode 100644 futility/flashrom_drv.c create mode 100644 futility/flashrom_wp_drv.c create mode 100644 host/lib/flashrom_drv.c diff --git a/Makefile b/Makefile index 4f0dee41..e6c3bcac 100644 --- a/Makefile +++ b/Makefile @@ -436,6 +436,7 @@ ALL_OBJS += ${FWLIB_OBJS} ${TLCL_OBJS} COMMONLIB_SRCS = \ host/lib/fmap.c \ host/lib/flashrom.c \ + host/lib/flashrom_drv.c \ host/lib/subprocess.c # Intermediate library for the vboot_reference utilities to link against. @@ -664,7 +665,8 @@ USE_FLASHROM ?= 1 ifneq ($(filter-out 0,${USE_FLASHROM}),) $(info building with libflashrom support) FLASHROM_LIBS := $(shell ${PKG_CONFIG} --libs flashrom) -FUTIL_SRCS += futility/flashrom_drv.c \ +FUTIL_SRCS += host/lib/flashrom_drv.c \ + futility/flashrom_wp_drv.c \ futility/updater_archive.c \ futility/updater_quirks.c \ futility/updater_utils.c \ diff --git a/futility/flashrom_drv.c b/futility/flashrom_drv.c deleted file mode 100644 index 8630b8f3..00000000 --- a/futility/flashrom_drv.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * The utility functions for firmware updater. - */ - -#include - -#include "2common.h" -#include "crossystem.h" -#include "host_misc.h" -#include "util_misc.h" -#include "updater.h" - -#define FLASHROM_OUTPUT_WP_PATTERN "write protect is " - -/* System environment values. */ -static const char * const FLASHROM_OUTPUT_WP_ENABLED = - FLASHROM_OUTPUT_WP_PATTERN "enabled", - * const FLASHROM_OUTPUT_WP_DISABLED = - FLASHROM_OUTPUT_WP_PATTERN "disabled"; - -// global to allow verbosity level to be injected into callback. -static enum flashrom_log_level g_verbose_screen = FLASHROM_MSG_INFO; - -static int flashrom_print_cb(enum flashrom_log_level level, const char *fmt, - va_list ap) -{ - int ret = 0; - FILE *output_type = (level < FLASHROM_MSG_INFO) ? stderr : stdout; - - if (level > g_verbose_screen) - return ret; - - 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) - 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; -} - -int flashrom_read_image(struct firmware_image *image, const char *region, - int verbosity) -{ - int r = 0; - size_t len = 0; - - g_verbose_screen = verbosity; - - char *programmer, *params; - char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); - - 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 (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_layout_set(flashctx, layout); - } - - image->data = calloc(1, len); - image->size = len; - image->file_name = strdup(""); - - r |= flashrom_image_read(flashctx, image->data, len); - -err_cleanup: - r |= flashrom_programmer_shutdown(prog); - flashrom_layout_release(layout); - flashrom_flash_release(flashctx); - free(tmp); - - return r; -} - -int flashrom_write_image(const struct firmware_image *image, - const char *region, - const struct firmware_image *diff_image, - int do_verify, int verbosity) -{ - int r = 0; - size_t len = 0; - - g_verbose_screen = verbosity; - - char *programmer, *params; - char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); - - 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_layout_set(flashctx, layout); - } - - flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, true); - flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true); - if (!do_verify) - 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 flashrom_get_wp(const char *programmer) -{ - char *command, *result; - const char *postfix; - int r; - - /* grep is needed because host_shell only returns 1 line. */ - postfix = " 2>/dev/null | grep \"" FLASHROM_OUTPUT_WP_PATTERN "\""; - - - /* TODO(b/203715651): link with flashrom directly. */ - ASPRINTF(&command, "flashrom --wp-status -p %s %s", programmer, postfix); - - /* invokes flashrom(8) with non-zero result if error. */ - result = host_shell(command); - strip_string(result, NULL); - free(command); - VB2_DEBUG("wp-status: %s\n", result); - - if (strstr(result, FLASHROM_OUTPUT_WP_ENABLED)) - r = WP_ENABLED; - else if (strstr(result, FLASHROM_OUTPUT_WP_DISABLED)) - r = WP_DISABLED; - else - r = WP_ERROR; - free(result); - - return r; -} diff --git a/futility/flashrom_wp_drv.c b/futility/flashrom_wp_drv.c new file mode 100644 index 00000000..ff7a8214 --- /dev/null +++ b/futility/flashrom_wp_drv.c @@ -0,0 +1,50 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * The utility functions for firmware updater. + */ + +#include + +#include "updater.h" + +#define FLASHROM_OUTPUT_WP_PATTERN "write protect is " + +/* System environment values. */ +static const char * const FLASHROM_OUTPUT_WP_ENABLED = + FLASHROM_OUTPUT_WP_PATTERN "enabled", + * const FLASHROM_OUTPUT_WP_DISABLED = + FLASHROM_OUTPUT_WP_PATTERN "disabled"; + + +/* Helper function to return write protection status via given programmer. */ +enum wp_state flashrom_get_wp(const char *programmer) +{ + char *command, *result; + const char *postfix; + int r; + + /* grep is needed because host_shell only returns 1 line. */ + postfix = " 2>/dev/null | grep \"" FLASHROM_OUTPUT_WP_PATTERN "\""; + + + /* TODO(b/203715651): link with flashrom directly. */ + ASPRINTF(&command, "flashrom --wp-status -p %s %s", programmer, postfix); + + /* invokes flashrom(8) with non-zero result if error. */ + result = host_shell(command); + strip_string(result, NULL); + free(command); + VB2_DEBUG("wp-status: %s\n", result); + + if (strstr(result, FLASHROM_OUTPUT_WP_ENABLED)) + r = WP_ENABLED; + else if (strstr(result, FLASHROM_OUTPUT_WP_DISABLED)) + r = WP_DISABLED; + else + r = WP_ERROR; + free(result); + + return r; +} diff --git a/futility/updater_utils.h b/futility/updater_utils.h index e2c8b961..4ab61c93 100644 --- a/futility/updater_utils.h +++ b/futility/updater_utils.h @@ -225,11 +225,4 @@ void init_system_properties(struct system_property *props, int num); */ const char *get_firmware_rootkey_hash(const struct firmware_image *image); -int flashrom_read_image(struct firmware_image *image, const char *region, - int verbosity); -int flashrom_write_image(const struct firmware_image *image, - const char *region, - const struct firmware_image *diff_image, - int do_verify, int verbosity); - #endif /* VBOOT_REFERENCE_FUTILITY_UPDATER_UTILS_H_ */ diff --git a/host/lib/flashrom_drv.c b/host/lib/flashrom_drv.c new file mode 100644 index 00000000..02250472 --- /dev/null +++ b/host/lib/flashrom_drv.c @@ -0,0 +1,190 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * The utility functions for firmware updater. + */ + +#include + +#include "2common.h" +#include "crossystem.h" +#include "host_misc.h" +#include "util_misc.h" +//#include "updater.h" +#include "../../futility/futility.h" +#include "flashrom.h" + +// global to allow verbosity level to be injected into callback. +static enum flashrom_log_level g_verbose_screen = FLASHROM_MSG_INFO; + +static int flashrom_print_cb(enum flashrom_log_level level, const char *fmt, + va_list ap) +{ + int ret = 0; + FILE *output_type = (level < FLASHROM_MSG_INFO) ? stderr : stdout; + + if (level > g_verbose_screen) + return ret; + + 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) + 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; +} + +int flashrom_read_image(struct firmware_image *image, const char *region, + int verbosity) +{ + int r = 0; + size_t len = 0; + + g_verbose_screen = verbosity; + + char *programmer, *params; + char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); + + 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 (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_layout_set(flashctx, layout); + } + + image->data = calloc(1, len); + image->size = len; + image->file_name = strdup(""); + + r |= flashrom_image_read(flashctx, image->data, len); + +err_cleanup: + r |= flashrom_programmer_shutdown(prog); + flashrom_layout_release(layout); + flashrom_flash_release(flashctx); + free(tmp); + + return r; +} + +int flashrom_write_image(const struct firmware_image *image, + const char *region, + const struct firmware_image *diff_image, + int do_verify, int verbosity) +{ + int r = 0; + size_t len = 0; + + g_verbose_screen = verbosity; + + char *programmer, *params; + char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); + + 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_layout_set(flashctx, layout); + } + + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, true); + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true); + if (!do_verify) + 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; +} diff --git a/host/lib/include/flashrom.h b/host/lib/include/flashrom.h index 0a4f885b..eb6d5313 100644 --- a/host/lib/include/flashrom.h +++ b/host/lib/include/flashrom.h @@ -40,6 +40,8 @@ struct firmware_image { * @return VB2_SUCCESS on success, or a relevant error. */ vb2_error_t flashrom_read(struct firmware_image *image, const char *region); +int flashrom_read_image(struct firmware_image *image, const char *region, + int verbosity); /** * Write using flashrom from a buffer. @@ -52,3 +54,7 @@ vb2_error_t flashrom_read(struct firmware_image *image, const char *region); * @return VB2_SUCCESS on success, or a relevant error. */ vb2_error_t flashrom_write(struct firmware_image *image, const char *region); +int flashrom_write_image(const struct firmware_image *image, + const char *region, + const struct firmware_image *diff_image, + int do_verify, int verbosity); -- cgit v1.2.1