[{"id":1759042,"web_url":"http://patchwork.ozlabs.org/comment/1759042/","msgid":"<1503985073.8990.15.camel@gmail.com>","list_archive_url":null,"date":"2017-08-29T05:37:53","subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","submitter":{"id":64457,"url":"http://patchwork.ozlabs.org/api/people/64457/","name":"Cyril Bur","email":"cyrilbur@gmail.com"},"content":"On Mon, 2017-08-28 at 21:19 -0700, William A. Kennington III wrote:\n> This changes refactors all of the output variables from flash_get_info\n> into a new output struct. Callers now supply the info struct, and always\n> get all of the info with each call. There are never any allocations done\n> by this function so it shouldn't be much slower to always populate all\n> of the information.\n> \n\nHi William,\n\nAs nice as this refactor is (thanks for the effort!), unfortunately\nwe're a bit stuck with the interface as is, both openbmc and petitboot\nprojects link against a dynamic libflash.\n\nIronically I'm about to send a series which which does rework the\nlibffs api a bit - although I'm quite sure only external/ffspart\nactually uses what I've changed. blocklevel_get_info() though is pretty\ncore and changing that won't work.\n\nPerhaps you've prompted a discussion that now might be a good time to\ndo a significant rewrite of libflash/libffs which are now being used\nfor a completely different purpose for which they were first written,\nhopefully Stewart will weigh in.\n\n\nCyril\n\n> Signed-off-by: William A. Kennington III <wak@google.com>\n> ---\n>  core/flash.c                           | 15 +++++------\n>  external/common/arch_flash_arm.c       |  6 ++---\n>  external/common/arch_flash_common.c    |  6 ++---\n>  external/gard/gard.c                   | 10 +++----\n>  external/opal-prd/pnor.c               | 12 ++++-----\n>  external/opal-prd/pnor.h               |  3 +--\n>  external/opal-prd/test/test_pnor_ops.c |  7 +++--\n>  external/pflash/pflash.c               | 46 ++++++++++++++++----------------\n>  libflash/blocklevel.c                  | 35 ++++++++++++-------------\n>  libflash/blocklevel.h                  | 16 +++++++++---\n>  libflash/file.c                        | 48 ++++++++++++++--------------------\n>  libflash/libffs.c                      |  8 +++---\n>  libflash/libflash.c                    | 15 +++++------\n>  libflash/mbox-flash.c                  | 19 ++++----------\n>  libflash/test/test-flash.c             |  6 ++---\n>  platforms/mambo/mambo.c                | 15 ++++-------\n>  16 files changed, 125 insertions(+), 142 deletions(-)\n> \n> diff --git a/core/flash.c b/core/flash.c\n> index 53e6eba08..35a0c4c32 100644\n> --- a/core/flash.c\n> +++ b/core/flash.c\n> @@ -254,21 +254,20 @@ static int num_flashes(void)\n>  \n>  int flash_register(struct blocklevel_device *bl)\n>  {\n> -\tuint64_t size;\n> -\tuint32_t block_size;\n> +\tstruct blocklevel_info bl_info;\n>  \tstruct ffs_handle *ffs;\n>  \tstruct dt_node *node;\n>  \tstruct flash *flash;\n> -\tconst char *name;\n>  \tint rc;\n>  \n> -\trc = blocklevel_get_info(bl, &name, &size, &block_size);\n> +\trc = blocklevel_get_info(bl, &bl_info);\n>  \tif (rc)\n>  \t\treturn rc;\n>  \n>  \tprlog(PR_INFO, \"FLASH: registering flash device %s \"\n>  \t\t\t\"(size 0x%llx, blocksize 0x%x)\\n\",\n> -\t\t\tname ?: \"(unnamed)\", size, block_size);\n> +\t\t\tbl_info.name ? bl_info.name : \"(unnamed)\", bl_info.size,\n> +\t\t\tbl_info.erase_granule);\n>  \n>  \tlock(&flash_lock);\n>  \n> @@ -281,8 +280,8 @@ int flash_register(struct blocklevel_device *bl)\n>  \n>  \tflash->busy = false;\n>  \tflash->bl = bl;\n> -\tflash->size = size;\n> -\tflash->block_size = block_size;\n> +\tflash->size = bl_info.size;\n> +\tflash->block_size = bl_info.erase_granule;\n>  \tflash->id = num_flashes();\n>  \n>  \tlist_add(&flashes, &flash->list);\n> @@ -302,7 +301,7 @@ int flash_register(struct blocklevel_device *bl)\n>  \n>  \tnode = flash_add_dt_node(flash, flash->id);\n>  \n> -\tsetup_system_flash(flash, node, name, ffs);\n> +\tsetup_system_flash(flash, node, bl_info.name, ffs);\n>  \n>  \tif (ffs)\n>  \t\tffs_close(ffs);\n> diff --git a/external/common/arch_flash_arm.c b/external/common/arch_flash_arm.c\n> index 3cdd41ded..ac43de0c4 100644\n> --- a/external/common/arch_flash_arm.c\n> +++ b/external/common/arch_flash_arm.c\n> @@ -303,13 +303,13 @@ int arch_flash_erase_chip(struct blocklevel_device *bl)\n>  \tif (!arch_data.flash_chip) {\n>  \t\t/* Just assume its a regular erase */\n>  \t\tint rc;\n> -\t\tuint64_t total_size;\n> +\t\tstruct blocklevel_info bl_info;\n>  \n> -\t\trc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> +\t\trc = blocklevel_get_info(bl, &bl_info);\n>  \t\tif (rc)\n>  \t\t\treturn rc;\n>  \n> -\t\treturn blocklevel_erase(bl, 0, total_size);\n> +\t\treturn blocklevel_erase(bl, 0, bl_info.size);\n>  \t}\n>  \n>  \treturn flash_erase_chip(arch_data.flash_chip);\n> diff --git a/external/common/arch_flash_common.c b/external/common/arch_flash_common.c\n> index 6bce7e1ba..41239662a 100644\n> --- a/external/common/arch_flash_common.c\n> +++ b/external/common/arch_flash_common.c\n> @@ -31,13 +31,13 @@\n>  int __attribute__((weak)) arch_flash_erase_chip(struct blocklevel_device *bl)\n>  {\n>  \tint rc;\n> -\tuint64_t total_size;\n> +\tstruct blocklevel_info bl_info;\n>  \n> -\trc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> +\trc = blocklevel_get_info(bl, &bl_info);\n>  \tif (rc)\n>  \t\treturn rc;\n>  \n> -\treturn blocklevel_erase(bl, 0, total_size);\n> +\treturn blocklevel_erase(bl, 0, bl_info.size);\n>  }\n>  \n>  int __attribute__((weak,const)) arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b)\n> diff --git a/external/gard/gard.c b/external/gard/gard.c\n> index c5cb93b88..3946cad6f 100644\n> --- a/external/gard/gard.c\n> +++ b/external/gard/gard.c\n> @@ -596,7 +596,7 @@ int main(int argc, char **argv)\n>  \tconst char *action, *progname;\n>  \tchar *filename = NULL;\n>  \tstruct gard_ctx _ctx, *ctx;\n> -\tuint64_t bl_size;\n> +\tstruct blocklevel_info bl_info;\n>  \tint rc, i = 0;\n>  \tbool part = 0;\n>  \tbool ecc = 0;\n> @@ -665,17 +665,17 @@ int main(int argc, char **argv)\n>  \t\tgoto out_free;\n>  \t}\n>  \n> -\trc = blocklevel_get_info(ctx->bl, NULL, &bl_size, NULL);\n> +\trc = blocklevel_get_info(ctx->bl, &bl_info);\n>  \tif (rc)\n>  \t\tgoto out;\n>  \n> -\tif (bl_size > UINT_MAX) {\n> +\tif (bl_info.size > UINT_MAX) {\n>  \t\tfprintf(stderr, \"MTD device bigger than %i: size: %\" PRIu64 \"\\n\",\n> -\t\t\tUINT_MAX, bl_size);\n> +\t\t\tUINT_MAX, bl_info.size);\n>  \t\trc = EXIT_FAILURE;\n>  \t\tgoto out;\n>  \t}\n> -\tctx->f_size = bl_size;\n> +\tctx->f_size = bl_info.size;\n>  \n>  \tif (!part) {\n>  \t\trc = ffs_init(0, ctx->f_size, ctx->bl, &ctx->ffs, 1);\n> diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c\n> index c032421d1..afb6ccd1f 100644\n> --- a/external/opal-prd/pnor.c\n> +++ b/external/opal-prd/pnor.c\n> @@ -64,13 +64,13 @@ int pnor_init(struct pnor *pnor)\n>  \t\treturn -1;\n>  \t}\n>  \n> -\trc = blocklevel_get_info(pnor->bl, NULL, &(pnor->size), &(pnor->erasesize));\n> +\trc = blocklevel_get_info(pnor->bl, &pnor->bl_info);\n>  \tif (rc) {\n>  \t\tpr_log(LOG_ERR, \"PNOR: blocklevel_get_info() failed. Can't use PNOR\");\n>  \t\tgoto out;\n>  \t}\n>  \n> -\trc = ffs_init(0, pnor->size, pnor->bl, &pnor->ffsh, 0);\n> +\trc = ffs_init(0, pnor->bl_info.size, pnor->bl, &pnor->ffsh, 0);\n>  \tif (rc) {\n>  \t\tpr_log(LOG_ERR, \"PNOR: Failed to open pnor partition table\");\n>  \t\tgoto out;\n> @@ -121,8 +121,8 @@ static int mtd_write(struct pnor *pnor, void *data, uint64_t offset,\n>  {\n>  \tint rc;\n>  \n> -\tif (len > pnor->size || offset > pnor->size ||\n> -\t    len + offset > pnor->size)\n> +\tif (len > pnor->bl_info.size || offset > pnor->bl_info.size ||\n> +\t    len + offset > pnor->bl_info.size)\n>  \t\treturn -ERANGE;\n>  \n>  \trc = blocklevel_smart_write(pnor->bl, offset, data, len);\n> @@ -137,8 +137,8 @@ static int mtd_read(struct pnor *pnor, void *data, uint64_t offset,\n>  {\n>  \tint rc;\n>  \n> -\tif (len > pnor->size || offset > pnor->size ||\n> -\t    len + offset > pnor->size)\n> +\tif (len > pnor->bl_info.size || offset > pnor->bl_info.size ||\n> +\t    len + offset > pnor->bl_info.size)\n>  \t\treturn -ERANGE;\n>  \n>  \trc = blocklevel_read(pnor->bl, offset, data, len);\n> diff --git a/external/opal-prd/pnor.h b/external/opal-prd/pnor.h\n> index 28571af64..1ee033659 100644\n> --- a/external/opal-prd/pnor.h\n> +++ b/external/opal-prd/pnor.h\n> @@ -7,8 +7,7 @@\n>  struct pnor {\n>  \tchar\t\t\t*path;\n>  \tstruct ffs_handle\t*ffsh;\n> -\tuint64_t\t\tsize;\n> -\tuint32_t\t\terasesize;\n> +\tstruct blocklevel_info bl_info;\n>  \tstruct blocklevel_device *bl;\n>  };\n>  \n> diff --git a/external/opal-prd/test/test_pnor_ops.c b/external/opal-prd/test/test_pnor_ops.c\n> index fd5e2c22a..3743362e1 100644\n> --- a/external/opal-prd/test/test_pnor_ops.c\n> +++ b/external/opal-prd/test/test_pnor_ops.c\n> @@ -130,11 +130,14 @@ int main(int argc, char **argv)\n>  \tfor (i = 0; i < 2; i++)\n>  \t\twrite(fd, data, 16);\n>  \n> +\t/* Unused */\n> +\tpnor.bl_info.name = NULL;\n> +\n>  \t/* Adjust this if making the file smaller */\n> -\tpnor.size = 32;\n> +\tpnor.bl_info.size = 32;\n>  \n>  \t/* This is fake. Make it smaller than the size */\n> -\tpnor.erasesize = 4;\n> +\tpnor.bl_info.erase_granule = 4;\n>  \n>  \tprintf(\"Write: \");\n>  \tmemset(data, 'A', sizeof(data));\n> diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c\n> index bfc975fe5..3f501e583 100644\n> --- a/external/pflash/pflash.c\n> +++ b/external/pflash/pflash.c\n> @@ -43,11 +43,9 @@\n>  \n>  struct flash_details {\n>  \tstruct blocklevel_device *bl;\n> +\tstruct blocklevel_info bl_info;\n>  \tint need_relock;\n> -\tconst char *name;\n>  \tuint64_t toc;\n> -\tuint64_t total_size;\n> -\tuint32_t erase_granule;\n>  };\n>  \n>  /* Full pflash version number (possibly includes gitid). */\n> @@ -144,7 +142,7 @@ static struct ffs_handle *open_ffs(struct flash_details *flash)\n>  \tstruct ffs_handle *ffsh;\n>  \tint rc;\n>  \n> -\trc = ffs_init(flash->toc, flash->total_size,\n> +\trc = ffs_init(flash->toc, flash->bl_info.size,\n>  \t\t\tflash->bl, &ffsh, 0);\n>  \tif (rc) {\n>  \t\tfprintf(stderr, \"Error %d opening ffs !\\n\", rc);\n> @@ -166,11 +164,11 @@ static void print_flash_info(struct flash_details *flash)\n>  \n>  \tprintf(\"Flash info:\\n\");\n>  \tprintf(\"-----------\\n\");\n> -\tprintf(\"Name          = %s\\n\", flash->name);\n> +\tprintf(\"Name          = %s\\n\", flash->bl_info.name);\n>  \tprintf(\"Total size    = %\" PRIu64 \"MB\\t Flags E:ECC, P:PRESERVED, R:READONLY\\n\",\n> -\t\t\tflash->total_size >> 20);\n> +\t\t\tflash->bl_info.size >> 20);\n>  \tprintf(\"Erase granule = %2d%-13sB:BACKUP, F:REPROVISION\\n\",\n> -\t\t\tflash->erase_granule >> 10, \"KB\");\n> +\t\t\tflash->bl_info.erase_granule >> 10, \"KB\");\n>  \n>  \tif (bmc_flash)\n>  \t\treturn;\n> @@ -282,9 +280,11 @@ static int erase_chip(struct flash_details *flash)\n>  \t * likes the progress bars.\n>  \t * Lets do an erase block at a time erase then...\n>  \t */\n> -\tprogress_init(flash->total_size);\n> -\tfor (pos = 0; pos < flash->total_size; pos += flash->erase_granule) {\n> -\t\trc = blocklevel_erase(flash->bl, pos, flash->erase_granule);\n> +\tprogress_init(flash->bl_info.size);\n> +\tfor (pos = 0; pos < flash->bl_info.size;\n> +\t\t\tpos += flash->bl_info.erase_granule) {\n> +\t\trc = blocklevel_erase(flash->bl, pos,\n> +\t\t\t\tflash->bl_info.erase_granule);\n>  \t\tif (rc)\n>  \t\t\tbreak;\n>  \t\tprogress_tick(pos);\n> @@ -303,7 +303,7 @@ static int erase_range(struct flash_details *flash,\n>  \t\tuint32_t start, uint32_t size, bool will_program,\n>  \t\tstruct ffs_handle *ffsh, int ffs_index)\n>  {\n> -\tuint32_t done = 0, erase_mask = flash->erase_granule - 1;\n> +\tuint32_t done = 0, erase_mask = flash->bl_info.erase_granule - 1;\n>  \tbool confirm;\n>  \tint rc;\n>  \n> @@ -326,25 +326,26 @@ static int erase_range(struct flash_details *flash,\n>  \tif (start & erase_mask) {\n>  \t\t/* Align to next erase block */\n>  \t\trc = blocklevel_smart_erase(flash->bl, start,\n> -\t\t\t\tflash->erase_granule - (start & erase_mask));\n> +\t\t\t\tflash->bl_info.erase_granule - (start & erase_mask));\n>  \t\tif (rc) {\n>  \t\t\tfprintf(stderr, \"Failed to blocklevel_smart_erase(): %d\\n\", rc);\n>  \t\t\treturn 1;\n>  \t\t}\n> -\t\tstart += flash->erase_granule - (start & erase_mask);\n> -\t\tsize -= flash->erase_granule - (start & erase_mask);\n> -\t\tdone = flash->erase_granule - (start & erase_mask);\n> +\t\tstart += flash->bl_info.erase_granule - (start & erase_mask);\n> +\t\tsize -= flash->bl_info.erase_granule - (start & erase_mask);\n> +\t\tdone = flash->bl_info.erase_granule - (start & erase_mask);\n>  \t}\n>  \tprogress_tick(done);\n>  \twhile (size & ~(erase_mask)) {\n> -\t\trc = blocklevel_smart_erase(flash->bl, start, flash->erase_granule);\n> +\t\trc = blocklevel_smart_erase(flash->bl, start,\n> +\t\t\t\tflash->bl_info.erase_granule);\n>  \t\tif (rc) {\n>  \t\t\tfprintf(stderr, \"Failed to blocklevel_smart_erase(): %d\\n\", rc);\n>  \t\t\treturn 1;\n>  \t\t}\n> -\t\tstart += flash->erase_granule;\n> -\t\tsize -= flash->erase_granule;\n> -\t\tdone += flash->erase_granule;\n> +\t\tstart += flash->bl_info.erase_granule;\n> +\t\tsize -= flash->bl_info.erase_granule;\n> +\t\tdone += flash->bl_info.erase_granule;\n>  \t\tprogress_tick(done);\n>  \t}\n>  \tif (size) {\n> @@ -1003,8 +1004,7 @@ int main(int argc, char *argv[])\n>  \t\tgoto out;\n>  \t}\n>  \n> -\trc = blocklevel_get_info(flash.bl, &flash.name,\n> -\t\t\t    &flash.total_size, &flash.erase_granule);\n> +\trc = blocklevel_get_info(flash.bl, &flash.bl_info);\n>  \tif (rc) {\n>  \t\tfprintf(stderr, \"Error %d getting flash info\\n\", rc);\n>  \t\trc = 1;\n> @@ -1025,7 +1025,7 @@ int main(int argc, char *argv[])\n>  \n>  \t/* If read specified and no read_size, use flash size */\n>  \tif (do_read && !read_size && !part_name)\n> -\t\tread_size = flash.total_size;\n> +\t\tread_size = flash.bl_info.size;\n>  \n>  \t/* We have a partition, adjust read/write size if needed */\n>  \tif (part_name || print_detail) {\n> @@ -1087,7 +1087,7 @@ int main(int argc, char *argv[])\n>  \t\t/* Set address */\n>  \t\taddress = pstart;\n>  \t} else if (erase) {\n> -\t\tif ((address | write_size) & (flash.erase_granule - 1)) {\n> +\t\tif ((address | write_size) & (flash.bl_info.erase_granule - 1)) {\n>  \t\t\tif (must_confirm) {\n>  \t\t\t\tprintf(\"ERROR: Erase at 0x%08x for 0x%08x isn't erase block aligned\\n\",\n>  \t\t\t\t\t\taddress, write_size);\n> diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c\n> index 33d5c5d2f..3955be823 100644\n> --- a/libflash/blocklevel.c\n> +++ b/libflash/blocklevel.c\n> @@ -229,12 +229,11 @@ int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)\n>  \treturn rc;\n>  }\n>  \n> -int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,\n> -\t\tuint32_t *erase_granule)\n> +int blocklevel_get_info(struct blocklevel_device *bl, struct blocklevel_info *bl_info)\n>  {\n>  \tint rc;\n>  \n> -\tif (!bl || !bl->get_info) {\n> +\tif (!bl || !bl->get_info || !bl_info) {\n>  \t\terrno = EINVAL;\n>  \t\treturn FLASH_ERR_PARM_ERROR;\n>  \t}\n> @@ -243,12 +242,12 @@ int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_\n>  \tif (rc)\n>  \t\treturn rc;\n>  \n> -\trc = bl->get_info(bl, name, total_size, erase_granule);\n> +\trc = bl->get_info(bl, bl_info);\n>  \n>  \t/* Check the validity of what we are being told */\n> -\tif (erase_granule && *erase_granule != bl->erase_mask + 1)\n> +\tif (bl_info->erase_granule != bl->erase_mask + 1)\n>  \t\tFL_ERR(\"blocklevel_get_info: WARNING: erase_granule (0x%08x) and erase_mask\"\n> -\t\t\t\t\" (0x%08x) don't match\\n\", *erase_granule, bl->erase_mask + 1);\n> +\t\t\t\t\" (0x%08x) don't match\\n\", bl_info->erase_granule, bl->erase_mask + 1);\n>  \n>  \trelease(bl);\n>  \n> @@ -417,7 +416,7 @@ out:\n>  \n>  int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)\n>  {\n> -\tuint32_t erase_size;\n> +\tstruct blocklevel_info bl_info;\n>  \tconst void *write_buf = buf;\n>  \tvoid *write_buf_start = NULL;\n>  \tvoid *erase_buf;\n> @@ -435,7 +434,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi\n>  \t\treturn blocklevel_write(bl, pos, buf, len);\n>  \t}\n>  \n> -\trc = blocklevel_get_info(bl, NULL, NULL, &erase_size);\n> +\trc = blocklevel_get_info(bl, &bl_info);\n>  \tif (rc)\n>  \t\treturn rc;\n>  \n> @@ -458,7 +457,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi\n>  \t\twrite_buf = write_buf_start;\n>  \t}\n>  \n> -\terase_buf = malloc(erase_size);\n> +\terase_buf = malloc(bl_info.erase_granule);\n>  \tif (!erase_buf) {\n>  \t\terrno = ENOMEM;\n>  \t\trc = FLASH_ERR_MALLOC_FAILED;\n> @@ -470,32 +469,32 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi\n>  \t\tgoto out_free;\n>  \n>  \twhile (len > 0) {\n> -\t\tuint32_t erase_block = pos & ~(erase_size - 1);\n> -\t\tuint32_t block_offset = pos & (erase_size - 1);\n> -\t\tuint32_t size = erase_size > len ? len : erase_size;\n> +\t\tuint32_t erase_block = pos & ~(bl_info.erase_granule - 1);\n> +\t\tuint32_t block_offset = pos & (bl_info.erase_granule - 1);\n> +\t\tuint32_t size = bl_info.erase_granule > len ? len : bl_info.erase_granule;\n>  \t\tint cmp;\n>  \n>  \t\t/* Write crosses an erase boundary, shrink the write to the boundary */\n> -\t\tif (erase_size < block_offset + size) {\n> -\t\t\tsize = erase_size - block_offset;\n> +\t\tif (bl_info.erase_granule < block_offset + size) {\n> +\t\t\tsize = bl_info.erase_granule - block_offset;\n>  \t\t}\n>  \n> -\t\trc = bl->read(bl, erase_block, erase_buf, erase_size);\n> +\t\trc = bl->read(bl, erase_block, erase_buf, bl_info.erase_granule);\n>  \t\tif (rc)\n>  \t\t\tgoto out;\n>  \n>  \t\tcmp = blocklevel_flashcmp(erase_buf + block_offset, write_buf, size);\n>  \t\tFL_DBG(\"%s: region 0x%08x..0x%08x \", __func__,\n> -\t\t\t\terase_block, erase_size);\n> +\t\t\t\terase_block, bl_info.erase_granule);\n>  \t\tif (cmp != 0) {\n>  \t\t\tFL_DBG(\"needs \");\n>  \t\t\tif (cmp == -1) {\n>  \t\t\t\tFL_DBG(\"erase and \");\n> -\t\t\t\tbl->erase(bl, erase_block, erase_size);\n> +\t\t\t\tbl->erase(bl, erase_block, bl_info.erase_granule);\n>  \t\t\t}\n>  \t\t\tFL_DBG(\"write\\n\");\n>  \t\t\tmemcpy(erase_buf + block_offset, write_buf, size);\n> -\t\t\trc = bl->write(bl, erase_block, erase_buf, erase_size);\n> +\t\t\trc = bl->write(bl, erase_block, erase_buf, bl_info.erase_granule);\n>  \t\t\tif (rc)\n>  \t\t\t\tgoto out;\n>  \t\t}\n> diff --git a/libflash/blocklevel.h b/libflash/blocklevel.h\n> index ba42c83d0..d2d269054 100644\n> --- a/libflash/blocklevel.h\n> +++ b/libflash/blocklevel.h\n> @@ -34,6 +34,15 @@ enum blocklevel_flags {\n>  \tWRITE_NEED_ERASE = 1,\n>  };\n>  \n> +struct blocklevel_info {\n> +\t/* name is not owned by this struct and must persist for the\n> +\t * liftime of blocklevel_info\n> +\t */\n> +\tconst char *name;\n> +\tuint64_t size;\n> +\tuint32_t erase_granule;\n> +};\n> +\n>  /*\n>   * libffs may be used with different backends, all should provide these for\n>   * libflash to get the information it needs\n> @@ -45,8 +54,7 @@ struct blocklevel_device {\n>  \tint (*read)(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len);\n>  \tint (*write)(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);\n>  \tint (*erase)(struct blocklevel_device *bl, uint64_t pos, uint64_t len);\n> -\tint (*get_info)(struct blocklevel_device *bl, const char **name, uint64_t *total_size,\n> -\t\t\tuint32_t *erase_granule);\n> +\tint (*get_info)(struct blocklevel_device *bl, struct blocklevel_info *bl_info);\n>  \n>  \t/*\n>  \t * Keep the erase mask so that blocklevel_erase() can do sanity checking\n> @@ -62,8 +70,8 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6\n>  int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);\n>  int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);\n>  int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len);\n> -int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,\n> -\t\tuint32_t *erase_granule);\n> +\n> +int blocklevel_get_info(struct blocklevel_device *bl, struct blocklevel_info *bl_info);\n>  \n>  /*\n>   * blocklevel_smart_write() performs reads on the data to see if it\n> diff --git a/libflash/file.c b/libflash/file.c\n> index 7065eb4fa..b87679cd1 100644\n> --- a/libflash/file.c\n> +++ b/libflash/file.c\n> @@ -212,6 +212,7 @@ static int get_info_name(struct file_data *file_data, char **name)\n>  \t}\n>  \tlpath[len] = '\\0';\n>  \n> +\tfree(*name);\n>  \t*name = lpath;\n>  \n>  \tfree(path);\n> @@ -219,8 +220,8 @@ static int get_info_name(struct file_data *file_data, char **name)\n>  }\n>  \n>  \n> -static int mtd_get_info(struct blocklevel_device *bl, const char **name,\n> -\t\tuint64_t *total_size, uint32_t *erase_granule)\n> +static int mtd_get_info(struct blocklevel_device *bl,\n> +\t\tstruct blocklevel_info *bl_info)\n>  {\n>  \tstruct file_data *file_data = container_of(bl, struct file_data, bl);\n>  \tstruct mtd_info_user mtd_info;\n> @@ -230,24 +231,19 @@ static int mtd_get_info(struct blocklevel_device *bl, const char **name,\n>  \tif (rc == -1)\n>  \t\treturn FLASH_ERR_BAD_READ;\n>  \n> -\tif (total_size)\n> -\t\t*total_size = mtd_info.size;\n> -\n> -\tif (erase_granule)\n> -\t\t*erase_granule = mtd_info.erasesize;\n> +\trc = get_info_name(file_data, &(file_data->name));\n> +\tif (rc)\n> +\t\treturn rc;\n>  \n> -\tif (name) {\n> -\t\trc = get_info_name(file_data, &(file_data->name));\n> -\t\tif (rc)\n> -\t\t\treturn rc;\n> -\t\t*name = file_data->name;\n> -\t}\n> +\tbl_info->name = file_data->name;\n> +\tbl_info->size = mtd_info.size;\n> +\tbl_info->erase_granule = mtd_info.erasesize;\n>  \n>  \treturn 0;\n>  }\n>  \n> -static int file_get_info(struct blocklevel_device *bl, const char **name,\n> -\t\tuint64_t *total_size, uint32_t *erase_granule)\n> +static int file_get_info(struct blocklevel_device *bl,\n> +\t\tstruct blocklevel_info *bl_info)\n>  {\n>  \tstruct file_data *file_data = container_of(bl, struct file_data, bl);\n>  \tstruct stat st;\n> @@ -256,18 +252,13 @@ static int file_get_info(struct blocklevel_device *bl, const char **name,\n>  \tif (fstat(file_data->fd, &st))\n>  \t\treturn FLASH_ERR_PARM_ERROR;\n>  \n> -\tif (total_size)\n> -\t\t*total_size = st.st_size;\n> -\n> -\tif (erase_granule)\n> -\t\t*erase_granule = 1;\n> +\trc = get_info_name(file_data, &(file_data->name));\n> +\tif (rc)\n> +\t\treturn rc;\n>  \n> -\tif (name) {\n> -\t\trc = get_info_name(file_data, &(file_data->name));\n> -\t\tif (rc)\n> -\t\t\treturn rc;\n> -\t\t*name = file_data->name;\n> -\t}\n> +\tbl_info->name = file_data->name;\n> +\tbl_info->size = st.st_size;\n> +\tbl_info->erase_granule = 1;\n>  \n>  \treturn 0;\n>  }\n> @@ -315,8 +306,9 @@ int file_init(int fd, struct blocklevel_device **bl)\n>  \t\tfile_data->bl.erase = &mtd_erase;\n>  \t\tfile_data->bl.get_info = &mtd_get_info;\n>  \t\tfile_data->bl.flags = WRITE_NEED_ERASE;\n> -\t\tmtd_get_info(&file_data->bl, NULL, NULL, &(file_data->bl.erase_mask));\n> -\t\tfile_data->bl.erase_mask--;\n> +\t\tstruct blocklevel_info bl_info;\n> +\t\tmtd_get_info(&file_data->bl, &bl_info);\n> +\t\tfile_data->bl.erase_mask = bl_info.erase_granule - 1;\n>  \t} else if (!S_ISREG(sbuf.st_mode)) {\n>  \t\t/* If not a char device or a regular file something went wrong */\n>  \t\tgoto out;\n> diff --git a/libflash/libffs.c b/libflash/libffs.c\n> index 038f59425..6fc23eee9 100644\n> --- a/libflash/libffs.c\n> +++ b/libflash/libffs.c\n> @@ -216,25 +216,25 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,\n>  {\n>  \tstruct __ffs_hdr blank_hdr;\n>  \tstruct __ffs_hdr raw_hdr;\n> +\tstruct blocklevel_info bl_info;\n>  \tstruct ffs_handle *f;\n> -\tuint64_t total_size;\n>  \tint rc, i;\n>  \n>  \tif (!ffs || !bl)\n>  \t\treturn FLASH_ERR_PARM_ERROR;\n>  \t*ffs = NULL;\n>  \n> -\trc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> +\trc = blocklevel_get_info(bl, &bl_info);\n>  \tif (rc) {\n>  \t\tFL_ERR(\"FFS: Error %d retrieving flash info\\n\", rc);\n>  \t\treturn rc;\n>  \t}\n> -\tif (total_size > UINT_MAX)\n> +\tif (bl_info.size > UINT_MAX)\n>  \t\treturn FLASH_ERR_VERIFY_FAILURE;\n>  \tif ((offset + max_size) < offset)\n>  \t\treturn FLASH_ERR_PARM_ERROR;\n>  \n> -\tif ((max_size > total_size))\n> +\tif ((max_size > bl_info.size))\n>  \t\treturn FLASH_ERR_PARM_ERROR;\n>  \n>  \t/* Read flash header */\n> diff --git a/libflash/libflash.c b/libflash/libflash.c\n> index 38f87b86e..82a2baecc 100644\n> --- a/libflash/libflash.c\n> +++ b/libflash/libflash.c\n> @@ -792,16 +792,15 @@ static int flash_configure(struct flash_chip *c)\n>  \treturn 0;\n>  }\n>  \n> -static int flash_get_info(struct blocklevel_device *bl, const char **name,\n> -\t\t   uint64_t *total_size, uint32_t *erase_granule)\n> +static int flash_get_info(struct blocklevel_device *bl,\n> +\t\tstruct blocklevel_info *bl_info)\n>  {\n>  \tstruct flash_chip *c = container_of(bl, struct flash_chip, bl);\n> -\tif (name)\n> -\t\t*name = c->info.name;\n> -\tif (total_size)\n> -\t\t*total_size = c->tsize;\n> -\tif (erase_granule)\n> -\t\t*erase_granule = c->min_erase_mask + 1;\n> +\n> +\tbl_info->name = c->info.name;\n> +\tbl_info->size = c->tsize;\n> +\tbl_info->erase_granule = c->min_erase_mask + 1;\n> +\n>  \treturn 0;\n>  }\n>  \n> diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c\n> index 950e24f05..d4200ce53 100644\n> --- a/libflash/mbox-flash.c\n> +++ b/libflash/mbox-flash.c\n> @@ -745,8 +745,8 @@ static int mbox_flash_read(struct blocklevel_device *bl, uint64_t pos,\n>  \treturn rc;\n>  }\n>  \n> -static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,\n> -\t\tuint64_t *total_size, uint32_t *erase_granule)\n> +static int mbox_flash_get_info(struct blocklevel_device *bl,\n> +\t\tstruct blocklevel_info *bl_info)\n>  {\n>  \tstruct mbox_flash_data *mbox_flash;\n>  \tstruct bmc_mbox_msg *msg;\n> @@ -761,14 +761,7 @@ static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,\n>  \tif (!msg)\n>  \t\treturn FLASH_ERR_MALLOC_FAILED;\n>  \n> -\t/*\n> -\t * We want to avoid runtime mallocs in skiboot. The expected\n> -\t * behavour to uses of libflash is that one can free() the memory\n> -\t * returned.\n> -\t * NULL will do for now.\n> -\t */\n> -\tif (name)\n> -\t\t*name = NULL;\n> +\tbl_info->name = \"pnor_mbox\";\n>  \n>  \tmbox_flash->busy = true;\n>  \trc = msg_send(mbox_flash, msg);\n> @@ -784,10 +777,8 @@ static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,\n>  \n>  \tmbox_flash->bl.erase_mask = mbox_flash->erase_granule - 1;\n>  \n> -\tif (total_size)\n> -\t\t*total_size = mbox_flash->total_size;\n> -\tif (erase_granule)\n> -\t\t*erase_granule = mbox_flash->erase_granule;\n> +\tbl_info->size = mbox_flash->total_size;\n> +\tbl_info->erase_granule = mbox_flash->erase_granule;\n>  \n>  out:\n>  \tmsg_free_memory(msg);\n> diff --git a/libflash/test/test-flash.c b/libflash/test/test-flash.c\n> index 3f77d6f3e..1ca467bb0 100644\n> --- a/libflash/test/test-flash.c\n> +++ b/libflash/test/test-flash.c\n> @@ -367,9 +367,7 @@ struct spi_flash_ctrl sim_ctrl = {\n>  int main(void)\n>  {\n>  \tstruct blocklevel_device *bl;\n> -\tuint64_t total_size;\n> -\tuint32_t erase_granule;\n> -\tconst char *name;\n> +\tstruct blocklevel_info bl_info;\n>  \tuint16_t *test;\n>  \tstruct ecc64 *ecc_test;\n>  \tuint64_t *test64;\n> @@ -384,7 +382,7 @@ int main(void)\n>  \t\tERR(\"flash_init failed with err %d\\n\", rc);\n>  \t\texit(1);\n>  \t}\n> -\trc = flash_get_info(bl, &name, &total_size, &erase_granule);\n> +\trc = flash_get_info(bl, &bl_info);\n>  \tif (rc) {\n>  \t\tERR(\"flash_get_info failed with err %d\\n\", rc);\n>  \t\texit(1);\n> diff --git a/platforms/mambo/mambo.c b/platforms/mambo/mambo.c\n> index cb6e103cc..dd7872a8e 100644\n> --- a/platforms/mambo/mambo.c\n> +++ b/platforms/mambo/mambo.c\n> @@ -125,19 +125,14 @@ static int bogus_disk_erase(struct blocklevel_device *bl __unused,\n>  \treturn 0; /* NOP */\n>  }\n>  \n> -static int bogus_disk_get_info(struct blocklevel_device *bl, const char **name,\n> -\t\t\t      uint64_t *total_size, uint32_t *erase_granule)\n> +static int bogus_disk_get_info(struct blocklevel_device *bl,\n> +\t\t\tstruct blocklevel_info *bl_info)\n>  {\n>  \tstruct bogus_disk_info *bdi = bl->priv;\n>  \n> -\tif (total_size)\n> -\t\t*total_size = bdi->size;\n> -\n> -\tif (erase_granule)\n> -\t\t*erase_granule = BD_SECT_SZ;\n> -\n> -\tif (name)\n> -\t\t*name = \"mambobogus\";\n> +\tbl_info->name = \"mambobogus\";\n> +\tbl_info->size = bdi->size;\n> +\tbl_info->erase_granule = BD_SECT_SZ;\n>  \n>  \treturn 0;\n>  }","headers":{"Return-Path":"<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","skiboot@lists.ozlabs.org"],"Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","skiboot@lists.ozlabs.org"],"Received":["from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xhHVD4Yx8z9t3J\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 29 Aug 2017 15:38:12 +1000 (AEST)","from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xhHVD3LTQzDqXy\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 29 Aug 2017 15:38:12 +1000 (AEST)","from mail-io0-x22c.google.com (mail-io0-x22c.google.com\n\t[IPv6:2607:f8b0:4001:c06::22c])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xhHV146H0zDqNY\n\tfor <skiboot@lists.ozlabs.org>; Tue, 29 Aug 2017 15:38:01 +1000 (AEST)","by mail-io0-x22c.google.com with SMTP id s101so12788293ioe.0\n\tfor <skiboot@lists.ozlabs.org>; Mon, 28 Aug 2017 22:38:01 -0700 (PDT)","from camb691.ozlabs.ibm.com ([122.99.82.10])\n\tby smtp.googlemail.com with ESMTPSA id\n\tr20sm991830itb.32.2017.08.28.22.37.56\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tMon, 28 Aug 2017 22:37:58 -0700 (PDT)"],"Authentication-Results":["ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"ChFhhFir\"; dkim-atps=neutral","lists.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"ChFhhFir\"; dkim-atps=neutral","lists.ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"ChFhhFir\"; dkim-atps=neutral"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=message-id:subject:from:to:date:in-reply-to:references:mime-version\n\t:content-transfer-encoding;\n\tbh=NST4l2q3r+8nSfQc+JQ//Sat+hgMC6gaANFFEmFScWM=;\n\tb=ChFhhFirgu9qlZyyl6qbkh//W/8ONWdf/PBhJ2ZoIAZh8oFspkHT+Y9cgDCtttnULF\n\tysX+wxebSSiHT4B1Xizxu4HUc71VemSQwe/ykkWNMU0DIYgmfewtpCRjh2krJxncPGJk\n\to/rrhCvMxHzPaClaE2ZXoCaq+CEjWU/cVrK6P52CnUaCMK3lhZgg+oJIdHsPB1rCv/P5\n\ta/l+vxOYxLzjewiVsv1dHuEAiO6DO4T2/bn8XW7s3ur1M5rR2xU5ciTEBt5rav2+D/Yf\n\tbOMXeuhqJ7N0levEFa2GV2T2QQfGAzYPQ/jCbgjfmr62vVYX2Xywsr/rw6ynOX699bg+\n\tcTJg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:message-id:subject:from:to:date:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=NST4l2q3r+8nSfQc+JQ//Sat+hgMC6gaANFFEmFScWM=;\n\tb=sNkH4a8LAXqjI3dLFqMOlBSPjUJEttbLEG8O5/Xsv9yNEtLSxlSzHpHODTa5NeA6R4\n\tKJdAzzR7Q7z8leDGAKNkJAf0PtoiXt6MEK5cDz8eu8o6oPqwj66Ii8luk8faGmqMfnfo\n\tME1Xfvl99XgSSTYBgRI119uBAFr2JBr51o7H3Xy/G5ZdDzZbzubA9OpIPwRYRfyGuOSk\n\tdNpuZWLAk6VvAy8nvcLrGH5e+HrF5cfdhyhqQ7ui8v/iy9guI0XGREnF0VtX7XtNxGpc\n\ti97l+zh4jSSyhck5VRp0clC4fvsh3FslG4nRPVKGKy0GQezDS/GRApv54qRQ8+dCZgzn\n\tgCQw==","X-Gm-Message-State":"AHYfb5iW3UDcnws3OBmhV2VQtnxBoo76pQNBGMdJNSPXpIF5TDG1zaAB\n\t+b+7jUv9W5P0SMA01Dc=","X-Received":"by 10.107.168.101 with SMTP id r98mr2898860ioe.332.1503985078786;\n\tMon, 28 Aug 2017 22:37:58 -0700 (PDT)","Message-ID":"<1503985073.8990.15.camel@gmail.com>","From":"Cyril Bur <cyrilbur@gmail.com>","To":"\"William A. Kennington III\" <wak@google.com>, skiboot@lists.ozlabs.org","Date":"Tue, 29 Aug 2017 15:37:53 +1000","In-Reply-To":"<20170829041922.4193-1-wak@google.com>","References":"<20170829041922.4193-1-wak@google.com>","X-Mailer":"Evolution 3.24.5 ","Mime-Version":"1.0","Subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","X-BeenThere":"skiboot@lists.ozlabs.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"Mailing list for skiboot development <skiboot.lists.ozlabs.org>","List-Unsubscribe":"<https://lists.ozlabs.org/options/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=unsubscribe>","List-Archive":"<http://lists.ozlabs.org/pipermail/skiboot/>","List-Post":"<mailto:skiboot@lists.ozlabs.org>","List-Help":"<mailto:skiboot-request@lists.ozlabs.org?subject=help>","List-Subscribe":"<https://lists.ozlabs.org/listinfo/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=subscribe>","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org","Sender":"\"Skiboot\"\n\t<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>"}},{"id":1759064,"web_url":"http://patchwork.ozlabs.org/comment/1759064/","msgid":"<CAPnigKkOUz2jK97cKN9PKxE=AB=ZbA_nAJjfrjv_S7FCzHsNXA@mail.gmail.com>","list_archive_url":null,"date":"2017-08-29T06:34:57","subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","submitter":{"id":70409,"url":"http://patchwork.ozlabs.org/api/people/70409/","name":"William Kennington","email":"wak@google.com"},"content":"Cyril,\n\nSounds good. I actually wrote this up a couple of months back, but I'd like\nto upstream as many of our changes as possible. It just occurred to me that\nwe may not actually need this change at all to support one of the flash\nchanges we made. It would be nice to clean up these interfaces though.\n\nOn Mon, Aug 28, 2017 at 10:38 PM Cyril Bur <cyrilbur@gmail.com> wrote:\n\n> On Mon, 2017-08-28 at 21:19 -0700, William A. Kennington III wrote:\n> > This changes refactors all of the output variables from flash_get_info\n> > into a new output struct. Callers now supply the info struct, and always\n> > get all of the info with each call. There are never any allocations done\n> > by this function so it shouldn't be much slower to always populate all\n> > of the information.\n> >\n>\n> Hi William,\n>\n> As nice as this refactor is (thanks for the effort!), unfortunately\n> we're a bit stuck with the interface as is, both openbmc and petitboot\n> projects link against a dynamic libflash.\n>\n> Ironically I'm about to send a series which which does rework the\n> libffs api a bit - although I'm quite sure only external/ffspart\n> actually uses what I've changed. blocklevel_get_info() though is pretty\n> core and changing that won't work.\n>\n> Perhaps you've prompted a discussion that now might be a good time to\n> do a significant rewrite of libflash/libffs which are now being used\n> for a completely different purpose for which they were first written,\n> hopefully Stewart will weigh in.\n>\n>\n> Cyril\n>\n> > Signed-off-by: William A. Kennington III <wak@google.com>\n> > ---\n> >  core/flash.c                           | 15 +++++------\n> >  external/common/arch_flash_arm.c       |  6 ++---\n> >  external/common/arch_flash_common.c    |  6 ++---\n> >  external/gard/gard.c                   | 10 +++----\n> >  external/opal-prd/pnor.c               | 12 ++++-----\n> >  external/opal-prd/pnor.h               |  3 +--\n> >  external/opal-prd/test/test_pnor_ops.c |  7 +++--\n> >  external/pflash/pflash.c               | 46\n> ++++++++++++++++----------------\n> >  libflash/blocklevel.c                  | 35 ++++++++++++-------------\n> >  libflash/blocklevel.h                  | 16 +++++++++---\n> >  libflash/file.c                        | 48\n> ++++++++++++++--------------------\n> >  libflash/libffs.c                      |  8 +++---\n> >  libflash/libflash.c                    | 15 +++++------\n> >  libflash/mbox-flash.c                  | 19 ++++----------\n> >  libflash/test/test-flash.c             |  6 ++---\n> >  platforms/mambo/mambo.c                | 15 ++++-------\n> >  16 files changed, 125 insertions(+), 142 deletions(-)\n> >\n> > diff --git a/core/flash.c b/core/flash.c\n> > index 53e6eba08..35a0c4c32 100644\n> > --- a/core/flash.c\n> > +++ b/core/flash.c\n> > @@ -254,21 +254,20 @@ static int num_flashes(void)\n> >\n> >  int flash_register(struct blocklevel_device *bl)\n> >  {\n> > -     uint64_t size;\n> > -     uint32_t block_size;\n> > +     struct blocklevel_info bl_info;\n> >       struct ffs_handle *ffs;\n> >       struct dt_node *node;\n> >       struct flash *flash;\n> > -     const char *name;\n> >       int rc;\n> >\n> > -     rc = blocklevel_get_info(bl, &name, &size, &block_size);\n> > +     rc = blocklevel_get_info(bl, &bl_info);\n> >       if (rc)\n> >               return rc;\n> >\n> >       prlog(PR_INFO, \"FLASH: registering flash device %s \"\n> >                       \"(size 0x%llx, blocksize 0x%x)\\n\",\n> > -                     name ?: \"(unnamed)\", size, block_size);\n> > +                     bl_info.name ? bl_info.name : \"(unnamed)\",\n> bl_info.size,\n> > +                     bl_info.erase_granule);\n> >\n> >       lock(&flash_lock);\n> >\n> > @@ -281,8 +280,8 @@ int flash_register(struct blocklevel_device *bl)\n> >\n> >       flash->busy = false;\n> >       flash->bl = bl;\n> > -     flash->size = size;\n> > -     flash->block_size = block_size;\n> > +     flash->size = bl_info.size;\n> > +     flash->block_size = bl_info.erase_granule;\n> >       flash->id = num_flashes();\n> >\n> >       list_add(&flashes, &flash->list);\n> > @@ -302,7 +301,7 @@ int flash_register(struct blocklevel_device *bl)\n> >\n> >       node = flash_add_dt_node(flash, flash->id);\n> >\n> > -     setup_system_flash(flash, node, name, ffs);\n> > +     setup_system_flash(flash, node, bl_info.name, ffs);\n> >\n> >       if (ffs)\n> >               ffs_close(ffs);\n> > diff --git a/external/common/arch_flash_arm.c\n> b/external/common/arch_flash_arm.c\n> > index 3cdd41ded..ac43de0c4 100644\n> > --- a/external/common/arch_flash_arm.c\n> > +++ b/external/common/arch_flash_arm.c\n> > @@ -303,13 +303,13 @@ int arch_flash_erase_chip(struct blocklevel_device\n> *bl)\n> >       if (!arch_data.flash_chip) {\n> >               /* Just assume its a regular erase */\n> >               int rc;\n> > -             uint64_t total_size;\n> > +             struct blocklevel_info bl_info;\n> >\n> > -             rc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> > +             rc = blocklevel_get_info(bl, &bl_info);\n> >               if (rc)\n> >                       return rc;\n> >\n> > -             return blocklevel_erase(bl, 0, total_size);\n> > +             return blocklevel_erase(bl, 0, bl_info.size);\n> >       }\n> >\n> >       return flash_erase_chip(arch_data.flash_chip);\n> > diff --git a/external/common/arch_flash_common.c\n> b/external/common/arch_flash_common.c\n> > index 6bce7e1ba..41239662a 100644\n> > --- a/external/common/arch_flash_common.c\n> > +++ b/external/common/arch_flash_common.c\n> > @@ -31,13 +31,13 @@\n> >  int __attribute__((weak)) arch_flash_erase_chip(struct\n> blocklevel_device *bl)\n> >  {\n> >       int rc;\n> > -     uint64_t total_size;\n> > +     struct blocklevel_info bl_info;\n> >\n> > -     rc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> > +     rc = blocklevel_get_info(bl, &bl_info);\n> >       if (rc)\n> >               return rc;\n> >\n> > -     return blocklevel_erase(bl, 0, total_size);\n> > +     return blocklevel_erase(bl, 0, bl_info.size);\n> >  }\n> >\n> >  int __attribute__((weak,const)) arch_flash_4b_mode(struct\n> blocklevel_device *bl, int set_4b)\n> > diff --git a/external/gard/gard.c b/external/gard/gard.c\n> > index c5cb93b88..3946cad6f 100644\n> > --- a/external/gard/gard.c\n> > +++ b/external/gard/gard.c\n> > @@ -596,7 +596,7 @@ int main(int argc, char **argv)\n> >       const char *action, *progname;\n> >       char *filename = NULL;\n> >       struct gard_ctx _ctx, *ctx;\n> > -     uint64_t bl_size;\n> > +     struct blocklevel_info bl_info;\n> >       int rc, i = 0;\n> >       bool part = 0;\n> >       bool ecc = 0;\n> > @@ -665,17 +665,17 @@ int main(int argc, char **argv)\n> >               goto out_free;\n> >       }\n> >\n> > -     rc = blocklevel_get_info(ctx->bl, NULL, &bl_size, NULL);\n> > +     rc = blocklevel_get_info(ctx->bl, &bl_info);\n> >       if (rc)\n> >               goto out;\n> >\n> > -     if (bl_size > UINT_MAX) {\n> > +     if (bl_info.size > UINT_MAX) {\n> >               fprintf(stderr, \"MTD device bigger than %i: size: %\"\n> PRIu64 \"\\n\",\n> > -                     UINT_MAX, bl_size);\n> > +                     UINT_MAX, bl_info.size);\n> >               rc = EXIT_FAILURE;\n> >               goto out;\n> >       }\n> > -     ctx->f_size = bl_size;\n> > +     ctx->f_size = bl_info.size;\n> >\n> >       if (!part) {\n> >               rc = ffs_init(0, ctx->f_size, ctx->bl, &ctx->ffs, 1);\n> > diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c\n> > index c032421d1..afb6ccd1f 100644\n> > --- a/external/opal-prd/pnor.c\n> > +++ b/external/opal-prd/pnor.c\n> > @@ -64,13 +64,13 @@ int pnor_init(struct pnor *pnor)\n> >               return -1;\n> >       }\n> >\n> > -     rc = blocklevel_get_info(pnor->bl, NULL, &(pnor->size),\n> &(pnor->erasesize));\n> > +     rc = blocklevel_get_info(pnor->bl, &pnor->bl_info);\n> >       if (rc) {\n> >               pr_log(LOG_ERR, \"PNOR: blocklevel_get_info() failed. Can't\n> use PNOR\");\n> >               goto out;\n> >       }\n> >\n> > -     rc = ffs_init(0, pnor->size, pnor->bl, &pnor->ffsh, 0);\n> > +     rc = ffs_init(0, pnor->bl_info.size, pnor->bl, &pnor->ffsh, 0);\n> >       if (rc) {\n> >               pr_log(LOG_ERR, \"PNOR: Failed to open pnor partition\n> table\");\n> >               goto out;\n> > @@ -121,8 +121,8 @@ static int mtd_write(struct pnor *pnor, void *data,\n> uint64_t offset,\n> >  {\n> >       int rc;\n> >\n> > -     if (len > pnor->size || offset > pnor->size ||\n> > -         len + offset > pnor->size)\n> > +     if (len > pnor->bl_info.size || offset > pnor->bl_info.size ||\n> > +         len + offset > pnor->bl_info.size)\n> >               return -ERANGE;\n> >\n> >       rc = blocklevel_smart_write(pnor->bl, offset, data, len);\n> > @@ -137,8 +137,8 @@ static int mtd_read(struct pnor *pnor, void *data,\n> uint64_t offset,\n> >  {\n> >       int rc;\n> >\n> > -     if (len > pnor->size || offset > pnor->size ||\n> > -         len + offset > pnor->size)\n> > +     if (len > pnor->bl_info.size || offset > pnor->bl_info.size ||\n> > +         len + offset > pnor->bl_info.size)\n> >               return -ERANGE;\n> >\n> >       rc = blocklevel_read(pnor->bl, offset, data, len);\n> > diff --git a/external/opal-prd/pnor.h b/external/opal-prd/pnor.h\n> > index 28571af64..1ee033659 100644\n> > --- a/external/opal-prd/pnor.h\n> > +++ b/external/opal-prd/pnor.h\n> > @@ -7,8 +7,7 @@\n> >  struct pnor {\n> >       char                    *path;\n> >       struct ffs_handle       *ffsh;\n> > -     uint64_t                size;\n> > -     uint32_t                erasesize;\n> > +     struct blocklevel_info bl_info;\n> >       struct blocklevel_device *bl;\n> >  };\n> >\n> > diff --git a/external/opal-prd/test/test_pnor_ops.c\n> b/external/opal-prd/test/test_pnor_ops.c\n> > index fd5e2c22a..3743362e1 100644\n> > --- a/external/opal-prd/test/test_pnor_ops.c\n> > +++ b/external/opal-prd/test/test_pnor_ops.c\n> > @@ -130,11 +130,14 @@ int main(int argc, char **argv)\n> >       for (i = 0; i < 2; i++)\n> >               write(fd, data, 16);\n> >\n> > +     /* Unused */\n> > +     pnor.bl_info.name = NULL;\n> > +\n> >       /* Adjust this if making the file smaller */\n> > -     pnor.size = 32;\n> > +     pnor.bl_info.size = 32;\n> >\n> >       /* This is fake. Make it smaller than the size */\n> > -     pnor.erasesize = 4;\n> > +     pnor.bl_info.erase_granule = 4;\n> >\n> >       printf(\"Write: \");\n> >       memset(data, 'A', sizeof(data));\n> > diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c\n> > index bfc975fe5..3f501e583 100644\n> > --- a/external/pflash/pflash.c\n> > +++ b/external/pflash/pflash.c\n> > @@ -43,11 +43,9 @@\n> >\n> >  struct flash_details {\n> >       struct blocklevel_device *bl;\n> > +     struct blocklevel_info bl_info;\n> >       int need_relock;\n> > -     const char *name;\n> >       uint64_t toc;\n> > -     uint64_t total_size;\n> > -     uint32_t erase_granule;\n> >  };\n> >\n> >  /* Full pflash version number (possibly includes gitid). */\n> > @@ -144,7 +142,7 @@ static struct ffs_handle *open_ffs(struct\n> flash_details *flash)\n> >       struct ffs_handle *ffsh;\n> >       int rc;\n> >\n> > -     rc = ffs_init(flash->toc, flash->total_size,\n> > +     rc = ffs_init(flash->toc, flash->bl_info.size,\n> >                       flash->bl, &ffsh, 0);\n> >       if (rc) {\n> >               fprintf(stderr, \"Error %d opening ffs !\\n\", rc);\n> > @@ -166,11 +164,11 @@ static void print_flash_info(struct flash_details\n> *flash)\n> >\n> >       printf(\"Flash info:\\n\");\n> >       printf(\"-----------\\n\");\n> > -     printf(\"Name          = %s\\n\", flash->name);\n> > +     printf(\"Name          = %s\\n\", flash->bl_info.name);\n> >       printf(\"Total size    = %\" PRIu64 \"MB\\t Flags E:ECC, P:PRESERVED,\n> R:READONLY\\n\",\n> > -                     flash->total_size >> 20);\n> > +                     flash->bl_info.size >> 20);\n> >       printf(\"Erase granule = %2d%-13sB:BACKUP, F:REPROVISION\\n\",\n> > -                     flash->erase_granule >> 10, \"KB\");\n> > +                     flash->bl_info.erase_granule >> 10, \"KB\");\n> >\n> >       if (bmc_flash)\n> >               return;\n> > @@ -282,9 +280,11 @@ static int erase_chip(struct flash_details *flash)\n> >        * likes the progress bars.\n> >        * Lets do an erase block at a time erase then...\n> >        */\n> > -     progress_init(flash->total_size);\n> > -     for (pos = 0; pos < flash->total_size; pos +=\n> flash->erase_granule) {\n> > -             rc = blocklevel_erase(flash->bl, pos,\n> flash->erase_granule);\n> > +     progress_init(flash->bl_info.size);\n> > +     for (pos = 0; pos < flash->bl_info.size;\n> > +                     pos += flash->bl_info.erase_granule) {\n> > +             rc = blocklevel_erase(flash->bl, pos,\n> > +                             flash->bl_info.erase_granule);\n> >               if (rc)\n> >                       break;\n> >               progress_tick(pos);\n> > @@ -303,7 +303,7 @@ static int erase_range(struct flash_details *flash,\n> >               uint32_t start, uint32_t size, bool will_program,\n> >               struct ffs_handle *ffsh, int ffs_index)\n> >  {\n> > -     uint32_t done = 0, erase_mask = flash->erase_granule - 1;\n> > +     uint32_t done = 0, erase_mask = flash->bl_info.erase_granule - 1;\n> >       bool confirm;\n> >       int rc;\n> >\n> > @@ -326,25 +326,26 @@ static int erase_range(struct flash_details *flash,\n> >       if (start & erase_mask) {\n> >               /* Align to next erase block */\n> >               rc = blocklevel_smart_erase(flash->bl, start,\n> > -                             flash->erase_granule - (start &\n> erase_mask));\n> > +                             flash->bl_info.erase_granule - (start &\n> erase_mask));\n> >               if (rc) {\n> >                       fprintf(stderr, \"Failed to\n> blocklevel_smart_erase(): %d\\n\", rc);\n> >                       return 1;\n> >               }\n> > -             start += flash->erase_granule - (start & erase_mask);\n> > -             size -= flash->erase_granule - (start & erase_mask);\n> > -             done = flash->erase_granule - (start & erase_mask);\n> > +             start += flash->bl_info.erase_granule - (start &\n> erase_mask);\n> > +             size -= flash->bl_info.erase_granule - (start &\n> erase_mask);\n> > +             done = flash->bl_info.erase_granule - (start & erase_mask);\n> >       }\n> >       progress_tick(done);\n> >       while (size & ~(erase_mask)) {\n> > -             rc = blocklevel_smart_erase(flash->bl, start,\n> flash->erase_granule);\n> > +             rc = blocklevel_smart_erase(flash->bl, start,\n> > +                             flash->bl_info.erase_granule);\n> >               if (rc) {\n> >                       fprintf(stderr, \"Failed to\n> blocklevel_smart_erase(): %d\\n\", rc);\n> >                       return 1;\n> >               }\n> > -             start += flash->erase_granule;\n> > -             size -= flash->erase_granule;\n> > -             done += flash->erase_granule;\n> > +             start += flash->bl_info.erase_granule;\n> > +             size -= flash->bl_info.erase_granule;\n> > +             done += flash->bl_info.erase_granule;\n> >               progress_tick(done);\n> >       }\n> >       if (size) {\n> > @@ -1003,8 +1004,7 @@ int main(int argc, char *argv[])\n> >               goto out;\n> >       }\n> >\n> > -     rc = blocklevel_get_info(flash.bl, &flash.name,\n> > -                         &flash.total_size, &flash.erase_granule);\n> > +     rc = blocklevel_get_info(flash.bl, &flash.bl_info);\n> >       if (rc) {\n> >               fprintf(stderr, \"Error %d getting flash info\\n\", rc);\n> >               rc = 1;\n> > @@ -1025,7 +1025,7 @@ int main(int argc, char *argv[])\n> >\n> >       /* If read specified and no read_size, use flash size */\n> >       if (do_read && !read_size && !part_name)\n> > -             read_size = flash.total_size;\n> > +             read_size = flash.bl_info.size;\n> >\n> >       /* We have a partition, adjust read/write size if needed */\n> >       if (part_name || print_detail) {\n> > @@ -1087,7 +1087,7 @@ int main(int argc, char *argv[])\n> >               /* Set address */\n> >               address = pstart;\n> >       } else if (erase) {\n> > -             if ((address | write_size) & (flash.erase_granule - 1)) {\n> > +             if ((address | write_size) & (flash.bl_info.erase_granule\n> - 1)) {\n> >                       if (must_confirm) {\n> >                               printf(\"ERROR: Erase at 0x%08x for 0x%08x\n> isn't erase block aligned\\n\",\n> >                                               address, write_size);\n> > diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c\n> > index 33d5c5d2f..3955be823 100644\n> > --- a/libflash/blocklevel.c\n> > +++ b/libflash/blocklevel.c\n> > @@ -229,12 +229,11 @@ int blocklevel_erase(struct blocklevel_device *bl,\n> uint64_t pos, uint64_t len)\n> >       return rc;\n> >  }\n> >\n> > -int blocklevel_get_info(struct blocklevel_device *bl, const char\n> **name, uint64_t *total_size,\n> > -             uint32_t *erase_granule)\n> > +int blocklevel_get_info(struct blocklevel_device *bl, struct\n> blocklevel_info *bl_info)\n> >  {\n> >       int rc;\n> >\n> > -     if (!bl || !bl->get_info) {\n> > +     if (!bl || !bl->get_info || !bl_info) {\n> >               errno = EINVAL;\n> >               return FLASH_ERR_PARM_ERROR;\n> >       }\n> > @@ -243,12 +242,12 @@ int blocklevel_get_info(struct blocklevel_device\n> *bl, const char **name, uint64_\n> >       if (rc)\n> >               return rc;\n> >\n> > -     rc = bl->get_info(bl, name, total_size, erase_granule);\n> > +     rc = bl->get_info(bl, bl_info);\n> >\n> >       /* Check the validity of what we are being told */\n> > -     if (erase_granule && *erase_granule != bl->erase_mask + 1)\n> > +     if (bl_info->erase_granule != bl->erase_mask + 1)\n> >               FL_ERR(\"blocklevel_get_info: WARNING: erase_granule\n> (0x%08x) and erase_mask\"\n> > -                             \" (0x%08x) don't match\\n\", *erase_granule,\n> bl->erase_mask + 1);\n> > +                             \" (0x%08x) don't match\\n\",\n> bl_info->erase_granule, bl->erase_mask + 1);\n> >\n> >       release(bl);\n> >\n> > @@ -417,7 +416,7 @@ out:\n> >\n> >  int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos,\n> const void *buf, uint64_t len)\n> >  {\n> > -     uint32_t erase_size;\n> > +     struct blocklevel_info bl_info;\n> >       const void *write_buf = buf;\n> >       void *write_buf_start = NULL;\n> >       void *erase_buf;\n> > @@ -435,7 +434,7 @@ int blocklevel_smart_write(struct blocklevel_device\n> *bl, uint64_t pos, const voi\n> >               return blocklevel_write(bl, pos, buf, len);\n> >       }\n> >\n> > -     rc = blocklevel_get_info(bl, NULL, NULL, &erase_size);\n> > +     rc = blocklevel_get_info(bl, &bl_info);\n> >       if (rc)\n> >               return rc;\n> >\n> > @@ -458,7 +457,7 @@ int blocklevel_smart_write(struct blocklevel_device\n> *bl, uint64_t pos, const voi\n> >               write_buf = write_buf_start;\n> >       }\n> >\n> > -     erase_buf = malloc(erase_size);\n> > +     erase_buf = malloc(bl_info.erase_granule);\n> >       if (!erase_buf) {\n> >               errno = ENOMEM;\n> >               rc = FLASH_ERR_MALLOC_FAILED;\n> > @@ -470,32 +469,32 @@ int blocklevel_smart_write(struct\n> blocklevel_device *bl, uint64_t pos, const voi\n> >               goto out_free;\n> >\n> >       while (len > 0) {\n> > -             uint32_t erase_block = pos & ~(erase_size - 1);\n> > -             uint32_t block_offset = pos & (erase_size - 1);\n> > -             uint32_t size = erase_size > len ? len : erase_size;\n> > +             uint32_t erase_block = pos & ~(bl_info.erase_granule - 1);\n> > +             uint32_t block_offset = pos & (bl_info.erase_granule - 1);\n> > +             uint32_t size = bl_info.erase_granule > len ? len :\n> bl_info.erase_granule;\n> >               int cmp;\n> >\n> >               /* Write crosses an erase boundary, shrink the write to\n> the boundary */\n> > -             if (erase_size < block_offset + size) {\n> > -                     size = erase_size - block_offset;\n> > +             if (bl_info.erase_granule < block_offset + size) {\n> > +                     size = bl_info.erase_granule - block_offset;\n> >               }\n> >\n> > -             rc = bl->read(bl, erase_block, erase_buf, erase_size);\n> > +             rc = bl->read(bl, erase_block, erase_buf,\n> bl_info.erase_granule);\n> >               if (rc)\n> >                       goto out;\n> >\n> >               cmp = blocklevel_flashcmp(erase_buf + block_offset,\n> write_buf, size);\n> >               FL_DBG(\"%s: region 0x%08x..0x%08x \", __func__,\n> > -                             erase_block, erase_size);\n> > +                             erase_block, bl_info.erase_granule);\n> >               if (cmp != 0) {\n> >                       FL_DBG(\"needs \");\n> >                       if (cmp == -1) {\n> >                               FL_DBG(\"erase and \");\n> > -                             bl->erase(bl, erase_block, erase_size);\n> > +                             bl->erase(bl, erase_block,\n> bl_info.erase_granule);\n> >                       }\n> >                       FL_DBG(\"write\\n\");\n> >                       memcpy(erase_buf + block_offset, write_buf, size);\n> > -                     rc = bl->write(bl, erase_block, erase_buf,\n> erase_size);\n> > +                     rc = bl->write(bl, erase_block, erase_buf,\n> bl_info.erase_granule);\n> >                       if (rc)\n> >                               goto out;\n> >               }\n> > diff --git a/libflash/blocklevel.h b/libflash/blocklevel.h\n> > index ba42c83d0..d2d269054 100644\n> > --- a/libflash/blocklevel.h\n> > +++ b/libflash/blocklevel.h\n> > @@ -34,6 +34,15 @@ enum blocklevel_flags {\n> >       WRITE_NEED_ERASE = 1,\n> >  };\n> >\n> > +struct blocklevel_info {\n> > +     /* name is not owned by this struct and must persist for the\n> > +      * liftime of blocklevel_info\n> > +      */\n> > +     const char *name;\n> > +     uint64_t size;\n> > +     uint32_t erase_granule;\n> > +};\n> > +\n> >  /*\n> >   * libffs may be used with different backends, all should provide these\n> for\n> >   * libflash to get the information it needs\n> > @@ -45,8 +54,7 @@ struct blocklevel_device {\n> >       int (*read)(struct blocklevel_device *bl, uint64_t pos, void *buf,\n> uint64_t len);\n> >       int (*write)(struct blocklevel_device *bl, uint64_t pos, const\n> void *buf, uint64_t len);\n> >       int (*erase)(struct blocklevel_device *bl, uint64_t pos, uint64_t\n> len);\n> > -     int (*get_info)(struct blocklevel_device *bl, const char **name,\n> uint64_t *total_size,\n> > -                     uint32_t *erase_granule);\n> > +     int (*get_info)(struct blocklevel_device *bl, struct\n> blocklevel_info *bl_info);\n> >\n> >       /*\n> >        * Keep the erase mask so that blocklevel_erase() can do sanity\n> checking\n> > @@ -62,8 +70,8 @@ int blocklevel_read(struct blocklevel_device *bl,\n> uint64_t pos, void *buf, uint6\n> >  int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos,\n> const void *buf, uint64_t len);\n> >  int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const\n> void *buf, uint64_t len);\n> >  int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos,\n> uint64_t len);\n> > -int blocklevel_get_info(struct blocklevel_device *bl, const char\n> **name, uint64_t *total_size,\n> > -             uint32_t *erase_granule);\n> > +\n> > +int blocklevel_get_info(struct blocklevel_device *bl, struct\n> blocklevel_info *bl_info);\n> >\n> >  /*\n> >   * blocklevel_smart_write() performs reads on the data to see if it\n> > diff --git a/libflash/file.c b/libflash/file.c\n> > index 7065eb4fa..b87679cd1 100644\n> > --- a/libflash/file.c\n> > +++ b/libflash/file.c\n> > @@ -212,6 +212,7 @@ static int get_info_name(struct file_data\n> *file_data, char **name)\n> >       }\n> >       lpath[len] = '\\0';\n> >\n> > +     free(*name);\n> >       *name = lpath;\n> >\n> >       free(path);\n> > @@ -219,8 +220,8 @@ static int get_info_name(struct file_data\n> *file_data, char **name)\n> >  }\n> >\n> >\n> > -static int mtd_get_info(struct blocklevel_device *bl, const char **name,\n> > -             uint64_t *total_size, uint32_t *erase_granule)\n> > +static int mtd_get_info(struct blocklevel_device *bl,\n> > +             struct blocklevel_info *bl_info)\n> >  {\n> >       struct file_data *file_data = container_of(bl, struct file_data,\n> bl);\n> >       struct mtd_info_user mtd_info;\n> > @@ -230,24 +231,19 @@ static int mtd_get_info(struct blocklevel_device\n> *bl, const char **name,\n> >       if (rc == -1)\n> >               return FLASH_ERR_BAD_READ;\n> >\n> > -     if (total_size)\n> > -             *total_size = mtd_info.size;\n> > -\n> > -     if (erase_granule)\n> > -             *erase_granule = mtd_info.erasesize;\n> > +     rc = get_info_name(file_data, &(file_data->name));\n> > +     if (rc)\n> > +             return rc;\n> >\n> > -     if (name) {\n> > -             rc = get_info_name(file_data, &(file_data->name));\n> > -             if (rc)\n> > -                     return rc;\n> > -             *name = file_data->name;\n> > -     }\n> > +     bl_info->name = file_data->name;\n> > +     bl_info->size = mtd_info.size;\n> > +     bl_info->erase_granule = mtd_info.erasesize;\n> >\n> >       return 0;\n> >  }\n> >\n> > -static int file_get_info(struct blocklevel_device *bl, const char\n> **name,\n> > -             uint64_t *total_size, uint32_t *erase_granule)\n> > +static int file_get_info(struct blocklevel_device *bl,\n> > +             struct blocklevel_info *bl_info)\n> >  {\n> >       struct file_data *file_data = container_of(bl, struct file_data,\n> bl);\n> >       struct stat st;\n> > @@ -256,18 +252,13 @@ static int file_get_info(struct blocklevel_device\n> *bl, const char **name,\n> >       if (fstat(file_data->fd, &st))\n> >               return FLASH_ERR_PARM_ERROR;\n> >\n> > -     if (total_size)\n> > -             *total_size = st.st_size;\n> > -\n> > -     if (erase_granule)\n> > -             *erase_granule = 1;\n> > +     rc = get_info_name(file_data, &(file_data->name));\n> > +     if (rc)\n> > +             return rc;\n> >\n> > -     if (name) {\n> > -             rc = get_info_name(file_data, &(file_data->name));\n> > -             if (rc)\n> > -                     return rc;\n> > -             *name = file_data->name;\n> > -     }\n> > +     bl_info->name = file_data->name;\n> > +     bl_info->size = st.st_size;\n> > +     bl_info->erase_granule = 1;\n> >\n> >       return 0;\n> >  }\n> > @@ -315,8 +306,9 @@ int file_init(int fd, struct blocklevel_device **bl)\n> >               file_data->bl.erase = &mtd_erase;\n> >               file_data->bl.get_info = &mtd_get_info;\n> >               file_data->bl.flags = WRITE_NEED_ERASE;\n> > -             mtd_get_info(&file_data->bl, NULL, NULL,\n> &(file_data->bl.erase_mask));\n> > -             file_data->bl.erase_mask--;\n> > +             struct blocklevel_info bl_info;\n> > +             mtd_get_info(&file_data->bl, &bl_info);\n> > +             file_data->bl.erase_mask = bl_info.erase_granule - 1;\n> >       } else if (!S_ISREG(sbuf.st_mode)) {\n> >               /* If not a char device or a regular file something went\n> wrong */\n> >               goto out;\n> > diff --git a/libflash/libffs.c b/libflash/libffs.c\n> > index 038f59425..6fc23eee9 100644\n> > --- a/libflash/libffs.c\n> > +++ b/libflash/libffs.c\n> > @@ -216,25 +216,25 @@ int ffs_init(uint32_t offset, uint32_t max_size,\n> struct blocklevel_device *bl,\n> >  {\n> >       struct __ffs_hdr blank_hdr;\n> >       struct __ffs_hdr raw_hdr;\n> > +     struct blocklevel_info bl_info;\n> >       struct ffs_handle *f;\n> > -     uint64_t total_size;\n> >       int rc, i;\n> >\n> >       if (!ffs || !bl)\n> >               return FLASH_ERR_PARM_ERROR;\n> >       *ffs = NULL;\n> >\n> > -     rc = blocklevel_get_info(bl, NULL, &total_size, NULL);\n> > +     rc = blocklevel_get_info(bl, &bl_info);\n> >       if (rc) {\n> >               FL_ERR(\"FFS: Error %d retrieving flash info\\n\", rc);\n> >               return rc;\n> >       }\n> > -     if (total_size > UINT_MAX)\n> > +     if (bl_info.size > UINT_MAX)\n> >               return FLASH_ERR_VERIFY_FAILURE;\n> >       if ((offset + max_size) < offset)\n> >               return FLASH_ERR_PARM_ERROR;\n> >\n> > -     if ((max_size > total_size))\n> > +     if ((max_size > bl_info.size))\n> >               return FLASH_ERR_PARM_ERROR;\n> >\n> >       /* Read flash header */\n> > diff --git a/libflash/libflash.c b/libflash/libflash.c\n> > index 38f87b86e..82a2baecc 100644\n> > --- a/libflash/libflash.c\n> > +++ b/libflash/libflash.c\n> > @@ -792,16 +792,15 @@ static int flash_configure(struct flash_chip *c)\n> >       return 0;\n> >  }\n> >\n> > -static int flash_get_info(struct blocklevel_device *bl, const char\n> **name,\n> > -                uint64_t *total_size, uint32_t *erase_granule)\n> > +static int flash_get_info(struct blocklevel_device *bl,\n> > +             struct blocklevel_info *bl_info)\n> >  {\n> >       struct flash_chip *c = container_of(bl, struct flash_chip, bl);\n> > -     if (name)\n> > -             *name = c->info.name;\n> > -     if (total_size)\n> > -             *total_size = c->tsize;\n> > -     if (erase_granule)\n> > -             *erase_granule = c->min_erase_mask + 1;\n> > +\n> > +     bl_info->name = c->info.name;\n> > +     bl_info->size = c->tsize;\n> > +     bl_info->erase_granule = c->min_erase_mask + 1;\n> > +\n> >       return 0;\n> >  }\n> >\n> > diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c\n> > index 950e24f05..d4200ce53 100644\n> > --- a/libflash/mbox-flash.c\n> > +++ b/libflash/mbox-flash.c\n> > @@ -745,8 +745,8 @@ static int mbox_flash_read(struct blocklevel_device\n> *bl, uint64_t pos,\n> >       return rc;\n> >  }\n> >\n> > -static int mbox_flash_get_info(struct blocklevel_device *bl, const char\n> **name,\n> > -             uint64_t *total_size, uint32_t *erase_granule)\n> > +static int mbox_flash_get_info(struct blocklevel_device *bl,\n> > +             struct blocklevel_info *bl_info)\n> >  {\n> >       struct mbox_flash_data *mbox_flash;\n> >       struct bmc_mbox_msg *msg;\n> > @@ -761,14 +761,7 @@ static int mbox_flash_get_info(struct\n> blocklevel_device *bl, const char **name,\n> >       if (!msg)\n> >               return FLASH_ERR_MALLOC_FAILED;\n> >\n> > -     /*\n> > -      * We want to avoid runtime mallocs in skiboot. The expected\n> > -      * behavour to uses of libflash is that one can free() the memory\n> > -      * returned.\n> > -      * NULL will do for now.\n> > -      */\n> > -     if (name)\n> > -             *name = NULL;\n> > +     bl_info->name = \"pnor_mbox\";\n> >\n> >       mbox_flash->busy = true;\n> >       rc = msg_send(mbox_flash, msg);\n> > @@ -784,10 +777,8 @@ static int mbox_flash_get_info(struct\n> blocklevel_device *bl, const char **name,\n> >\n> >       mbox_flash->bl.erase_mask = mbox_flash->erase_granule - 1;\n> >\n> > -     if (total_size)\n> > -             *total_size = mbox_flash->total_size;\n> > -     if (erase_granule)\n> > -             *erase_granule = mbox_flash->erase_granule;\n> > +     bl_info->size = mbox_flash->total_size;\n> > +     bl_info->erase_granule = mbox_flash->erase_granule;\n> >\n> >  out:\n> >       msg_free_memory(msg);\n> > diff --git a/libflash/test/test-flash.c b/libflash/test/test-flash.c\n> > index 3f77d6f3e..1ca467bb0 100644\n> > --- a/libflash/test/test-flash.c\n> > +++ b/libflash/test/test-flash.c\n> > @@ -367,9 +367,7 @@ struct spi_flash_ctrl sim_ctrl = {\n> >  int main(void)\n> >  {\n> >       struct blocklevel_device *bl;\n> > -     uint64_t total_size;\n> > -     uint32_t erase_granule;\n> > -     const char *name;\n> > +     struct blocklevel_info bl_info;\n> >       uint16_t *test;\n> >       struct ecc64 *ecc_test;\n> >       uint64_t *test64;\n> > @@ -384,7 +382,7 @@ int main(void)\n> >               ERR(\"flash_init failed with err %d\\n\", rc);\n> >               exit(1);\n> >       }\n> > -     rc = flash_get_info(bl, &name, &total_size, &erase_granule);\n> > +     rc = flash_get_info(bl, &bl_info);\n> >       if (rc) {\n> >               ERR(\"flash_get_info failed with err %d\\n\", rc);\n> >               exit(1);\n> > diff --git a/platforms/mambo/mambo.c b/platforms/mambo/mambo.c\n> > index cb6e103cc..dd7872a8e 100644\n> > --- a/platforms/mambo/mambo.c\n> > +++ b/platforms/mambo/mambo.c\n> > @@ -125,19 +125,14 @@ static int bogus_disk_erase(struct\n> blocklevel_device *bl __unused,\n> >       return 0; /* NOP */\n> >  }\n> >\n> > -static int bogus_disk_get_info(struct blocklevel_device *bl, const char\n> **name,\n> > -                           uint64_t *total_size, uint32_t\n> *erase_granule)\n> > +static int bogus_disk_get_info(struct blocklevel_device *bl,\n> > +                     struct blocklevel_info *bl_info)\n> >  {\n> >       struct bogus_disk_info *bdi = bl->priv;\n> >\n> > -     if (total_size)\n> > -             *total_size = bdi->size;\n> > -\n> > -     if (erase_granule)\n> > -             *erase_granule = BD_SECT_SZ;\n> > -\n> > -     if (name)\n> > -             *name = \"mambobogus\";\n> > +     bl_info->name = \"mambobogus\";\n> > +     bl_info->size = bdi->size;\n> > +     bl_info->erase_granule = BD_SECT_SZ;\n> >\n> >       return 0;\n> >  }\n>\n<div dir=\"ltr\">Cyril,<div><br></div><div>Sounds good. I actually wrote this up a couple of months back, but I&#39;d like to upstream as many of our changes as possible. It just occurred to me that we may not actually need this change at all to support one of the flash changes we made. It would be nice to clean up these interfaces though.</div></div><br><div class=\"gmail_quote\"><div dir=\"ltr\">On Mon, Aug 28, 2017 at 10:38 PM Cyril Bur &lt;<a href=\"mailto:cyrilbur@gmail.com\">cyrilbur@gmail.com</a>&gt; wrote:<br></div><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">On Mon, 2017-08-28 at 21:19 -0700, William A. Kennington III wrote:<br>\n&gt; This changes refactors all of the output variables from flash_get_info<br>\n&gt; into a new output struct. Callers now supply the info struct, and always<br>\n&gt; get all of the info with each call. There are never any allocations done<br>\n&gt; by this function so it shouldn&#39;t be much slower to always populate all<br>\n&gt; of the information.<br>\n&gt;<br>\n<br>\nHi William,<br>\n<br>\nAs nice as this refactor is (thanks for the effort!), unfortunately<br>\nwe&#39;re a bit stuck with the interface as is, both openbmc and petitboot<br>\nprojects link against a dynamic libflash.<br>\n<br>\nIronically I&#39;m about to send a series which which does rework the<br>\nlibffs api a bit - although I&#39;m quite sure only external/ffspart<br>\nactually uses what I&#39;ve changed. blocklevel_get_info() though is pretty<br>\ncore and changing that won&#39;t work.<br>\n<br>\nPerhaps you&#39;ve prompted a discussion that now might be a good time to<br>\ndo a significant rewrite of libflash/libffs which are now being used<br>\nfor a completely different purpose for which they were first written,<br>\nhopefully Stewart will weigh in.<br>\n<br>\n<br>\nCyril<br>\n<br>\n&gt; Signed-off-by: William A. Kennington III &lt;<a href=\"mailto:wak@google.com\" target=\"_blank\">wak@google.com</a>&gt;<br>\n&gt; ---<br>\n&gt;  core/flash.c                           | 15 +++++------<br>\n&gt;  external/common/arch_flash_arm.c       |  6 ++---<br>\n&gt;  external/common/arch_flash_common.c    |  6 ++---<br>\n&gt;  external/gard/gard.c                   | 10 +++----<br>\n&gt;  external/opal-prd/pnor.c               | 12 ++++-----<br>\n&gt;  external/opal-prd/pnor.h               |  3 +--<br>\n&gt;  external/opal-prd/test/test_pnor_ops.c |  7 +++--<br>\n&gt;  external/pflash/pflash.c               | 46 ++++++++++++++++----------------<br>\n&gt;  libflash/blocklevel.c                  | 35 ++++++++++++-------------<br>\n&gt;  libflash/blocklevel.h                  | 16 +++++++++---<br>\n&gt;  libflash/file.c                        | 48 ++++++++++++++--------------------<br>\n&gt;  libflash/libffs.c                      |  8 +++---<br>\n&gt;  libflash/libflash.c                    | 15 +++++------<br>\n&gt;  libflash/mbox-flash.c                  | 19 ++++----------<br>\n&gt;  libflash/test/test-flash.c             |  6 ++---<br>\n&gt;  platforms/mambo/mambo.c                | 15 ++++-------<br>\n&gt;  16 files changed, 125 insertions(+), 142 deletions(-)<br>\n&gt;<br>\n&gt; diff --git a/core/flash.c b/core/flash.c<br>\n&gt; index 53e6eba08..35a0c4c32 100644<br>\n&gt; --- a/core/flash.c<br>\n&gt; +++ b/core/flash.c<br>\n&gt; @@ -254,21 +254,20 @@ static int num_flashes(void)<br>\n&gt;<br>\n&gt;  int flash_register(struct blocklevel_device *bl)<br>\n&gt;  {<br>\n&gt; -     uint64_t size;<br>\n&gt; -     uint32_t block_size;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       struct ffs_handle *ffs;<br>\n&gt;       struct dt_node *node;<br>\n&gt;       struct flash *flash;<br>\n&gt; -     const char *name;<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(bl, &amp;name, &amp;size, &amp;block_size);<br>\n&gt; +     rc = blocklevel_get_info(bl, &amp;bl_info);<br>\n&gt;       if (rc)<br>\n&gt;               return rc;<br>\n&gt;<br>\n&gt;       prlog(PR_INFO, &quot;FLASH: registering flash device %s &quot;<br>\n&gt;                       &quot;(size 0x%llx, blocksize 0x%x)\\n&quot;,<br>\n&gt; -                     name ?: &quot;(unnamed)&quot;, size, block_size);<br>\n&gt; +                     <a href=\"http://bl_info.name\" rel=\"noreferrer\" target=\"_blank\">bl_info.name</a> ? <a href=\"http://bl_info.name\" rel=\"noreferrer\" target=\"_blank\">bl_info.name</a> : &quot;(unnamed)&quot;, bl_info.size,<br>\n&gt; +                     bl_info.erase_granule);<br>\n&gt;<br>\n&gt;       lock(&amp;flash_lock);<br>\n&gt;<br>\n&gt; @@ -281,8 +280,8 @@ int flash_register(struct blocklevel_device *bl)<br>\n&gt;<br>\n&gt;       flash-&gt;busy = false;<br>\n&gt;       flash-&gt;bl = bl;<br>\n&gt; -     flash-&gt;size = size;<br>\n&gt; -     flash-&gt;block_size = block_size;<br>\n&gt; +     flash-&gt;size = bl_info.size;<br>\n&gt; +     flash-&gt;block_size = bl_info.erase_granule;<br>\n&gt;       flash-&gt;id = num_flashes();<br>\n&gt;<br>\n&gt;       list_add(&amp;flashes, &amp;flash-&gt;list);<br>\n&gt; @@ -302,7 +301,7 @@ int flash_register(struct blocklevel_device *bl)<br>\n&gt;<br>\n&gt;       node = flash_add_dt_node(flash, flash-&gt;id);<br>\n&gt;<br>\n&gt; -     setup_system_flash(flash, node, name, ffs);<br>\n&gt; +     setup_system_flash(flash, node, <a href=\"http://bl_info.name\" rel=\"noreferrer\" target=\"_blank\">bl_info.name</a>, ffs);<br>\n&gt;<br>\n&gt;       if (ffs)<br>\n&gt;               ffs_close(ffs);<br>\n&gt; diff --git a/external/common/arch_flash_arm.c b/external/common/arch_flash_arm.c<br>\n&gt; index 3cdd41ded..ac43de0c4 100644<br>\n&gt; --- a/external/common/arch_flash_arm.c<br>\n&gt; +++ b/external/common/arch_flash_arm.c<br>\n&gt; @@ -303,13 +303,13 @@ int arch_flash_erase_chip(struct blocklevel_device *bl)<br>\n&gt;       if (!arch_data.flash_chip) {<br>\n&gt;               /* Just assume its a regular erase */<br>\n&gt;               int rc;<br>\n&gt; -             uint64_t total_size;<br>\n&gt; +             struct blocklevel_info bl_info;<br>\n&gt;<br>\n&gt; -             rc = blocklevel_get_info(bl, NULL, &amp;total_size, NULL);<br>\n&gt; +             rc = blocklevel_get_info(bl, &amp;bl_info);<br>\n&gt;               if (rc)<br>\n&gt;                       return rc;<br>\n&gt;<br>\n&gt; -             return blocklevel_erase(bl, 0, total_size);<br>\n&gt; +             return blocklevel_erase(bl, 0, bl_info.size);<br>\n&gt;       }<br>\n&gt;<br>\n&gt;       return flash_erase_chip(arch_data.flash_chip);<br>\n&gt; diff --git a/external/common/arch_flash_common.c b/external/common/arch_flash_common.c<br>\n&gt; index 6bce7e1ba..41239662a 100644<br>\n&gt; --- a/external/common/arch_flash_common.c<br>\n&gt; +++ b/external/common/arch_flash_common.c<br>\n&gt; @@ -31,13 +31,13 @@<br>\n&gt;  int __attribute__((weak)) arch_flash_erase_chip(struct blocklevel_device *bl)<br>\n&gt;  {<br>\n&gt;       int rc;<br>\n&gt; -     uint64_t total_size;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(bl, NULL, &amp;total_size, NULL);<br>\n&gt; +     rc = blocklevel_get_info(bl, &amp;bl_info);<br>\n&gt;       if (rc)<br>\n&gt;               return rc;<br>\n&gt;<br>\n&gt; -     return blocklevel_erase(bl, 0, total_size);<br>\n&gt; +     return blocklevel_erase(bl, 0, bl_info.size);<br>\n&gt;  }<br>\n&gt;<br>\n&gt;  int __attribute__((weak,const)) arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b)<br>\n&gt; diff --git a/external/gard/gard.c b/external/gard/gard.c<br>\n&gt; index c5cb93b88..3946cad6f 100644<br>\n&gt; --- a/external/gard/gard.c<br>\n&gt; +++ b/external/gard/gard.c<br>\n&gt; @@ -596,7 +596,7 @@ int main(int argc, char **argv)<br>\n&gt;       const char *action, *progname;<br>\n&gt;       char *filename = NULL;<br>\n&gt;       struct gard_ctx _ctx, *ctx;<br>\n&gt; -     uint64_t bl_size;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       int rc, i = 0;<br>\n&gt;       bool part = 0;<br>\n&gt;       bool ecc = 0;<br>\n&gt; @@ -665,17 +665,17 @@ int main(int argc, char **argv)<br>\n&gt;               goto out_free;<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(ctx-&gt;bl, NULL, &amp;bl_size, NULL);<br>\n&gt; +     rc = blocklevel_get_info(ctx-&gt;bl, &amp;bl_info);<br>\n&gt;       if (rc)<br>\n&gt;               goto out;<br>\n&gt;<br>\n&gt; -     if (bl_size &gt; UINT_MAX) {<br>\n&gt; +     if (bl_info.size &gt; UINT_MAX) {<br>\n&gt;               fprintf(stderr, &quot;MTD device bigger than %i: size: %&quot; PRIu64 &quot;\\n&quot;,<br>\n&gt; -                     UINT_MAX, bl_size);<br>\n&gt; +                     UINT_MAX, bl_info.size);<br>\n&gt;               rc = EXIT_FAILURE;<br>\n&gt;               goto out;<br>\n&gt;       }<br>\n&gt; -     ctx-&gt;f_size = bl_size;<br>\n&gt; +     ctx-&gt;f_size = bl_info.size;<br>\n&gt;<br>\n&gt;       if (!part) {<br>\n&gt;               rc = ffs_init(0, ctx-&gt;f_size, ctx-&gt;bl, &amp;ctx-&gt;ffs, 1);<br>\n&gt; diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c<br>\n&gt; index c032421d1..afb6ccd1f 100644<br>\n&gt; --- a/external/opal-prd/pnor.c<br>\n&gt; +++ b/external/opal-prd/pnor.c<br>\n&gt; @@ -64,13 +64,13 @@ int pnor_init(struct pnor *pnor)<br>\n&gt;               return -1;<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(pnor-&gt;bl, NULL, &amp;(pnor-&gt;size), &amp;(pnor-&gt;erasesize));<br>\n&gt; +     rc = blocklevel_get_info(pnor-&gt;bl, &amp;pnor-&gt;bl_info);<br>\n&gt;       if (rc) {<br>\n&gt;               pr_log(LOG_ERR, &quot;PNOR: blocklevel_get_info() failed. Can&#39;t use PNOR&quot;);<br>\n&gt;               goto out;<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     rc = ffs_init(0, pnor-&gt;size, pnor-&gt;bl, &amp;pnor-&gt;ffsh, 0);<br>\n&gt; +     rc = ffs_init(0, pnor-&gt;bl_info.size, pnor-&gt;bl, &amp;pnor-&gt;ffsh, 0);<br>\n&gt;       if (rc) {<br>\n&gt;               pr_log(LOG_ERR, &quot;PNOR: Failed to open pnor partition table&quot;);<br>\n&gt;               goto out;<br>\n&gt; @@ -121,8 +121,8 @@ static int mtd_write(struct pnor *pnor, void *data, uint64_t offset,<br>\n&gt;  {<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; -     if (len &gt; pnor-&gt;size || offset &gt; pnor-&gt;size ||<br>\n&gt; -         len + offset &gt; pnor-&gt;size)<br>\n&gt; +     if (len &gt; pnor-&gt;bl_info.size || offset &gt; pnor-&gt;bl_info.size ||<br>\n&gt; +         len + offset &gt; pnor-&gt;bl_info.size)<br>\n&gt;               return -ERANGE;<br>\n&gt;<br>\n&gt;       rc = blocklevel_smart_write(pnor-&gt;bl, offset, data, len);<br>\n&gt; @@ -137,8 +137,8 @@ static int mtd_read(struct pnor *pnor, void *data, uint64_t offset,<br>\n&gt;  {<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; -     if (len &gt; pnor-&gt;size || offset &gt; pnor-&gt;size ||<br>\n&gt; -         len + offset &gt; pnor-&gt;size)<br>\n&gt; +     if (len &gt; pnor-&gt;bl_info.size || offset &gt; pnor-&gt;bl_info.size ||<br>\n&gt; +         len + offset &gt; pnor-&gt;bl_info.size)<br>\n&gt;               return -ERANGE;<br>\n&gt;<br>\n&gt;       rc = blocklevel_read(pnor-&gt;bl, offset, data, len);<br>\n&gt; diff --git a/external/opal-prd/pnor.h b/external/opal-prd/pnor.h<br>\n&gt; index 28571af64..1ee033659 100644<br>\n&gt; --- a/external/opal-prd/pnor.h<br>\n&gt; +++ b/external/opal-prd/pnor.h<br>\n&gt; @@ -7,8 +7,7 @@<br>\n&gt;  struct pnor {<br>\n&gt;       char                    *path;<br>\n&gt;       struct ffs_handle       *ffsh;<br>\n&gt; -     uint64_t                size;<br>\n&gt; -     uint32_t                erasesize;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       struct blocklevel_device *bl;<br>\n&gt;  };<br>\n&gt;<br>\n&gt; diff --git a/external/opal-prd/test/test_pnor_ops.c b/external/opal-prd/test/test_pnor_ops.c<br>\n&gt; index fd5e2c22a..3743362e1 100644<br>\n&gt; --- a/external/opal-prd/test/test_pnor_ops.c<br>\n&gt; +++ b/external/opal-prd/test/test_pnor_ops.c<br>\n&gt; @@ -130,11 +130,14 @@ int main(int argc, char **argv)<br>\n&gt;       for (i = 0; i &lt; 2; i++)<br>\n&gt;               write(fd, data, 16);<br>\n&gt;<br>\n&gt; +     /* Unused */<br>\n&gt; +     <a href=\"http://pnor.bl_info.name\" rel=\"noreferrer\" target=\"_blank\">pnor.bl_info.name</a> = NULL;<br>\n&gt; +<br>\n&gt;       /* Adjust this if making the file smaller */<br>\n&gt; -     pnor.size = 32;<br>\n&gt; +     pnor.bl_info.size = 32;<br>\n&gt;<br>\n&gt;       /* This is fake. Make it smaller than the size */<br>\n&gt; -     pnor.erasesize = 4;<br>\n&gt; +     pnor.bl_info.erase_granule = 4;<br>\n&gt;<br>\n&gt;       printf(&quot;Write: &quot;);<br>\n&gt;       memset(data, &#39;A&#39;, sizeof(data));<br>\n&gt; diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c<br>\n&gt; index bfc975fe5..3f501e583 100644<br>\n&gt; --- a/external/pflash/pflash.c<br>\n&gt; +++ b/external/pflash/pflash.c<br>\n&gt; @@ -43,11 +43,9 @@<br>\n&gt;<br>\n&gt;  struct flash_details {<br>\n&gt;       struct blocklevel_device *bl;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       int need_relock;<br>\n&gt; -     const char *name;<br>\n&gt;       uint64_t toc;<br>\n&gt; -     uint64_t total_size;<br>\n&gt; -     uint32_t erase_granule;<br>\n&gt;  };<br>\n&gt;<br>\n&gt;  /* Full pflash version number (possibly includes gitid). */<br>\n&gt; @@ -144,7 +142,7 @@ static struct ffs_handle *open_ffs(struct flash_details *flash)<br>\n&gt;       struct ffs_handle *ffsh;<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; -     rc = ffs_init(flash-&gt;toc, flash-&gt;total_size,<br>\n&gt; +     rc = ffs_init(flash-&gt;toc, flash-&gt;bl_info.size,<br>\n&gt;                       flash-&gt;bl, &amp;ffsh, 0);<br>\n&gt;       if (rc) {<br>\n&gt;               fprintf(stderr, &quot;Error %d opening ffs !\\n&quot;, rc);<br>\n&gt; @@ -166,11 +164,11 @@ static void print_flash_info(struct flash_details *flash)<br>\n&gt;<br>\n&gt;       printf(&quot;Flash info:\\n&quot;);<br>\n&gt;       printf(&quot;-----------\\n&quot;);<br>\n&gt; -     printf(&quot;Name          = %s\\n&quot;, flash-&gt;name);<br>\n&gt; +     printf(&quot;Name          = %s\\n&quot;, flash-&gt;<a href=\"http://bl_info.name\" rel=\"noreferrer\" target=\"_blank\">bl_info.name</a>);<br>\n&gt;       printf(&quot;Total size    = %&quot; PRIu64 &quot;MB\\t Flags E:ECC, P:PRESERVED, R:READONLY\\n&quot;,<br>\n&gt; -                     flash-&gt;total_size &gt;&gt; 20);<br>\n&gt; +                     flash-&gt;bl_info.size &gt;&gt; 20);<br>\n&gt;       printf(&quot;Erase granule = %2d%-13sB:BACKUP, F:REPROVISION\\n&quot;,<br>\n&gt; -                     flash-&gt;erase_granule &gt;&gt; 10, &quot;KB&quot;);<br>\n&gt; +                     flash-&gt;bl_info.erase_granule &gt;&gt; 10, &quot;KB&quot;);<br>\n&gt;<br>\n&gt;       if (bmc_flash)<br>\n&gt;               return;<br>\n&gt; @@ -282,9 +280,11 @@ static int erase_chip(struct flash_details *flash)<br>\n&gt;        * likes the progress bars.<br>\n&gt;        * Lets do an erase block at a time erase then...<br>\n&gt;        */<br>\n&gt; -     progress_init(flash-&gt;total_size);<br>\n&gt; -     for (pos = 0; pos &lt; flash-&gt;total_size; pos += flash-&gt;erase_granule) {<br>\n&gt; -             rc = blocklevel_erase(flash-&gt;bl, pos, flash-&gt;erase_granule);<br>\n&gt; +     progress_init(flash-&gt;bl_info.size);<br>\n&gt; +     for (pos = 0; pos &lt; flash-&gt;bl_info.size;<br>\n&gt; +                     pos += flash-&gt;bl_info.erase_granule) {<br>\n&gt; +             rc = blocklevel_erase(flash-&gt;bl, pos,<br>\n&gt; +                             flash-&gt;bl_info.erase_granule);<br>\n&gt;               if (rc)<br>\n&gt;                       break;<br>\n&gt;               progress_tick(pos);<br>\n&gt; @@ -303,7 +303,7 @@ static int erase_range(struct flash_details *flash,<br>\n&gt;               uint32_t start, uint32_t size, bool will_program,<br>\n&gt;               struct ffs_handle *ffsh, int ffs_index)<br>\n&gt;  {<br>\n&gt; -     uint32_t done = 0, erase_mask = flash-&gt;erase_granule - 1;<br>\n&gt; +     uint32_t done = 0, erase_mask = flash-&gt;bl_info.erase_granule - 1;<br>\n&gt;       bool confirm;<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; @@ -326,25 +326,26 @@ static int erase_range(struct flash_details *flash,<br>\n&gt;       if (start &amp; erase_mask) {<br>\n&gt;               /* Align to next erase block */<br>\n&gt;               rc = blocklevel_smart_erase(flash-&gt;bl, start,<br>\n&gt; -                             flash-&gt;erase_granule - (start &amp; erase_mask));<br>\n&gt; +                             flash-&gt;bl_info.erase_granule - (start &amp; erase_mask));<br>\n&gt;               if (rc) {<br>\n&gt;                       fprintf(stderr, &quot;Failed to blocklevel_smart_erase(): %d\\n&quot;, rc);<br>\n&gt;                       return 1;<br>\n&gt;               }<br>\n&gt; -             start += flash-&gt;erase_granule - (start &amp; erase_mask);<br>\n&gt; -             size -= flash-&gt;erase_granule - (start &amp; erase_mask);<br>\n&gt; -             done = flash-&gt;erase_granule - (start &amp; erase_mask);<br>\n&gt; +             start += flash-&gt;bl_info.erase_granule - (start &amp; erase_mask);<br>\n&gt; +             size -= flash-&gt;bl_info.erase_granule - (start &amp; erase_mask);<br>\n&gt; +             done = flash-&gt;bl_info.erase_granule - (start &amp; erase_mask);<br>\n&gt;       }<br>\n&gt;       progress_tick(done);<br>\n&gt;       while (size &amp; ~(erase_mask)) {<br>\n&gt; -             rc = blocklevel_smart_erase(flash-&gt;bl, start, flash-&gt;erase_granule);<br>\n&gt; +             rc = blocklevel_smart_erase(flash-&gt;bl, start,<br>\n&gt; +                             flash-&gt;bl_info.erase_granule);<br>\n&gt;               if (rc) {<br>\n&gt;                       fprintf(stderr, &quot;Failed to blocklevel_smart_erase(): %d\\n&quot;, rc);<br>\n&gt;                       return 1;<br>\n&gt;               }<br>\n&gt; -             start += flash-&gt;erase_granule;<br>\n&gt; -             size -= flash-&gt;erase_granule;<br>\n&gt; -             done += flash-&gt;erase_granule;<br>\n&gt; +             start += flash-&gt;bl_info.erase_granule;<br>\n&gt; +             size -= flash-&gt;bl_info.erase_granule;<br>\n&gt; +             done += flash-&gt;bl_info.erase_granule;<br>\n&gt;               progress_tick(done);<br>\n&gt;       }<br>\n&gt;       if (size) {<br>\n&gt; @@ -1003,8 +1004,7 @@ int main(int argc, char *argv[])<br>\n&gt;               goto out;<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(flash.bl, &amp;<a href=\"http://flash.name\" rel=\"noreferrer\" target=\"_blank\">flash.name</a>,<br>\n&gt; -                         &amp;flash.total_size, &amp;flash.erase_granule);<br>\n&gt; +     rc = blocklevel_get_info(flash.bl, &amp;flash.bl_info);<br>\n&gt;       if (rc) {<br>\n&gt;               fprintf(stderr, &quot;Error %d getting flash info\\n&quot;, rc);<br>\n&gt;               rc = 1;<br>\n&gt; @@ -1025,7 +1025,7 @@ int main(int argc, char *argv[])<br>\n&gt;<br>\n&gt;       /* If read specified and no read_size, use flash size */<br>\n&gt;       if (do_read &amp;&amp; !read_size &amp;&amp; !part_name)<br>\n&gt; -             read_size = flash.total_size;<br>\n&gt; +             read_size = flash.bl_info.size;<br>\n&gt;<br>\n&gt;       /* We have a partition, adjust read/write size if needed */<br>\n&gt;       if (part_name || print_detail) {<br>\n&gt; @@ -1087,7 +1087,7 @@ int main(int argc, char *argv[])<br>\n&gt;               /* Set address */<br>\n&gt;               address = pstart;<br>\n&gt;       } else if (erase) {<br>\n&gt; -             if ((address | write_size) &amp; (flash.erase_granule - 1)) {<br>\n&gt; +             if ((address | write_size) &amp; (flash.bl_info.erase_granule - 1)) {<br>\n&gt;                       if (must_confirm) {<br>\n&gt;                               printf(&quot;ERROR: Erase at 0x%08x for 0x%08x isn&#39;t erase block aligned\\n&quot;,<br>\n&gt;                                               address, write_size);<br>\n&gt; diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c<br>\n&gt; index 33d5c5d2f..3955be823 100644<br>\n&gt; --- a/libflash/blocklevel.c<br>\n&gt; +++ b/libflash/blocklevel.c<br>\n&gt; @@ -229,12 +229,11 @@ int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)<br>\n&gt;       return rc;<br>\n&gt;  }<br>\n&gt;<br>\n&gt; -int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,<br>\n&gt; -             uint32_t *erase_granule)<br>\n&gt; +int blocklevel_get_info(struct blocklevel_device *bl, struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       int rc;<br>\n&gt;<br>\n&gt; -     if (!bl || !bl-&gt;get_info) {<br>\n&gt; +     if (!bl || !bl-&gt;get_info || !bl_info) {<br>\n&gt;               errno = EINVAL;<br>\n&gt;               return FLASH_ERR_PARM_ERROR;<br>\n&gt;       }<br>\n&gt; @@ -243,12 +242,12 @@ int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_<br>\n&gt;       if (rc)<br>\n&gt;               return rc;<br>\n&gt;<br>\n&gt; -     rc = bl-&gt;get_info(bl, name, total_size, erase_granule);<br>\n&gt; +     rc = bl-&gt;get_info(bl, bl_info);<br>\n&gt;<br>\n&gt;       /* Check the validity of what we are being told */<br>\n&gt; -     if (erase_granule &amp;&amp; *erase_granule != bl-&gt;erase_mask + 1)<br>\n&gt; +     if (bl_info-&gt;erase_granule != bl-&gt;erase_mask + 1)<br>\n&gt;               FL_ERR(&quot;blocklevel_get_info: WARNING: erase_granule (0x%08x) and erase_mask&quot;<br>\n&gt; -                             &quot; (0x%08x) don&#39;t match\\n&quot;, *erase_granule, bl-&gt;erase_mask + 1);<br>\n&gt; +                             &quot; (0x%08x) don&#39;t match\\n&quot;, bl_info-&gt;erase_granule, bl-&gt;erase_mask + 1);<br>\n&gt;<br>\n&gt;       release(bl);<br>\n&gt;<br>\n&gt; @@ -417,7 +416,7 @@ out:<br>\n&gt;<br>\n&gt;  int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)<br>\n&gt;  {<br>\n&gt; -     uint32_t erase_size;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       const void *write_buf = buf;<br>\n&gt;       void *write_buf_start = NULL;<br>\n&gt;       void *erase_buf;<br>\n&gt; @@ -435,7 +434,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi<br>\n&gt;               return blocklevel_write(bl, pos, buf, len);<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(bl, NULL, NULL, &amp;erase_size);<br>\n&gt; +     rc = blocklevel_get_info(bl, &amp;bl_info);<br>\n&gt;       if (rc)<br>\n&gt;               return rc;<br>\n&gt;<br>\n&gt; @@ -458,7 +457,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi<br>\n&gt;               write_buf = write_buf_start;<br>\n&gt;       }<br>\n&gt;<br>\n&gt; -     erase_buf = malloc(erase_size);<br>\n&gt; +     erase_buf = malloc(bl_info.erase_granule);<br>\n&gt;       if (!erase_buf) {<br>\n&gt;               errno = ENOMEM;<br>\n&gt;               rc = FLASH_ERR_MALLOC_FAILED;<br>\n&gt; @@ -470,32 +469,32 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi<br>\n&gt;               goto out_free;<br>\n&gt;<br>\n&gt;       while (len &gt; 0) {<br>\n&gt; -             uint32_t erase_block = pos &amp; ~(erase_size - 1);<br>\n&gt; -             uint32_t block_offset = pos &amp; (erase_size - 1);<br>\n&gt; -             uint32_t size = erase_size &gt; len ? len : erase_size;<br>\n&gt; +             uint32_t erase_block = pos &amp; ~(bl_info.erase_granule - 1);<br>\n&gt; +             uint32_t block_offset = pos &amp; (bl_info.erase_granule - 1);<br>\n&gt; +             uint32_t size = bl_info.erase_granule &gt; len ? len : bl_info.erase_granule;<br>\n&gt;               int cmp;<br>\n&gt;<br>\n&gt;               /* Write crosses an erase boundary, shrink the write to the boundary */<br>\n&gt; -             if (erase_size &lt; block_offset + size) {<br>\n&gt; -                     size = erase_size - block_offset;<br>\n&gt; +             if (bl_info.erase_granule &lt; block_offset + size) {<br>\n&gt; +                     size = bl_info.erase_granule - block_offset;<br>\n&gt;               }<br>\n&gt;<br>\n&gt; -             rc = bl-&gt;read(bl, erase_block, erase_buf, erase_size);<br>\n&gt; +             rc = bl-&gt;read(bl, erase_block, erase_buf, bl_info.erase_granule);<br>\n&gt;               if (rc)<br>\n&gt;                       goto out;<br>\n&gt;<br>\n&gt;               cmp = blocklevel_flashcmp(erase_buf + block_offset, write_buf, size);<br>\n&gt;               FL_DBG(&quot;%s: region 0x%08x..0x%08x &quot;, __func__,<br>\n&gt; -                             erase_block, erase_size);<br>\n&gt; +                             erase_block, bl_info.erase_granule);<br>\n&gt;               if (cmp != 0) {<br>\n&gt;                       FL_DBG(&quot;needs &quot;);<br>\n&gt;                       if (cmp == -1) {<br>\n&gt;                               FL_DBG(&quot;erase and &quot;);<br>\n&gt; -                             bl-&gt;erase(bl, erase_block, erase_size);<br>\n&gt; +                             bl-&gt;erase(bl, erase_block, bl_info.erase_granule);<br>\n&gt;                       }<br>\n&gt;                       FL_DBG(&quot;write\\n&quot;);<br>\n&gt;                       memcpy(erase_buf + block_offset, write_buf, size);<br>\n&gt; -                     rc = bl-&gt;write(bl, erase_block, erase_buf, erase_size);<br>\n&gt; +                     rc = bl-&gt;write(bl, erase_block, erase_buf, bl_info.erase_granule);<br>\n&gt;                       if (rc)<br>\n&gt;                               goto out;<br>\n&gt;               }<br>\n&gt; diff --git a/libflash/blocklevel.h b/libflash/blocklevel.h<br>\n&gt; index ba42c83d0..d2d269054 100644<br>\n&gt; --- a/libflash/blocklevel.h<br>\n&gt; +++ b/libflash/blocklevel.h<br>\n&gt; @@ -34,6 +34,15 @@ enum blocklevel_flags {<br>\n&gt;       WRITE_NEED_ERASE = 1,<br>\n&gt;  };<br>\n&gt;<br>\n&gt; +struct blocklevel_info {<br>\n&gt; +     /* name is not owned by this struct and must persist for the<br>\n&gt; +      * liftime of blocklevel_info<br>\n&gt; +      */<br>\n&gt; +     const char *name;<br>\n&gt; +     uint64_t size;<br>\n&gt; +     uint32_t erase_granule;<br>\n&gt; +};<br>\n&gt; +<br>\n&gt;  /*<br>\n&gt;   * libffs may be used with different backends, all should provide these for<br>\n&gt;   * libflash to get the information it needs<br>\n&gt; @@ -45,8 +54,7 @@ struct blocklevel_device {<br>\n&gt;       int (*read)(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len);<br>\n&gt;       int (*write)(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);<br>\n&gt;       int (*erase)(struct blocklevel_device *bl, uint64_t pos, uint64_t len);<br>\n&gt; -     int (*get_info)(struct blocklevel_device *bl, const char **name, uint64_t *total_size,<br>\n&gt; -                     uint32_t *erase_granule);<br>\n&gt; +     int (*get_info)(struct blocklevel_device *bl, struct blocklevel_info *bl_info);<br>\n&gt;<br>\n&gt;       /*<br>\n&gt;        * Keep the erase mask so that blocklevel_erase() can do sanity checking<br>\n&gt; @@ -62,8 +70,8 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6<br>\n&gt;  int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);<br>\n&gt;  int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len);<br>\n&gt;  int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len);<br>\n&gt; -int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,<br>\n&gt; -             uint32_t *erase_granule);<br>\n&gt; +<br>\n&gt; +int blocklevel_get_info(struct blocklevel_device *bl, struct blocklevel_info *bl_info);<br>\n&gt;<br>\n&gt;  /*<br>\n&gt;   * blocklevel_smart_write() performs reads on the data to see if it<br>\n&gt; diff --git a/libflash/file.c b/libflash/file.c<br>\n&gt; index 7065eb4fa..b87679cd1 100644<br>\n&gt; --- a/libflash/file.c<br>\n&gt; +++ b/libflash/file.c<br>\n&gt; @@ -212,6 +212,7 @@ static int get_info_name(struct file_data *file_data, char **name)<br>\n&gt;       }<br>\n&gt;       lpath[len] = &#39;\\0&#39;;<br>\n&gt;<br>\n&gt; +     free(*name);<br>\n&gt;       *name = lpath;<br>\n&gt;<br>\n&gt;       free(path);<br>\n&gt; @@ -219,8 +220,8 @@ static int get_info_name(struct file_data *file_data, char **name)<br>\n&gt;  }<br>\n&gt;<br>\n&gt;<br>\n&gt; -static int mtd_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt; -             uint64_t *total_size, uint32_t *erase_granule)<br>\n&gt; +static int mtd_get_info(struct blocklevel_device *bl,<br>\n&gt; +             struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       struct file_data *file_data = container_of(bl, struct file_data, bl);<br>\n&gt;       struct mtd_info_user mtd_info;<br>\n&gt; @@ -230,24 +231,19 @@ static int mtd_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt;       if (rc == -1)<br>\n&gt;               return FLASH_ERR_BAD_READ;<br>\n&gt;<br>\n&gt; -     if (total_size)<br>\n&gt; -             *total_size = mtd_info.size;<br>\n&gt; -<br>\n&gt; -     if (erase_granule)<br>\n&gt; -             *erase_granule = mtd_info.erasesize;<br>\n&gt; +     rc = get_info_name(file_data, &amp;(file_data-&gt;name));<br>\n&gt; +     if (rc)<br>\n&gt; +             return rc;<br>\n&gt;<br>\n&gt; -     if (name) {<br>\n&gt; -             rc = get_info_name(file_data, &amp;(file_data-&gt;name));<br>\n&gt; -             if (rc)<br>\n&gt; -                     return rc;<br>\n&gt; -             *name = file_data-&gt;name;<br>\n&gt; -     }<br>\n&gt; +     bl_info-&gt;name = file_data-&gt;name;<br>\n&gt; +     bl_info-&gt;size = mtd_info.size;<br>\n&gt; +     bl_info-&gt;erase_granule = mtd_info.erasesize;<br>\n&gt;<br>\n&gt;       return 0;<br>\n&gt;  }<br>\n&gt;<br>\n&gt; -static int file_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt; -             uint64_t *total_size, uint32_t *erase_granule)<br>\n&gt; +static int file_get_info(struct blocklevel_device *bl,<br>\n&gt; +             struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       struct file_data *file_data = container_of(bl, struct file_data, bl);<br>\n&gt;       struct stat st;<br>\n&gt; @@ -256,18 +252,13 @@ static int file_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt;       if (fstat(file_data-&gt;fd, &amp;st))<br>\n&gt;               return FLASH_ERR_PARM_ERROR;<br>\n&gt;<br>\n&gt; -     if (total_size)<br>\n&gt; -             *total_size = st.st_size;<br>\n&gt; -<br>\n&gt; -     if (erase_granule)<br>\n&gt; -             *erase_granule = 1;<br>\n&gt; +     rc = get_info_name(file_data, &amp;(file_data-&gt;name));<br>\n&gt; +     if (rc)<br>\n&gt; +             return rc;<br>\n&gt;<br>\n&gt; -     if (name) {<br>\n&gt; -             rc = get_info_name(file_data, &amp;(file_data-&gt;name));<br>\n&gt; -             if (rc)<br>\n&gt; -                     return rc;<br>\n&gt; -             *name = file_data-&gt;name;<br>\n&gt; -     }<br>\n&gt; +     bl_info-&gt;name = file_data-&gt;name;<br>\n&gt; +     bl_info-&gt;size = st.st_size;<br>\n&gt; +     bl_info-&gt;erase_granule = 1;<br>\n&gt;<br>\n&gt;       return 0;<br>\n&gt;  }<br>\n&gt; @@ -315,8 +306,9 @@ int file_init(int fd, struct blocklevel_device **bl)<br>\n&gt;               file_data-&gt;bl.erase = &amp;mtd_erase;<br>\n&gt;               file_data-&gt;bl.get_info = &amp;mtd_get_info;<br>\n&gt;               file_data-&gt;bl.flags = WRITE_NEED_ERASE;<br>\n&gt; -             mtd_get_info(&amp;file_data-&gt;bl, NULL, NULL, &amp;(file_data-&gt;bl.erase_mask));<br>\n&gt; -             file_data-&gt;bl.erase_mask--;<br>\n&gt; +             struct blocklevel_info bl_info;<br>\n&gt; +             mtd_get_info(&amp;file_data-&gt;bl, &amp;bl_info);<br>\n&gt; +             file_data-&gt;bl.erase_mask = bl_info.erase_granule - 1;<br>\n&gt;       } else if (!S_ISREG(sbuf.st_mode)) {<br>\n&gt;               /* If not a char device or a regular file something went wrong */<br>\n&gt;               goto out;<br>\n&gt; diff --git a/libflash/libffs.c b/libflash/libffs.c<br>\n&gt; index 038f59425..6fc23eee9 100644<br>\n&gt; --- a/libflash/libffs.c<br>\n&gt; +++ b/libflash/libffs.c<br>\n&gt; @@ -216,25 +216,25 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,<br>\n&gt;  {<br>\n&gt;       struct __ffs_hdr blank_hdr;<br>\n&gt;       struct __ffs_hdr raw_hdr;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       struct ffs_handle *f;<br>\n&gt; -     uint64_t total_size;<br>\n&gt;       int rc, i;<br>\n&gt;<br>\n&gt;       if (!ffs || !bl)<br>\n&gt;               return FLASH_ERR_PARM_ERROR;<br>\n&gt;       *ffs = NULL;<br>\n&gt;<br>\n&gt; -     rc = blocklevel_get_info(bl, NULL, &amp;total_size, NULL);<br>\n&gt; +     rc = blocklevel_get_info(bl, &amp;bl_info);<br>\n&gt;       if (rc) {<br>\n&gt;               FL_ERR(&quot;FFS: Error %d retrieving flash info\\n&quot;, rc);<br>\n&gt;               return rc;<br>\n&gt;       }<br>\n&gt; -     if (total_size &gt; UINT_MAX)<br>\n&gt; +     if (bl_info.size &gt; UINT_MAX)<br>\n&gt;               return FLASH_ERR_VERIFY_FAILURE;<br>\n&gt;       if ((offset + max_size) &lt; offset)<br>\n&gt;               return FLASH_ERR_PARM_ERROR;<br>\n&gt;<br>\n&gt; -     if ((max_size &gt; total_size))<br>\n&gt; +     if ((max_size &gt; bl_info.size))<br>\n&gt;               return FLASH_ERR_PARM_ERROR;<br>\n&gt;<br>\n&gt;       /* Read flash header */<br>\n&gt; diff --git a/libflash/libflash.c b/libflash/libflash.c<br>\n&gt; index 38f87b86e..82a2baecc 100644<br>\n&gt; --- a/libflash/libflash.c<br>\n&gt; +++ b/libflash/libflash.c<br>\n&gt; @@ -792,16 +792,15 @@ static int flash_configure(struct flash_chip *c)<br>\n&gt;       return 0;<br>\n&gt;  }<br>\n&gt;<br>\n&gt; -static int flash_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt; -                uint64_t *total_size, uint32_t *erase_granule)<br>\n&gt; +static int flash_get_info(struct blocklevel_device *bl,<br>\n&gt; +             struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       struct flash_chip *c = container_of(bl, struct flash_chip, bl);<br>\n&gt; -     if (name)<br>\n&gt; -             *name = c-&gt;<a href=\"http://info.name\" rel=\"noreferrer\" target=\"_blank\">info.name</a>;<br>\n&gt; -     if (total_size)<br>\n&gt; -             *total_size = c-&gt;tsize;<br>\n&gt; -     if (erase_granule)<br>\n&gt; -             *erase_granule = c-&gt;min_erase_mask + 1;<br>\n&gt; +<br>\n&gt; +     bl_info-&gt;name = c-&gt;<a href=\"http://info.name\" rel=\"noreferrer\" target=\"_blank\">info.name</a>;<br>\n&gt; +     bl_info-&gt;size = c-&gt;tsize;<br>\n&gt; +     bl_info-&gt;erase_granule = c-&gt;min_erase_mask + 1;<br>\n&gt; +<br>\n&gt;       return 0;<br>\n&gt;  }<br>\n&gt;<br>\n&gt; diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c<br>\n&gt; index 950e24f05..d4200ce53 100644<br>\n&gt; --- a/libflash/mbox-flash.c<br>\n&gt; +++ b/libflash/mbox-flash.c<br>\n&gt; @@ -745,8 +745,8 @@ static int mbox_flash_read(struct blocklevel_device *bl, uint64_t pos,<br>\n&gt;       return rc;<br>\n&gt;  }<br>\n&gt;<br>\n&gt; -static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt; -             uint64_t *total_size, uint32_t *erase_granule)<br>\n&gt; +static int mbox_flash_get_info(struct blocklevel_device *bl,<br>\n&gt; +             struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       struct mbox_flash_data *mbox_flash;<br>\n&gt;       struct bmc_mbox_msg *msg;<br>\n&gt; @@ -761,14 +761,7 @@ static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt;       if (!msg)<br>\n&gt;               return FLASH_ERR_MALLOC_FAILED;<br>\n&gt;<br>\n&gt; -     /*<br>\n&gt; -      * We want to avoid runtime mallocs in skiboot. The expected<br>\n&gt; -      * behavour to uses of libflash is that one can free() the memory<br>\n&gt; -      * returned.<br>\n&gt; -      * NULL will do for now.<br>\n&gt; -      */<br>\n&gt; -     if (name)<br>\n&gt; -             *name = NULL;<br>\n&gt; +     bl_info-&gt;name = &quot;pnor_mbox&quot;;<br>\n&gt;<br>\n&gt;       mbox_flash-&gt;busy = true;<br>\n&gt;       rc = msg_send(mbox_flash, msg);<br>\n&gt; @@ -784,10 +777,8 @@ static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt;<br>\n&gt;       mbox_flash-&gt;bl.erase_mask = mbox_flash-&gt;erase_granule - 1;<br>\n&gt;<br>\n&gt; -     if (total_size)<br>\n&gt; -             *total_size = mbox_flash-&gt;total_size;<br>\n&gt; -     if (erase_granule)<br>\n&gt; -             *erase_granule = mbox_flash-&gt;erase_granule;<br>\n&gt; +     bl_info-&gt;size = mbox_flash-&gt;total_size;<br>\n&gt; +     bl_info-&gt;erase_granule = mbox_flash-&gt;erase_granule;<br>\n&gt;<br>\n&gt;  out:<br>\n&gt;       msg_free_memory(msg);<br>\n&gt; diff --git a/libflash/test/test-flash.c b/libflash/test/test-flash.c<br>\n&gt; index 3f77d6f3e..1ca467bb0 100644<br>\n&gt; --- a/libflash/test/test-flash.c<br>\n&gt; +++ b/libflash/test/test-flash.c<br>\n&gt; @@ -367,9 +367,7 @@ struct spi_flash_ctrl sim_ctrl = {<br>\n&gt;  int main(void)<br>\n&gt;  {<br>\n&gt;       struct blocklevel_device *bl;<br>\n&gt; -     uint64_t total_size;<br>\n&gt; -     uint32_t erase_granule;<br>\n&gt; -     const char *name;<br>\n&gt; +     struct blocklevel_info bl_info;<br>\n&gt;       uint16_t *test;<br>\n&gt;       struct ecc64 *ecc_test;<br>\n&gt;       uint64_t *test64;<br>\n&gt; @@ -384,7 +382,7 @@ int main(void)<br>\n&gt;               ERR(&quot;flash_init failed with err %d\\n&quot;, rc);<br>\n&gt;               exit(1);<br>\n&gt;       }<br>\n&gt; -     rc = flash_get_info(bl, &amp;name, &amp;total_size, &amp;erase_granule);<br>\n&gt; +     rc = flash_get_info(bl, &amp;bl_info);<br>\n&gt;       if (rc) {<br>\n&gt;               ERR(&quot;flash_get_info failed with err %d\\n&quot;, rc);<br>\n&gt;               exit(1);<br>\n&gt; diff --git a/platforms/mambo/mambo.c b/platforms/mambo/mambo.c<br>\n&gt; index cb6e103cc..dd7872a8e 100644<br>\n&gt; --- a/platforms/mambo/mambo.c<br>\n&gt; +++ b/platforms/mambo/mambo.c<br>\n&gt; @@ -125,19 +125,14 @@ static int bogus_disk_erase(struct blocklevel_device *bl __unused,<br>\n&gt;       return 0; /* NOP */<br>\n&gt;  }<br>\n&gt;<br>\n&gt; -static int bogus_disk_get_info(struct blocklevel_device *bl, const char **name,<br>\n&gt; -                           uint64_t *total_size, uint32_t *erase_granule)<br>\n&gt; +static int bogus_disk_get_info(struct blocklevel_device *bl,<br>\n&gt; +                     struct blocklevel_info *bl_info)<br>\n&gt;  {<br>\n&gt;       struct bogus_disk_info *bdi = bl-&gt;priv;<br>\n&gt;<br>\n&gt; -     if (total_size)<br>\n&gt; -             *total_size = bdi-&gt;size;<br>\n&gt; -<br>\n&gt; -     if (erase_granule)<br>\n&gt; -             *erase_granule = BD_SECT_SZ;<br>\n&gt; -<br>\n&gt; -     if (name)<br>\n&gt; -             *name = &quot;mambobogus&quot;;<br>\n&gt; +     bl_info-&gt;name = &quot;mambobogus&quot;;<br>\n&gt; +     bl_info-&gt;size = bdi-&gt;size;<br>\n&gt; +     bl_info-&gt;erase_granule = BD_SECT_SZ;<br>\n&gt;<br>\n&gt;       return 0;<br>\n&gt;  }<br>\n</blockquote></div>","headers":{"Return-Path":"<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","skiboot@lists.ozlabs.org"],"Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","skiboot@lists.ozlabs.org"],"Received":["from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xhK3H3Xrlz9ryr\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 29 Aug 2017 16:48:27 +1000 (AEST)","from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xhK3H2MVhzDqj2\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 29 Aug 2017 16:48:27 +1000 (AEST)","from mail-qk0-x232.google.com (mail-qk0-x232.google.com\n\t[IPv6:2607:f8b0:400d:c09::232])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xhJlz2dbWzDrKh\n\tfor <skiboot@lists.ozlabs.org>; Tue, 29 Aug 2017 16:35:11 +1000 (AEST)","by mail-qk0-x232.google.com with SMTP id k126so11382283qkb.4\n\tfor <skiboot@lists.ozlabs.org>; Mon, 28 Aug 2017 23:35:11 -0700 (PDT)"],"Authentication-Results":["ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=google.com header.i=@google.com\n\theader.b=\"fh7ELpWC\"; dkim-atps=neutral","lists.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=google.com header.i=@google.com\n\theader.b=\"fh7ELpWC\"; dkim-atps=neutral","lists.ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=google.com header.i=@google.com\n\theader.b=\"fh7ELpWC\"; dkim-atps=neutral"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n\ts=20161025; \n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to;\n\tbh=apxY9v95Vy3BVTeyOSxIi81LKwEX08ZKF98oAXipmYw=;\n\tb=fh7ELpWCp0XvFQNgupL3QIdaBVs7FQGFMhpC2GdQYNd2Q39wNMMeMnTZBlROFMTunM\n\t9GDX7Ti7P7cWtzFvJuq2BJ8ceGlTFMAj7IHFlgrzv//Kp4DHD2clEbUVntyz5W0fd9mh\n\tIH+bBNXX+FwZ/Pu0bL2zea1+iU99w0UAoMu7xf9PiYaUuUl96luiBaY2I0x3PBF7l9r3\n\t3nttRKNASrs5eNMB0NNJDV9aDhwpmcNzsXQPn1RCBIr7sMuJ9L/8Qtv4Nsjct5B3Ii2e\n\tUlZJbwHLDavm401Ja6q9UT0XYPcYa7WtEXH5G8Xdkfthwphlu9AWYezsI7P9jxFfIPS3\n\tBs2g==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to;\n\tbh=apxY9v95Vy3BVTeyOSxIi81LKwEX08ZKF98oAXipmYw=;\n\tb=r6trLhsZ1jrdfd1FYZb/7K9feLaeu65wr2oYLxkdJsqROgOlnPuv+mwYQBX9vOzFjV\n\thyYSw7D5Y1TlN97xLFVNyoTeArvcK6ABvIWfiQdG7ToP0bLp0cXXAmEe2DG4aQpSRCTp\n\tcplGALYl5+box8pxq3EavtxWA1ltusJkZ7ZzM+pEpDB2TkZZ5gds8AqfUQbeKZejBG6Y\n\twYCywt3zJ57tu6K23XE2GPoMscum2Lx3SjY+m4YSV+USvr3dh6WDDhr9MBtQQnhSQxtd\n\t3lt9mGZLnNstYg76w/OT7HtS8TLu9bI04zTUXmiZUNXC63QTNkojuZ1IpGA6B9oK3u9b\n\tlvOQ==","X-Gm-Message-State":"AHYfb5iraDIdzSyPS1ZozxDo36sjyPwdRqY/pHDOrg/xhifnEgwcldJ0\n\tsry2Udl0OiY7g8zVm5mJPrvAs70B17u+","X-Google-Smtp-Source":"ADKCNb7ryOBI6GFduDJcj+ZxjkyysmvI4JeRG+wJuH/s0HLuBneMwfDJ2nW7FgCsUwGa046iQ+FHczOxKZITrVlTZl4=","X-Received":"by 10.55.99.147 with SMTP id x141mr4280088qkb.270.1503988508382; \n\tMon, 28 Aug 2017 23:35:08 -0700 (PDT)","MIME-Version":"1.0","References":"<20170829041922.4193-1-wak@google.com>\n\t<1503985073.8990.15.camel@gmail.com>","In-Reply-To":"<1503985073.8990.15.camel@gmail.com>","From":"William Kennington <wak@google.com>","Date":"Tue, 29 Aug 2017 06:34:57 +0000","Message-ID":"<CAPnigKkOUz2jK97cKN9PKxE=AB=ZbA_nAJjfrjv_S7FCzHsNXA@mail.gmail.com>","To":"Cyril Bur <cyrilbur@gmail.com>, skiboot@lists.ozlabs.org","Subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","X-BeenThere":"skiboot@lists.ozlabs.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"Mailing list for skiboot development <skiboot.lists.ozlabs.org>","List-Unsubscribe":"<https://lists.ozlabs.org/options/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=unsubscribe>","List-Archive":"<http://lists.ozlabs.org/pipermail/skiboot/>","List-Post":"<mailto:skiboot@lists.ozlabs.org>","List-Help":"<mailto:skiboot-request@lists.ozlabs.org?subject=help>","List-Subscribe":"<https://lists.ozlabs.org/listinfo/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=subscribe>","Content-Type":"multipart/mixed;\n\tboundary=\"===============4987974658537604703==\"","Errors-To":"skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org","Sender":"\"Skiboot\"\n\t<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>"}},{"id":1772377,"web_url":"http://patchwork.ozlabs.org/comment/1772377/","msgid":"<878th8lrht.fsf@linux.vnet.ibm.com>","list_archive_url":null,"date":"2017-09-21T02:23:10","subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","submitter":{"id":48041,"url":"http://patchwork.ozlabs.org/api/people/48041/","name":"Stewart Smith","email":"stewart@linux.vnet.ibm.com"},"content":"Cyril Bur <cyrilbur@gmail.com> writes:\n> On Mon, 2017-08-28 at 21:19 -0700, William A. Kennington III wrote:\n>> This changes refactors all of the output variables from flash_get_info\n>> into a new output struct. Callers now supply the info struct, and always\n>> get all of the info with each call. There are never any allocations done\n>> by this function so it shouldn't be much slower to always populate all\n>> of the information.\n>> \n>\n> Hi William,\n>\n> As nice as this refactor is (thanks for the effort!), unfortunately\n> we're a bit stuck with the interface as is, both openbmc and petitboot\n> projects link against a dynamic libflash.\n\nWe can always bump the .so version and they can update asynchronously.","headers":{"Return-Path":"<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","skiboot@lists.ozlabs.org"],"Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","skiboot@lists.ozlabs.org"],"Received":["from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xyL515L2pz9sNr\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 21 Sep 2017 12:23:33 +1000 (AEST)","from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xyL504vzFzDqY3\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 21 Sep 2017 12:23:32 +1000 (AEST)","from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com\n\t[148.163.158.5])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xyL4k6z0hzDqBc\n\tfor <skiboot@lists.ozlabs.org>; Thu, 21 Sep 2017 12:23:18 +1000 (AEST)","from pps.filterd (m0098421.ppops.net [127.0.0.1])\n\tby mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id\n\tv8L2J8lR095324\n\tfor <skiboot@lists.ozlabs.org>; Wed, 20 Sep 2017 22:23:16 -0400","from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158])\n\tby mx0a-001b2d01.pphosted.com with ESMTP id 2d41px11f8-1\n\t(version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT)\n\tfor <skiboot@lists.ozlabs.org>; Wed, 20 Sep 2017 22:23:15 -0400","from localhost\n\tby e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use\n\tOnly! Violators will be prosecuted\n\tfor <skiboot@lists.ozlabs.org> from <stewart@linux.vnet.ibm.com>;\n\tWed, 20 Sep 2017 20:23:15 -0600","from b03cxnp08025.gho.boulder.ibm.com (9.17.130.17)\n\tby e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway:\n\tAuthorized Use Only! Violators will be prosecuted; \n\tWed, 20 Sep 2017 20:23:13 -0600","from b03ledav005.gho.boulder.ibm.com\n\t(b03ledav005.gho.boulder.ibm.com [9.17.130.236])\n\tby b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with\n\tESMTP id v8L2NDaU64094348; Wed, 20 Sep 2017 19:23:13 -0700","from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1])\n\tby IMSVA (Postfix) with ESMTP id 004AEBE038;\n\tWed, 20 Sep 2017 20:23:13 -0600 (MDT)","from birb.localdomain (unknown [9.83.1.138])\n\tby b03ledav005.gho.boulder.ibm.com (Postfix) with SMTP id 216FEBE039; \n\tWed, 20 Sep 2017 20:23:11 -0600 (MDT)","by birb.localdomain (Postfix, from userid 1000)\n\tid 48D344F0F8F; Thu, 21 Sep 2017 12:23:10 +1000 (AEST)"],"Authentication-Results":"ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com\n\t(client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com;\n\tenvelope-from=stewart@linux.vnet.ibm.com; receiver=<UNKNOWN>)","From":"Stewart Smith <stewart@linux.vnet.ibm.com>","To":"Cyril Bur <cyrilbur@gmail.com>,\n\t\"William A. Kennington III\" <wak@google.com>, skiboot@lists.ozlabs.org","In-Reply-To":"<1503985073.8990.15.camel@gmail.com>","References":"<20170829041922.4193-1-wak@google.com>\n\t<1503985073.8990.15.camel@gmail.com>","Date":"Thu, 21 Sep 2017 12:23:10 +1000","MIME-Version":"1.0","X-TM-AS-GCONF":"00","x-cbid":"17092102-0024-0000-0000-00001739760C","X-IBM-SpamModules-Scores":"","X-IBM-SpamModules-Versions":"BY=3.00007770; HX=3.00000241; KW=3.00000007;\n\tPH=3.00000004; SC=3.00000230; SDB=6.00920022; UDB=6.00462263;\n\tIPR=6.00700248; \n\tBA=6.00005599; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009;\n\tZB=6.00000000; \n\tZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00017228;\n\tXFM=3.00000015; UTC=2017-09-21 02:23:14","X-IBM-AV-DETECTION":"SAVI=unused REMOTE=unused XFE=unused","x-cbparentid":"17092102-0025-0000-0000-00004CCD5013","Message-Id":"<878th8lrht.fsf@linux.vnet.ibm.com>","X-Proofpoint-Virus-Version":"vendor=fsecure engine=2.50.10432:, ,\n\tdefinitions=2017-09-20_06:, , signatures=0","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n\tspamscore=0 suspectscore=1\n\tmalwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam\n\tadjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000\n\tdefinitions=main-1709210030","Subject":"Re: [Skiboot] [PATCH] blocklevel_info: Refactor the passing of\n\toutput data","X-BeenThere":"skiboot@lists.ozlabs.org","X-Mailman-Version":"2.1.24","Precedence":"list","List-Id":"Mailing list for skiboot development <skiboot.lists.ozlabs.org>","List-Unsubscribe":"<https://lists.ozlabs.org/options/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=unsubscribe>","List-Archive":"<http://lists.ozlabs.org/pipermail/skiboot/>","List-Post":"<mailto:skiboot@lists.ozlabs.org>","List-Help":"<mailto:skiboot-request@lists.ozlabs.org?subject=help>","List-Subscribe":"<https://lists.ozlabs.org/listinfo/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=subscribe>","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org","Sender":"\"Skiboot\"\n\t<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>"}}]