From patchwork Tue Dec 11 04:18:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stewart Smith X-Patchwork-Id: 1010836 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.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43DRX84wwVz9s3Z for ; Tue, 11 Dec 2018 15:18:48 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 43DRX83QtXzDqr5 for ; Tue, 11 Dec 2018 15:18:48 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=stewart@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 43DRX20ffCzDqjg for ; Tue, 11 Dec 2018 15:18:41 +1100 (AEDT) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id wBB4DmD2127769 for ; Mon, 10 Dec 2018 23:18:39 -0500 Received: from e32.co.us.ibm.com (e32.co.us.ibm.com [32.97.110.150]) by mx0a-001b2d01.pphosted.com with ESMTP id 2pa0byvfty-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 10 Dec 2018 23:18:39 -0500 Received: from localhost by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 11 Dec 2018 04:18:38 -0000 Received: from b03cxnp07028.gho.boulder.ibm.com (9.17.130.15) by e32.co.us.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 11 Dec 2018 04:18:36 -0000 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id wBB4IZJV18088098 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 11 Dec 2018 04:18:35 GMT Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 73C7E136053 for ; Tue, 11 Dec 2018 04:18:35 +0000 (GMT) Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 068C313604F for ; Tue, 11 Dec 2018 04:18:34 +0000 (GMT) Received: from birb.localdomain (unknown [9.185.142.54]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP for ; Tue, 11 Dec 2018 04:18:34 +0000 (GMT) Received: by birb.localdomain (Postfix, from userid 1000) id 011924EC62A; Tue, 11 Dec 2018 15:18:30 +1100 (AEDT) From: Stewart Smith To: skiboot@lists.ozlabs.org Date: Tue, 11 Dec 2018 15:18:30 +1100 X-Mailer: git-send-email 2.19.2 MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18121104-0004-0000-0000-000014C048F1 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00010211; HX=3.00000242; KW=3.00000007; PH=3.00000004; SC=3.00000270; SDB=6.01130033; UDB=6.00587166; IPR=6.00910167; MB=3.00024649; MTD=3.00000008; XFM=3.00000015; UTC=2018-12-11 04:18:37 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18121104-0005-0000-0000-000089CF3DA1 Message-Id: <20181211041830.9193-1-stewart@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-12-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1812110039 Subject: [Skiboot] [PATCH] pflash: Support encoding/decoding ECC'd partitions X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" With the new --ecc option, pflash can add/remove ECC when reading/writing flash partitions protected by ECC. This is *not* flawless with current PNORs out in the wild though, as they do not typically fill the whole partition with valid ECC data, so you have to know how big the valid ECC'd data is and specify the size manually. Note that for some partitions this is pratically impossible without knowing the details of the content of the partition. A future patch is likely to introduce an option to "stop reading data when ECC starts failing and assume everything is okay rather than error out" to support reading the "valid" data from existing PNOR images. Signed-off-by: Stewart Smith --- external/pflash/pflash.c | 43 ++++++++++++++----- external/pflash/test/results/00-usage.out | 4 ++ .../pflash/test/results/05-bad-numbers.out | 4 ++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c index c81520cb9039..8cccb506f5fc 100644 --- a/external/pflash/pflash.c +++ b/external/pflash/pflash.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "progress.h" @@ -48,6 +49,7 @@ struct flash_details { uint64_t toc; uint64_t total_size; uint32_t erase_granule; + bool mark_ecc; }; /* Full pflash version number (possibly includes gitid). */ @@ -142,7 +144,7 @@ static struct ffs_handle *open_ffs(struct flash_details *flash) int rc; rc = ffs_init(flash->toc, flash->total_size, - flash->bl, &ffsh, 0); + flash->bl, &ffsh, flash->mark_ecc); if (rc) { fprintf(stderr, "Error %d opening ffs !\n", rc); if (flash->toc) { @@ -429,7 +431,7 @@ static int program_file(struct blocklevel_device *bl, } printf("Programming & Verifying...\n"); - progress_init(size >> 8); + progress_init(size); while(size) { ssize_t len; @@ -456,7 +458,7 @@ static int program_file(struct blocklevel_device *bl, goto out; } start += len; - progress_tick(actual_size >> 8); + progress_tick(actual_size); } progress_end(); @@ -487,7 +489,7 @@ static int do_read_file(struct blocklevel_device *bl, const char *file, printf("Reading to \"%s\" from 0x%08x..0x%08x !\n", file, start, start + size); - progress_init(size >> 8); + progress_init(size); while(size) { ssize_t len; @@ -511,7 +513,7 @@ static int do_read_file(struct blocklevel_device *bl, const char *file, start += rc; size -= rc; done += rc; - progress_tick(done >> 8); + progress_tick(done); } progress_end(); close(fd); @@ -690,6 +692,10 @@ static void print_help(const char *pname) printf("\t\tUsed to ECC clear a partition of the flash\n"); printf("\t\tMust be used in conjunction with -P. Will erase the\n"); printf("\t\tpartition and then set all the ECC bits as they should be\n\n"); + printf("\t-9 --ecc\n"); + printf("\t\tEncode/Decode ECC where specified in the FFS header.\n"); + printf("\t\tThis 9 byte ECC method is used for some OpenPOWER\n"); + printf("\t\tpartitions.\n"); printf("\t-i, --info\n"); printf("\t\tDisplay some information about the flash.\n\n"); printf("\t--detail\n"); @@ -706,7 +712,8 @@ int main(int argc, char *argv[]) struct flash_details flash = { 0 }; static struct ffs_handle *ffsh = NULL; uint32_t ffs_index; - uint32_t address = 0, read_size = 0, write_size = 0, detail_id = UINT_MAX; + uint32_t address = 0, read_size = 0, detail_id = UINT_MAX; + uint32_t write_size = 0, write_size_minus_ecc = 0; bool erase = false, do_clear = false; bool program = false, erase_all = false, info = false, do_read = false; bool enable_4B = false, disable_4B = false; @@ -743,11 +750,12 @@ int main(int argc, char *argv[]) {"skip", required_argument, NULL, 'k'}, {"toc", required_argument, NULL, 'T'}, {"clear", no_argument, NULL, 'c'}, + {"ecc", no_argument, NULL, '9'}, {NULL, 0, NULL, 0 } }; int c, oidx = 0; - c = getopt_long(argc, argv, "+:a:s:P:r:43Eep:fdihvbtgS:T:cF:", + c = getopt_long(argc, argv, "+:a:s:P:r:43Eep:fdihvbtgS:T:c9F:", long_opts, &oidx); if (c == -1) break; @@ -862,6 +870,9 @@ int main(int argc, char *argv[]) } } break; + case '9': + flash.mark_ecc = true; + break; case ':': fprintf(stderr, "Unrecognised option \"%s\" to '%c'\n", optarg, optopt); no_action = true; @@ -1052,6 +1063,9 @@ int main(int argc, char *argv[]) write_size = stbuf.st_size; } + /* Only take ECC into account under some conditions later */ + write_size_minus_ecc = write_size; + /* If read specified and no read_size, use flash size */ if (do_read && !read_size && !part_name) read_size = flash.total_size; @@ -1095,18 +1109,27 @@ int main(int argc, char *argv[]) /* Read size is obtained from partition "actual" size */ if (!read_size) read_size = pactsize; + /* If we're decoding ecc and partition is ECC'd, then adjust */ + if (ecc && flash.mark_ecc) + read_size = (ecc_buffer_size_minus_ecc(read_size)/9)*9; /* Write size is max size of partition */ if (!write_size) write_size = pmaxsz; + /* But write size can take into account ECC as well */ + if (ecc && flash.mark_ecc) + write_size_minus_ecc = (ecc_buffer_size_minus_ecc(write_size)/9)*9; + else + write_size_minus_ecc = write_size; + /* Crop write size to partition size if --force was passed */ - if (write_size > pmaxsz && !must_confirm) { + if ((write_size_minus_ecc > pmaxsz) && !must_confirm) { printf("WARNING: Size (%d bytes) larger than partition" " (%d bytes), cropping to fit\n", write_size, pmaxsz); write_size = pmaxsz; - } else if (write_size > pmaxsz) { + } else if (write_size_minus_ecc > pmaxsz) { printf("ERROR: Size (%d bytes) larger than partition" " (%d bytes). Use --force to force\n", write_size, pmaxsz); @@ -1169,7 +1192,7 @@ int main(int argc, char *argv[]) rc = erase_range(&flash, address, write_size, program, ffsh, ffs_index); if (!rc && program) - rc = program_file(flash.bl, write_file, address, write_size, + rc = program_file(flash.bl, write_file, address, write_size_minus_ecc, ffsh, ffs_index); if (!rc && do_clear) rc = set_ecc(&flash, address, write_size); diff --git a/external/pflash/test/results/00-usage.out b/external/pflash/test/results/00-usage.out index caf7b8d8d580..a3721ca8e3b8 100644 --- a/external/pflash/test/results/00-usage.out +++ b/external/pflash/test/results/00-usage.out @@ -97,6 +97,10 @@ Usage: ./pflash [options] commands... Must be used in conjunction with -P. Will erase the partition and then set all the ECC bits as they should be + -9 --ecc + Encode/Decode ECC where specified in the FFS header. + This 9 byte ECC method is used for some OpenPOWER + partitions. -i, --info Display some information about the flash. diff --git a/external/pflash/test/results/05-bad-numbers.out b/external/pflash/test/results/05-bad-numbers.out index 17db6650f591..2a76c28c0186 100644 --- a/external/pflash/test/results/05-bad-numbers.out +++ b/external/pflash/test/results/05-bad-numbers.out @@ -97,6 +97,10 @@ Usage: ./pflash [options] commands... Must be used in conjunction with -P. Will erase the partition and then set all the ECC bits as they should be + -9 --ecc + Encode/Decode ECC where specified in the FFS header. + This 9 byte ECC method is used for some OpenPOWER + partitions. -i, --info Display some information about the flash.