summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--flash.h11
-rw-r--r--flashrom.c309
-rw-r--r--libflashrom.c334
-rw-r--r--libflashrom.h70
5 files changed, 723 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 4ebde1efb..88130c812 100644
--- a/Makefile
+++ b/Makefile
@@ -1357,6 +1357,12 @@ install: $(PROGRAM)$(EXEC_SUFFIX) $(PROGRAM).8
$(INSTALL) -m 0755 $(PROGRAM)$(EXEC_SUFFIX) $(DESTDIR)$(PREFIX)/sbin
$(INSTALL) -m 0644 $(PROGRAM).8 $(DESTDIR)$(MANDIR)/man8
+libinstall: libflashrom.a libflashrom.h
+ mkdir -p $(DESTDIR)$(PREFIX)/lib
+ $(INSTALL) -m 0644 libflashrom.a $(DESTDIR)$(PREFIX)/lib
+ mkdir -p $(DESTDIR)$(PREFIX)/include
+ $(INSTALL) -m 0644 libflashrom.h $(DESTDIR)$(PREFIX)/include
+
export: $(PROGRAM).8
@rm -rf $(EXPORTDIR)/flashrom-$(RELEASENAME)
@svn export -r BASE . $(EXPORTDIR)/flashrom-$(RELEASENAME)
diff --git a/flash.h b/flash.h
index b383edaf3..1da7e4121 100644
--- a/flash.h
+++ b/flash.h
@@ -138,7 +138,8 @@ enum test_state {
#define TEST_BAD_PRE (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = NT }
#define TEST_BAD_PREW (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD }
-struct flashctx;
+struct flashrom_flashctx;
+#define flashctx flashrom_flashctx /* TODO: Agree on a name and convert all occurences. */
typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
struct flashchip {
@@ -204,7 +205,7 @@ struct flashchip {
enum write_granularity gran;
};
-struct flashctx {
+struct flashrom_flashctx {
struct flashchip *chip;
/* FIXME: The memory mappings should be saved in a more structured way. */
/* The physical_* fields store the respective addresses in the physical address space of the CPU. */
@@ -218,6 +219,12 @@ struct flashctx {
struct registered_master *mst;
const struct flashrom_layout *layout;
struct single_layout fallback_layout;
+ struct {
+ bool force;
+ bool force_boardmismatch;
+ bool verify_after_write;
+ bool verify_whole_chip;
+ } flags;
};
/* Timing used in probe routines. ZERO is -2 to differentiate between an unset
diff --git a/flashrom.c b/flashrom.c
index 273eb9971..3be3d3214 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -409,6 +409,7 @@ const struct programmer_entry programmer_table[] = {
#define SHUTDOWN_MAXFN 32
static int shutdown_fn_count = 0;
+/** @private */
struct shutdown_func_data {
int (*func) (void *data);
void *data;
@@ -1835,7 +1836,7 @@ static int erase_block(struct flashctx *const flashctx,
* @return 0 on success,
* 1 if all available erase functions failed.
*/
-int erase_by_layout(struct flashctx *const flashctx)
+static int erase_by_layout(struct flashctx *const flashctx)
{
struct walk_info info = { 0 };
return walk_by_layout(flashctx, &info, &erase_block);
@@ -1946,8 +1947,8 @@ _free_ret:
* @return 0 on success,
* 1 if anything has gone wrong.
*/
-int write_by_layout(struct flashctx *const flashctx,
- void *const curcontents, const void *const newcontents)
+static int write_by_layout(struct flashctx *const flashctx,
+ void *const curcontents, const void *const newcontents)
{
struct walk_info info;
info.curcontents = curcontents;
@@ -1968,8 +1969,8 @@ int write_by_layout(struct flashctx *const flashctx,
* 1 if reading failed,
* 3 if the contents don't match.
*/
-int verify_by_layout(struct flashctx *const flashctx,
- void *const curcontents, const uint8_t *const newcontents)
+static int verify_by_layout(struct flashctx *const flashctx,
+ void *const curcontents, const uint8_t *const newcontents)
{
const struct flashrom_layout *const layout = get_layout(flashctx);
@@ -2484,3 +2485,301 @@ out:
free(newcontents);
return ret;
}
+
+/** @private */
+static int prepare_flash_access(struct flashctx *const flash,
+ const bool read_it, const bool write_it,
+ const bool erase_it, const bool verify_it)
+{
+ if (chip_safety_check(flash, flash->flags.force, read_it, write_it, erase_it, verify_it)) {
+ msg_cerr("Aborting.\n");
+ return 1;
+ }
+
+ if (flash->layout == get_global_layout() && normalize_romentries(flash)) {
+ msg_cerr("Requested regions can not be handled. Aborting.\n");
+ return 1;
+ }
+
+ if (map_flash(flash) != 0)
+ return 1;
+
+ /* Given the existence of read locks, we want to unlock for read,
+ erase and write. */
+ if (flash->chip->unlock)
+ flash->chip->unlock(flash);
+
+ return 0;
+}
+
+/** @private */
+static void finalize_flash_access(struct flashctx *const flash)
+{
+ unmap_flash(flash);
+}
+
+/**
+ * @addtogroup flashrom-flash
+ * @{
+ */
+
+/**
+ * @brief Erase the specified ROM chip.
+ *
+ * If a layout is set in the given flash context, only included regions
+ * will be erased.
+ *
+ * @param flashctx The context of the flash chip to erase.
+ * @return 0 on success.
+ */
+int flashrom_flash_erase(struct flashctx *const flashctx)
+{
+ if (prepare_flash_access(flashctx, false, false, true, false))
+ return 1;
+
+ const int ret = erase_by_layout(flashctx);
+
+ finalize_flash_access(flashctx);
+
+ return ret;
+}
+
+/** @} */ /* end flashrom-flash */
+
+/**
+ * @defgroup flashrom-ops Operations
+ * @{
+ */
+
+/**
+ * @brief Read the current image from the specified ROM chip.
+ *
+ * If a layout is set in the specified flash context, only included regions
+ * will be read.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Target buffer to write image to.
+ * @param buffer_len Size of target buffer in bytes.
+ * @return 0 on success,
+ * 2 if buffer_len is too short for the flash chip's contents,
+ * or 1 on any other failure.
+ */
+int flashrom_image_read(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len)
+{
+ const size_t flash_size = flashctx->chip->total_size * 1024;
+
+ if (flash_size > buffer_len)
+ return 2;
+
+ if (prepare_flash_access(flashctx, true, false, false, false))
+ return 1;
+
+ msg_cinfo("Reading flash... ");
+
+ int ret = 1;
+ if (read_by_layout(flashctx, buffer)) {
+ msg_cerr("Read operation failed!\n");
+ msg_cinfo("FAILED.\n");
+ goto _finalize_ret;
+ }
+ msg_cinfo("done.\n");
+ ret = 0;
+
+_finalize_ret:
+ finalize_flash_access(flashctx);
+ return ret;
+}
+
+static void combine_image_by_layout(const struct flashctx *const flashctx,
+ uint8_t *const newcontents, const uint8_t *const oldcontents)
+{
+ const struct flashrom_layout *const layout = get_layout(flashctx);
+
+ size_t i;
+ for (i = 0; i < layout->num_entries; ++i) {
+ if (layout->entries[i].included)
+ continue;
+
+ const chipoff_t region_start = layout->entries[i].start;
+ const chipsize_t region_len = layout->entries[i].end - layout->entries[i].start + 1;
+
+ memcpy(newcontents + region_start, oldcontents + region_start, region_len);
+ }
+}
+
+/**
+ * @brief Write the specified image to the ROM chip.
+ *
+ * If a layout is set in the specified flash context, only erase blocks
+ * containing included regions will be touched.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Source buffer to read image from.
+ * @param buffer_len Size of source buffer in bytes.
+ * @return 0 on success,
+ * 4 if buffer_len doesn't match the size of the flash chip,
+ * 3 if write was tried but nothing has changed,
+ * 2 if write failed and flash contents changed,
+ * or 1 on any other failure.
+ */
+int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len)
+{
+ const size_t flash_size = flashctx->chip->total_size * 1024;
+ const bool verify_all = flashctx->flags.verify_whole_chip;
+ const bool verify = flashctx->flags.verify_after_write;
+
+ if (buffer_len != flash_size)
+ return 4;
+
+ int ret = 1;
+
+ uint8_t *const newcontents = buffer;
+ uint8_t *const curcontents = malloc(flash_size);
+ uint8_t *oldcontents = NULL;
+ if (verify_all)
+ oldcontents = malloc(flash_size);
+ if (!curcontents || (verify_all && !oldcontents)) {
+ msg_gerr("Out of memory!\n");
+ goto _free_ret;
+ }
+
+#if CONFIG_INTERNAL == 1
+ if (programmer == PROGRAMMER_INTERNAL && cb_check_image(newcontents, flash_size) < 0) {
+ if (flashctx->flags.force_boardmismatch) {
+ msg_pinfo("Proceeding anyway because user forced us to.\n");
+ } else {
+ msg_perr("Aborting. You can override this with "
+ "-p internal:boardmismatch=force.\n");
+ goto _free_ret;
+ }
+ }
+#endif
+
+ if (prepare_flash_access(flashctx, false, true, false, verify))
+ goto _free_ret;
+
+ /*
+ * Read the whole chip to be able to check whether regions need to be
+ * erased and to give better diagnostics in case write fails.
+ * The alternative is to read only the regions which are to be
+ * preserved, but in that case we might perform unneeded erase which
+ * takes time as well.
+ */
+ msg_cinfo("Reading old flash chip contents... ");
+ if (verify_all) {
+ if (flashctx->chip->read(flashctx, oldcontents, 0, flash_size)) {
+ msg_cinfo("FAILED.\n");
+ goto _finalize_ret;
+ }
+ memcpy(curcontents, oldcontents, flash_size);
+ } else {
+ if (read_by_layout(flashctx, curcontents)) {
+ msg_cinfo("FAILED.\n");
+ goto _finalize_ret;
+ }
+ }
+ msg_cinfo("done.\n");
+
+ if (write_by_layout(flashctx, curcontents, newcontents)) {
+ msg_cerr("Uh oh. Erase/write failed. ");
+ ret = 2;
+ if (verify_all) {
+ msg_cerr("Checking if anything has changed.\n");
+ msg_cinfo("Reading current flash chip contents... ");
+ if (!flashctx->chip->read(flashctx, curcontents, 0, flash_size)) {
+ msg_cinfo("done.\n");
+ if (!memcmp(oldcontents, curcontents, flash_size)) {
+ nonfatal_help_message();
+ goto _finalize_ret;
+ }
+ msg_cerr("Apparently at least some data has changed.\n");
+ } else
+ msg_cerr("Can't even read anymore!\n");
+ emergency_help_message();
+ goto _finalize_ret;
+ } else {
+ msg_cerr("\n");
+ }
+ emergency_help_message();
+ goto _finalize_ret;
+ }
+
+ /* Verify only if we actually changed something. */
+ if (verify && !all_skipped) {
+ const struct flashrom_layout *const layout_bak = flashctx->layout;
+
+ msg_cinfo("Verifying flash... ");
+
+ /* Work around chips which need some time to calm down. */
+ programmer_delay(1000*1000);
+
+ if (verify_all) {
+ combine_image_by_layout(flashctx, newcontents, oldcontents);
+ flashctx->layout = NULL;
+ }
+ ret = verify_by_layout(flashctx, curcontents, newcontents);
+ flashctx->layout = layout_bak;
+ /* If we tried to write, and verification now fails, we
+ might have an emergency situation. */
+ if (ret)
+ emergency_help_message();
+ else
+ msg_cinfo("VERIFIED.\n");
+ } else {
+ /* We didn't change anything. */
+ ret = 0;
+ }
+
+_finalize_ret:
+ finalize_flash_access(flashctx);
+_free_ret:
+ free(oldcontents);
+ free(curcontents);
+ return ret;
+}
+
+/**
+ * @brief Verify the ROM chip's contents with the specified image.
+ *
+ * If a layout is set in the specified flash context, only included regions
+ * will be verified.
+ *
+ * @param flashctx The context of the flash chip.
+ * @param buffer Source buffer to verify with.
+ * @param buffer_len Size of source buffer in bytes.
+ * @return 0 on success,
+ * 3 if the chip's contents don't match,
+ * 2 if buffer_len doesn't match the size of the flash chip,
+ * or 1 on any other failure.
+ */
+int flashrom_image_verify(struct flashctx *const flashctx, const void *const buffer, const size_t buffer_len)
+{
+ const size_t flash_size = flashctx->chip->total_size * 1024;
+
+ if (buffer_len != flash_size)
+ return 2;
+
+ const uint8_t *const newcontents = buffer;
+ uint8_t *const curcontents = malloc(flash_size);
+ if (!curcontents) {
+ msg_gerr("Out of memory!\n");
+ return 1;
+ }
+
+ int ret = 1;
+
+ if (prepare_flash_access(flashctx, false, false, false, true))
+ goto _free_ret;
+
+ msg_cinfo("Verifying flash... ");
+ ret = verify_by_layout(flashctx, curcontents, newcontents);
+ if (!ret)
+ msg_cinfo("VERIFIED.\n");
+
+ finalize_flash_access(flashctx);
+_free_ret:
+ free(curcontents);
+ return ret;
+}
+
+/** @} */ /* end flashrom-ops */
diff --git a/libflashrom.c b/libflashrom.c
new file mode 100644
index 000000000..5447bae9e
--- /dev/null
+++ b/libflashrom.c
@@ -0,0 +1,334 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2012, 2016 secunet Security Networks AG
+ * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+/**
+ * @mainpage
+ *
+ * Have a look at the Modules section for a function reference.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "flash.h"
+#include "programmer.h"
+#include "layout.h"
+#include "libflashrom.h"
+
+/**
+ * @defgroup flashrom-general General
+ * @{
+ */
+
+/** Pointer to log callback function. */
+static flashrom_log_callback *global_log_callback = NULL;
+
+/**
+ * @brief Initialize libflashrom.
+ *
+ * @param perform_selfcheck If not zero, perform a self check.
+ * @return 0 on success
+ */
+int flashrom_init(const int perform_selfcheck)
+{
+ if (perform_selfcheck && selfcheck())
+ return 1;
+ myusec_calibrate_delay();
+ return 0;
+}
+
+/**
+ * @brief Shut down libflashrom.
+ * @return 0 on success
+ */
+int flashrom_shutdown(void)
+{
+ return 0; /* TODO: nothing to do? */
+}
+
+/* TODO: flashrom_set_loglevel()? do we need it?
+ For now, let the user decide in his callback. */
+
+/**
+ * @brief Set the log callback function.
+ *
+ * Set a callback function which will be invoked whenever libflashrom wants
+ * to output messages. This allows frontends to do whatever they see fit with
+ * such messages, e.g. write them to syslog, or to file, or print them in a
+ * GUI window, etc.
+ *
+ * @param log_callback Pointer to the new log callback function.
+ */
+void flashrom_set_log_callback(flashrom_log_callback *const log_callback)
+{
+ global_log_callback = log_callback;
+}
+/** @private */
+int print(const enum msglevel level, const char *const fmt, ...)
+{
+ if (global_log_callback) {
+ int ret;
+ va_list args;
+ va_start(args, fmt);
+ ret = global_log_callback(level, fmt, args);
+ va_end(args);
+ return ret;
+ }
+ return 0;
+}
+
+/** @} */ /* end flashrom-general */
+
+
+
+/**
+ * @defgroup flashrom-query Querying
+ * @{
+ */
+
+/* TBD */
+
+/** @} */ /* end flashrom-query */
+
+
+
+/**
+ * @defgroup flashrom-prog Programmers
+ * @{
+ */
+
+/**
+ * @brief Initialize the specified programmer.
+ *
+ * Currently, only one programmer may be initialized at a time.
+ *
+ * @param[out] flashprog Points to a pointer of type struct flashrom_programmer
+ * that will be set if programmer initialization succeeds.
+ * *flashprog has to be shutdown by the caller with @ref
+ * flashrom_programmer_shutdown.
+ * @param[in] prog_name Name of the programmer to initialize.
+ * @param[in] prog_param Pointer to programmer specific parameters.
+ * @return 0 on success
+ */
+int flashrom_programmer_init(struct flashrom_programmer **const flashprog,
+ const char *const prog_name, const char *const prog_param)
+{
+ unsigned prog;
+
+ for (prog = 0; prog < PROGRAMMER_INVALID; prog++) {
+ if (strcmp(prog_name, programmer_table[prog].name) == 0)
+ break;
+ }
+ if (prog >= PROGRAMMER_INVALID) {
+ msg_ginfo("Error: Unknown programmer \"%s\". Valid choices are:\n", prog_name);
+ list_programmers_linebreak(0, 80, 0);
+ return 1;
+ }
+ return programmer_init(prog, prog_param);
+}
+
+/**
+ * @brief Shut down the initialized programmer.
+ *
+ * @param flashprog The programmer to shut down.
+ * @return 0 on success
+ */
+int flashrom_programmer_shutdown(struct flashrom_programmer *const flashprog)
+{
+ return programmer_shutdown();
+}
+
+/* TODO: flashrom_programmer_capabilities()? */
+
+/** @} */ /* end flashrom-prog */
+
+
+
+/**
+ * @defgroup flashrom-flash Flash chips
+ * @{
+ */
+
+/**
+ * @brief Probe for a flash chip.
+ *
+ * Probes for a flash chip and returns a flash context, that can be used
+ * later with flash chip and @ref flashrom-ops "image operations", if
+ * exactly one matching chip is found.
+ *
+ * @param[out] flashctx Points to a pointer of type struct flashrom_flashctx
+ * that will be set if exactly one chip is found. *flashctx
+ * has to be freed by the caller with @ref flashrom_flash_release.
+ * @param[in] flashprog The flash programmer used to access the chip.
+ * @param[in] chip_name Name of a chip to probe for, or NULL to probe for
+ * all known chips.
+ * @return 0 on success,
+ * 3 if multiple chips were found,
+ * 2 if no chip was found,
+ * or 1 on any other error.
+ */
+int flashrom_flash_probe(struct flashrom_flashctx **const flashctx,
+ const struct flashrom_programmer *const flashprog,
+ const char *const chip_name)
+{
+ int i, ret = 2;
+ struct flashrom_flashctx second_flashctx = { 0, };
+
+ chip_to_probe = chip_name; /* chip_to_probe is global in flashrom.c */
+
+ *flashctx = malloc(sizeof(**flashctx));
+ if (!*flashctx)
+ return 1;
+ memset(*flashctx, 0, sizeof(**flashctx));
+
+ for (i = 0; i < registered_master_count; ++i) {
+ int flash_idx = -1;
+ if (!ret || (flash_idx = probe_flash(&registered_masters[i], 0, *flashctx, 0)) != -1) {
+ ret = 0;
+ /* We found one chip, now check that there is no second match. */
+ if (probe_flash(&registered_masters[i], flash_idx + 1, &second_flashctx, 0) != -1) {
+ ret = 3;
+ break;
+ }
+ }
+ }
+ if (ret) {
+ free(*flashctx);
+ *flashctx = NULL;
+ }
+ return ret;
+}
+
+/**
+ * @brief Returns the size of the specified flash chip in bytes.
+ *
+ * @param flashctx The queried flash context.
+ * @return Size of flash chip in bytes.
+ */
+size_t flashrom_flash_getsize(const struct flashrom_flashctx *const flashctx)
+{
+ return flashctx->chip->total_size * 1024;
+}
+
+/**
+ * @brief Free a flash context.
+ *
+ * @param flashctx Flash context to free.
+ */
+void flashrom_flash_release(struct flashrom_flashctx *const flashctx)
+{
+ free(flashctx);
+}
+
+/**
+ * @brief Set a flag in the given flash context.
+ *
+ * @param flashctx Flash context to alter.
+ * @param flag Flag that is to be set / cleared.
+ * @param value Value to set.
+ */
+void flashrom_flag_set(struct flashrom_flashctx *const flashctx,
+ const enum flashrom_flag flag, const bool value)
+{
+ switch (flag) {
+ case FLASHROM_FLAG_FORCE: flashctx->flags.force = value; break;
+ case FLASHROM_FLAG_FORCE_BOARDMISMATCH: flashctx->flags.force_boardmismatch = value; break;
+ case FLASHROM_FLAG_VERIFY_AFTER_WRITE: flashctx->flags.verify_after_write = value; break;
+ case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: flashctx->flags.verify_whole_chip = value; break;
+ }
+}
+
+/**
+ * @brief Return the current value of a flag in the given flash context.
+ *
+ * @param flashctx Flash context to read from.
+ * @param flag Flag to be read.
+ * @return Current value of the flag.
+ */
+bool flashrom_flag_get(const struct flashrom_flashctx *const flashctx, const enum flashrom_flag flag)
+{
+ switch (flag) {
+ case FLASHROM_FLAG_FORCE: return flashctx->flags.force;
+ case FLASHROM_FLAG_FORCE_BOARDMISMATCH: return flashctx->flags.force_boardmismatch;
+ case FLASHROM_FLAG_VERIFY_AFTER_WRITE: return flashctx->flags.verify_after_write;
+ case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: return flashctx->flags.verify_whole_chip;
+ default: return false;
+ }
+}
+
+/** @} */ /* end flashrom-flash */
+
+
+
+/**
+ * @defgroup flashrom-layout Layout handling
+ * @{
+ */
+
+/**
+ * @brief Mark given region as included.
+ *
+ * @param layout The layout to alter.
+ * @param name The name of the region to include.
+ *
+ * @return 0 on success,
+ * 1 if the given name can't be found.
+ */
+int flashrom_layout_include_region(struct flashrom_layout *const layout, const char *name)
+{
+ size_t i;
+ for (i = 0; i < layout->num_entries; ++i) {
+ if (!strcmp(layout->entries[i].name, name)) {
+ layout->entries[i].included = true;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**
+ * @brief Free a layout.
+ *
+ * @param layout Layout to free.
+ */
+void flashrom_layout_release(struct flashrom_layout *const layout)
+{
+ if (layout == get_global_layout())
+ return;
+
+ free(layout);
+}
+
+/**
+ * @brief Set the active layout for a flash context.
+ *
+ * Note: This just sets a pointer. The caller must not release the layout
+ * as long as he uses it through the given flash context.
+ *
+ * @param flashctx Flash context whose layout will be set.
+ * @param layout Layout to bet set.
+ */
+void flashrom_layout_set(struct flashrom_flashctx *const flashctx, const struct flashrom_layout *const layout)
+{
+ flashctx->layout = layout;
+}
+
+/** @} */ /* end flashrom-layout */
diff --git a/libflashrom.h b/libflashrom.h
new file mode 100644
index 000000000..42b02f9fa
--- /dev/null
+++ b/libflashrom.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2012 secunet Security Networks AG
+ * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __LIBFLASHROM_H__
+#define __LIBFLASHROM_H__ 1
+
+#include <stdarg.h>
+
+int flashrom_init(int perform_selfcheck);
+int flashrom_shutdown(void);
+/** @ingroup flashrom-general */
+enum flashrom_log_level { /* This has to match enum msglevel. */
+ FLASHROM_MSG_ERROR = 0,
+ FLASHROM_MSG_INFO = 1,
+ FLASHROM_MSG_DEBUG = 2,
+ FLASHROM_MSG_DEBUG2 = 3,
+ FLASHROM_MSG_SPEW = 4,
+};
+/** @ingroup flashrom-general */
+typedef int(flashrom_log_callback)(enum flashrom_log_level, const char *format, va_list);
+void flashrom_set_log_callback(flashrom_log_callback *);
+
+struct flashrom_programmer;
+int flashrom_programmer_init(struct flashrom_programmer **, const char *prog_name, const char *prog_params);
+int flashrom_programmer_shutdown(struct flashrom_programmer *);
+
+struct flashrom_flashctx;
+int flashrom_flash_probe(struct flashrom_flashctx **, const struct flashrom_programmer *, const char *chip_name);
+size_t flashrom_flash_getsize(const struct flashrom_flashctx *);
+int flashrom_flash_erase(struct flashrom_flashctx *);
+void flashrom_flash_release(struct flashrom_flashctx *);
+
+/** @ingroup flashrom-flash */
+enum flashrom_flag {
+ FLASHROM_FLAG_FORCE,
+ FLASHROM_FLAG_FORCE_BOARDMISMATCH,
+ FLASHROM_FLAG_VERIFY_AFTER_WRITE,
+ FLASHROM_FLAG_VERIFY_WHOLE_CHIP,
+};
+void flashrom_flag_set(struct flashrom_flashctx *, enum flashrom_flag, bool value);
+bool flashrom_flag_get(const struct flashrom_flashctx *, enum flashrom_flag);
+
+int flashrom_image_read(struct flashrom_flashctx *, void *buffer, size_t buffer_len);
+int flashrom_image_write(struct flashrom_flashctx *, const void *buffer, size_t buffer_len);
+int flashrom_image_verify(struct flashrom_flashctx *, const void *buffer, size_t buffer_len);
+
+struct flashrom_layout;
+int flashrom_layout_include_region(struct flashrom_layout *, const char *name);
+void flashrom_layout_release(struct flashrom_layout *);
+void flashrom_layout_set(struct flashrom_flashctx *, const struct flashrom_layout *);
+
+#endif /* !__LIBFLASHROM_H__ */