From patchwork Fri Feb 20 00:37:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Neuling X-Patchwork-Id: 441813 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43E551400EA for ; Fri, 20 Feb 2015 11:38:51 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 326AB1A0ECA for ; Fri, 20 Feb 2015 11:38:51 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 632921A0E8F for ; Fri, 20 Feb 2015 11:38:22 +1100 (AEDT) Received: from localhost.localdomain (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 2F764140283; Fri, 20 Feb 2015 11:38:22 +1100 (AEDT) Received: by localhost.localdomain (Postfix, from userid 1000) id 1A5A5D47040; Fri, 20 Feb 2015 11:38:22 +1100 (AEDT) From: Michael Neuling To: stewart@linux.vnet.ibm.com Date: Fri, 20 Feb 2015 11:37:54 +1100 Message-Id: <1424392679-27859-11-git-send-email-mikey@neuling.org> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1424392679-27859-1-git-send-email-mikey@neuling.org> References: <1424392679-27859-1-git-send-email-mikey@neuling.org> Cc: imunsie@au.ibm.com, grimm@linux.vnet.ibm.com, skiboot@lists.ozlabs.org Subject: [Skiboot] [PATCH 11/16] flash: Add ECC to load_resource() X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Add decoding, checking and correction of ECC enabled partitions in pnor_load_resource(). Signed-off-by: Michael Neuling Reviewed-by: Joel Stanley --- core/flash.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/core/flash.c b/core/flash.c index e107aaf..51a66c9 100644 --- a/core/flash.c +++ b/core/flash.c @@ -22,6 +22,7 @@ #include #include #include +#include struct flash { bool registered; @@ -353,20 +354,28 @@ struct flash_hostboot_header { struct flash_hostboot_toc toc[FLASH_HOSTBOOT_TOC_MAX_ENTRIES]; }; +/* start and total size include ECC */ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid, - uint32_t *start, uint32_t *total_size) + uint32_t *start, uint32_t *total_size, + bool *ecc) { struct flash_hostboot_header *header; char eyecatcher[5]; - uint32_t i; + uint32_t i, partsize; bool rc; header = malloc(FLASH_SUBPART_HEADER_SIZE); if (!header) return false; + /* Get raw partition size without ECC */ + partsize = *total_size; + if (ecc) + partsize = BUFFER_SIZE_MINUS_ECC(*total_size); + /* Get the TOC */ - rc = flash_read(chip, *start, header, FLASH_SUBPART_HEADER_SIZE); + rc = ffs_flash_read(chip, *start, header, FLASH_SUBPART_HEADER_SIZE, + ecc); if (rc) { prerror("FLASH: flash subpartition TOC read failed %i\n", rc); goto end; @@ -401,8 +410,8 @@ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid, if (ec != subid) continue; - /* Sanity check the offset and size */ - if (offset + size > *total_size) { + /* Sanity check the offset and size. */ + if (offset + size > partsize) { prerror("FLASH: flash subpartition too big: %i\n", i); goto end; } @@ -416,14 +425,20 @@ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid, goto end; } - /* All good, let's adjust the start and size */ prlog(PR_DEBUG, "FLASH: flash found subpartition: " "%i size: %i offset %i\n", i, size, offset); + + /* + * Adjust the start and size. The start location in the needs + * to account for ecc but the size doesn't. + */ *start += offset; - size = (size + (FLASH_SUBPART_ALIGNMENT - 1)) & - ~(FLASH_SUBPART_ALIGNMENT - 1); *total_size = size; + if (ecc) { + *start += ECC_SIZE(offset); + *total_size += ECC_SIZE(size); + } rc = 0; goto end; } @@ -433,14 +448,18 @@ end: return rc; } +/* + * load a resource from FLASH + * buf and len shouldn't account for ECC even if partition is ECCed. + */ bool flash_load_resource(enum resource_id id, uint32_t subid, void *buf, size_t *len) { - int i, rc, part_num, part_size, part_start; + int i, rc, part_num, part_size, part_start, size; struct ffs_handle *ffs; struct flash *flash; const char *name; - bool status; + bool status, ecc; status = false; @@ -483,33 +502,51 @@ bool flash_load_resource(enum resource_id id, uint32_t subid, goto out_free_ffs; } rc = ffs_part_info(ffs, part_num, NULL, - &part_start, &part_size, NULL, NULL); + &part_start, &part_size, NULL, &ecc); if (rc) { prerror("FLASH: Failed to get %s partition info\n", name); goto out_free_ffs; } + prlog(PR_DEBUG,"FLASH: %s partition %s ECC\n", + name, ecc ? "has" : "doesn't have"); + + /* + * part_start/size are raw pointers into the partition. + * ie. they will account for ECC if included. + */ /* Find the sub partition if required */ if (subid != RESOURCE_SUBID_NONE) { rc = flash_find_subpartition(flash->chip, subid, &part_start, - &part_size); + &part_size, &ecc); if (rc) goto out_free_ffs; } - if (part_size > *len) { + /* Work out what the final size of buffer will be without ECC */ + size = part_size; + if (ecc) { + if ECC_BUFFER_SIZE_CHECK(part_size) { + prerror("FLASH: %s image invalid size for ECC %d\n", + name, part_size); + goto out_free_ffs; + } + size = BUFFER_SIZE_MINUS_ECC(part_size); + } + + if (size > *len) { prerror("FLASH: %s image too large (%d > %zd)\n", name, part_size, *len); goto out_free_ffs; } - rc = flash_read(flash->chip, part_start, buf, part_size); + rc = ffs_flash_read(flash->chip, part_start, buf, size, ecc); if (rc) { prerror("FLASH: failed to read %s partition\n", name); goto out_free_ffs; } - *len = part_size; + *len = size; status = true; out_free_ffs: