<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Hello,<br>
<br>
My name is Łukasz Dmitrowski and I am one of coreboot/flashrom GSoC
students this year. You can read about my project here:
<a class="moz-txt-link-freetext" href="http://blogs.coreboot.org/blog/author/dmitro/">http://blogs.coreboot.org/blog/author/dmitro/</a>.<br>
<br>
One of my first steps is updating and extending Nico Hubers
libflashrom patch. Work is still in progress, but some changes are
already made, so I thought that it will be good idea to send a patch
just for review to know if I am going in a good direction. I want to
improve my skills and provide best code quality as I can, so I am
open for criticism - I am here to learn :)<br>
<br>
Patch summary:<br>
<br>
Makefile: I added cli_common.o and print.o to LIB_OBJS - it solves
undefined references in current libflashrom version, but spoils
standard flashrom build with 'make', I did not investigated it yet
as my focus is to extend library with new functions and update
already existing, need to discuss it with my mentor<br>
<br>
cli_classic.c, cli_output.c, flash.h: Only Nico Hubers changes here,
didn't touch it<br>
<br>
libflashrom.c, libflashrom.h: I added 8 functions and made a few
changes to existing ones, as some of used functions are static, or
does not exist.<br>
<br>
New functions:<br>
<br>
int fl_supported_programmers(const char **supported_programmers);<br>
int fl_supported_flash_chips(fl_flashchip_info_t *fchips);<br>
int fl_supported_boards(fl_board_info_t *boards);<br>
int fl_supported_chipsets(fl_chipset_info_t *chipsets);<br>
int fl_supported_programmers_number();<br>
int fl_supported_flash_chips_number();<br>
int fl_supported_boards_number();<br>
int fl_supported_chipsets_number();<br>
<br>
New types:<br>
fl_flashchip_info_t - smaller version of struct flashchip<br>
fl_board_info_t - smaller version of struct board_info <br>
fl_chipset_info_t - smaller version of struct penable<br>
fl_test_state - copy of enum test_state<br>
<br>
So we have 4 functions that return a list of supported programmers,
chips, boards and chipsets. Next 4 functions return number of
supported hardware of certain type. For example, to obtain a list of
supported boards, you can create an array of structures
fl_board_info of suitable size (the size is known -
fl_supported_boards_number()), then pass it to
fl_supported_boards(fl_board_info_t *boards) and you will have it
filled with data.<br>
<br>
Regarding changes in Nico Hubers functions: I made temporary
comments for every change and marked it with LD_CHANGE_NOTE. Every
comment contains previous code and reason why it has been commented
out. <br>
<br>
Thanks in advance for your insights!<br>
<br>
Regards,<br>
Lukasz Dmitrowski<br>
<br>
---<br>
<br>
Signed-off-by: Łukasz Dmitrowski <a class="moz-txt-link-rfc2396E" href="mailto:lukasz.dmitrowski@gmail.com"><lukasz.dmitrowski@gmail.com></a><br>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<br>
Index: Makefile<br>
===================================================================<br>
--- Makefile (revision 1891)<br>
+++ Makefile (working copy)<br>
@@ -374,7 +374,7 @@<br>
###############################################################################<br>
# Library code.<br>
<br>
-LIB_OBJS = layout.o flashrom.o udelay.o programmer.o helpers.o<br>
+LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o
helpers.o cli_common.o print.o<br>
<br>
###############################################################################<br>
# Frontend related stuff.<br>
Index: cli_classic.c<br>
===================================================================<br>
--- cli_classic.c (revision 1891)<br>
+++ cli_classic.c (working copy)<br>
@@ -30,6 +30,7 @@<br>
#include "flash.h"<br>
#include "flashchips.h"<br>
#include "programmer.h"<br>
+#include "libflashrom.h"<br>
<br>
static void cli_classic_usage(const char *name)<br>
{<br>
@@ -135,6 +136,8 @@<br>
char *tempstr = NULL;<br>
char *pparam = NULL;<br>
<br>
+ fl_set_log_callback((fl_log_callback_t *)&fl_print_cb);<br>
+<br>
print_version();<br>
print_banner();<br>
<br>
Index: cli_output.c<br>
===================================================================<br>
--- cli_output.c (revision 1891)<br>
+++ cli_output.c (working copy)<br>
@@ -71,9 +71,8 @@<br>
#endif /* !STANDALONE */<br>
<br>
/* Please note that level is the verbosity, not the importance of
the message. */<br>
-int print(enum msglevel level, const char *fmt, ...)<br>
+int fl_print_cb(enum msglevel level, const char *fmt, va_list ap)<br>
{<br>
- va_list ap;<br>
int ret = 0;<br>
FILE *output_type = stdout;<br>
<br>
@@ -81,9 +80,7 @@<br>
output_type = stderr;<br>
<br>
if (level <= verbose_screen) {<br>
- va_start(ap, fmt);<br>
ret = vfprintf(output_type, fmt, ap);<br>
- va_end(ap);<br>
/* msg_*spew often happens inside chip accessors in
possibly<br>
* time-critical operations. Don't slow them down by
flushing. */<br>
if (level != MSG_SPEW)<br>
@@ -91,9 +88,7 @@<br>
}<br>
#ifndef STANDALONE<br>
if ((level <= verbose_logfile) && logfile) {<br>
- va_start(ap, fmt);<br>
ret = vfprintf(logfile, fmt, ap);<br>
- va_end(ap);<br>
if (level != MSG_SPEW)<br>
fflush(logfile);<br>
}<br>
Index: flash.h<br>
===================================================================<br>
--- flash.h (revision 1891)<br>
+++ flash.h (working copy)<br>
@@ -31,6 +31,7 @@<br>
#include <stdint.h><br>
#include <stddef.h><br>
#include <stdbool.h><br>
+#include <stdarg.h><br>
#if IS_WINDOWS<br>
#include <windows.h><br>
#undef min<br>
@@ -317,6 +318,7 @@<br>
MSG_DEBUG2 = 4,<br>
MSG_SPEW = 5,<br>
};<br>
+int fl_print_cb(enum msglevel level, const char *fmt, va_list ap);<br>
/* Let gcc and clang check for correct printf-style format strings.
*/<br>
int print(enum msglevel level, const char *fmt, ...)<br>
#ifdef __MINGW32__<br>
Index: libflashrom.c<br>
===================================================================<br>
--- libflashrom.c (revision 0)<br>
+++ libflashrom.c (working copy)<br>
@@ -0,0 +1,603 @@<br>
+/*<br>
+ * This file is part of the flashrom project.<br>
+ *<br>
+ * Copyright (C) 2012 secunet Security Networks AG<br>
+ * (Written by Nico Huber <a class="moz-txt-link-rfc2396E" href="mailto:nico.huber@secunet.com"><nico.huber@secunet.com></a> for
secunet)<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or
modify<br>
+ * it under the terms of the GNU General Public License as
published by<br>
+ * the Free Software Foundation; either version 2 of the License,
or<br>
+ * (at your option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU General Public
License<br>
+ * along with this program; if not, write to the Free Software<br>
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA<br>
+ */<br>
+/**<br>
+ * @mainpage<br>
+ *<br>
+ * Have a look at the Modules section for a function reference.<br>
+ */<br>
+<br>
+#include <stdlib.h><br>
+#include <string.h><br>
+#include <stdarg.h><br>
+<br>
+#include "flash.h"<br>
+#include "programmer.h"<br>
+#include "libflashrom.h"<br>
+<br>
+/**<br>
+ * @defgroup fl-general General<br>
+ * @{<br>
+ */<br>
+<br>
+/** Pointer to log callback function. */<br>
+static fl_log_callback_t *fl_log_callback = NULL;<br>
+<br>
+/**<br>
+ * @brief Initialize libflashrom.<br>
+ *<br>
+ * @param perform_selfcheck If not zero, perform a self check.<br>
+ * @return 0 on success<br>
+ */<br>
+int fl_init(const int perform_selfcheck)<br>
+{<br>
+ if (perform_selfcheck && selfcheck())<br>
+ return 1;<br>
+ myusec_calibrate_delay();<br>
+ return 0;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Shut down libflashrom.<br>
+ * @return 0 on success<br>
+ */<br>
+int fl_shutdown(void)<br>
+{<br>
+ return 0; /* TODO: nothing to do? */<br>
+}<br>
+<br>
+/* TODO: fl_set_loglevel()? do we need it?<br>
+ For now, let the user decide in his callback. */<br>
+<br>
+/**<br>
+ * @brief Set the log callback function.<br>
+ *<br>
+ * Set a callback function which will be invoked whenever
libflashrom wants<br>
+ * to output messages. This allows frontends to do whatever they
see fit with<br>
+ * such messages, e.g. write them to syslog, or to file, or print
them in a<br>
+ * GUI window, etc.<br>
+ *<br>
+ * @param log_callback Pointer to the new log callback function.<br>
+ */<br>
+void fl_set_log_callback(fl_log_callback_t *const log_callback)<br>
+{<br>
+ fl_log_callback = log_callback;<br>
+}<br>
+/** @private */<br>
+int print(const enum msglevel level, const char *const fmt, ...)<br>
+{<br>
+ if (fl_log_callback) {<br>
+ int ret;<br>
+ va_list args;<br>
+ va_start(args, fmt);<br>
+ ret = fl_log_callback(level, fmt, args);<br>
+ va_end(args);<br>
+ return ret;<br>
+ }<br>
+ return 0;<br>
+}<br>
+<br>
+/** @} */ /* end fl-general */<br>
+<br>
+<br>
+<br>
+/**<br>
+ * @defgroup fl-query Querying<br>
+ * @{<br>
+ */<br>
+<br>
+int fl_supported_programmers(const char **supported_programmers)<br>
+{<br>
+ int ret = 0;<br>
+ enum programmer p = 0;<br>
+<br>
+ if (supported_programmers != NULL) {<br>
+ for (; p < PROGRAMMER_INVALID; ++p)<br>
+ supported_programmers[p] =
programmer_table[p].name;<br>
+ } else {<br>
+ ret = 1;<br>
+ }<br>
+<br>
+ return ret;<br>
+}<br>
+<br>
+int fl_supported_programmers_number()<br>
+{<br>
+ return PROGRAMMER_INVALID;<br>
+}<br>
+<br>
+int fl_supported_flash_chips(fl_flashchip_info_t *fchips)<br>
+{<br>
+ int ret = 0;<br>
+ int i = 0;<br>
+<br>
+ if (fchips != NULL) {<br>
+ for (; i < flashchips_size; ++i) {<br>
+ fchips[i].vendor = flashchips[i].vendor;<br>
+ fchips[i].name = flashchips[i].name;<br>
+ fchips[i].tested.erase =
flashchips[i].tested.erase;<br>
+ fchips[i].tested.probe =
flashchips[i].tested.probe;<br>
+ fchips[i].tested.read =
flashchips[i].tested.read;<br>
+ fchips[i].tested.write =
flashchips[i].tested.write;<br>
+ fchips[i].total_size =
flashchips[i].total_size;<br>
+ }<br>
+ } else {<br>
+ ret = 1;<br>
+ }<br>
+<br>
+ return ret;<br>
+}<br>
+<br>
+int fl_supported_flash_chips_number()<br>
+{<br>
+ return flashchips_size;<br>
+}<br>
+<br>
+int fl_supported_boards(fl_board_info_t *boards)<br>
+{<br>
+ int ret = 0;<br>
+ const struct board_info *binfo = boards_known;<br>
+<br>
+ if (boards != NULL) {<br>
+ while (binfo->vendor != NULL) {<br>
+ boards->vendor = binfo->vendor;<br>
+ boards->name = binfo->name;<br>
+ boards->working = binfo->working;<br>
+ ++binfo;<br>
+ ++boards;<br>
+ }<br>
+ } else {<br>
+ ret = 1;<br>
+ }<br>
+<br>
+ return ret;<br>
+}<br>
+<br>
+int fl_supported_boards_number()<br>
+{<br>
+ int boards_number = 0;<br>
+ const struct board_info *binfo = boards_known;<br>
+<br>
+ while (binfo->vendor != NULL) {<br>
+ ++boards_number;<br>
+ ++binfo;<br>
+ }<br>
+<br>
+ return boards_number;<br>
+}<br>
+<br>
+int fl_supported_chipsets(fl_chipset_info_t *chipsets)<br>
+{<br>
+ int ret = 0;<br>
+ const struct penable *chipset = chipset_enables;<br>
+<br>
+ if (chipsets != NULL) {<br>
+ while (chipset->vendor_name != NULL) {<br>
+ chipsets->vendor =
chipset->vendor_name;<br>
+ chipsets->chipset =
chipset->device_name;<br>
+ chipsets->status = chipset->status;<br>
+ ++chipset;<br>
+ ++chipsets;<br>
+ }<br>
+ } else {<br>
+ return ret;<br>
+ }<br>
+<br>
+ return ret;<br>
+}<br>
+<br>
+int fl_supported_chipsets_number()<br>
+{<br>
+ int chipsets_number = 0;<br>
+ const struct penable *chipset = chipset_enables;<br>
+<br>
+ while (chipset->vendor_name != NULL) {<br>
+ ++chipsets_number;<br>
+ ++chipset;<br>
+ }<br>
+<br>
+ return chipsets_number;<br>
+}<br>
+<br>
+/** @} */ /* end fl-query */<br>
+<br>
+<br>
+<br>
+/**<br>
+ * @defgroup fl-prog Programmers<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Initialize the specified programmer.<br>
+ *<br>
+ * @param prog_name Name of the programmer to initialize.<br>
+ * @param prog_param Pointer to programmer specific parameters.<br>
+ * @return 0 on success<br>
+ */<br>
+int fl_programmer_init(const char *const prog_name, const char
*const prog_param)<br>
+{<br>
+ unsigned prog;<br>
+<br>
+ for (prog = 0; prog < PROGRAMMER_INVALID; prog++) {<br>
+ if (strcmp(prog_name, programmer_table[prog].name)
== 0)<br>
+ break;<br>
+ }<br>
+ if (prog >= PROGRAMMER_INVALID) {<br>
+ msg_ginfo("Error: Unknown programmer \"%s\". Valid
choices are:\n", prog_name);<br>
+ list_programmers_linebreak(0, 80, 0);<br>
+ return 1;<br>
+ }<br>
+ return programmer_init(prog, prog_param);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Shut down the initialized programmer.<br>
+ *<br>
+ * @return 0 on success<br>
+ */<br>
+int fl_programmer_shutdown(void)<br>
+{<br>
+ return programmer_shutdown();<br>
+}<br>
+<br>
+/* TODO: fl_programmer_capabilities()? */<br>
+<br>
+/** @} */ /* end fl-prog */<br>
+<br>
+<br>
+<br>
+/**<br>
+ * @defgroup fl-flash Flash chips<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Probe for a flash chip.<br>
+ *<br>
+ * Probes for a flash chip and returns a flash context, that can be
used<br>
+ * later with flash chip and @ref fl-ops "image operations", if
exactly one<br>
+ * matching chip is found.<br>
+ *<br>
+ * @param[out] flashctx Points to a pointer of type fl_flashctx_t
that will<br>
+ * be set if exactly one chip is found.
*flashctx has<br>
+ * to be freed by the caller with @ref
fl_flash_release.<br>
+ * @param[in] chip_name Name of a chip to probe for, or NULL to
probe for<br>
+ * all known chips.<br>
+ * @return 0 on success,<br>
+ * 3 if multiple chips were found,<br>
+ * 2 if no chip was found,<br>
+ * or 1 on any other error.<br>
+ */<br>
+int fl_flash_probe(fl_flashctx_t **const flashctx, const char
*const chip_name)<br>
+{<br>
+ int i, ret = 2;<br>
+ fl_flashctx_t second_flashctx = { 0, };<br>
+<br>
+ chip_to_probe = chip_name; /* chip_to_probe is global in
flashrom.c */<br>
+<br>
+ *flashctx = malloc(sizeof(**flashctx));<br>
+ if (!*flashctx)<br>
+ return 1;<br>
+ memset(*flashctx, 0, sizeof(**flashctx));<br>
+<br>
+ /* LD_CHANGE_NOTE for (i = 0; i <
registered_programmer_count; ++i) {<br>
+ *<br>
+ * Reason of change: registered_programmer_count does not
exist, I assume that a proper one is<br>
+ * now registered_master_count - I will check and confirm<br>
+ */<br>
+ for (i = 0; i < registered_master_count; ++i) {<br>
+ int flash_idx = -1;<br>
+ /* LD_CHANGE_NOTE if (!ret || (flash_idx =
probe_flash(®istered_programmers[i], 0, *flashctx, 0)) != -1)
{<br>
+ *<br>
+ * Reason of change: registered_programmers does
not exist, I assume that a proper one is<br>
+ * now registered_masters - I will check and
confirm<br>
+ */<br>
+ if (!ret || (flash_idx =
probe_flash(®istered_masters[i], 0, *flashctx, 0)) != -1) {<br>
+ ret = 0;<br>
+ /* We found one chip, now check that there
is no second match. */<br>
+ /* LD_CHANGE_NOTE if
(probe_flash(®istered_programmers[i], flash_idx + 1,
&second_flashctx, 0) != -1) {<br>
+ *<br>
+ * Reason of change: registered_programmers
does not exist, I assume that a proper one is<br>
+ * now registered_masters - I will check
and confirm<br>
+ *<br>
+ */<br>
+ if (probe_flash(®istered_masters[i],
flash_idx + 1, &second_flashctx, 0) != -1) {<br>
+ ret = 3;<br>
+ break;<br>
+ }<br>
+ }<br>
+ }<br>
+ if (ret) {<br>
+ free(*flashctx);<br>
+ *flashctx = NULL;<br>
+ }<br>
+ return ret;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Returns the size of the specified flash chip in bytes.<br>
+ *<br>
+ * @param flashctx The queried flash context.<br>
+ * @return Size of flash chip in bytes.<br>
+ */<br>
+size_t fl_flash_getsize(const fl_flashctx_t *const flashctx)<br>
+{<br>
+ return flashctx->chip->total_size << 10;<br>
+}<br>
+<br>
+/** @private */<br>
+int erase_and_write_flash(struct flashctx *flash, uint8_t
*oldcontents, uint8_t *newcontents);<br>
+/** @private */<br>
+/* LD_CHANGE_NOTE void emergency_help_message(void);<br>
+ *<br>
+ * Reason of change: This has been commented out as
emergency_help_message is static<br>
+ */<br>
+/**<br>
+ * @brief Erase the specified ROM chip.<br>
+ *<br>
+ * @param flashctx The context of the flash chip to erase.<br>
+ * @return 0 on success.<br>
+ */<br>
+int fl_flash_erase(fl_flashctx_t *const flashctx)<br>
+{<br>
+ const size_t flash_size = flashctx->chip->total_size
* 1024;<br>
+<br>
+ int ret = 0;<br>
+<br>
+ uint8_t *const newcontents = malloc(flash_size);<br>
+ if (!newcontents) {<br>
+ msg_gerr("Out of memory!\n");<br>
+ return 1;<br>
+ }<br>
+ uint8_t *const oldcontents = malloc(flash_size);<br>
+ if (!oldcontents) {<br>
+ msg_gerr("Out of memory!\n");<br>
+ free(newcontents);<br>
+ return 1;<br>
+ }<br>
+<br>
+ if (flashctx->chip->unlock)<br>
+ flashctx->chip->unlock(flashctx);<br>
+<br>
+ /* Assume worst case for old contents: All bits are 0. */<br>
+ memset(oldcontents, 0x00, flash_size);<br>
+ /* Assume best case for new contents: All bits should be 1.
*/<br>
+ memset(newcontents, 0xff, flash_size);<br>
+ /* Side effect of the assumptions above: Default write
action is erase<br>
+ * because newcontents looks like a completely erased chip,
and<br>
+ * oldcontents being completely 0x00 means we have to erase
everything<br>
+ * before we can write.<br>
+ */<br>
+<br>
+ if (erase_and_write_flash(flashctx, oldcontents,
newcontents)) {<br>
+ /* FIXME: Do we really want the scary warning if
erase failed?<br>
+ * After all, after erase the chip is either blank
or partially<br>
+ * blank or it has the old contents. A blank chip
won't boot,<br>
+ * so if the user wanted erase and reboots
afterwards, the user<br>
+ * knows very well that booting won't work.<br>
+ */<br>
+ /* LD_CHANGE_NOTE emergency_help_message();<br>
+ *<br>
+ * Reason of change: This function is static<br>
+ */<br>
+ ret = 1;<br>
+ }<br>
+<br>
+ free(oldcontents);<br>
+ free(newcontents);<br>
+ return ret;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Free a flash context.<br>
+ *<br>
+ * @param flashctx Flash context to free.<br>
+ */<br>
+void fl_flash_release(fl_flashctx_t *const flashctx)<br>
+{<br>
+ free(flashctx);<br>
+}<br>
+<br>
+/** @} */ /* end fl-flash */<br>
+<br>
+<br>
+<br>
+/**<br>
+ * @defgroup fl-ops Operations<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Read the current image from the specified ROM chip.<br>
+ *<br>
+ * @param flashctx The context of the flash chip.<br>
+ * @param buffer Target buffer to write image to.<br>
+ * @param buffer_len Size of target buffer in bytes.<br>
+ * @return 0 on success,<br>
+ * 2 if buffer_len is to short for the flash chip's
contents,<br>
+ * or 1 on any other failure.<br>
+ */<br>
+int fl_image_read(fl_flashctx_t *const flashctx, void *const
buffer, const size_t buffer_len)<br>
+{<br>
+ const size_t flash_size = flashctx->chip->total_size
* 1024;<br>
+<br>
+ int ret = 0;<br>
+<br>
+ if (flashctx->chip->unlock)<br>
+ flashctx->chip->unlock(flashctx);<br>
+<br>
+ msg_cinfo("Reading flash... ");<br>
+ if (flash_size > buffer_len) {<br>
+ msg_cerr("Buffer to short for this flash chip (%u
< %u).\n",<br>
+ (unsigned int)buffer_len, (unsigned
int)flash_size);<br>
+ ret = 2;<br>
+ goto _out;<br>
+ }<br>
+ if (!flashctx->chip->read) {<br>
+ msg_cerr("No read function available for this flash
chip.\n");<br>
+ ret = 1;<br>
+ goto _out;<br>
+ }<br>
+ if (flashctx->chip->read(flashctx, buffer, 0,
flash_size)) {<br>
+ msg_cerr("Read operation failed!\n");<br>
+ ret = 1;<br>
+ goto _out;<br>
+ }<br>
+_out:<br>
+ msg_cinfo("%s.\n", ret ? "FAILED" : "done");<br>
+ return ret;<br>
+}<br>
+<br>
+/** @private */<br>
+/* LD_CHANGE_NOTE void nonfatal_help_message(void);<br>
+ *<br>
+ * Reason of change: This function is static<br>
+ */<br>
+/**<br>
+ * @brief Write the specified image to the ROM chip.<br>
+ *<br>
+ * @param flashctx The context of the flash chip.<br>
+ * @param buffer Source buffer to read image from.<br>
+ * @param buffer_len Size of source buffer in bytes.<br>
+ * @return 0 on success,<br>
+ * 4 if buffer_len doesn't match the size of the flash
chip,<br>
+ * 3 if write was tried, but nothing has changed,<br>
+ * 2 if write was tried, but flash contents changed,<br>
+ * or 1 on any other failure.<br>
+ */<br>
+int fl_image_write(fl_flashctx_t *const flashctx, void *const
buffer, const size_t buffer_len)<br>
+{<br>
+ const size_t flash_size = flashctx->chip->total_size
* 1024;<br>
+<br>
+ int ret = 0;<br>
+<br>
+ if (buffer_len != flash_size) {<br>
+ msg_cerr("Buffer size doesn't match size of flash
chip (%u != %u)\n.",<br>
+ (unsigned int)buffer_len, (unsigned
int)flash_size);<br>
+ return 4;<br>
+ }<br>
+<br>
+ uint8_t *const newcontents = buffer;<br>
+ uint8_t *const oldcontents = malloc(flash_size);<br>
+ if (!oldcontents) {<br>
+ msg_gerr("Out of memory!\n");<br>
+ return 1;<br>
+ }<br>
+ if (fl_image_read(flashctx, oldcontents, flash_size)) {<br>
+ ret = 1;<br>
+ goto _free_out;<br>
+ }<br>
+<br>
+ /* LD_CHANGE_NOTE handle_romentries(flashctx, oldcontents,
newcontents);<br>
+ *<br>
+ * Reason of change: This function does not exist. There is
a need to investigate what was<br>
+ * its purpose and how it can be replaced.<br>
+ */<br>
+<br>
+ if (erase_and_write_flash(flashctx, oldcontents,
newcontents)) {<br>
+ msg_cerr("Uh oh. Erase/write failed. Checking if
anything changed.\n");<br>
+ if (!flashctx->chip->read(flashctx,
newcontents, 0, flash_size)) {<br>
+ if (!memcmp(oldcontents, newcontents,
flash_size)) {<br>
+ msg_cinfo("Good. It seems nothing
was changed.\n");<br>
+ /* LD_CHANGE_NOTE
nonfatal_help_message();<br>
+ *<br>
+ * Reason of change: This function
is static<br>
+ */<br>
+ ret = 3;<br>
+ goto _free_out;<br>
+ }<br>
+ }<br>
+ /* LD_CHANGE_NOTE emergency_help_message();<br>
+ *<br>
+ * Reason of change: This function is static<br>
+ */<br>
+ ret = 2;<br>
+ goto _free_out;<br>
+ }<br>
+<br>
+_free_out:<br>
+ free(oldcontents);<br>
+ return ret;<br>
+}<br>
+<br>
+/** @private */<br>
+/* LD_CHANGE_NOTE int compare_range(const uint8_t *wantbuf, const
uint8_t *havebuf, unsigned int start, unsigned int len);<br>
+ *<br>
+ * Reason of change: This function is static<br>
+ */<br>
+/**<br>
+ * @brief Verify the ROM chip's contents with the specified image.<br>
+ *<br>
+ * @param flashctx The context of the flash chip.<br>
+ * @param buffer Source buffer to verify with.<br>
+ * @param buffer_len Size of source buffer in bytes.<br>
+ * @return 0 on success,<br>
+ * 2 if buffer_len doesn't match the size of the flash
chip,<br>
+ * or 1 on any other failure.<br>
+ */<br>
+int fl_image_verify(fl_flashctx_t *const flashctx, void *const
buffer, const size_t buffer_len)<br>
+{<br>
+ const size_t flash_size = flashctx->chip->total_size
* 1024;<br>
+<br>
+ int ret = 0;<br>
+<br>
+ if (buffer_len != flash_size) {<br>
+ msg_cerr("Buffer size doesn't match size of flash
chip (%u != %u)\n.",<br>
+ (unsigned int)buffer_len, (unsigned
int)flash_size);<br>
+ return 2;<br>
+ }<br>
+<br>
+ /* LD_CHANGE_NOTE uint8_t *const newcontents = buffer; -
used only in handle_romentries() function<br>
+ *<br>
+ * Reason of change: This pointer is used only in
handle_romentries function, which has been<br>
+ * commented out<br>
+ */<br>
+ uint8_t *const oldcontents = malloc(flash_size);<br>
+ if (!oldcontents) {<br>
+ msg_gerr("Out of memory!\n");<br>
+ return 1;<br>
+ }<br>
+ if (fl_image_read(flashctx, oldcontents, flash_size)) {<br>
+ ret = 1;<br>
+ goto _free_out;<br>
+ }<br>
+<br>
+ /* LD_CHANGE_NOTE handle_romentries(flashctx, oldcontents,
newcontents);<br>
+ *<br>
+ * Reason of change: This function does not exist<br>
+ */<br>
+<br>
+ msg_cinfo("Verifying flash... ");<br>
+<br>
+ /* LD_CHANGE_NOTE ret = compare_range(newcontents,
oldcontents, 0, flash_size);<br>
+ *<br>
+ * Reason of change: This function is static. For now
replaced with ret = 1 as ret must be used<br>
+ */<br>
+ ret = 1;<br>
+ if (!ret)<br>
+ msg_cinfo("VERIFIED.\n");<br>
+<br>
+_free_out:<br>
+ free(oldcontents);<br>
+ return ret;<br>
+}<br>
+<br>
+/** @} */ /* end fl-ops */<br>
Index: libflashrom.h<br>
===================================================================<br>
--- libflashrom.h (revision 0)<br>
+++ libflashrom.h (working copy)<br>
@@ -0,0 +1,97 @@<br>
+/*<br>
+ * This file is part of the flashrom project.<br>
+ *<br>
+ * Copyright (C) 2012 secunet Security Networks AG<br>
+ * (Written by Nico Huber <a class="moz-txt-link-rfc2396E" href="mailto:nico.huber@secunet.com"><nico.huber@secunet.com></a> for
secunet)<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or
modify<br>
+ * it under the terms of the GNU General Public License as
published by<br>
+ * the Free Software Foundation; either version 2 of the License,
or<br>
+ * (at your option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU General Public
License<br>
+ * along with this program; if not, write to the Free Software<br>
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA<br>
+ */<br>
+<br>
+#ifndef __LIBFLASHROM_H__<br>
+#define __LIBFLASHROM_H__ 1<br>
+<br>
+#include <stdarg.h><br>
+<br>
+int fl_init(int perform_selfcheck);<br>
+int fl_shutdown(void);<br>
+/** @ingroup fl-general */<br>
+typedef enum { /* This has to match enum msglevel. */<br>
+ FL_MSG_ERROR = 0,<br>
+ FL_MSG_INFO = 1,<br>
+ FL_MSG_DEBUG = 2,<br>
+ FL_MSG_DEBUG2 = 3,<br>
+ FL_MSG_SPEW = 4,<br>
+} fl_log_level_t;<br>
+/** @ingroup fl-general */<br>
+typedef int(fl_log_callback_t)(fl_log_level_t, const char *format,
va_list);<br>
+void fl_set_log_callback(fl_log_callback_t *);<br>
+<br>
+typedef enum {<br>
+ FL_TESTED_OK = 0,<br>
+ FL_TESTED_NT = 1,<br>
+ FL_TESTED_BAD = 2,<br>
+ FL_TESTED_DEP = 3,<br>
+ FL_TESTED_NA = 4,<br>
+} fl_test_state;<br>
+<br>
+typedef struct {<br>
+ const char *vendor;<br>
+ const char *name;<br>
+ unsigned int total_size;<br>
+<br>
+ struct fl_tested {<br>
+ fl_test_state probe;<br>
+ fl_test_state read;<br>
+ fl_test_state erase;<br>
+ fl_test_state write;<br>
+ } tested;<br>
+} fl_flashchip_info_t;<br>
+<br>
+typedef struct {<br>
+ const char *vendor;<br>
+ const char *name;<br>
+ fl_test_state working;<br>
+} fl_board_info_t;<br>
+<br>
+typedef struct {<br>
+ const char *vendor;<br>
+ const char *chipset;<br>
+ fl_test_state status;<br>
+} fl_chipset_info_t;<br>
+<br>
+int fl_supported_programmers(const char **supported_programmers);<br>
+int fl_supported_flash_chips(fl_flashchip_info_t *fchips);<br>
+int fl_supported_boards(fl_board_info_t *boards);<br>
+int fl_supported_chipsets(fl_chipset_info_t *chipsets);<br>
+int fl_supported_programmers_number();<br>
+int fl_supported_flash_chips_number();<br>
+int fl_supported_boards_number();<br>
+int fl_supported_chipsets_number();<br>
+<br>
+int fl_programmer_init(const char *prog_name, const char
*prog_params);<br>
+int fl_programmer_shutdown(void);<br>
+<br>
+struct flashctx;<br>
+typedef struct flashctx fl_flashctx_t;<br>
+int fl_flash_probe(fl_flashctx_t **, const char *chip_name);<br>
+size_t fl_flash_getsize(const fl_flashctx_t *);<br>
+int fl_flash_erase(fl_flashctx_t *);<br>
+void fl_flash_release(fl_flashctx_t *);<br>
+<br>
+int fl_image_read(fl_flashctx_t *, void *buffer, size_t
buffer_len);<br>
+int fl_image_write(fl_flashctx_t *, void *buffer, size_t
buffer_len);<br>
+int fl_image_verify(fl_flashctx_t *, void *buffer, size_t
buffer_len);<br>
+<br>
+#endif /* !__LIBFLASHROM_H__ */<br>
</body>
</html>