Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/59714 )
Change subject: util/cbfstool: Port elogtool to libflashrom ......................................................................
util/cbfstool: Port elogtool to libflashrom
This also uncouples cbfstool from being overly Chromium specific. However the main objective is to not subprocess flashrom any more and instead use the programmatic API.
BUG=b:207808292 TEST=none
Change-Id: I79df2934b9b0492a554a4fecdd533a0abe1df231 Signed-off-by: Edward O'Callaghan quasisec@google.com --- M util/cbfstool/Makefile.inc M util/cbfstool/elogtool.c A util/cbfstool/uflashrom.c A util/cbfstool/uflashrom.h 4 files changed, 168 insertions(+), 9 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/14/59714/1
diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index 4651f51..3282c91 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -92,6 +92,7 @@ elogobj := elogobj := elogtool.o elogobj += eventlog.o +elogobj += uflashrom.o elogobj += valstr.o elogobj += elog.o elogobj += common.o diff --git a/util/cbfstool/elogtool.c b/util/cbfstool/elogtool.c index 253e2ee..68aa207 100644 --- a/util/cbfstool/elogtool.c +++ b/util/cbfstool/elogtool.c @@ -11,9 +11,9 @@
#include <common.h> #include <commonlib/bsd/elog.h> -#include <flashrom.h>
#include "eventlog.h" +#include "uflashrom.h"
/* Only refers to the data max size. The "-1" is the checksum byte */ #define ELOG_MAX_EVENT_DATA_SIZE (ELOG_MAX_EVENT_SIZE - sizeof(struct event_header) - 1) @@ -78,16 +78,17 @@ */ static int elog_read(struct buffer *buffer, const char *filename) { + struct firmware_programmer image = { + .programmer = FLASHROM_PROGRAMMER_INTERNAL_AP, + .data = NULL, + .size = 0, + }; if (filename == NULL) { - uint8_t *buf; - uint32_t buf_size; - - if (flashrom_read(FLASHROM_PROGRAMMER_INTERNAL_AP, ELOG_RW_REGION_NAME, - &buf, &buf_size) != VB2_SUCCESS) { + if (flashrom_read(&image, ELOG_RW_REGION_NAME) != 0) { fprintf(stderr, "Could not read RW_ELOG region using flashrom\n"); return ELOGTOOL_EXIT_READ_ERROR; } - buffer_init(buffer, NULL, buf, buf_size); + buffer_init(buffer, NULL, image.data, image.size); } else if (buffer_from_file(buffer, filename) != 0) { fprintf(stderr, "Could not read input file: %s\n", filename); return ELOGTOOL_EXIT_READ_ERROR; @@ -108,9 +109,13 @@ */ static int elog_write(struct buffer *buf, const char *filename) { + struct firmware_programmer image = { + .programmer = FLASHROM_PROGRAMMER_INTERNAL_AP, + .data = buffer_get(buf), + .size = buffer_size(buf), + }; if (filename == NULL) { - if (flashrom_write(FLASHROM_PROGRAMMER_INTERNAL_AP, ELOG_RW_REGION_NAME, - buffer_get(buf), buffer_size(buf)) != VB2_SUCCESS) { + if (flashrom_write(&image, ELOG_RW_REGION_NAME) != 0) { fprintf(stderr, "Failed to write to RW_ELOG region using flashrom\n"); return ELOGTOOL_EXIT_WRITE_ERROR; diff --git a/util/cbfstool/uflashrom.c b/util/cbfstool/uflashrom.c new file mode 100644 index 0000000..f53bfbe --- /dev/null +++ b/util/cbfstool/uflashrom.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include <libflashrom.h> + +#include "uflashrom.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; +} + +int flashrom_read(struct firmware_programmer *image, const char *region) +{ + int r = 0; + size_t len = 0; + + 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, image->programmer, NULL); + r |= flashrom_flash_probe(&flashctx, prog, NULL); + + len = flashrom_flash_getsize(flashctx); + if (region) { + 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); // XXX + image->size = len; // XXX + + r |= flashrom_image_read(flashctx, image->data, len); + + r |= flashrom_programmer_shutdown(prog); + flashrom_flash_release(flashctx); + + return r; +} + +int flashrom_write(struct firmware_programmer *image, const char *region) +{ + int r = 0; + size_t len = 0; + + 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, image->programmer, NULL); + 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 (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); + + r |= flashrom_image_write(flashctx, image->data, image->size, NULL); + +err_cleanup: + r |= flashrom_programmer_shutdown(prog); + flashrom_layout_release(layout); + flashrom_flash_release(flashctx); + free(tmp); + + return r; +} diff --git a/util/cbfstool/uflashrom.h b/util/cbfstool/uflashrom.h new file mode 100644 index 0000000..82f79d6 --- /dev/null +++ b/util/cbfstool/uflashrom.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef UFLASHROM_H +#define UFLASHROM_H + +#define FLASHROM_PROGRAMMER_INTERNAL_AP "internal" + +struct firmware_programmer { + const char *programmer; + uint32_t size; + uint8_t *data; +}; + +int flashrom_read(struct firmware_programmer *image, const char *region); +int flashrom_write(struct firmware_programmer *image, const char *region); + +#endif /* UFASHROM_H */