<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(&registered_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(&registered_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(&registered_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(&registered_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>