summaryrefslogtreecommitdiff
path: root/host
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2020-05-27 07:30:24 -0600
committerCommit Bot <commit-bot@chromium.org>2020-06-09 16:30:56 +0000
commit1978c84e51cc8eb99f55167c6b5b6cc85439f832 (patch)
tree6d16f00d1022c19559031285ca53786817b18c66 /host
parent5ae4df3bbf2efd4471c98d5a185544f589155f87 (diff)
downloadvboot-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.c158
-rw-r--r--host/lib/include/flashrom.h50
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);