diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2020-05-27 07:30:24 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-06-09 16:30:56 +0000 |
commit | 1978c84e51cc8eb99f55167c6b5b6cc85439f832 (patch) | |
tree | 6d16f00d1022c19559031285ca53786817b18c66 /host | |
parent | 5ae4df3bbf2efd4471c98d5a185544f589155f87 (diff) | |
download | vboot-1978c84e51cc8eb99f55167c6b5b6cc85439f832.tar.gz |
host/lib: add lightweight flashrom wrapper library
Lightweight wrapper around flashrom, exposing two APIs:
flashrom_read(programmer, region, data_out, size_out)
flashrom_write(programmer, region, data, size)
|region| can be NULL, in which case operate on the whole flash chip.
The intended usage of this wrapper library is to read/write VBNV from
SPI flash directly, avoiding the call thru mosys (which has deprecated
the command). Bringing this logic into crossystem directly will also
help with expanding VBNV to 64-bytes.
BUG=chromium:1032351,chromium:1030473,chromium:789276
BRANCH=none
TEST=provided unit tests
Change-Id: I3997bd03a2db7e58e4e76fc200c637dd3b5b20a4
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2218888
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/flashrom.c | 158 | ||||
-rw-r--r-- | host/lib/include/flashrom.h | 50 |
2 files changed, 208 insertions, 0 deletions
diff --git a/host/lib/flashrom.c b/host/lib/flashrom.c new file mode 100644 index 00000000..061c5b84 --- /dev/null +++ b/host/lib/flashrom.c @@ -0,0 +1,158 @@ +/* Copyright 2020 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. + */ + +/* For strdup */ +#define _POSIX_C_SOURCE 200809L + +#include <fcntl.h> +#include <limits.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "2api.h" +#include "2return_codes.h" +#include "host_misc.h" +#include "flashrom.h" +#include "subprocess.h" + +#define FLASHROM_EXEC_NAME "flashrom" + +/** + * Helper to create a temporary file, and optionally write some data + * into it. + * + * @param data If data needs to be written to the file, a + * pointer to the buffer. Pass NULL to just + * create an empty temporary file. + * @param data_size The size of the buffer to write, if applicable. + * @param path_out An output pointer for the filename. Caller + * should free. + * + * @return VB2_SUCCESS on success, or a relevant error. + */ +static vb2_error_t write_temp_file(const uint8_t *data, uint32_t data_size, + char **path_out) +{ + int fd; + ssize_t write_rv; + vb2_error_t rv; + char *path; + + *path_out = NULL; + path = strdup(P_tmpdir "/vb2_flashrom.XXXXXX"); + + fd = mkstemp(path); + if (fd < 0) { + rv = VB2_ERROR_WRITE_FILE_OPEN; + goto fail; + } + + while (data && data_size > 0) { + write_rv = write(fd, data, data_size); + if (write_rv < 0) { + close(fd); + unlink(path); + rv = VB2_ERROR_WRITE_FILE_DATA; + goto fail; + } + + data_size -= write_rv; + data += write_rv; + } + + close(fd); + *path_out = path; + return VB2_SUCCESS; + + fail: + free(path); + return rv; +} + +static vb2_error_t run_flashrom(const char *const argv[]) +{ + int status = subprocess_run(argv, &subprocess_null, &subprocess_null, + &subprocess_null); + if (status) { + fprintf(stderr, "Flashrom invocation failed (exit status %d):", + status); + + for (const char *const *argp = argv; *argp; argp++) + fprintf(stderr, " %s", *argp); + + fprintf(stderr, "\n"); + return VB2_ERROR_FLASHROM; + } + + return VB2_SUCCESS; +} + +vb2_error_t flashrom_read(const char *programmer, const char *region, + uint8_t **data_out, uint32_t *size_out) +{ + char *tmpfile; + char region_param[PATH_MAX]; + vb2_error_t rv; + + *data_out = NULL; + *size_out = 0; + + VB2_TRY(write_temp_file(NULL, 0, &tmpfile)); + + if (region) + snprintf(region_param, sizeof(region_param), "%s:%s", region, + tmpfile); + + const char *const argv[] = { + FLASHROM_EXEC_NAME, + "-p", + programmer, + "-r", + region ? "-i" : tmpfile, + region ? region_param : NULL, + NULL, + }; + + rv = run_flashrom(argv); + if (rv == VB2_SUCCESS) + rv = vb2_read_file(tmpfile, data_out, size_out); + + unlink(tmpfile); + free(tmpfile); + return rv; +} + +vb2_error_t flashrom_write(const char *programmer, const char *region, + uint8_t *data, uint32_t size) +{ + char *tmpfile; + char region_param[PATH_MAX]; + vb2_error_t rv; + + VB2_TRY(write_temp_file(data, size, &tmpfile)); + + if (region) + snprintf(region_param, sizeof(region_param), "%s:%s", region, + tmpfile); + + const char *const argv[] = { + FLASHROM_EXEC_NAME, + "-p", + programmer, + "-w", + region ? "-i" : tmpfile, + region ? region_param : NULL, + NULL, + }; + + rv = run_flashrom(argv); + unlink(tmpfile); + free(tmpfile); + return rv; +} diff --git a/host/lib/include/flashrom.h b/host/lib/include/flashrom.h new file mode 100644 index 00000000..560fbb0e --- /dev/null +++ b/host/lib/include/flashrom.h @@ -0,0 +1,50 @@ +/* Copyright 2020 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. + * + * Host utilites to execute flashrom command. + */ + +#include <stdint.h> + +#include "2return_codes.h" + +#define FLASHROM_PROGRAMMER_INTERNAL_AP "host" +#define FLASHROM_PROGRAMMER_INTERNAL_EC "ec" + +/** + * Read using flashrom into an allocated buffer. + * + * @param programmer The name of the programmer to use. There are + * named constants FLASHROM_PROGRAMMER_INTERNAL_AP + * and FLASHROM_PROGRAMMER_INTERNAL_EC available + * for the AP and EC respectively, or a custom + * programmer string can be provided. + * @param region The name of the fmap region to read, or NULL to + * read the entire flash chip. + * @param data_out Output parameter of allocated buffer to read into. + * The caller should free the buffer. + * @param size_out Output parameter of buffer size. + * + * @return VB2_SUCCESS on success, or a relevant error. + */ +vb2_error_t flashrom_read(const char *programmer, const char *region, + uint8_t **data_out, uint32_t *size_out); + +/** + * Write using flashrom from a buffer. + * + * @param programmer The name of the programmer to use. There are + * named constants FLASHROM_PROGRAMMER_INTERNAL_AP + * and FLASHROM_PROGRAMMER_INTERNAL_EC available + * for the AP and EC respectively, or a custom + * programmer string can be provided. + * @param region The name of the fmap region to write, or NULL to + * write the entire flash chip. + * @param data The buffer to write. + * @param size The size of the buffer to write. + * + * @return VB2_SUCCESS on success, or a relevant error. + */ +vb2_error_t flashrom_write(const char *programmer, const char *region, + uint8_t *data, uint32_t size); |