@@ -158,6 +158,105 @@ static struct ffs_handle *open_ffs(struct flash_details *flash)
return ffsh;
}
+static bool part_in_toc(struct flash_details *flash, uint32_t toc, const char *part)
+{
+ uint32_t saved_toc = flash->toc;
+ int i;
+ struct ffs_handle *ffsh;
+ bool part_exists = false;
+
+ flash->toc = toc;
+
+ if (saved_toc == toc)
+ return true;
+
+ ffsh = open_ffs(flash);
+ if (!ffsh) {
+ flash->toc = saved_toc;
+ return false;
+ }
+
+ for (i = 0;; i++) {
+ char *name = NULL;
+ int rc;
+ rc = ffs_part_info(ffsh, i, &name, NULL, NULL, NULL, NULL);
+ if (rc == FFS_ERR_PART_NOT_FOUND)
+ break;
+
+ if (strcmp(name, part) == 0) {
+ part_exists = true;
+ }
+ free(name);
+ }
+ ffs_close(ffsh);
+
+ flash->toc = saved_toc;
+
+ return part_exists;
+}
+
+static void print_ffs_csv_info(struct flash_details *flash,
+ uint32_t toc, uint32_t next_toc)
+{
+ struct ffs_entry *ent;
+ struct ffs_handle *ffsh;
+ int rc;
+ int i;
+
+ ffsh = open_ffs(flash);
+ if (!ffsh)
+ return;
+
+ for (i = 0;; i++) {
+ uint32_t start, size, act;
+ char *name = NULL, *flags;
+ const char *fname;
+ int l;
+
+ rc = ffs_part_info(ffsh, i, &name, &start, &size, &act, NULL);
+ if (rc == FFS_ERR_PART_NOT_FOUND)
+ break;
+
+ ent = ffs_entry_get(ffsh, i);
+ if (rc || !ent) {
+ fprintf(stderr, "Error %d scanning partitions\n",
+ !ent ? FFS_ERR_PART_NOT_FOUND : rc);
+ goto out;
+ }
+
+
+ l = asprintf(&flags, "%s%s%s%s%s%s%s%s",
+ has_ecc(ent) ? "E" : "",
+ has_vercheck_flag(ent, FFS_VERCHECK_SHA512V) ? "V" : "",
+ has_vercheck_flag(ent, FFS_VERCHECK_SHA512EC) ? "I" : "",
+ has_flag(ent, FFS_MISCFLAGS_PRESERVED) ? "P" : "",
+ has_flag(ent, FFS_MISCFLAGS_READONLY) ? "R" : "",
+ has_flag(ent, FFS_MISCFLAGS_BACKUP) ? "B" : "",
+ has_flag(ent, FFS_MISCFLAGS_REPROVISION) ? "F" : "",
+ (!part_in_toc(flash, next_toc, name)) ? "1" : ""
+ );
+ if (l < 0)
+ goto out;
+
+ if (strcmp(name, "BACKUP_PART") == 0)
+ fname = "/dev/null";
+ else
+ fname = name;
+
+ if (!(strcmp(name, "part") == 0) &&
+ !(strcmp(name, "OTHER_SIDE") == 0))
+ printf("%s,0x%08x,0x%08x,%s,%s\n",
+ name, start, size, flags, fname);
+
+ free(flags);
+out:
+ free(name);
+ }
+
+ ffs_close(ffsh);
+ return;
+}
+
static void print_flash_info(struct flash_details *flash)
{
struct ffs_handle *ffsh;
@@ -194,6 +293,42 @@ static void print_flash_info(struct flash_details *flash)
flash->toc = toc;
}
+static void print_flash_csv_info(struct flash_details *flash)
+{
+ struct ffs_handle *ffsh;
+ uint32_t toc;
+
+ if (bmc_flash)
+ return;
+
+ toc = flash->toc;
+
+ ffsh = open_ffs(flash);
+ if (!ffsh)
+ return;
+
+ uint32_t start;
+ uint32_t next_toc = toc;
+ int i;
+
+ for (i = 0;; i++) {
+ char *name = NULL;
+ int rc;
+
+ rc = ffs_part_info(ffsh, i, &name, &start, NULL, NULL, NULL);
+ if (rc == FFS_ERR_PART_NOT_FOUND)
+ break;
+
+ if (strcmp(name, "OTHER_SIDE") == 0) {
+ next_toc = start;
+ }
+ free(name);
+ }
+ ffs_close(ffsh);
+
+ print_ffs_csv_info(flash, toc, next_toc);
+}
+
static struct ffs_handle *open_partition(struct flash_details *flash,
const char *name, uint32_t *index)
{
@@ -667,6 +802,8 @@ static void print_help(const char *pname)
printf("\t\tpartition and then set all the ECC bits as they should be\n\n");
printf("\t-i, --info\n");
printf("\t\tDisplay some information about the flash.\n\n");
+ printf("\t-I, --csv\n");
+ printf("\t\tSame as -i, but output as CSV consumable by ffspart\n\n");
printf("\t--detail\n");
printf("\t\tDisplays detailed info about a particular partition.\n");
printf("\t\tAccepts a numeric partition or can be used in conjuction\n");
@@ -684,6 +821,7 @@ int main(int argc, char *argv[])
uint32_t address = 0, read_size = 0, write_size = 0, detail_id = UINT_MAX;
bool erase = false, do_clear = false;
bool program = false, erase_all = false, info = false, do_read = false;
+ bool csv_info = false;
bool enable_4B = false, disable_4B = false;
bool show_help = false, show_version = false;
bool no_action = false, tune = false;
@@ -708,6 +846,7 @@ int main(int argc, char *argv[])
{"force", no_argument, NULL, 'f'},
{"flash-file", required_argument, NULL, 'F'},
{"info", no_argument, NULL, 'i'},
+ {"csv", no_argument, NULL, 'I'},
{"detail", optional_argument, NULL, 'm'},
{"tune", no_argument, NULL, 't'},
{"dummy", no_argument, NULL, 'd'},
@@ -721,7 +860,7 @@ int main(int argc, char *argv[])
};
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:fdiIhvbtgS:T:cF:",
long_opts, &oidx);
if (c == -1)
break;
@@ -784,6 +923,10 @@ int main(int argc, char *argv[])
case 'i':
info = true;
break;
+ case 'I':
+ info = true;
+ csv_info = true;
+ break;
case 'b':
bmc_flash = true;
break;
@@ -1099,7 +1242,10 @@ int main(int argc, char *argv[])
* because of --size, but still respect if it came from --toc (we
* assume the user knows what they're doing in that case)
*/
- print_flash_info(&flash);
+ if (csv_info)
+ print_flash_csv_info(&flash);
+ else
+ print_flash_info(&flash);
}
if (print_detail)
@@ -193,6 +193,11 @@ bool has_flag(struct ffs_entry *ent, uint16_t flag)
return ((ent->user.miscflags & flag) != 0);
}
+bool has_vercheck_flag(struct ffs_entry *ent, uint8_t flag)
+{
+ return ((ent->user.vercheck & flag) != 0);
+}
+
struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index)
{
int i = 0;
@@ -94,6 +94,8 @@ bool has_ecc(struct ffs_entry *ent);
bool has_flag(struct ffs_entry *ent, uint16_t flag);
+bool has_vercheck_flag(struct ffs_entry *ent, uint8_t flag);
+
/* Init */
int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
We add a -I/--csv option to pflash that takes an existing PNOR image and exports a CSV file consumable by ffspart to create a binary identical PNOR image (when combined with files matching the contents of each partition). Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com> --- external/pflash/pflash.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++- libflash/libffs.c | 5 ++ libflash/libffs.h | 2 + 3 files changed, 155 insertions(+), 2 deletions(-)