Skip to content

Commit

Permalink
pflash option to retrieve PNOR partition flags
Browse files Browse the repository at this point in the history
This commit extends pflash with an option to retrieve and print
information for a particular partition, including the content from
"pflash -i" and a verbose list of set miscellaneous flags. -i option
is also updated to print a short list of flags in addition to the
ECC flag, with one character per flag. A test of the new option is
included in libflash/test.

Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
Reviewed-by: Cyril Bur <cyril.bur@au1.ibm.com>
[stewart@linux.vnet.ibm.com: various test fixes, enable gcov]
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
  • Loading branch information
Michael Tritz authored and stewartsmith committed Jul 19, 2017
1 parent eae8678 commit f2c87a3
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 16 deletions.
134 changes: 123 additions & 11 deletions external/pflash/pflash.c
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -90,6 +92,7 @@ static void print_ffs_info(uint32_t toc_offset)
{
struct ffs_handle *ffs_handle;
uint32_t other_side_offset = 0;
struct ffs_entry *ent;
int rc;
uint32_t i;

Expand All @@ -103,25 +106,40 @@ static void print_ffs_info(uint32_t toc_offset)
return;
}

for (i = 0;; i++) {
for (i = 0; rc == 0; i++) {
uint32_t start, size, act, end;
bool ecc;
char *name;
char *name = NULL, *flags;
int l;

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;

ent = ffs_entry_get(ffs_handle, i);
if (rc || !ent) {
fprintf(stderr, "Error %d scanning partitions\n",
!ent ? FFS_ERR_PART_NOT_FOUND : rc);
goto out;
}

l = asprintf(&flags, "[%c%c%c%c%c]",
has_ecc(ent) ? 'E' : '-',
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' : '-');
if (l < 0)
goto out;

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;

free(flags);
out:
free(name);
}

Expand Down Expand Up @@ -413,6 +431,81 @@ static void disable_4B_addresses(void)
}
}

static void print_partition_detail(uint32_t toc_offset, uint32_t part_id, char *name)
{
uint32_t start, size, act, end;
struct ffs_handle *ffs_handle;
char *ent_name = NULL, *flags;
struct ffs_entry *ent;
int rc, l;

rc = ffs_init(toc_offset, fl_total_size, bl, &ffs_handle, 0);
if (rc) {
fprintf(stderr, "Error %d opening ffs !\n", rc);
return;
}

if (name) {
uint32_t i;

for (i = 0;;i++) {
rc = ffs_part_info(ffs_handle, i, &ent_name, &start, &size, &act,
NULL);
if (rc == FFS_ERR_PART_NOT_FOUND) {
fprintf(stderr, "Partition with name %s doesn't exist within TOC at 0x%08x\n", name, toc_offset);
goto out;
}
if (rc || strncmp(ent_name, name, FFS_PART_NAME_MAX) == 0) {
part_id = i;
break;
}
free(ent_name);
ent_name = NULL;
}
} else {
rc = ffs_part_info(ffs_handle, part_id, &ent_name, &start, &size, &act,
NULL);
if (rc == FFS_ERR_PART_NOT_FOUND) {
fprintf(stderr, "Partition with ID %d doesn't exist within TOC at 0x%08x\n",
part_id, toc_offset);
goto out;
}
}
ent = ffs_entry_get(ffs_handle, part_id);
if (rc || !ent) {
fprintf(stderr, "Error %d scanning partitions\n", !ent ?
FFS_ERR_PART_NOT_FOUND : rc);
goto out;
}

printf("Detailed partition information\n");
end = start + size;
printf("Name:\n");
printf("%s (ID=%02d)\n\n", ent_name, part_id);
printf("%-10s %-10s %-10s\n", "Start", "End", "Actual");
printf("0x%08x 0x%08x 0x%08x\n\n", start, end, act);

printf("Flags:\n");

l = asprintf(&flags, "%s%s%s%s%s", has_ecc(ent) ? "ECC [E]\n" : "",
has_flag(ent, FFS_MISCFLAGS_PRESERVED) ? "PRESERVED [P]\n" : "",
has_flag(ent, FFS_MISCFLAGS_READONLY) ? "READONLY [R]\n" : "",
has_flag(ent, FFS_MISCFLAGS_BACKUP) ? "BACKUP [B]\n" : "",
has_flag(ent, FFS_MISCFLAGS_REPROVISION) ?
"REPROVISION [F]\n" : "");
if (l < 0) {
fprintf(stderr, "Memory allocation failure printing flags!\n");
goto out;
}

printf("%s", flags);
free(flags);

out:
ffs_close(ffs_handle);
free(ent_name);
}

static void print_version(void)
{
printf("Open-Power Flash tool %s\n", version);
Expand Down Expand Up @@ -494,6 +587,10 @@ 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--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");
printf("\t\twith the -P flag.\n\n");
printf("\t-h, --help\n");
printf("\t\tThis message.\n\n");
}
Expand All @@ -508,15 +605,15 @@ 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, detail_id = UINT_MAX;
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;
bool enable_4B = false, disable_4B = false;
bool show_help = false, show_version = false;
bool no_action = false, tune = false;
char *write_file = NULL, *read_file = NULL, *part_name = NULL;
bool ffs_toc_seen = false, direct = false;
bool ffs_toc_seen = false, direct = false, print_detail = false;
int rc;

