[Skiboot] [PATCH] pflash option to retrieve PNOR partition flags

Cyril Bur cyrilbur at gmail.com
Tue Jun 6 16:35:13 AEST 2017


On Thu, 2017-06-01 at 22:14 -0500, Michael Tritz wrote:
> This commit extends pflash with an option to retrieve and print the
> miscellaneous partition flags for a particular partition. "pflash -i"
> is also updated to print the miscellaneous flags in addition to the 
> ECC flag, with one character per flag. A test of the new option is
> included in libflash/test. 
> 
> Resolves openbmc/openbmc#1351
> 
> Change-Id: Iebb8a6d34c537cecd2eb44ddf41271c8fbe25258
> Signed-off-by: Michael Tritz <mtritz at us.ibm.com>
> ---
>  external/pflash/pflash.c          |  87 +++++++++++++++++++++++++++++++++++---
>  libflash/libffs.c                 |  32 ++++++++++++++
>  libflash/libffs.h                 |   5 +++
>  libflash/test/test-miscprint.pnor | Bin 0 -> 3072 bytes
>  libflash/test/test-miscprint.sh   |  35 +++++++++++++++
>  5 files changed, 153 insertions(+), 6 deletions(-)
>  create mode 100644 libflash/test/test-miscprint.pnor
>  create mode 100644 libflash/test/test-miscprint.sh
> 
> diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c
> index a344987e..a0e5db7c 100644
> --- a/external/pflash/pflash.c
> +++ b/external/pflash/pflash.c
> @@ -105,19 +105,41 @@ static void print_ffs_info(uint32_t toc_offset)
>  
>  	for (i = 0;; i++) {
>  		uint32_t start, size, act, end;
> -		bool ecc;
> +		bool ecc, preserved, readonly, backup, reprovision;
>  		char *name;
>  
> -		rc = ffs_part_info(ffs_handle, i, &name, &start, &size, &act, &ecc);
> +		rc = ffs_part_info(ffs_handle, i, &name, &start, &size, &act, NULL);
>  		if (rc == FFS_ERR_PART_NOT_FOUND)
>  			break;
>  		if (rc) {
>  			fprintf(stderr, "Error %d scanning partitions\n", rc);
>  			break;
>  		}
> +
> +		rc = ffs_part_flags(ffs_handle, i, &ecc, &preserved, &readonly,
> +				&backup, &reprovision);

Please see my response to Patricks email - ffs_entry_get() and
ffs_entry_user_get()!!

> +		if (rc == FFS_ERR_PART_NOT_FOUND){
> +			return;
> +		}
> +		if (rc) {
> +			fprintf(stderr, "Error %d scanning partitions\n", rc);
> +			return;
> +		}
> +
> +		char flags [strlen("[EPRBF]")];

So, I can see what you're doing here. I think asprintf() will provide a
cleaner solution.

> +		int l;
> +		l = snprintf(flags, sizeof(flags), "[%s%s%s%s%s]",
> +				(ecc) ? "E" : "",
> +				(preserved) ? "P" : "",
> +				(readonly) ? "R" : "",
> +				(backup) ? "B" : "",
> +				(reprovision) ? "F" : "");

You can probably use %c and ' '. Expanding on Patricks idea, perhaps a
'-' to indicate the absence of the flag?

> +		if (strcmp(flags, "[]") == 0)
> +			flags[0] = '\0';

Probably leave the "[       ]" if there are no flags

> +
>  		end = start + size;
>  		printf("ID=%02d %15s %08x..%08x (actual=%08x) %s\n",
> -		       i, name, start, end, act, ecc ? "[ECC]" : "");
> +		       i, name, start, end, act, flags);
>  
>  		if (strcmp(name, "OTHER_SIDE") == 0)
>  			other_side_offset = start;
> @@ -413,6 +435,48 @@ static void disable_4B_addresses(void)
>  	}
>  }
>  
> +static void print_partition_flags(uint32_t part_ID)
> +{
> +	bool ecc, preserved, readonly, backup, reprovision;
> +
> +	struct ffs_handle *ffs_handle;
> +	int rc;
> +
> +	rc = ffs_init(0, fl_total_size, bl, &ffs_handle, 0);
> +	if (rc) {
> +		fprintf(stderr, "Error %d opening ffs !\n", rc);
> +		return;
> +	}
> +
> +	rc = ffs_part_flags(ffs_handle, part_ID, &ecc, &preserved, &readonly,
> +			&backup, &reprovision);
> +	if (rc == FFS_ERR_PART_NOT_FOUND){
> +		fprintf(stderr, "Partition not found! Can't read flags.\n");
> +		return;
> +	}
> +	if (rc) {
> +		fprintf(stderr, "Error %d scanning partitions\n", rc);
> +		return;
> +	}
> +
> +	ffs_close(ffs_handle);
> +
> +	char buf [strlen("ECC,PRESERVED,READONLY,BACKUP,REPROVISION.")];
> +	int l;
> +	l = snprintf(buf, sizeof(buf), "%s%s%s%s%s",
> +				 (ecc) ? "ECC," : "",
> +				 (preserved) ? "PRESERVED," : "",
> +				 (readonly) ? "READONLY," : "",
> +				 (backup) ? "BACKUP," : "",
> +				 (reprovision) ? "REPROVISION." : "");
> +	if (l)
> +	   buf[l-1] = '\0';
> +
> +	printf(buf);
> +
> +	return;
> +}
> +
>  static void print_version(void)
>  {
>  	printf("Open-Power Flash tool %s\n", version);
> @@ -457,6 +521,9 @@ static void print_help(const char *pname)
>  	printf("\t-T, --toc\n");
>  	printf("\t\tlibffs TOC on which to operate, defaults to 0.\n");
>  	printf("\t\tleading 0x is required for interpretation of a hex value\n\n");
> +	printf("\t-m --misc\n");
> +	printf("\t\tReturn the misc. flags for a particular partition of a\n");
> +	printf("\t\tparticular file.\n\n");
>  	printf(" Commands:\n");
>  	printf("\t-4, --enable-4B\n");
>  	printf("\t\tSwitch the flash and controller to 4-bytes address\n");
> @@ -508,7 +575,7 @@ void exiting(void)
>  int main(int argc, char *argv[])
>  {
>  	const char *pname = argv[0];
> -	uint32_t address = 0, read_size = 0, write_size = 0;
> +	uint32_t address = 0, read_size = 0, write_size = 0, part_ID = 0;
>  	uint32_t erase_start = 0, erase_size = 0;
>  	bool erase = false, do_clear = false;
>  	bool program = false, erase_all = false, info = false, do_read = false;
> @@ -517,6 +584,7 @@ int main(int argc, char *argv[])
>  	bool no_action = false, tune = false;
>  	char *write_file = NULL, *read_file = NULL, *part_name = NULL;
>  	bool ffs_toc_seen = false, direct = false;
> +	bool print_flags = false;
>  	int rc;
>  
>  	while(1) {
> @@ -543,11 +611,12 @@ int main(int argc, char *argv[])
>  			{"side",	required_argument,	NULL,	'S'},
>  			{"toc",		required_argument,	NULL,	'T'},
>  			{"clear",   no_argument,        NULL,   'c'},
> +			{"misc",    required_argument,  NULL,   'm'},
>  			{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:cF:m:",
>  				long_opts, &oidx);
>  		if (c == -1)
>  			break;
> @@ -622,6 +691,10 @@ int main(int argc, char *argv[])
>  		case 'c':
>  			do_clear = true;
>  			break;
> +		case 'm':
> +			print_flags = true;
> +			part_ID = strtoul(optarg, NULL, 10);
> +			break;
>  		case ':':
>  			fprintf(stderr, "Unrecognised option \"%s\" to '%c'\n", optarg, optopt);
>  			no_action = true;
> @@ -651,7 +724,7 @@ int main(int argc, char *argv[])
>  	 * also tune them as a side effect
>  	 */
>  	no_action = no_action || (!erase && !program && !info && !do_read &&
> -		!enable_4B && !disable_4B && !tune && !do_clear);
> +		!enable_4B && !disable_4B && !tune && !do_clear && !print_flags);
>  
>  	/* Nothing to do, if we didn't already, print usage */
>  	if (no_action && !show_version)
> @@ -871,6 +944,8 @@ int main(int argc, char *argv[])
>  		 */
>  		print_flash_info(flash_side ? 0 : ffs_toc);
>  	}
> +	if (print_flags)
> +		print_partition_flags(part_ID);
>  
>  	/* Unlock flash (PNOR only) */
>  	if ((erase || program || do_clear) && !bmc_flash && !flashfilename) {
> diff --git a/libflash/libffs.c b/libflash/libffs.c
> index 763e061c..c7b43998 100644
> --- a/libflash/libffs.c
> +++ b/libflash/libffs.c
> @@ -198,6 +198,11 @@ bool has_ecc(struct ffs_entry *ent)
>  	return ((ent->user.datainteg & FFS_ENRY_INTEG_ECC) != 0);
>  }
>  
> +bool has_flag(struct ffs_entry *ent, uint8_t FLAG)
> +{
> +	return ((ent->user.miscflags & FLAG) != 0);
> +}
> +
>  int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
>  		struct ffs_handle **ffs, bool mark_ecc)
>  {
> @@ -362,6 +367,33 @@ int ffs_lookup_part(struct ffs_handle *ffs, const char *name,
>  	return ent ? 0 : FFS_ERR_PART_NOT_FOUND;
>  }
>  
> +int ffs_part_flags(struct ffs_handle *ffs, uint32_t part_idx, bool *ecc,
> +			bool *preserved, bool *readonly, bool *backup, bool *reprovision)
> +{
> +	struct ffs_entry *ent;
> +
> +	ent = ffs_get_part(ffs, part_idx);
> +	if (!ent)
> +		return FFS_ERR_PART_NOT_FOUND;
> +
> +	if (ecc)
> +		*ecc = has_ecc(ent);
> +
> +	if (preserved)
> +		*preserved = has_flag(ent, FFS_MISCFLAGS_PRESERVED);
> +
> +	if (readonly)
> +		*readonly = has_flag(ent, FFS_MISCFLAGS_READONLY);
> +
> +	if (backup)
> +		*backup = has_flag(ent, FFS_MISCFLAGS_BACKUP);
> +
> +	if (reprovision)
> +		*reprovision = has_flag(ent, FFS_MISCFLAGS_REPROVISION);
> +
> +	return 0;
> +}
> +
>  int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
>  		  char **name, uint32_t *start,
>  		  uint32_t *total_size, uint32_t *act_size, bool *ecc)
> diff --git a/libflash/libffs.h b/libflash/libffs.h
> index 2c1fbd83..973feea5 100644
> --- a/libflash/libffs.h
> +++ b/libflash/libffs.h
> @@ -92,6 +92,8 @@ struct ffs_entry_user {
>  
>  bool has_ecc(struct ffs_entry *ent);
>  
> +bool has_flag(struct ffs_entry *ent, uint8_t flag);
> +
>  /* Init */
>  
>  int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
> @@ -122,6 +124,9 @@ void ffs_close(struct ffs_handle *ffs);
>  int ffs_lookup_part(struct ffs_handle *ffs, const char *name,
>  		    uint32_t *part_idx);
>  
> +int ffs_part_flags(struct ffs_handle *ffs, uint32_t part_idx, bool *ecc,
> +			bool *preserved, bool *readonly, bool *backup, bool *reprovision);
> +
>  int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
>  		  char **name, uint32_t *start,
>  		  uint32_t *total_size, uint32_t *act_size, bool *ecc);
> diff --git a/libflash/test/test-miscprint.pnor b/libflash/test/test-miscprint.pnor
> new file mode 100644
> index 0000000000000000000000000000000000000000..8a84ebaf079cb0af235ecd8568c3c990456d7764
> GIT binary patch
> literal 3072
> zcmWG=3<_ajU|@ve1|ZGKz`zWo7+63AG6--CyjqZ0RDvu9Wi$Q<0w5b?4oEYQ2Actu
> zrViCVudg#8$TiqCD9qIbVI;^-2B`f^Kqi<Erx5BOtOj%e;`!_9- at XoVb#(Ff^NB>#
> zg=|06?;u&IGmsR5nGWaz#Pc6*`TQ`*H6X}8%rn^2-w&n{*?v%*;rG7)OdIL+>dh;E
> zIXOCehX$bN1%){*{DEnQfc**})#QN}=k{&_#q%f_4S~@R7!85Z5Eu=C(GVC7fzc2k
> GKLh~mR(fav
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/libflash/test/test-miscprint.sh b/libflash/test/test-miscprint.sh
> new file mode 100644
> index 00000000..d064cf10
> --- /dev/null
> +++ b/libflash/test/test-miscprint.sh
> @@ -0,0 +1,35 @@
> +#!/bin/bash
> +
> +# test-miscprint.pnor is constructed as follows:
> +# PRESERVED,0x00000300,0x00000100,P,/dev/zero
> +# READONLY,0x00000400,0x00000100,R,/dev/zero
> +# REPROVISION,0x00000500,0x00000100,F,/dev/zero
> +# BACKUP,0x00000600,0x00000100,B,/dev/zero
> +
> +pass=true
> +
> +output=$(pflash -m 1 -F "$(dirname -- "$0")/test-miscprint.pnor")
> +if [[ $output != "PRESERVED" ]]; then
> +    pass=false
> +fi
> +
> +output=$(pflash -m 2 -F "$(dirname -- "$0")/test-miscprint.pnor")
> +if [[ $output != "READONLY" ]]; then
> +    pass=false
> +fi
> +
> +output=$(pflash -m 3 -F "$(dirname -- "$0")/test-miscprint.pnor")
> +if [[ $output != "REPROVISION" ]]; then
> +    pass=false
> +fi
> +
> +output=$(pflash -m 4 -F "$(dirname -- "$0")/test-miscprint.pnor")
> +if [[ $output != "BACKUP" ]]; then
> +    pass=false
> +fi
> +
> +if [[ pass ]]; then
> +    echo "Test passed!"
> +else
> +    echo "Test failed!"
> +fi


More information about the Skiboot mailing list