summaryrefslogtreecommitdiffstats
path: root/libflashrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'libflashrom.c')
-rw-r--r--libflashrom.c522
1 files changed, 205 insertions, 317 deletions
diff --git a/libflashrom.c b/libflashrom.c
index ae2d33daa..4a59e2a12 100644
--- a/libflashrom.c
+++ b/libflashrom.c
@@ -14,11 +14,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-/**
- * @mainpage
- *
- * Have a look at the Modules section for a function reference.
- */
#include <errno.h>
#include <stdlib.h>
@@ -29,24 +24,14 @@
#include "fmap.h"
#include "programmer.h"
#include "layout.h"
-#include "hwaccess.h"
#include "ich_descriptors.h"
#include "libflashrom.h"
+#include "writeprotect.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())
@@ -55,28 +40,13 @@ int flashrom_init(const int perform_selfcheck)
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.
- */
+ For now, let the user decide in their callback. */
void flashrom_set_log_callback(flashrom_log_callback *const log_callback)
{
global_log_callback = log_callback;
@@ -95,84 +65,61 @@ int print(const enum flashrom_log_level level, const char *const fmt, ...)
return 0;
}
-/** @} */ /* end flashrom-general */
-
-
-
-/**
- * @defgroup flashrom-query Querying
- * @{
- */
-
-/**
- * @brief Returns flashrom version
- * @return flashrom version
- */
-const char *flashrom_version_info(void)
+void flashrom_set_progress_callback(struct flashrom_flashctx *flashctx, flashrom_progress_callback *progress_callback, struct flashrom_progress *progress_state)
{
- return flashrom_version;
+ flashctx->progress_callback = progress_callback;
+ flashctx->progress_state = progress_state;
}
-
-/**
- * @brief Returns list of supported programmers
- * @return List of supported programmers, or NULL if an error occurred
- */
-const char **flashrom_supported_programmers(void)
+/** @private */
+void update_progress(struct flashrom_flashctx *flashctx, enum flashrom_progress_stage stage, size_t current, size_t total)
{
- enum programmer p = 0;
- const char **supported_programmers = malloc((PROGRAMMER_INVALID + 1) * sizeof(char*));
-
- if (supported_programmers != NULL) {
- for (; p < PROGRAMMER_INVALID; ++p) {
- supported_programmers[p] = programmer_table[p].name;
- }
- } else {
- msg_gerr("Memory allocation error!\n");
- }
+ if (flashctx->progress_callback == NULL)
+ return;
+ if (current > total)
+ current = total;
+
+ flashctx->progress_state->stage = stage;
+ flashctx->progress_state->current = current;
+ flashctx->progress_state->total = total;
+ flashctx->progress_callback(flashctx);
+}
- return supported_programmers;
+const char *flashrom_version_info(void)
+{
+ return flashrom_version;
}
-/**
- * @brief Returns list of supported flash chips
- * @return List of supported flash chips, or NULL if an error occurred
- */
struct flashrom_flashchip_info *flashrom_supported_flash_chips(void)
{
- unsigned int i = 0;
struct flashrom_flashchip_info *supported_flashchips =
malloc(flashchips_size * sizeof(*supported_flashchips));
- if (supported_flashchips != NULL) {
- for (; i < flashchips_size; ++i) {
- supported_flashchips[i].vendor = flashchips[i].vendor;
- supported_flashchips[i].name = flashchips[i].name;
- supported_flashchips[i].tested.erase =
- (enum flashrom_test_state)flashchips[i].tested.erase;
- supported_flashchips[i].tested.probe =
- (enum flashrom_test_state)flashchips[i].tested.probe;
- supported_flashchips[i].tested.read =
- (enum flashrom_test_state)flashchips[i].tested.read;
- supported_flashchips[i].tested.write =
- (enum flashrom_test_state)flashchips[i].tested.write;
- supported_flashchips[i].total_size = flashchips[i].total_size;
- }
- } else {
+ if (!supported_flashchips) {
msg_gerr("Memory allocation error!\n");
+ return NULL;
+ }
+
+ for (unsigned int i = 0; i < flashchips_size; ++i) {
+ supported_flashchips[i].vendor = flashchips[i].vendor;
+ supported_flashchips[i].name = flashchips[i].name;
+ supported_flashchips[i].tested.erase =
+ (enum flashrom_test_state)flashchips[i].tested.erase;
+ supported_flashchips[i].tested.probe =
+ (enum flashrom_test_state)flashchips[i].tested.probe;
+ supported_flashchips[i].tested.read =
+ (enum flashrom_test_state)flashchips[i].tested.read;
+ supported_flashchips[i].tested.write =
+ (enum flashrom_test_state)flashchips[i].tested.write;
+ supported_flashchips[i].total_size = flashchips[i].total_size;
}
return supported_flashchips;
}
-/**
- * @brief Returns list of supported mainboards
- * @return List of supported mainboards, or NULL if an error occurred
- */
struct flashrom_board_info *flashrom_supported_boards(void)
{
#if CONFIG_INTERNAL == 1
int boards_known_size = 0;
- int i = 0;
const struct board_info *binfo = boards_known;
while ((binfo++)->vendor)
@@ -182,17 +129,18 @@ struct flashrom_board_info *flashrom_supported_boards(void)
++boards_known_size;
struct flashrom_board_info *supported_boards =
- malloc(boards_known_size * sizeof(struct flashrom_board_info));
-
- if (supported_boards != NULL) {
- for (; i < boards_known_size; ++i) {
- supported_boards[i].vendor = binfo[i].vendor;
- supported_boards[i].name = binfo[i].name;
- supported_boards[i].working =
- (enum flashrom_test_state) binfo[i].working;
- }
- } else {
+ malloc(boards_known_size * sizeof(*supported_boards));
+
+ if (!supported_boards) {
msg_gerr("Memory allocation error!\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < boards_known_size; ++i) {
+ supported_boards[i].vendor = binfo[i].vendor;
+ supported_boards[i].name = binfo[i].name;
+ supported_boards[i].working =
+ (enum flashrom_test_state) binfo[i].working;
}
return supported_boards;
@@ -201,15 +149,10 @@ struct flashrom_board_info *flashrom_supported_boards(void)
#endif
}
-/**
- * @brief Returns list of supported chipsets
- * @return List of supported chipsets, or NULL if an error occurred
- */
struct flashrom_chipset_info *flashrom_supported_chipsets(void)
{
#if CONFIG_INTERNAL == 1
int chipset_enables_size = 0;
- int i = 0;
const struct penable *chipset = chipset_enables;
while ((chipset++)->vendor_name)
@@ -221,17 +164,18 @@ struct flashrom_chipset_info *flashrom_supported_chipsets(void)
struct flashrom_chipset_info *supported_chipsets =
malloc(chipset_enables_size * sizeof(*supported_chipsets));
- if (supported_chipsets != NULL) {
- for (; i < chipset_enables_size; ++i) {
- supported_chipsets[i].vendor = chipset[i].vendor_name;
- supported_chipsets[i].chipset = chipset[i].device_name;
- supported_chipsets[i].vendor_id = chipset[i].vendor_id;
- supported_chipsets[i].chipset_id = chipset[i].device_id;
- supported_chipsets[i].status =
- (enum flashrom_test_state) chipset[i].status;
- }
- } else {
+ if (!supported_chipsets) {
msg_gerr("Memory allocation error!\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < chipset_enables_size; ++i) {
+ supported_chipsets[i].vendor = chipset[i].vendor_name;
+ supported_chipsets[i].chipset = chipset[i].device_name;
+ supported_chipsets[i].vendor_id = chipset[i].vendor_id;
+ supported_chipsets[i].chipset_id = chipset[i].device_id;
+ supported_chipsets[i].status =
+ (enum flashrom_test_state) chipset[i].status;
}
return supported_chipsets;
@@ -240,62 +184,29 @@ struct flashrom_chipset_info *flashrom_supported_chipsets(void)
#endif
}
-/**
- * @brief Frees memory allocated by libflashrom API
- * @param Pointer to block of memory which should be freed
- * @return 0 on success
- */
int flashrom_data_free(void *const p)
{
free(p);
return 0;
}
-/** @} */ /* 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)
+ for (prog = 0; prog < programmer_table_size; prog++) {
+ if (strcmp(prog_name, programmer_table[prog]->name) == 0)
break;
}
- if (prog >= PROGRAMMER_INVALID) {
+ if (prog >= programmer_table_size) {
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);
+ return programmer_init(programmer_table[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();
@@ -303,33 +214,6 @@ int flashrom_programmer_shutdown(struct flashrom_programmer *const flashprog)
/* 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)
@@ -337,8 +221,6 @@ int flashrom_flash_probe(struct flashrom_flashctx **const flashctx,
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;
@@ -346,130 +228,80 @@ int flashrom_flash_probe(struct flashrom_flashctx **const 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) {
+ if (!ret || (flash_idx = probe_flash(&registered_masters[i], 0, *flashctx, 0, chip_name)) != -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) {
+ if (probe_flash(&registered_masters[i], flash_idx + 1, &second_flashctx, 0, chip_name) != -1) {
+ flashrom_layout_release(second_flashctx.default_layout);
+ free(second_flashctx.chip);
ret = 3;
break;
}
}
}
if (ret) {
- free(*flashctx);
+ flashrom_flash_release(*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)
{
+ if (!flashctx)
+ return;
+
+ flashrom_layout_release(flashctx->default_layout);
+ free(flashctx->chip);
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;
+ 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;
+ case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS: flashctx->flags.skip_unreadable_regions = value; break;
+ case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS: flashctx->flags.skip_unwritable_regions = 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;
+ 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;
+ case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS: return flashctx->flags.skip_unreadable_regions;
+ case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS: return flashctx->flags.skip_unwritable_regions;
+ default: return false;
}
}
-/** @} */ /* end flashrom-flash */
-
-
-
-/**
- * @defgroup flashrom-layout Layout handling
- * @{
- */
-
-/**
- * @brief Read a layout from the Intel ICH descriptor in the flash.
- *
- * Optionally verify that the layout matches the one in the given
- * descriptor dump.
- *
- * @param[out] layout Points to a struct flashrom_layout pointer that
- * gets set if the descriptor is read and parsed
- * successfully.
- * @param[in] flashctx Flash context to read the descriptor from flash.
- * @param[in] dump The descriptor dump to compare to or NULL.
- * @param[in] len The length of the descriptor dump.
- *
- * @return 0 on success,
- * 6 if descriptor parsing isn't implemented for the host,
- * 5 if the descriptors don't match,
- * 4 if the descriptor dump couldn't be parsed,
- * 3 if the descriptor on flash couldn't be parsed,
- * 2 if the descriptor on flash couldn't be read,
- * 1 on any other error.
- */
int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct flashctx *const flashctx,
const void *const dump, const size_t len)
{
#ifndef __FLASHROM_LITTLE_ENDIAN__
return 6;
#else
- struct ich_layout dump_layout;
+ struct flashrom_layout *dump_layout = NULL, *chip_layout = NULL;
int ret = 1;
void *const desc = malloc(0x1000);
- struct ich_layout *const chip_layout = malloc(sizeof(*chip_layout));
- if (!desc || !chip_layout) {
- msg_gerr("Out of memory!\n");
- goto _free_ret;
- }
-
if (prepare_flash_access(flashctx, true, false, false, false))
goto _free_ret;
msg_cinfo("Reading ich descriptor... ");
- if (flashctx->chip->read(flashctx, desc, 0, 0x1000)) {
+ if (read_flash(flashctx, desc, 0, 0x1000)) {
msg_cerr("Read operation failed!\n");
msg_cinfo("FAILED.\n");
ret = 2;
@@ -477,7 +309,7 @@ int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct
}
msg_cinfo("done.\n");
- if (layout_from_ich_descriptors(chip_layout, desc, 0x1000)) {
+ if (layout_from_ich_descriptors(&chip_layout, desc, 0x1000)) {
msg_cerr("Couldn't parse the descriptor!\n");
ret = 3;
goto _finalize_ret;
@@ -490,8 +322,14 @@ int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct
goto _finalize_ret;
}
- if (chip_layout->base.num_entries != dump_layout.base.num_entries ||
- memcmp(chip_layout->entries, dump_layout.entries, sizeof(dump_layout.entries))) {
+ const struct romentry *chip_entry = layout_next(chip_layout, NULL);
+ const struct romentry *dump_entry = layout_next(dump_layout, NULL);
+ while (chip_entry && dump_entry && !memcmp(chip_entry, dump_entry, sizeof(*chip_entry))) {
+ chip_entry = layout_next(chip_layout, chip_entry);
+ dump_entry = layout_next(dump_layout, dump_entry);
+ }
+ flashrom_layout_release(dump_layout);
+ if (chip_entry || dump_entry) {
msg_cerr("Descriptors don't match!\n");
ret = 5;
goto _finalize_ret;
@@ -505,7 +343,7 @@ _finalize_ret:
finalize_flash_access(flashctx);
_free_ret:
if (ret)
- free(chip_layout);
+ flashrom_layout_release(chip_layout);
free(desc);
return ret;
#endif
@@ -516,31 +354,29 @@ static int flashrom_layout_parse_fmap(struct flashrom_layout **layout,
struct flashctx *const flashctx, const struct fmap *const fmap)
{
int i;
- struct flashrom_layout *l = get_global_layout();
+ char name[FMAP_STRLEN + 1];
+ const struct fmap_area *area;
+ struct flashrom_layout *l;
- if (!fmap || !l)
+ if (!fmap || flashrom_layout_new(&l))
return 1;
- if (l->num_entries + fmap->nareas > MAX_ROMLAYOUT) {
- msg_gerr("Cannot add fmap entries to layout - Too many entries.\n");
- return 1;
- }
+ for (i = 0, area = fmap->areas; i < fmap->nareas; i++, area++) {
+ if (area->size == 0) {
+ /* Layout regions use inclusive upper and lower bounds,
+ * so it's impossible to represent a region with zero
+ * size although it's allowed in fmap. */
+ msg_gwarn("Ignoring zero-size fmap region \"%s\";"
+ " empty regions are unsupported.\n",
+ area->name);
+ continue;
+ }
- for (i = 0; i < fmap->nareas; i++) {
- l->entries[l->num_entries].start = fmap->areas[i].offset;
- l->entries[l->num_entries].end = fmap->areas[i].offset + fmap->areas[i].size - 1;
- l->entries[l->num_entries].included = false;
- l->entries[l->num_entries].name =
- strndup((const char *)fmap->areas[i].name, FMAP_STRLEN);
- if (!l->entries[l->num_entries].name) {
- msg_gerr("Error adding layout entry: %s\n", strerror(errno));
+ snprintf(name, sizeof(name), "%s", area->name);
+ if (flashrom_layout_add_region(l, area->offset, area->offset + area->size - 1, name)) {
+ flashrom_layout_release(l);
return 1;
}
- msg_gdbg("fmap %08x - %08x named %s\n",
- l->entries[l->num_entries].start,
- l->entries[l->num_entries].end,
- l->entries[l->num_entries].name);
- l->num_entries++;
}
*layout = l;
@@ -548,22 +384,8 @@ static int flashrom_layout_parse_fmap(struct flashrom_layout **layout,
}
#endif /* __FLASHROM_LITTLE_ENDIAN__ */
-/**
- * @brief Read a layout by searching the flash chip for fmap.
- *
- * @param[out] layout Points to a struct flashrom_layout pointer that
- * gets set if the fmap is read and parsed successfully.
- * @param[in] flashctx Flash context
- * @param[in] offset Offset to begin searching for fmap.
- * @param[in] offset Length of address space to search.
- *
- * @return 0 on success,
- * 3 if fmap parsing isn't implemented for the host,
- * 2 if the fmap couldn't be read,
- * 1 on any other error.
- */
int flashrom_layout_read_fmap_from_rom(struct flashrom_layout **const layout,
- struct flashctx *const flashctx, off_t offset, size_t len)
+ struct flashctx *const flashctx, size_t offset, size_t len)
{
#ifndef __FLASHROM_LITTLE_ENDIAN__
return 3;
@@ -588,20 +410,6 @@ int flashrom_layout_read_fmap_from_rom(struct flashrom_layout **const layout,
#endif
}
-/**
- * @brief Read a layout by searching buffer for fmap.
- *
- * @param[out] layout Points to a struct flashrom_layout pointer that
- * gets set if the fmap is read and parsed successfully.
- * @param[in] flashctx Flash context
- * @param[in] buffer Buffer to search in
- * @param[in] size Size of buffer to search
- *
- * @return 0 on success,
- * 3 if fmap parsing isn't implemented for the host,
- * 2 if the fmap couldn't be read,
- * 1 on any other error.
- */
int flashrom_layout_read_fmap_from_buffer(struct flashrom_layout **const layout,
struct flashctx *const flashctx, const uint8_t *const buf, size_t size)
{
@@ -634,18 +442,98 @@ _ret:
#endif
}
-/**
- * @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 */
+enum flashrom_wp_result flashrom_wp_cfg_new(struct flashrom_wp_cfg **cfg)
+{
+ *cfg = calloc(1, sizeof(**cfg));
+ return *cfg ? 0 : FLASHROM_WP_ERR_OTHER;
+}
+
+void flashrom_wp_cfg_release(struct flashrom_wp_cfg *cfg)
+{
+ free(cfg);
+}
+
+void flashrom_wp_set_mode(struct flashrom_wp_cfg *cfg, enum flashrom_wp_mode mode)
+{
+ cfg->mode = mode;
+}
+
+enum flashrom_wp_mode flashrom_wp_get_mode(const struct flashrom_wp_cfg *cfg)
+{
+ return cfg->mode;
+}
+
+void flashrom_wp_set_range(struct flashrom_wp_cfg *cfg, size_t start, size_t len)
+{
+ cfg->range.start = start;
+ cfg->range.len = len;
+}
+
+void flashrom_wp_get_range(size_t *start, size_t *len, const struct flashrom_wp_cfg *cfg)
+{
+ *start = cfg->range.start;
+ *len = cfg->range.len;
+}
+
+enum flashrom_wp_result flashrom_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg)
+{
+ if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_write_cfg)
+ return flash->mst->opaque.wp_write_cfg(flash, cfg);
+
+ if (wp_operations_available(flash))
+ return wp_write_cfg(flash, cfg);
+
+ return FLASHROM_WP_ERR_OTHER;
+}
+
+enum flashrom_wp_result flashrom_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash)
+{
+ if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_read_cfg)
+ return flash->mst->opaque.wp_read_cfg(cfg, flash);
+
+ if (wp_operations_available(flash))
+ return wp_read_cfg(cfg, flash);
+
+ return FLASHROM_WP_ERR_OTHER;
+}
+
+enum flashrom_wp_result flashrom_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashrom_flashctx *flash)
+{
+ if (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_get_ranges)
+ return flash->mst->opaque.wp_get_ranges(list, flash);
+
+ if (wp_operations_available(flash))
+ return wp_get_available_ranges(list, flash);
+
+ return FLASHROM_WP_ERR_OTHER;
+}
+
+size_t flashrom_wp_ranges_get_count(const struct flashrom_wp_ranges *list)
+{
+ return list->count;
+}
+
+enum flashrom_wp_result flashrom_wp_ranges_get_range(size_t *start, size_t *len, const struct flashrom_wp_ranges *list, unsigned int index)
+{
+ if (index >= list->count)
+ return FLASHROM_WP_ERR_OTHER;
+
+ *start = list->ranges[index].start;
+ *len = list->ranges[index].len;
+
+ return 0;
+}
+
+void flashrom_wp_ranges_release(struct flashrom_wp_ranges *list)
+{
+ if (!list)
+ return;
+
+ free(list->ranges);
+ free(list);
+}