while(1) {
Expand All @@ -535,6 +632,7 @@ int main(int argc, char *argv[])
{"force", no_argument, NULL, 'f'},
{"flash-file", required_argument, NULL, 'F'},
{"info", no_argument, NULL, 'i'},
{"detail", optional_argument, NULL, 'm'},
{"tune", no_argument, NULL, 't'},
{"dummy", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
Expand Down Expand Up @@ -622,6 +720,11 @@ int main(int argc, char *argv[])
case 'c':
do_clear = true;
break;
case 'm':
print_detail = true;
if (optarg)
detail_id = strtoul(optarg, NULL, 0);
break;
case ':':
fprintf(stderr, "Unrecognised option \"%s\" to '%c'\n", optarg, optopt);
no_action = true;
Expand Down Expand Up @@ -651,7 +754,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_detail);

/* Nothing to do, if we didn't already, print usage */
if (no_action && !show_version)
Expand Down Expand Up @@ -684,6 +787,12 @@ int main(int argc, char *argv[])
exit(1);
}

if (print_detail && ((detail_id == UINT_MAX && !part_name)
|| (detail_id != UINT_MAX && part_name))) {
fprintf(stderr, "--detail requires either a partition id or\n");
fprintf(stderr, "a partition name with -P\n");
}

/* part-name and erase-all make no sense together */
if (part_name && erase_all) {
fprintf(stderr, "--partition and --erase-all are mutually"
Expand Down Expand Up @@ -872,6 +981,9 @@ int main(int argc, char *argv[])
print_flash_info(flash_side ? 0 : ffs_toc);
}

if (print_detail)
print_partition_detail(flash_side ? 0 : ffs_toc, detail_id, part_name);

/* Unlock flash (PNOR only) */
if ((erase || program || do_clear) && !bmc_flash && !flashfilename) {
need_relock = arch_flash_set_wrprotect(bl, false);
Expand Down
11 changes: 8 additions & 3 deletions libflash/libffs.c
Expand Up @@ -188,7 +188,12 @@ static int ffs_entry_to_cpu(struct ffs_hdr *hdr,
return rc;
}

static struct ffs_entry *ffs_get_part(struct ffs_handle *ffs, uint32_t index)
bool has_flag(struct ffs_entry *ent, uint16_t flag)
{
return ((ent->user.miscflags & flag) != 0);
}

struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index)
{
int i = 0;
struct ffs_entry *ent = NULL;
Expand Down Expand Up @@ -379,7 +384,7 @@ int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
struct ffs_entry *ent;
char *n;

ent = ffs_get_part(ffs, part_idx);
ent = ffs_entry_get(ffs, part_idx);
if (!ent)
return FFS_ERR_PART_NOT_FOUND;

Expand Down Expand Up @@ -794,7 +799,7 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
uint32_t offset;
int rc;

ent = ffs_get_part(ffs, part_idx);
ent = ffs_entry_get(ffs, part_idx);
if (!ent) {
FL_DBG("FFS: Entry not found\n");
return FFS_ERR_PART_NOT_FOUND;
Expand Down
4 changes: 4 additions & 0 deletions libflash/libffs.h
Expand Up @@ -92,6 +92,8 @@ struct ffs_entry_user {

bool has_ecc(struct ffs_entry *ent);

bool has_flag(struct ffs_entry *ent, uint16_t flag);

/* Init */

int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
Expand Down Expand Up @@ -126,6 +128,8 @@ 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);

struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index);

int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
uint32_t act_size);

Expand Down
7 changes: 5 additions & 2 deletions libflash/test/Makefile.check
Expand Up @@ -4,8 +4,8 @@ LIBFLASH_TEST := libflash/test/test-flash libflash/test/test-ecc libflash/test/t
LCOV_EXCLUDE += $(LIBFLASH_TEST:%=%.c)

.PHONY : libflash-check libc-coverage
libflash-check: $(LIBFLASH_TEST:%=%-check) $(CORE_TEST:%=%-gcov-run)
libflash-coverage: $(LIBFLASH_TEST:%=%-gcov-run)
libflash-check: $(LIBFLASH_TEST:%=%-check) libflash/test/test-miscprint $(CORE_TEST:%=%-gcov-run)
libflash-coverage: $(LIBFLASH_TEST:%=%-gcov-run) libflash/test/test-miscprint

check: libflash-check libc-coverage
coverage: libflash-coverage
Expand All @@ -16,6 +16,9 @@ $(LIBFLASH_TEST:%=%-gcov-run) : %-run: %
$(LIBFLASH_TEST:%=%-check) : %-check: %
$(call QTEST, RUN-TEST ,$(VALGRIND) $<, $<)

libflash/test/test-miscprint: pflash
$(call Q, RUN-TEST , ./libflash/test/test-miscprint.sh, $@)

libflash/test/stubs.o: libflash/test/stubs.c
$(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -g -c -o $@ $<, $<)

Expand Down
Binary file added libflash/test/test-miscprint.pnor
Binary file not shown.
27 changes: 27 additions & 0 deletions libflash/test/test-miscprint.sh
@@ -0,0 +1,27 @@
#!/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

wd="libflash/test"
pflash="./external/pflash/pflash"

pnor="$wd/test-miscprint.pnor"

output1=$(${pflash} --detail=1 -F "$pnor" | grep "\[P\]")
output2=$(${pflash} --detail=2 -F "$pnor" | grep "\[R\]")
output3=$(${pflash} --detail=3 -F "$pnor" | grep "\[F\]")
output4=$(${pflash} --detail=4 -F "$pnor" | grep "\[B\]")

if [[ $output1 == "PRESERVED [P]" && $output2 == "READONLY [R]" &&
$output3 == "REPROVISION [F]" && $output4 == "BACKUP [B]" ]]; then
echo "Test passed!"
exit 0;
else
echo "Test failed!"
exit 1;
fi

0 comments on commit f2c87a3

Please sign in to comment.