[PATCH V2 3/4] lib/flash: Add support for platform versions
Cyril Bur
cyril.bur at au1.ibm.com
Mon Jan 18 09:11:47 AEDT 2016
On Fri, 15 Jan 2016 15:14:56 +1100
Sam Mendoza-Jonas <sam at mendozajonas.com> wrote:
> From: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
>
> Add basic libflash support to read the VERSION partition on BMC
> machines. This adds a dependency on the libflash shared library from
> Skiboot.
> The MTD partition is accessed through the libflash helper functions.
> Once read into a buffer, the VERSION partition is a simple list of
> newline-terminated version strings. Some BMC platforms may have two
> 'sides' to flash - these are interpreted as the "current" and "other"
> sides depending on which one the current Petitboot is running from.
>
> Signed-off-by: Sam Mendoza-Jonas <sam at mendozajonas.com>
Reviewed-by: Cyril Bur <cyrilbur at gmail.com>
> ---
> V2 Changes:
> Use of ffs_next_side() to check for redundant sections of flash.
> Update to handle 'keep_alive' changes to arch_flash_init().
>
> lib/Makefile.am | 19 ++++-
> lib/flash/config.h | 19 +++++
> lib/flash/flash.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/flash/flash.h | 23 ++++++
> 4 files changed, 273 insertions(+), 1 deletion(-)
> create mode 100644 lib/flash/config.h
> create mode 100644 lib/flash/flash.c
> create mode 100644 lib/flash/flash.h
>
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index a2421a5..a3ae943 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -48,4 +48,21 @@ lib_libpbcore_la_SOURCES = \
> lib/url/url.c \
> lib/url/url.h \
> lib/util/util.c \
> - lib/util/util.h
> + lib/util/util.h \
> + lib/flash/config.h \
> + lib/flash/flash.h
> +
> +if ENABLE_MTD
> +lib_libpbcore_la_SOURCES += \
> + lib/flash/flash.c
> +
> +lib_libpbcore_la_CPPFLAGS += \
> + $(AM_CPPFLAGS)
> +
> +lib_libpbcore_la_LDFLAGS = \
> + $(AM_LDFLAGS) \
> + -l:libflash.so
> +
> +lib_libpbcore_la_SOURCES += \
> + lib/flash/flash.c
> +endif
> diff --git a/lib/flash/config.h b/lib/flash/config.h
> new file mode 100644
> index 0000000..a132a01
> --- /dev/null
> +++ b/lib/flash/config.h
> @@ -0,0 +1,19 @@
> +/* For CCAN */
> +
> +#include <endian.h>
> +#include <byteswap.h>
> +
> +#define HAVE_TYPEOF 1
> +#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
> +
> +
> +#if __BYTE_ORDER == __LITTLE_ENDIAN
> +#define HAVE_BIG_ENDIAN 0
> +#define HAVE_LITTLE_ENDIAN 1
> +#else
> +#define HAVE_BIG_ENDIAN 1
> +#define HAVE_LITTLE_ENDIAN 0
> +#endif
> +
> +#define HAVE_BYTESWAP_H 1
> +#define HAVE_BSWAP_64 1
> diff --git a/lib/flash/flash.c b/lib/flash/flash.c
> new file mode 100644
> index 0000000..7ad80b1
> --- /dev/null
> +++ b/lib/flash/flash.c
> @@ -0,0 +1,213 @@
> +/*
> + * Copyright (C) 2015 IBM Corporation
> + *
> + * 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; version 2 of the License.
> + *
> + * 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.
> + *
> + */
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <getopt.h>
> +#include <errno.h>
> +#include <asm/byteorder.h>
> +
> +#include <log/log.h>
> +#include <talloc/talloc.h>
> +#include <flash/flash.h>
> +#include <ccan/endian/endian.h>
> +
> +#include <libflash/arch_flash.h>
> +#include <libflash/blocklevel.h>
> +#include <libflash/libflash.h>
> +#include <libflash/libffs.h>
> +#include <libflash/file.h>
> +#include <libflash/ecc.h>
> +
> +
> +struct flash_info {
> + /* Device information */
> + struct blocklevel_device *bl;
> + struct ffs_handle *ffs;
> + uint32_t size; /* raw size of partition */
> + const char *path;
> + bool ecc;
> + uint32_t erase_granule;
> +
> + /* Partition information */
> + uint32_t attr_part_idx;
> + uint32_t attr_data_pos;
> + uint32_t attr_data_len; /* Includes ECC bytes */
> +
> + /* 'Other Side' info if present */
> + struct flash_info *other_side;
> +
> +};
> +
> +static int partition_info(struct flash_info *info, const char *partition)
> +{
> + int rc;
> +
> + rc = ffs_lookup_part(info->ffs, partition, &info->attr_part_idx);
> + if (rc) {
> + pb_log("Failed to find %s partition\n", partition);
> + return rc;
> + }
> +
> + return ffs_part_info(info->ffs, info->attr_part_idx, NULL,
> + &info->attr_data_pos, &info->attr_data_len,
> + NULL, &info->ecc);
> +}
> +
> +static struct flash_info *flash_setup_buffer(void *ctx, const char *partition)
> +{
> + struct flash_info *info;
> + struct ffs_handle *tmp = NULL;
> + int rc = 0;
> +
> + if (!partition)
> + return NULL;
> +
> + info = talloc_zero(ctx, struct flash_info);
> + if (!info)
> + return NULL;
> +
> + rc = arch_flash_init(&info->bl, NULL, true);
> + if (rc) {
> + pb_log("Failed to init mtd device\n");
> + return NULL;
> + }
> +
> + rc = blocklevel_get_info(info->bl, &info->path, &info->size,
> + &info->erase_granule);
> + if (rc) {
> + pb_log("Failed to retrieve blocklevel info\n");
> + return NULL;
> + }
> +
> + rc = ffs_init(0, info->size, info->bl, &info->ffs, 1);
> + if (rc) {
> + pb_log("%s: Failed to init ffs\n", __func__);
> + goto out;
> + }
> +
> + rc = partition_info(info, partition);
> + if (rc) {
> + pb_log("Failed to retrieve partition info\n");
> + goto out;
> + }
> +
> + /* Check if there is a second flash side. If there is not, or
> + * we fail to recognise it, ignore it and continue */
> + ffs_next_side(info->ffs, &tmp, info->ecc);
> + if (tmp && ffs_equal(info->ffs, tmp) == false) {
> + pb_debug("Other side present on MTD device\n");
> + info->other_side = talloc_zero(info, struct flash_info);
> + info->other_side->ffs = tmp;
> + info->other_side->bl = info->bl;
> + info->other_side->size = info->size;
> + info->other_side->path = info->path;
> + info->other_side->ecc = info->ecc;
> + info->other_side->erase_granule = info->erase_granule;
> + rc = partition_info(info->other_side, partition);
> + if (rc)
> + pb_log("Failed to retrieve partition info "
> + "for other side - ignoring\n");
> + }
> +
> + pb_debug("%s Details\n", partition);
> + pb_debug("\tName\t\t%s\n", info->path);
> + pb_debug("\tFlash Size\t%u\n", info->size);
> + pb_debug("\tGranule\t\t%u\n", info->erase_granule);
> + pb_debug("\tECC\t\t%s\n", info->ecc ? "Protected" : "Unprotected");
> + pb_debug("\tCurrent Side info:\n");
> + pb_debug("\tIndex\t\t%u\n", info->attr_part_idx);
> + pb_debug("\tOffset\t\t%u\n", info->attr_data_pos);
> + pb_debug("\tPart. Size\t%u\n", info->attr_data_len);
> + if (info->other_side) {
> + pb_debug("\tOther Side info:\n");
> + pb_debug("\tIndex\t\t%u\n", info->other_side->attr_part_idx);
> + pb_debug("\tOffset\t\t%u\n", info->other_side->attr_data_pos);
> + pb_debug("\tPart. Size\t%u\n", info->other_side->attr_data_len);
> + }
> +
> + return info;
> +out:
> + arch_flash_close(info->bl, NULL);
> + talloc_free(info);
> + return NULL;
> +}
> +
> +int flash_parse_version(void *ctx, char ***versions, bool current)
> +{
> + char *saveptr, *tok, **tmp, *buffer;
> + const char *delim = "\n";
> + struct flash_info *info, *cur_info;
> + uint32_t len;
> + int rc, n = 0;
> +
> + saveptr = tok = NULL;
> + tmp = NULL;
> +
> + info = flash_setup_buffer(ctx, "VERSION");
> + if (!info)
> + return 0;
> +
> + if (current && !info->other_side)
> + return 0;
> +
> + cur_info = current ? info->other_side : info;
> +
> + len = cur_info->attr_data_len - ecc_size(cur_info->attr_data_len);
> + buffer = talloc_array(cur_info, char, len);
> + if (!buffer) {
> + pb_log("%s: Failed to init buffer!\n", __func__);
> + goto out;
> + }
> +
> + rc = blocklevel_read(cur_info->bl, cur_info->attr_data_pos,
> + buffer, len);
> + if (rc) {
> + pb_log("Failed to read VERSION partition\n");
> + goto out;
> + }
> +
> + /* open-power-platform */
> + tok = strtok_r(buffer, delim, &saveptr);
> + if (tok) {
> + tmp = talloc_realloc(ctx, tmp, char *, n + 1);
> + if (!tmp) {
> + pb_log("%s: Failed to allocate memory\n", __func__);
> + goto out;
> + }
> + tmp[n++] = talloc_strdup(ctx, tok);
> + }
> +
> + tok = strtok_r(NULL, delim, &saveptr);
> + while (tok) {
> + /* Ignore leading tab from subsequent lines */
> + tmp = talloc_realloc(ctx, tmp, char *, n + 1);
> + if (!tmp) {
> + pb_log("%s: Failed to reallocate memory\n", __func__);
> + n = 0;
> + goto out;
> + }
> + tmp[n++] = talloc_strdup(ctx, tok + 1);
> + tok = strtok_r(NULL, delim, &saveptr);
> + }
> +
> +out:
> + pb_debug("%d version strings read from %s side\n",
> + n, current ? "current" : "other");
> + arch_flash_close(info->bl, NULL);
> + talloc_free(info);
> + *versions = tmp;
> + return n;
> +}
> diff --git a/lib/flash/flash.h b/lib/flash/flash.h
> new file mode 100644
> index 0000000..d163d31
> --- /dev/null
> +++ b/lib/flash/flash.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright (C) 2015 IBM Corporation
> + *
> + * 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; version 2 of the License.
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef FLASH_H
> +#define FLASH_H
> +
> +#include <flash/config.h>
> +#include <types/types.h>
> +
> +int flash_parse_version(void *ctx, char ***versions, bool current);
> +
> +#endif /* FLASH_H */
More information about the Petitboot
mailing list