David Hendricks has uploaded this change for review. ( https://review.coreboot.org/23024
Change subject: test_v2.sh: Copy layout to local tempdir in local-layout mode
......................................................................
test_v2.sh: Copy layout to local tempdir in local-layout mode
The layout file wasn't being copied to the local tempdir when using
layout as the region mode and doing the test entirely locally.
BUG=none
BRANCH=none
TEST=ran test in layout mode locally
Change-Id: Ia2328d367ee3df5ac1c481c16e4502a81d69fd98
Signed-off-by: David Hendricks <dhendrix(a)chromium.org>
---
M tests/tests_v2/test_v2.sh
1 file changed, 2 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/24/23024/1
diff --git a/tests/tests_v2/test_v2.sh b/tests/tests_v2/test_v2.sh
index 9de8316..bf240d7 100755
--- a/tests/tests_v2/test_v2.sh
+++ b/tests/tests_v2/test_v2.sh
@@ -386,6 +386,8 @@
if [ $DO_REMOTE -eq 1 ]; then
scp root@"${REMOTE_HOST}:$LAYOUT_FILE" "${LOCAL_TMPDIR}/" 2>&1 >/dev/null
+ else
+ cp "$LAYOUT_FILE" "${LOCAL_TMPDIR}/"
fi
fi
elif [ $TEST_TYPE -eq $TEST_TYPE_WRITEPROTECT ]; then
--
To view, visit https://review.coreboot.org/23024
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia2328d367ee3df5ac1c481c16e4502a81d69fd98
Gerrit-Change-Number: 23024
Gerrit-PatchSet: 1
Gerrit-Owner: David Hendricks <david.hendricks(a)gmail.com>
Hello Louis Yung-Chieh Lo,
I'd like you to do a code review. Please visit
https://review.coreboot.org/23022
to review the following change.
Change subject: make args for -r/-w/-v non-positional and optional
......................................................................
make args for -r/-w/-v non-positional and optional
Ported from chromiumos:
https://chromium-review.googlesource.com/#/c/60515/
This makes a filename following -r, -w, and -v operations non-
positional. The first argument that does not begin with a hyphen (-)
is the filename for -r/-w/-v. If no such argument exists, then
-r/-w/-v options apply to files specified for individually included
regions via -i.
This has a few side-effects:
1. It allows us to omit the ROM-sized filename entirely when a
filename is provided for a particular region when using -i. For
example, "flashrom -i FOO:foo.bin -r".
2. It allows, for better or worse, the filename be specified anywhere
on the command line after the program name. Our scripts and docs
should still specify the file after -r/-w/-v for clarity.
For our purposes, if a filename is given for every included region
(-i region:filename) then the user does not need to specify a filename
after -r/-w/-v. However, if any -i option does not specify a filename,
then a file must be specified after -r/-w/-v.
The syntax will be backwards compatible for now so that one can still
mix -i options with and without the added filename specifier for each
region.
BUG=chromium:263495
BRANCH=none
TEST=manual (see notes below)
1. Write random data to RW_UNUSED region (on snow in this case)
without requiring an argument to -w. See that only RW_UNUSED
is erased and written, and that verify works:
dd if=/dev/urandom of=rw_unused.bin bs=1k count=1 conv=notrunc
flashrom -p host -i RW_UNUSED:rw_unused.bin -w -V
flashrom -p host -i RW_UNUSED:rw_unused.bin -v -V
2. Same as above, but specify a dummy file to test syntax
backwards compatibility:
dd if=/dev/urandom of=rw_unused.bin bs=1k count=1 conv=notrunc
dd if=/dev/urandom of=random_4M.bin bs=1M count=4
flashrom -p host -i RW_UNUSED:rw_unused.bin -w random_4M.bin -V
flashrom -p host -i RW_UNUSED:rw_unused.bin -v random_4M.bin -V
3. Test that dumping RW_UNUSED and GBB regions without -r arg dumps
two files and that they can be used to verify the content:
flashrom -p host -i RW_UNUSED:rw_unused.bin -i GBB:gbb.bin -r
flashrom -p host -i RW_UNUSED:rw_unused.bin -i GBB:gbb.bin -v
4. Same as above, but with dummy file:
flashrom -p host -i RW_UNUSED:rw_unused.bin -i GBB:gbb.bin -r x.bin
flashrom -p host -i RW_UNUSED:rw_unused.bin -i GBB:gbb.bin -v x.bin
Change-Id: Iefbcb7dc4fefe26f5afd1292dfd5c1687fa62803
Reviewed-on: https://gerrit.chromium.org/gerrit/60515
Reviewed-by: Yung-Chieh Lo <yjlou(a)chromium.org>
Commit-Queue: David Hendricks <dhendrix(a)chromium.org>
Tested-by: David Hendricks <dhendrix(a)chromium.org>
---
M cli_classic.c
M flashrom.8.tmpl
M flashrom.c
M layout.c
M layout.h
5 files changed, 232 insertions(+), 32 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/22/23022/1
diff --git a/cli_classic.c b/cli_classic.c
index c1481ec..9939b98 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -111,12 +111,12 @@
enum programmer prog = PROGRAMMER_INVALID;
int ret = 0;
- static const char optstring[] = "r:Rw:v:nNVEfc:l:i:p:Lzho:";
+ static const char optstring[] = "rRwvnNVEfc:l:i:p:Lzho:";
static const struct option long_options[] = {
- {"read", 1, NULL, 'r'},
- {"write", 1, NULL, 'w'},
+ {"read", 0, NULL, 'r'},
+ {"write", 0, NULL, 'w'},
{"erase", 0, NULL, 'E'},
- {"verify", 1, NULL, 'v'},
+ {"verify", 0, NULL, 'v'},
{"noverify", 0, NULL, 'n'},
{"noverify-all", 0, NULL, 'N'},
{"chip", 1, NULL, 'c'},
@@ -163,7 +163,6 @@
"specified. Aborting.\n");
cli_classic_abort_usage();
}
- filename = strdup(optarg);
read_it = 1;
break;
case 'w':
@@ -172,7 +171,6 @@
"specified. Aborting.\n");
cli_classic_abort_usage();
}
- filename = strdup(optarg);
write_it = 1;
break;
case 'v':
@@ -186,7 +184,6 @@
fprintf(stderr, "--verify and --noverify are mutually exclusive. Aborting.\n");
cli_classic_abort_usage();
}
- filename = strdup(optarg);
verify_it = 1;
break;
case 'n':
@@ -344,12 +341,12 @@
}
}
- if (optind < argc) {
- fprintf(stderr, "Error: Extra parameter found.\n");
- cli_classic_abort_usage();
+ if (read_it || write_it || verify_it) {
+ if (argv[optind])
+ filename = strdup(argv[optind]);
}
- if ((read_it | write_it | verify_it) && check_filename(filename, "image")) {
+ if ((read_it | write_it | verify_it) && filename && check_filename(filename, "image")) {
cli_classic_abort_usage();
}
if (layoutfile && check_filename(layoutfile, "layout")) {
@@ -560,6 +557,71 @@
flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !dont_verify_it);
flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, !dont_verify_all);
+ /*
+ * Common rules for -r/-w/-v syntax parsing:
+ * - If no filename is specified at all, quit.
+ * - If no filename is specified for -r/-w/-v, but files are specified
+ * for -i, then the number of file arguments for -i options must be
+ * equal to the total number of -i options.
+ *
+ * Rules for reading:
+ * - If files are specified for -i args but not -r, do partial reads for
+ * each -i arg, creating a new file for each region. Each -i option
+ * must specify a filename.
+ * - If filenames are specified for -r and -i args, then:
+ * - Do partial read for each -i arg, creating a new file for
+ * each region where a filename is provided (-i region:filename).
+ * - Create a ROM-sized file with partially filled content. For each
+ * -i arg, fill the corresponding offset with content from ROM.
+ *
+ * Rules for writing and verifying:
+ * - If files are specified for both -w/-v and -i args, -i files take
+ * priority. (Note: We determined this was the most useful syntax for
+ * chromium.org's flashrom after some discussion. Upstream may wish
+ * to quit in this case due to ambiguity).
+ * See: http://crbug.com/263495.
+ * - If file is specified for -w/-v and no files are specified with -i
+ * args, then the file is to be used for writing/verifying the entire
+ * ROM.
+ * - If files are specified for -i args but not -w, do partial writes
+ * for each -i arg. Likewise for -v and -i args. All -i args must
+ * supply a filename. Any omission is considered ambiguous.
+ * - Regions with a filename associated must not overlap. This is also
+ * considered ambiguous. Note: This is checked later since it requires
+ * processing the layout/fmap first.
+ */
+ if (read_it || write_it || verify_it) {
+ char op = 0;
+
+ if (read_it)
+ op = 'r';
+ else if (write_it)
+ op = 'w';
+ else if (verify_it)
+ op = 'v';
+
+ if (!filename) {
+ if (layout->num_entries == 0) {
+ msg_gerr("Error: No file specified for -%c.\n", op);
+ ret = 1;
+ goto out_shutdown;
+ }
+
+ for (i = 0; i < layout->num_entries; i++) {
+ if (!layout->entries[i].included)
+ continue;
+ char *const file = layout->entries[i].file;
+ if (!file || !strlen(file)) {
+ msg_gerr("Error: Missing filename for region \"%s\"\n", file);
+ ret = 1;
+ }
+ }
+
+ if (ret)
+ goto out_shutdown;
+ }
+ }
+
/* FIXME: We should issue an unconditional chip reset here. This can be
* done once we have a .reset function in struct flashchip.
* Give the chip time to settle.
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 6a05e8a..6e1ba7b 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -46,7 +46,7 @@
.SH SYNOPSIS
.B flashrom \fR[\fB\-h\fR|\fB\-R\fR|\fB\-L\fR|\fB\-z\fR|\
\fB\-p\fR <programmername>[:<parameters>]
- [\fB\-E\fR|\fB\-r\fR <file>|\fB\-w\fR <file>|\fB\-v\fR <file>] \
+ [\fB\-E\fR|\fB\-r\fR [file]|\fB\-w\fR [file]|\fB\-v\fR <file>] \
[\fB\-c\fR <chipname>]
[(\fB\-l\fR <file>|\fB\-\-ifd\fR) [\fB\-i\fR <image>[:<file>]]] \
[\fB\-n\fR] [\fB\-N\fR] [\fB\-f\fR]]
@@ -81,17 +81,29 @@
.B -p/--programmer
option to be used (please see below).
.TP
-.B "\-r, \-\-read <file>"
-Read flash ROM contents and save them into the given
-.BR <file> .
-If the file already exists, it will be overwritten.
+.B "\-r, \-\-read [file]"
+Read flash ROM contents. If
+.BR [file]
+is specified ROM contents will be saved to it. If the file already exists, it
+will be overwritten.
+.sp
+Alternatively,
+.B "\-i"
+may be used to output files for specific regions only.
.TP
-.B "\-w, \-\-write <file>"
-Write
-.B <file>
-into flash ROM. This will first automatically
+.B "\-w, \-\-write [file]"
+Write contents to ROM. If
+.B [file]
+is specified then its contents will be written to the ROM. See
+.B "\-i"
+option for information about using
+.B "\-i"
+with
+.B "\-w."
+.sp
+Write operations will erase
.B erase
-the chip, then write to it.
+necessary regions of chip before writing to it.
.sp
In the process the chip is also read several times. First an in-memory backup
is made for disaster recovery and to be able to skip regions that are
@@ -240,7 +252,7 @@
into region-sized files
.BR "foo.bin " and " bar.bin" ", run:
.sp
-.B " flashrom \-p prog \-l <layout> \-i foo:foo.bin -i bar:bar.bin -r rom.bin
+.B " flashrom \-p prog \-l <layout> \-i foo:foo.bin -i bar:bar.bin -r
.sp
To write files
.BR "foo.bin " and " bar.bin"
@@ -249,7 +261,7 @@
.BR <layout>
to the ROM, run:
.sp
-.B " flashrom \-p prog \-l <layout> \-i foo:foo.bin -i bar:bar.bin -w rom.bin
+.B " flashrom \-p prog \-l <layout> \-i foo:foo.bin -i bar:bar.bin -w
.TP
.B "\-L, \-\-list\-supported"
List the flash chips, chipsets, mainboards, and external programmers
diff --git a/flashrom.c b/flashrom.c
index 4f50c54..5035f83 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -1356,6 +1356,75 @@
#endif
}
+static int read_buf_from_include_args(const struct flashctx *const flash, unsigned char *buf, unsigned long size)
+{
+#ifdef __LIBPAYLOAD__
+ msg_gerr("Error: No file I/O support in libpayload\n");
+ return 1;
+#else
+ int ret = 0, i;
+ const struct flashrom_layout *const layout = get_layout(flash);
+ const struct romentry *entry;
+
+ /*
+ * Content will be read from -i args, so they must not overlap since
+ * we need to know exactly what content to write to the ROM.
+ */
+ if (included_regions_overlap(layout)) {
+ msg_gerr("Error: Included regions must not overlap when writing.\n");
+ return 1;
+ }
+
+ /* sanity check region boundaries before accessing the chip */
+ for (i = 0; i < layout->num_entries; i++) {
+ entry = &layout->entries[i];
+ if (!entry->included)
+ continue;
+
+ if ((entry->start > size) || (entry->end > size)) {
+ msg_gerr("Region \"%s\" exceeds the chip size.\n", entry->name);
+ return 1;
+ }
+ }
+
+ for (i = 0; i < layout->num_entries; i++) {
+ FILE *image;
+
+ entry = &layout->entries[i];
+ chipoff_t len = entry->end - entry->start + 1;
+
+ /* TODO(dhendrix) make sure layout->entries[i].file is NULL for non-included regions */
+ if (entry->included && entry->file) {
+ if ((image = fopen(entry->file, "rb")) == NULL) {
+ msg_gerr("Error: opening file \"%s\" failed: %s\n", entry->file, strerror(errno));
+ return 1;
+ }
+ } else {
+ continue;
+ }
+
+ struct stat image_stat;
+ if (fstat(fileno(image), &image_stat) != 0) {
+ msg_gerr("Error: getting metadata of file \"%s\" failed: %s\n", entry->file, strerror(errno));
+ ret = 1;
+ goto out;
+ }
+
+ unsigned long numbytes = fread(buf + entry->start, 1, len, image);
+ fclose(image);
+ if (numbytes != len) {
+ msg_gerr("Error: Failed to read file \"%s\". Got %ld bytes, "
+ "wanted %u!\n", entry->file, numbytes, len);
+ ret = 1;
+ break;
+ }
+
+ }
+out:
+ return ret;
+#endif
+}
+
/**
* @brief Writes included layout regions into buffer(s)
*
@@ -1441,15 +1510,19 @@
size_t i;
for (i = 0; i < layout->num_entries; i++) {
- if (!layout->entries[i].included)
- continue;
- if (!layout->entries[i].file)
+ if (!layout->entries[i].included || !layout->entries[i].file)
continue;
const chipoff_t region_start = layout->entries[i].start;
- const chipsize_t region_len = layout->entries[i].end - layout->entries[i].start + 1;
+ const chipoff_t region_end = layout->entries[i].end;
+ const chipsize_t region_len = region_end - region_start + 1;
const char *region_file = layout->entries[i].file;
+ if (i == 0)
+ msg_gdbg("\n"); /* avoid printing in caller's output */
+ msg_gdbg("Writing region %s [0x%06x:0x%06x] to file \"%s\"\n",
+ layout->entries[i].name, region_start, region_end, region_file);
+
ret = do_write_buf_to_file(buf + region_start, region_len, region_file);
if (ret)
goto out;
@@ -1466,7 +1539,6 @@
#endif
}
-
static int read_by_layout(struct flashctx *, uint8_t *);
int read_flash_to_file(struct flashctx *flash, const char *filename)
{
@@ -2598,8 +2670,18 @@
goto _free_ret;
}
- if (read_buf_from_file(newcontents, flash_size, filename, "the flash chip's size"))
- goto _free_ret;
+ /*
+ * This must be done before any files specified by -i arguments are
+ * processed and merged into newcontents since -i files take priority.
+ * See http://crbug.com/263495.
+ */
+ if (filename) {
+ if (read_buf_from_file(newcontents, flash_size, filename, "the flash chip's size"))
+ goto _free_ret;
+ } else {
+ if (read_buf_from_include_args(flash, newcontents, flash_size))
+ goto _free_ret;
+ }
ret = flashrom_image_write(flash, newcontents, flash_size);
@@ -2619,8 +2701,13 @@
goto _free_ret;
}
- if (read_buf_from_file(newcontents, flash_size, filename, "the flash chip's size"))
- goto _free_ret;
+ if (filename) {
+ if (read_buf_from_file(newcontents, flash_size, filename, "the flash chip's size"))
+ goto _free_ret;
+ } else {
+ if (read_buf_from_include_args(flash, newcontents, flash_size))
+ goto _free_ret;
+ }
ret = flashrom_image_verify(flash, newcontents, flash_size);
diff --git a/layout.c b/layout.c
index 4ae4a69..3493624 100644
--- a/layout.c
+++ b/layout.c
@@ -237,6 +237,44 @@
return 0;
}
+/* returns boolean 1 if any regions overlap, 0 otherwise */
+int included_regions_overlap(const struct flashrom_layout *const l)
+{
+ int i, overlap_detected = 0;
+
+ for (i = 0; i < l->num_entries; i++) {
+ int j;
+
+ if (!l->entries[i].included)
+ continue;
+
+ for (j = 0; j < l->num_entries; j++) {
+ if (!l->entries[j].included)
+ continue;
+
+ if (i == j)
+ continue;
+
+ if (l->entries[i].start > l->entries[j].end)
+ continue;
+
+ if (l->entries[i].end < l->entries[j].start)
+ continue;
+
+ msg_gdbg("Regions %s [0x%08x-0x%08x] and "
+ "%s [0x%08x-0x%08x] overlap\n",
+ l->entries[i].name, l->entries[i].start,
+ l->entries[i].end, l->entries[j].name,
+ l->entries[j].start, l->entries[j].end);
+ overlap_detected = 1;
+ goto out;
+ }
+
+ }
+out:
+ return overlap_detected;
+}
+
void layout_cleanup(void)
{
int i;
diff --git a/layout.h b/layout.h
index d1c793f..f401ef2 100644
--- a/layout.h
+++ b/layout.h
@@ -63,5 +63,6 @@
const struct flashrom_layout *get_layout(const struct flashrom_flashctx *const flashctx);
int process_include_args(struct flashrom_layout *);
+int included_regions_overlap(const struct flashrom_layout *const flashrom_layout);
#endif /* !__LAYOUT_H__ */
--
To view, visit https://review.coreboot.org/23022
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iefbcb7dc4fefe26f5afd1292dfd5c1687fa62803
Gerrit-Change-Number: 23022
Gerrit-PatchSet: 1
Gerrit-Owner: David Hendricks <david.hendricks(a)gmail.com>
Gerrit-Reviewer: Louis Yung-Chieh Lo <yjlou(a)chromium.org>
David Hendricks has uploaded this change for review. ( https://review.coreboot.org/23023
Change subject: Copy test_v2 directory from chromiumos branch
......................................................................
Copy test_v2 directory from chromiumos branch
This is a straight copy and should not be merged. The full patch
series will eventually be imported, but for now this is just a hack
to get stuff working.
Change-Id: I41bef98d32df61af400ecac46ea9571e722b2ac6
Signed-off-by: David Hendricks <dhendricks(a)fb.com>
---
A tests/tests_v2/cmd.sh
A tests/tests_v2/servo_hooks.sh
A tests/tests_v2/test_v2.sh
3 files changed, 1,371 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/23/23023/1
diff --git a/tests/tests_v2/cmd.sh b/tests/tests_v2/cmd.sh
new file mode 100755
index 0000000..1d1c47a
--- /dev/null
+++ b/tests/tests_v2/cmd.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+#
+# This file is part of the flashrom project. It is derived from
+# board_status.sh in coreboot.
+#
+# Copyright (C) 2016 Google Inc.
+# Copyright (C) 2014 Sage Electronic Engineering, LLC.
+
+USE_CUSTOM_HOOKS=0
+if [ -n "$CUSTOM_HOOKS_FILENAME" ]; then
+ USE_CUSTOM_HOOKS=1
+ . "$CUSTOM_HOOKS_FILENAME"
+ if [ $? -ne 0 ]; then
+ echo "Failed to source custom hooks file."
+ exit $EXIT_FAILURE
+ fi
+
+ if ! custom_hook_sanity_check; then
+ echo "Failed to run sanity check for custom hooks."
+ exit $EXIT_FAILURE
+ fi
+fi
+
+# test a command
+#
+# $1: 0 ($LOCAL) to run command locally,
+# 1 ($REMOTE) to run remotely if remote host defined
+# $2: command to test
+# $3: 0 ($FATAL) Exit with an error if the command fails
+# 1 ($NONFATAL) Don't exit on command test failure
+test_cmd()
+{
+ local rc
+ local cmd__="$(echo $2 | cut -d ' ' -f -1)"
+ local args="$(echo $2 | cut -d ' ' -f 2-)"
+
+ if [ -e "$cmd__" ]; then
+ return
+ fi
+
+ if [ "$1" -eq "$REMOTE" ] && [ -n "$REMOTE_HOST" ]; then
+ ssh $REMOTE_PORT_OPTION root@${REMOTE_HOST} command -v "$cmd__" $args > /dev/null 2>&1
+ rc=$?
+ else
+ command -v "$cmd__" $args >/dev/null 2>&1
+ rc=$?
+ fi
+
+ if [ $rc -eq 0 ]; then
+ return 0
+ fi
+
+ if [ "$3" = "1" ]; then
+ return 1
+ fi
+
+ echo "$2 not found"
+ exit $EXIT_FAILURE
+}
+
+# Same args as cmd() but with the addition of $4 which determines if the
+# command should be totally silenced or not.
+_cmd()
+{
+ local silent=$4
+ local rc=0
+
+ if [ -n "$3" ]; then
+ pipe_location="${3}"
+ else
+ pipe_location="/dev/null"
+ fi
+
+ if [ $1 -eq $REMOTE ] && [ -n "$REMOTE_HOST" ]; then
+ if [ $silent -eq 0 ]; then
+ ssh $REMOTE_PORT_OPTION "root@${REMOTE_HOST}" "$2" > "$pipe_location" 2>/dev/null
+ rc=$?
+ else
+ ssh $REMOTE_PORT_OPTION "root@${REMOTE_HOST}" "$2" >/dev/null 2>&1
+ rc=$?
+ fi
+ else
+ if [ $USE_CUSTOM_HOOKS -eq 1 ]; then
+ preflash_hook $1 "$2" "$3" $4
+ fi
+
+ if [ $silent -eq 0 ]; then
+ $SUDO_CMD $2 > "$pipe_location" 2>/dev/null
+ rc=$?
+ else
+ $SUDO_CMD $2 >/dev/null 2>&1
+ rc=$?
+ fi
+
+ if [ $USE_CUSTOM_HOOKS -eq 1 ]; then
+ postflash_hook $1 "$2" "$3" $4
+ fi
+ fi
+
+ return $rc
+}
+
+# run a command
+#
+# $1: 0 ($LOCAL) to run command locally,
+# 1 ($REMOTE) to run remotely if remote host defined
+# $2: command
+# $3: filename to direct output of command into
+cmd()
+{
+ _cmd $1 "$2" "$3" 0
+
+ if [ $? -eq 0 ]; then
+ return
+ fi
+
+ echo "Failed to run \"$2\", aborting"
+ rm -f "$3" # don't leave an empty file
+ return $EXIT_FAILURE
+}
+
+# run a command silently
+#
+# $1: 0 ($LOCAL) to run command locally,
+# 1 ($REMOTE) to run remotely if remote host defined
+# $2: command
+scmd()
+{
+ _cmd $1 "$2" "" 1
+
+ if [ $? -eq 0 ]; then
+ return
+ fi
+
+ echo "Failed to run \"$2\", aborting"
+ return $EXIT_FAILURE
+}
diff --git a/tests/tests_v2/servo_hooks.sh b/tests/tests_v2/servo_hooks.sh
new file mode 100644
index 0000000..01033e8
--- /dev/null
+++ b/tests/tests_v2/servo_hooks.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# Copyright (C) 2016 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+# Voltage gets exported from test_v2.sh and is mandatory for Servo.
+if [ -z "$VOLTAGE" ]; then
+ echo "Must specify voltage when using Servo."
+ exit $EXIT_FAILURE
+fi
+
+# Users who have multiple Servos attached might need to override port.
+if [ -z "$SERVO_PORT" ]; then
+ SERVO_PORT="9999"
+fi
+
+# Servo's SPI1 channel targets the EC, SPI2 targets the host ROM.
+if [ -z "$SERVO_SPI" ]; then
+ SERVO_SPI="spi2"
+fi
+
+custom_hook_sanity_check()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} ${SERVO_SPI}_buf_en ${SERVO_SPI}_buf_on_flex_en ${SERVO_SPI}_vref >/dev/null
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ printf "Servo sanity check failed. Some possible causes:\n"
+ printf "\t- Is servod running?\n"
+ printf "\t- If servod is not listening on port 9999, set SERVO_PORT as an environment variable.\n"
+ fi
+
+ return $rc
+}
+
+preflash_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} ${SERVO_SPI}_buf_en:on ${SERVO_SPI}_buf_on_flex_en:on ${SERVO_SPI}_vref:pp${VOLTAGE}
+ rc=$?
+ sleep 1
+
+ return $rc
+}
+
+postflash_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} ${SERVO_SPI}_buf_en:off ${SERVO_SPI}_buf_on_flex_en:off
+ rc=$?
+ sleep 1
+
+ return $rc
+}
+
+wp_sanity_check()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} fw_wp_en fw_wp_vref fw_wp >/dev/null
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ printf "dut-control failed. Check that servod is running.\n"
+ fi
+
+ return $rc
+}
+
+wp_enable_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} fw_wp_en:on fw_wp_vref:pp${VOLTAGE}
+ rc=$?
+ sleep 1
+
+ return $rc
+}
+
+wp_on_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} fw_wp:on
+ rc=$?
+ sleep 1
+
+ return $rc
+}
+
+wp_off_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} fw_wp:off
+ rc=$?
+ sleep 1
+
+ return $rc
+}
+
+wp_disable_hook()
+{
+ local rc=0
+
+ dut-control --port=${SERVO_PORT} fw_wp_en:off fw_wp_vref:off
+ rc=$?
+ sleep 1
+
+ return $rc
+}
diff --git a/tests/tests_v2/test_v2.sh b/tests/tests_v2/test_v2.sh
new file mode 100755
index 0000000..9de8316
--- /dev/null
+++ b/tests/tests_v2/test_v2.sh
@@ -0,0 +1,1106 @@
+#!/bin/sh
+#
+# Copyright (C) 2016 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Documentation for this script currently resides at: https://goo.gl/qNwdmm
+
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+RC=$EXIT_SUCCESS
+FATAL=0
+NONFATAL=1
+
+#
+# Stuff obtained from command-line
+#
+
+# Generic options
+BACKUP_IMAGE=""
+OLD_FLASHROM=""
+NEW_FLASHROM=""
+NO_CLEAN=0
+SKIP_CONSISTENCY_CHECK=0
+UPLOAD_RESULTS=0
+
+# LOCAL_FLASHROM is required if both a secondary programmer *and* a remote host
+# are used since OLD_FLASHROM and NEW_FLASHROM will be called on the remote
+# host and we need a local copy of flashrom to control the secondary programmer.
+# By default this will be set to the result of `which flashrom`.
+LOCAL_FLASHROM=""
+
+# Primary/Secondary programmer options
+PRIMARY_OPTS=""
+SECONDARY_OPTS=""
+
+# Calls preflash_hook() and postflash_hook() before and after doing a command.
+CUSTOM_HOOKS_FILENAME=""
+
+# if doing wp test, we require the commands that the programmer uses to enable/disable wp
+WP_HOOKS_FILENAME=""
+
+# logfile to store the script's output
+SCRIPT_LOGFILE="flashrom-test_script_output.txt"
+
+# Information stored to restore dut WP state at the end of a writeprotect test.
+HW_WP_STATE=0
+SW_WP_STATE=0
+WP_RANGE_START=0
+WP_RANGE_LEN=0
+
+# Test type
+TEST_TYPE_UNKNOWN=0
+TEST_TYPE_SINGLE=1
+TEST_TYPE_ENDURANCE=2
+TEST_TYPE_WRITEPROTECT=3
+TEST_TYPE=$TEST_TYPE_UNKNOWN
+
+# Region modes
+REGION_MODE_UNKNOWN=0
+REGION_MODE_CLOBBER=1
+REGION_MODE_DESCRIPTOR=2
+REGION_MODE_FLASHMAP=3
+REGION_MODE_LAYOUT=4
+REGION_MODE=$REGION_MODE_UNKNOWN
+DESCRIPTOR_REGION="BIOS"
+FLASHMAP_REGION="RW_SECTION_A"
+LAYOUT_FILE=""
+LAYOUT_REGION="RW"
+SMALL_REGION=0
+
+# Remote testing options
+SSH_PORT=""
+REMOTE_HOST=""
+REMOTE_PORT_OPTION=""
+REMOTE_ONLY=0
+REMOTE_PROGRAMMER_PARAMS=""
+SSH_CMD="ssh $REMOTE_PORT_OPTION root@${REMOTE_HOST} command -v"
+
+LOCAL=0
+REMOTE=1
+DO_REMOTE=0 # boolean to use for cmd() and tests
+
+WP_DISABLE=0
+WP_ENABLE=1
+
+# In case we need to run flashrom locally and we're not already root.
+SUDO_CMD=""
+if [ "$(id -u)" -ne "0" ]; then
+ SUDO_CMD="sudo"
+fi
+
+# 1KB
+K=1024
+
+show_help() {
+ printf "Usage:
+ ${0} <options>
+
+General options:
+ -b, --backup-image <path>
+ Backup image to write unconditionally at end of testing.
+ -h, --help
+ Show this message.
+ -l, --layout-file <path>
+ Layout file (required if mode is \"layout\", resides locally).
+ -m, --mode <arg>
+ Region access mode (clobber, descriptor, flashmap, layout).
+ -n, --new <path>
+ Path to new version of flashrom.
+ -o, --old <path>
+ Path to old (stable) version of flashrom.
+ -p, --primary-programmer <parameters>
+ Primary programmer options.
+ -r, --remote-host <host>
+ Remote host to test primary programmer on.
+ -s, --secondary-programmer <parameters>
+ Secondary programmer options.
+ -t, --type <arg>
+ Test type (single, endurance, writeprotect).
+ -u, --upload-results
+ Upload results to flashrom.org.
+ -v, --voltage
+ Chip voltage in millivolts (usually 1800 or 3300).
+
+Long options:
+ --custom-hooks <filename>
+ Supply a script with custom hooks to run before and after commands.
+ --descriptor-region <name>
+ Specify region to use in descriptor mode (default: $DESCRIPTOR_REGION)
+ --flashmap-region <name>
+ Specify region to use in flashmap mode (default: $FLASHMAP_REGION)
+ --layout-region <name>
+ Specify region to use in layout mode (default: $LAYOUT_REGION)
+ --local-flashrom <path>
+ Path to local version of flashrom when using both a secondary programmer
+ and remote host (default: $($SUDO_CMD which flashrom))
+ --no-clean
+ Do not remove temporary files.
+ --skip-consistency-check
+ Skip the consistency check (two consecutive reads) at beginning.
+ --small-region
+ Omit tests that require large amounts of space (>16KB).
+ --wp-hooks <filename>
+ Supply a script with commands that the connected external programmer
+ uses to enable and disable write protect for the DUT. This is required
+ when running a write-protect test.
+Remote connectivity options:
+ --ssh-port <port>
+ Use a specific SSH port.
+
+See documentation for usage examples (TODO: Migrate https://goo.gl/3jNoL7
+to flashrom wiki).\n
+"
+}
+
+getopt -T
+if [ $? -ne 4 ]; then
+ printf "GNU-compatible getopt(1) required.\n"
+ exit $EXIT_FAILURE
+fi
+
+LONGOPTS="backup-image:,help,,new:,old:,remote-host:,upload-results:"
+LONGOPTS="${LONGOPTS},primary-programmer:,secondary-programmer:,local-flashrom:"
+LONGOPTS="${LONGOPTS},custom-hooks:,mode:,skip-consistency-check,small-region"
+LONGOPTS="${LONGOPTS},wp-hooks:,type:,voltage:"
+LONGOPTS="${LONGOPTS},layout-file:,descriptor-region:,flashmap-region:,layout-region:"
+LONGOPTS="${LONGOPTS},no-clean"
+LONGOPTS="${LONGOPTS},ssh-port:"
+
+ARGS=$(getopt -o b:hl:m:n:o:p:r:s:t:u -l "$LONGOPTS" -n "$0" -- "$@");
+if [ $? != 0 ] ; then printf "Terminating...\n" >&2 ; exit 1 ; fi
+eval set -- "$ARGS"
+while true ; do
+ case "$1" in
+ # Generic options
+ -b|--backup-image)
+ shift
+ BACKUP_IMAGE="$1"
+ ;;
+ -h|--help)
+ show_help
+ exit $EXIT_SUCCESS
+ ;;
+ -l|--layout-file)
+ shift
+ LAYOUT_FILE="$1"
+ ;;
+ -m|--mode)
+ shift
+ if [ "$1" = "clobber" ]; then
+ REGION_MODE=$REGION_MODE_CLOBBER
+ elif [ "$1" = "descriptor" ]; then
+ REGION_MODE=$REGION_MODE_DESCRIPTOR
+ elif [ "$1" = "flashmap" ]; then
+ REGION_MODE=$REGION_MODE_FLASHMAP
+ elif [ "$1" = "layout" ]; then
+ REGION_MODE=$REGION_MODE_LAYOUT
+ else
+ printf "Unknown mode: $1\n"
+ exit $EXIT_FAILURE
+ fi
+ ;;
+ -n|--new)
+ shift
+ NEW_FLASHROM="$1"
+ ;;
+ -o|--old)
+ shift
+ OLD_FLASHROM="$1"
+ ;;
+ -p|--primary_programmer)
+ shift
+ PRIMARY_OPTS="-p $1"
+ ;;
+ -s|--secondary_programmer)
+ shift
+ SECONDARY_OPTS="-p $1"
+ ;;
+ -t|--type)
+ shift
+ if [ "$1" = "single" ]; then
+ TEST_TYPE=$TEST_TYPE_SINGLE
+ elif [ "$1" = "endurance" ]; then
+ TEST_TYPE=$TEST_TYPE_ENDURANCE
+ elif [ "$1" = "writeprotect" ]; then
+ TEST_TYPE=$TEST_TYPE_WRITEPROTECT
+ else
+ printf "Unknown type: $1\n"
+ exit $EXIT_FAILURE
+ fi
+ ;;
+ -r|--remote-host)
+ DO_REMOTE=1
+ shift
+ REMOTE_HOST="$1"
+ ;;
+ -u|--upload-results)
+ UPLOAD_RESULTS=1
+ ;;
+ -v|--voltage)
+ shift
+ VOLTAGE="$1"
+ ;;
+
+ # Longopts only
+ --custom-hooks)
+ shift
+ CUSTOM_HOOKS_FILENAME="$1"
+ ;;
+ --descriptor-region)
+ shift
+ DESCRIPTOR_REGION="$1"
+ ;;
+ --flashmap-region)
+ shift
+ FLASHMAP_REGION="$1"
+ ;;
+ --layout-region)
+ shift
+ LAYOUT_REGION="$1"
+ ;;
+ --local-flashrom)
+ shift
+ LOCAL_FLASHROM="$1"
+ ;;
+ --no-clean)
+ NO_CLEAN=1
+ ;;
+ --skip-consistency-check)
+ SKIP_CONSISTENCY_CHECK=1
+ ;;
+ --small-region)
+ SMALL_REGION=1
+ ;;
+ --wp-hooks)
+ shift
+ WP_HOOKS_FILENAME="$1"
+ ;;
+
+ # Remote testing options
+ --ssh-port)
+ shift
+ REMOTE_PORT_OPTION="-p $1"
+ ;;
+
+ # error handling
+ --)
+ shift
+ if [ -n "$*" ]; then
+ printf "Non-option parameters detected: '$*'\n"
+ exit $EXIT_FAILURE
+ fi
+ break
+ ;;
+ *)
+ printf "error processing options at '$1'\n"
+ exit $EXIT_FAILURE
+ esac
+ shift
+done
+
+# TODO: Implement this.
+if [ $UPLOAD_RESULTS -eq 1 ]; then
+ printf "TODO: Implement ability to upload results.\n"
+ exit $EXIT_FAILURE
+fi
+
+#
+# Source helper scripts
+#
+export REMOTE_HOST REMOTE_PORT_OPTION
+export LOCAL REMOTE FATAL NONFATAL EXIT_SUCCESS EXIT_FAILURE
+export CUSTOM_HOOKS_FILENAME SUDO_CMD VOLTAGE
+. "$(pwd)/tests/tests_v2/cmd.sh"
+
+# We will set up a logs directory within the tmpdirs to store
+# all output logs.
+LOGS="logs"
+
+# Setup temporary working directories:
+# LOCAL_TMPDIR: Working directory on local host.
+# REMOTE_TMPDIR: Working directory on remote host.
+# TMPDIR: The temporary directy in which we do most of the work. This is
+# convenient for commands that depend on $DO_REMOTE.
+LOCAL_TMPDIR=$(mktemp -d --tmpdir flashrom_test.XXXXXXXX)
+if [ $? -ne 0 ] ; then
+ printf "Could not create temporary directory\n"
+ exit $EXIT_FAILURE
+fi
+mkdir "${LOCAL_TMPDIR}/${LOGS}"
+
+if [ $DO_REMOTE -eq 1 ]; then
+ REMOTE_TMPDIR=$(ssh root@${REMOTE_HOST} mktemp -d --tmpdir flashrom_test.XXXXXXXX)
+ if [ $? -ne 0 ] ; then
+ printf "Could not create temporary directory\n"
+ exit $EXIT_FAILURE
+ fi
+ scmd $REMOTE "mkdir ${REMOTE_TMPDIR}/${LOGS}"
+fi
+
+if [ $DO_REMOTE -eq 0 ]; then
+ TMPDIR="$LOCAL_TMPDIR"
+else
+ TMPDIR="$REMOTE_TMPDIR"
+fi
+
+#
+# Test command-line validity.
+#
+if [ $TEST_TYPE -eq $TEST_TYPE_UNKNOWN ]; then
+ printf "Must specify a test type (-t/--type).\n"
+ exit $EXIT_FAILURE
+elif [ $TEST_TYPE -eq $TEST_TYPE_SINGLE ]; then
+ if [ $REGION_MODE -eq $REGION_MODE_UNKNOWN ]; then
+ printf "Must specify a region access mode (-m/--mode).\n"
+ exit $EXIT_FAILURE
+ elif [ $REGION_MODE -eq $REGION_MODE_LAYOUT ]; then
+ if [ -z "$LAYOUT_FILE" ]; then
+ printf "Must specify a layout file when using layout mode.\n"
+ exit $EXIT_FAILURE
+ fi
+
+ scmd $DO_REMOTE "stat $LAYOUT_FILE"
+ if [ $? -ne 0 ]; then
+ if [ $DO_REMOTE -eq 1 ]; then
+ tmp=" on remote host $REMOTE_HOST."
+ else
+ tmp=" on local host."
+ fi
+ printf "Layout file $LAYOUT_FILE not found${tmp}\n"
+ exit $EXIT_FAILURE
+ fi
+
+ if [ $DO_REMOTE -eq 1 ]; then
+ scp root@"${REMOTE_HOST}:$LAYOUT_FILE" "${LOCAL_TMPDIR}/" 2>&1 >/dev/null
+ fi
+ fi
+elif [ $TEST_TYPE -eq $TEST_TYPE_WRITEPROTECT ]; then
+ if [ -z "$WP_HOOKS_FILENAME" ] || [ ! -e "$WP_HOOKS_FILENAME" ]; then
+ printf "Must specify a wp hooks file when doing a write-protect test.\n"
+ exit $EXIT_FAILURE
+ fi
+
+ if [ -z "$VOLTAGE" ]; then
+ printf "Voltage (mV) must be specified when testing write protection.\n"
+ exit $EXIT_FAILURE
+ fi
+
+ . "$WP_HOOKS_FILENAME"
+
+ wp_sanity_check
+ if [ $? -ne $EXIT_SUCCESS ]; then
+ printf "Write-protect sanity check failed.\n"
+ exit $EXIT_FAILURE
+ fi
+fi
+
+if [ -n "$VOLTAGE" ]; then
+ echo "$VOLTAGE" | grep -q '[^0-9]'
+ if [ $? -ne 1 ]; then
+ printf "Voltage must be an integer with units of millivolts."
+ exit $EXIT_FAILURE
+ fi
+fi
+
+if [ $DO_REMOTE -eq 1 ]; then
+ # Test connection to remote host
+ test_cmd $DO_REMOTE "ls /" $NONFATAL
+ if [ $? -ne 0 ]; then
+ printf "Could not connect to remote host ${REMOTE_HOST}\n"
+ exit $EXIT_FAILURE
+ fi
+fi
+
+# Remote host and secondary programmer are in use, so either the user must
+# specify a local version of flashrom to control the secondary programmer
+# or it must be found in the default path.
+if [ $DO_REMOTE -eq 1 ] && [ -n "$SECONDARY_OPTS" ]; then
+ if [ -z "$LOCAL_FLASHROM" ]; then
+ LOCAL_FLASHROM="$($SUDO_CMD which flashrom)"
+ fi
+
+ if [ ! -e "$LOCAL_FLASHROM" ]; then
+ printf "$LOCAL_FLASHROM does not exist\n"
+ exit $EXIT_FAILURE
+ fi
+fi
+
+#
+# Dependencies
+#
+
+# cmp is used to compare files
+test_cmd $DO_REMOTE "cmp" $FATAL
+
+if [ ! -e "/dev/urandom" ]; then
+ printf "This script uses /dev/urandom\n"
+ exit $EXIT_FAILURE
+fi
+
+if [ ! -e "/dev/zero" ]; then
+ printf "This script uses /dev/zero\n"
+ exit $EXIT_FAILURE
+fi
+
+#
+# Setup.
+#
+grep -rH 'projectname = .*flashrom' .git/config >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ printf "Script must be run from root of flashrom directory\n"
+ exit $EXIT_FAILURE
+fi
+
+if [ -z "$OLD_FLASHROM" ]; then
+ if [ $DO_REMOTE -eq 1 ]; then
+ OLD_FLASHROM="$(ssh root@${REMOTE_HOST} which flashrom)"
+ else
+ OLD_FLASHROM="$($SUDO_CMD which flashrom)"
+ fi
+fi
+test_cmd $DO_REMOTE "$OLD_FLASHROM --help" $NONFATAL
+if [ $? -ne 0 ]; then
+ printf "Old flashrom binary is not usable.\n"
+ exit $EXIT_FAILURE
+fi
+
+# Check if both flashrom binaries support logging
+scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS --flash-name -o ${TMPDIR}/flash_name.txt"
+if [ $? -ne 0 ]; then
+ printf "Old flashrom binary does not support logging.\n"
+ exit $EXIT_FAILURE
+fi
+scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS --flash-name -o ${TMPDIR}/flash_name.txt"
+if [ $? -ne 0 ]; then
+ printf "New flashrom binary does not support logging.\n"
+ exit $EXIT_FAILURE
+fi
+scmd $DO_REMOTE "rm -f ${TMPDIR}/flash_name.txt"
+
+# print $1 and store it in the script log file
+print_and_log()
+{
+ printf "$1" | tee -a "${LOCAL_TMPDIR}/${LOGS}/${SCRIPT_LOGFILE}"
+}
+
+# Copy files from local tmpdir to remote host tmpdir
+copy_to_remote()
+{
+ for F in $@; do
+ scp "${LOCAL_TMPDIR}/${F}" root@"${REMOTE_HOST}:${REMOTE_TMPDIR}" 2>&1 >/dev/null
+ done
+}
+
+# Copy files from remote host tmpdir to local tmpdir
+copy_from_remote()
+{
+ for F in $@; do
+ scp root@"${REMOTE_HOST}:${REMOTE_TMPDIR}/${F}" "${LOCAL_TMPDIR}/" 2>&1 >/dev/null
+ done
+}
+
+# A wrapper for scmd calls to flashrom when we want to log the output
+# $1: 0 ($LOCAL) to run command locally,
+# 1 ($REMOTE) to run remotely if remote host defined
+# $2: arguments to be passed into scmd
+# $3: context of the flashrom call (to be used in the logfile)
+flashrom_log_scmd()
+{
+ local logfile="flashrom-${3}.txt"
+ local rc
+
+ if [ $1 -eq $REMOTE ]; then
+ tmpdir=$REMOTE_TMPDIR
+ else
+ tmpdir=$LOCAL_TMPDIR
+ fi
+
+ scmd $1 "$2 -o ${tmpdir}/${LOGS}/${logfile}"; rc=$?
+ # if the call was successful, we don't want to save the log (only save failure logs)
+ if [ $rc -eq $EXIT_SUCCESS ]; then
+ scmd $1 "rm -f ${tmpdir}/${LOGS}/${logfile}"
+ else
+ # if the log was stored remotely, we want to copy it over to local tmpdir
+ if [ $1 -eq $REMOTE ]; then
+ scp root@"${REMOTE_HOST}:${REMOTE_TMPDIR}/${LOGS}/${logfile}" "${LOCAL_TMPDIR}/${LOGS}" 2>&1 >/dev/null
+ fi
+ fi
+
+ return $rc
+}
+
+# Read current image as backup in case one hasn't already been specified.
+if [ -z "$BACKUP_IMAGE" ]; then
+ backup_file="backup.bin"
+ if [ $DO_REMOTE -eq 1 ]; then
+ BACKUP_IMAGE="${REMOTE_TMPDIR}/${backup_file}"
+ else
+ BACKUP_IMAGE="${LOCAL_TMPDIR}/${backup_file}"
+ fi
+
+ print_and_log "Reading backup image..."
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $BACKUP_IMAGE" "read_backup"
+
+ if [ $? -ne 0 ]; then
+ print_and_log "Failed to read backup image, aborting.\n"
+ exit $EXIT_FAILURE
+ fi
+
+ if [ $DO_REMOTE -eq 1 ]; then
+ copy_from_remote "$backup_file"
+ fi
+else
+ if [ $DO_REMOTE -eq 1 ]; then
+ scmd $DO_REMOTE "cp $BACKUP_IMAGE $REMOTE_TMPDIR"
+ copy_from_remote "$(basename $BACKUP_IMAGE)"
+ fi
+fi
+
+# The copy of flashrom to test. If unset, we'll assume the user wants to test
+# a newly built flashrom binary in the current directory.
+if [ -z "$NEW_FLASHROM" ] ; then
+ if [ -x "flashrom" ]; then
+ NEW_FLASHROM="flashrom"
+ else
+ print_and_log "Must supply new flashrom version to test\n"
+ exit $EXIT_FAILURE
+ fi
+fi
+
+print_and_log "Stable flashrom binary: ${OLD_FLASHROM}\n"
+print_and_log "New flashrom binary to test: ${NEW_FLASHROM}\n"
+print_and_log "Local temporary files will be stored in ${LOCAL_TMPDIR}\n"
+if [ $DO_REMOTE -eq 1 ]; then
+ print_and_log "Remote temporary files will be stored in ${REMOTE_HOST}:${REMOTE_TMPDIR}\n"
+ print_and_log "Backup image: ${REMOTE_HOST}:${BACKUP_IMAGE}\n"
+ print_and_log "Backup image also stored at: ${LOCAL_TMPDIR}/$(basename ${BACKUP_IMAGE})\n"
+else
+ print_and_log "Backup image: ${BACKUP_IMAGE}\n"
+fi
+
+#
+# Now the fun begins.
+#
+cmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS --get-size" "${LOCAL_TMPDIR}/chip_size.txt"
+tmp=$(cat ${LOCAL_TMPDIR}/chip_size.txt)
+cmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS --get-size" "${LOCAL_TMPDIR}/chip_size.txt"
+CHIP_SIZE=$(cat ${LOCAL_TMPDIR}/chip_size.txt)
+CHIP_SIZE_KB=$(($CHIP_SIZE / $K))
+CHIP_SIZE_HALF=$(($CHIP_SIZE / 2))
+if [ $CHIP_SIZE -ne $tmp ]; then
+ print_and_log "New flashrom and old flashrom disagree on chip size. Aborting.\n"
+ exit $EXIT_FAILURE
+else
+ print_and_log "Chip size: $CHIP_SIZE_KB KiB\n"
+fi
+
+# Upload results
+#do_upload()
+#{
+# # TODO: implement this
+#}
+
+# Remove temporary files
+do_cleanup()
+{
+ if [ $NO_CLEAN -eq 1 ]; then
+ print_and_log "Skipping cleanup.\n"
+ return $EXIT_SUCCESS
+ fi
+
+ rm -rf "$LOCAL_TMPDIR"
+ if [ -n "$REMOTE_HOST" ]; then
+ ssh root@${REMOTE_HOST} rm -rf "$REMOTE_TMPDIR"
+ fi
+
+ return $EXIT_SUCCESS
+}
+
+# $1: Message to display to user.
+test_fail()
+{
+ print_and_log "$1\n"
+ printf "Skipping cleanup (logs saved).\n"
+ exit $EXIT_FAILURE
+}
+
+write_backup_image()
+{
+ print_and_log "Writing backup image.\n"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -w $BACKUP_IMAGE" "write_backup"
+}
+
+save_wp_state()
+{
+ print_and_log "Saving initial write protect state\n"
+ if [ $DO_REMOTE -eq $REMOTE ]; then
+ cmd $DO_REMOTE "crossystem wpsw_cur" "${LOCAL_TMPDIR}/hw_wp_state.txt"
+ HW_WP_STATE=$(cat ${LOCAL_TMPDIR}/hw_wp_state.txt )
+ fi
+
+ cmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS --wp-status" "${LOCAL_TMPDIR}/wp_range.txt"
+ if grep -q 'enabled' "${LOCAL_TMPDIR}/wp_range.txt"; then
+ SW_WP_STATE=1
+ else
+ SW_WP_STATE=0
+ fi
+
+ WP_RANGE_START=$(grep 'range' "${LOCAL_TMPDIR}/wp_range.txt" | grep -o -E 'start=0x[0-9]*' | cut -d '=' -f 2-)
+ WP_RANGE_LEN=$(grep 'range' "${LOCAL_TMPDIR}/wp_range.txt" | grep -o -E 'len=0x[0-9]*' | cut -d '=' -f 2-)
+}
+
+restore_wp_state()
+{
+ print_and_log "Restoring initial write protect state\n"
+ local restore_opts="--wp-range $WP_RANGE_START $WP_RANGE_LEN"
+
+ if [ $SW_WP_STATE -eq 1 ]; then
+ restore_opts="--wp-enable $restore_opts"
+ elif [ $SW_WP_STATE -eq 0 ]; then
+ restore_opts="--wp-disable $restore_opts"
+ fi
+
+ wp_enable_hook
+ wp_off_hook
+ scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS $restore_opts"
+ # if we are running on a remote machine, we stored the hw wp state and can restore now
+ if [ $DO_REMOTE -eq $REMOTE ] && [ $HW_WP_STATE -eq 1 ]; then
+ wp_on_hook
+ fi
+ wp_disable_hook
+}
+
+# $1 is 0/1 for disable/enable
+# $2 and $3 are range start and range length
+set_wp_state()
+{
+ local wp_opts="--wp-range $2 $3"
+ if [ $1 -eq $WP_DISABLE ]; then
+ wp_opts="--wp-disable $wp_opts"
+ elif [ $1 -eq $WP_ENABLE ]; then
+ wp_opts="--wp-enable $wp_opts"
+ else
+ #invalid argument
+ return $EXIT_FAILURE
+ fi
+
+ wp_enable_hook
+ wp_off_hook
+ scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS $wp_opts"
+ wp_on_hook
+ wp_disable_hook
+}
+
+# this saves us some repeated code in the writeprotect test
+# $1 is the message to be passed into test_fail()
+wp_test_fail()
+{
+ set_wp_state $WP_DISABLE 0 0 # completely disable wp so we can write the backup
+ write_backup_image
+ restore_wp_state # restore the fw and sw writeprotect states to the initial saved states.
+ test_fail "$1"
+}
+
+# Read a region twice and compare results
+# $1: address of region (in bytes)
+# $2: length of region (in bytes)
+double_read_test()
+{
+ local cmp1="${TMPDIR}/cmp1.bin"
+ local cmp2="${TMPDIR}/cmp2.bin"
+ local layout="double_read_test_layout.txt"
+ local len=$(($2 / $K))
+
+ print_and_log "Doing double read test, size: $len KiB\n"
+ # FIXME: Figure out how to do printf remotely...
+ printf "%06x:%06x region\n" $1 $(($1 + $2 - 1)) > "${LOCAL_TMPDIR}/${layout}"
+ if [ $DO_REMOTE -eq 1 ]; then copy_to_remote "$layout" ; fi
+
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -r -l ${TMPDIR}/${layout} --ignore-fmap -i region:${cmp1}" "double_read_1"
+ # FIXME: second (or maybe third?) read should be done using secondary programmer, if applicable.
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -r -l ${TMPDIR}/${layout} --ignore-fmap -i region:${cmp2}" "double_read_2"
+ scmd $DO_REMOTE "cmp $cmp1 $cmp2"
+ if [ $? -ne 0 ]; then
+ test_fail "Double-read test failed, aborting."
+ fi
+}
+
+PARTIAL_WRITE_TEST_REGION_SIZE=0
+PARTIAL_WRITE_TEST_ALIGN_SIZE_KB=0
+
+# helper function to reduce repetitiveness of partial_write_test
+partial_write_test_helper()
+{
+ local test_name="$1"
+ local offset_kb=$2
+ local size_kb=$3
+ local hex="$4"
+ local oct=""
+
+ oct="\\$(printf "%03o" $hex)"
+ cp "${LOCAL_TMPDIR}/random_4k_test.bin" "${LOCAL_TMPDIR}/${test_name}.bin"
+ dd if=/dev/zero bs=1k count=${size_kb} 2>/dev/null | tr "\000" "$oct" > "${LOCAL_TMPDIR}/${hex}_${size_kb}k.bin"
+ while [ $(($(($offset_kb + $size_kb)) * $K)) -lt $PARTIAL_WRITE_TEST_REGION_SIZE ]; do
+ dd if="${LOCAL_TMPDIR}/${hex}_${size_kb}k.bin" of="${LOCAL_TMPDIR}/${test_name}.bin" bs=1k count=${size_kb} seek=${offset_kb} conv=notrunc 2>/dev/null
+ offset_kb=$(($offset_kb + $PARTIAL_WRITE_TEST_ALIGN_SIZE_KB))
+ done
+}
+
+# Regional partial write test. Given a region name, this will write patterns
+# of bytes designed to test corner cases.
+#
+# We assume that eraseable block size can be either 4KB or 64KB and
+# must test for both. For simplicity, we'll assume the region size is
+# at least 256KB.
+#
+# $1: Region name
+partial_write_test()
+{
+ local opts="--fast-verify"
+ local secondary_opts="" # for secondary programmer
+ local region_name="$1"
+ local filename=""
+ local test_num=0
+ local prev_test_num=0
+
+ if [ $REGION_MODE -ne $REGION_MODE_FLASHMAP ]; then
+ opts="$opts --ignore-fmap"
+ fi
+
+ if [ $TEST_TYPE -eq $TEST_TYPE_SINGLE ]; then
+ if [ $REGION_MODE -eq $REGION_MODE_LAYOUT ]; then
+ opts="$opts -l $LAYOUT_FILE"
+ secondary_opts="$opts"
+ elif [ $REGION_MODE -eq $REGION_MODE_CLOBBER ]; then
+ printf "000000:%06x RW\n" $(($CHIP_SIZE - 1)) > "${LOCAL_TMPDIR}/clobber_mode_layout.txt"
+ if [ $DO_REMOTE -eq 1 ]; then
+ copy_to_remote "clobber_mode_layout.txt"
+ fi
+ secondary_opts="$opts -l ${LOCAL_TMPDIR}/clobber_mode_layout.txt"
+ opts="$opts -l ${TMPDIR}/clobber_mode_layout.txt"
+ fi
+ fi
+
+ if [ $SMALL_REGION -eq 1 ]; then
+ PARTIAL_WRITE_TEST_ALIGN_SIZE_KB=16
+ else
+ PARTIAL_WRITE_TEST_ALIGN_SIZE_KB=256
+ fi
+
+ # FIXME: Add sanity checks.
+
+ print_and_log "Doing region-based partial write test on region \"$region_name\"\n"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS $opts -r -i ${region_name}:${TMPDIR}/${region_name}.bin" "read_region_${region_name}"
+ if [ $DO_REMOTE -eq 1 ]; then
+ copy_from_remote "${region_name}.bin"
+ fi
+
+ PARTIAL_WRITE_TEST_REGION_SIZE=$(stat --format=%s ${LOCAL_TMPDIR}/${region_name}.bin)
+ if [ $PARTIAL_WRITE_TEST_REGION_SIZE -lt $(($PARTIAL_WRITE_TEST_ALIGN_SIZE_KB * $K)) ]; then
+ print_and_log "Region $region_name is too small\n"
+ return $EXIT_FAILURE
+ fi
+
+ if [ $(($PARTIAL_WRITE_TEST_REGION_SIZE % $(($PARTIAL_WRITE_TEST_ALIGN_SIZE_KB)))) -ne 0 ]; then
+ print_and_log "Region $region_name is not aligned to $PARTIAL_WRITE_TEST_ALIGN_SIZE_KB\n"
+ return $EXIT_FAILURE
+ fi
+
+ # Test procedure:
+ # Clobber region with random content first. Then do writes using the
+ # following sequences for each 128KB:
+ # 0-2K : 0x00 (\000) Partial 4KB sector, lower half
+ # 2K-6K : 0x11 (\021) Crossover 4KB sector boundary
+ # 6K-8K : 0x22 (\042) Partial 4KB sector, upper half
+ # 8K-16K : 0x33 (\063) Full 4KB sectors
+ #
+ # Repeat the above sequence for 64KB-aligned sizes
+ # 0-32K : 0x44 (\104) Partial 64KB block, lower half
+ # 32K-96K : 0x55 (\125) Crossover 64KB block boundary
+ # 96K-128K : 0x66 (\146) Partial 64KB block, upper half
+ # 128K-256K : 0x77 (\167) Full 64KB blocks
+
+ test_num=0
+ dd if=/dev/urandom of="${LOCAL_TMPDIR}/random_4k_test.bin" bs=4k count=$(($PARTIAL_WRITE_TEST_REGION_SIZE / $((4 * $K)))) 2>/dev/null
+
+ # 0-2K : 0x00 (\000) Partial 4KB sector, lower half
+ partial_write_test_helper "4k_test_${test_num}" 0 2 "0x00"
+ prev_test_num=$test_num
+ test_num=$(($test_num + 1))
+
+ # 2K-6K : 0x11 (\021) Crossover 4KB sector boundary
+ partial_write_test_helper "4k_test_${test_num}" 2 4 "0x11"
+ test_num=$(($test_num + 1))
+
+ # 6K-8K : 0x22 (\042) Partial 4KB sector, upper half
+ partial_write_test_helper "4k_test_${test_num}" 6 2 "0x22"
+ test_num=$(($test_num + 1))
+
+ # 8K-16K : 0x33 (\063) Full 4KB sectors
+ partial_write_test_helper "4k_test_${test_num}" 8 8 "0x33"
+
+ for F in ${LOCAL_TMPDIR}/random_4k_test.bin ${LOCAL_TMPDIR}/4k_test_*.bin ; do
+ filename=$(basename $F)
+ if [ $DO_REMOTE -eq 1 ]; then
+ copy_to_remote $filename
+ fi
+
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS $opts -w -i ${region_name}:${TMPDIR}/${filename}" "write_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to write $filename to $region_name"
+ fi
+
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS $opts -v -i ${region_name}:${TMPDIR}/${filename}" "verify_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to verify write of $filename to $region_name"
+ fi
+
+ if [ -n "$SECONDARY_OPTS" ]; then
+ flashrom_log_scmd $LOCAL "$LOCAL_FLASHROM $SECONDARY_OPTS $secondary_opts -v -i ${region_name}:${LOCAL_TMPDIR}/${filename}" "verify_secondary_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to verify write of $filename to $region_name using secondary programmer"
+ fi
+ fi
+
+ print_and_log "\tWrote $filename to $region_name region successfully.\n"
+ done
+
+ if [ $SMALL_REGION -eq 1 ]; then
+ return $EXIT_SUCCESS
+ fi
+
+ #
+ # Second half: Tests for 64KB chunks
+ #
+ test_num=0
+ dd if=/dev/urandom of="${LOCAL_TMPDIR}/random_64k_test.bin" bs=128k count=$(($PARTIAL_WRITE_TEST_REGION_SIZE / $((128*$K)))) 2>/dev/null
+
+ # 0-32K : 0x44 (\104) Partial 64KB block, lower half
+ partial_write_test_helper "64k_test_${test_num}" 0 32 "0x44"
+ prev_test_num=$test_num
+ test_num=$(($test_num + 1))
+
+ # 32K-96K : 0x55 (\125) Crossover 64KB block boundary
+ partial_write_test_helper "64k_test_${test_num}" 32 64 "0x55"
+ test_num=$(($test_num + 1))
+
+ # 96K-128K : 0x66 (\146) Partial 64KB block, upper half
+ partial_write_test_helper "64k_test_${test_num}" 96 32 "0x66"
+ test_num=$(($test_num + 1))
+
+ # 128K-256K : 0x77 (\167) Full 64KB blocks
+ partial_write_test_helper "64k_test_${test_num}" 128 128 "0x77"
+
+ for F in ${LOCAL_TMPDIR}/random_64k_test.bin ${LOCAL_TMPDIR}/64k_test_*.bin ; do
+ filename=$(basename $F)
+ if [ $DO_REMOTE -eq 1 ]; then
+ copy_to_remote $filename
+ fi
+
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS $opts -w -i ${region_name}:${TMPDIR}/${filename}" "write_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to write $filename to $region_name"
+ fi
+
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS $opts -v -i ${region_name}:${TMPDIR}/${filename}" "verify_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to verify write of $filename to $region_name"
+ fi
+
+ if [ -n "$SECONDARY_OPTS" ]; then
+ flashrom_log_scmd $LOCAL "$LOCAL_FLASHROM $SECONDARY_OPTS $secondary_opts -v -i ${region_name}:${LOCAL_TMPDIR}/${filename}" "verify_secondary_${filename}"
+ if [ $? -ne 0 ]; then
+ test_fail "Failed to verify write of $filename to $region_name using secondary programmer"
+ fi
+ fi
+
+ print_and_log "\tWrote $filename to $region_name region successfully.\n"
+ done
+
+ return $EXIT_SUCCESS
+}
+
+# Before anything else, check to see if Flashrom can succesfully probe
+# for and find the flash chips. If not, we will abort.
+flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS" "verify_probe"
+if [ $? -ne 0 ]; then
+ test_fail "Failed to find flash chips while probing, aborting."
+fi
+
+# Read ROM twice to test for consistency.
+if [ $SKIP_CONSISTENCY_CHECK -eq 0 ]; then
+ double_read_test 0 $CHIP_SIZE
+fi
+
+if [ $TEST_TYPE -eq $TEST_TYPE_SINGLE ]; then
+ if [ $REGION_MODE -eq $REGION_MODE_CLOBBER ]; then
+ random_file="${TMPDIR}/random_${CHIP_SIZE_KB}K.bin"
+ cmp_file="${TMPDIR}/cmp.bin"
+
+ scmd $DO_REMOTE "dd if=/dev/urandom of=${random_file} bs=1k count=${CHIP_SIZE_KB}"
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -w $random_file" "clobber_write"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $cmp_file" "clobber_verify"
+ scmd $DO_REMOTE "cmp $random_file $cmp_file"
+ if [ $? -ne 0 ]; then
+ write_backup_image
+ test_fail "Failed to clobber entire ROM."
+ fi
+ scmd $DO_REMOTE "rm -f $cmp_file $random_file"
+
+ partial_write_test "RW"
+ if [ $? -ne 0 ]; then
+ print_and_log "Layout mode test failed\n"
+ RC=$EXIT_FAILURE
+ fi
+ elif [ $REGION_MODE -eq $REGION_MODE_DESCRIPTOR ]; then
+ # FIXME: This depends on descriptor regions being translated into internal
+ # layout representation automatically so we can target them using -i.
+ print_and_log "TODO: Descriptor mode\n"
+ exit $EXIT_FAILURE
+ elif [ $REGION_MODE -eq $REGION_MODE_FLASHMAP ]; then
+ partial_write_test "$FLASHMAP_REGION" 0
+ if [ $? -ne 0 ]; then
+ print_and_log "Flashmap mode test failed\n"
+ RC=$EXIT_FAILURE
+ fi
+ elif [ $REGION_MODE -eq $REGION_MODE_LAYOUT ]; then
+ rw_layout=""
+ addr=""
+ end=""
+ size=""
+ size_kb=""
+
+ # Look for a region name with any amount of leading whitespace
+ # and no trailing whitespace or characters.
+ rw_layout=$(grep "\s${LAYOUT_REGION}$" "${LOCAL_TMPDIR}/$(basename $LAYOUT_FILE)" | head -n 1)
+ if [ -z "$rw_layout" ]; then
+ print_and_log "No region matching \"${LAYOUT_REGION}\" found layout file \"${LAYOUT_FILE}\"\n"
+ test_fail ""
+ fi
+
+ addr="0x$(echo "$rw_layout" | cut -d ' ' -f -1 | awk -F ':' '{ print $1 }')"
+ end="0x$(echo "$rw_layout" | cut -d ' ' -f -1 | awk -F ':' '{ print $2 }')"
+ size="$(($end - $addr + 1))"
+ size_kb="$(($size / $K))"
+
+ print_and_log "\"$LAYOUT_REGION\" region address: ${addr}, size: $size_kb KiB\n"
+ partial_write_test "$LAYOUT_REGION"
+ if [ $? -ne 0 ]; then
+ print_and_log "Layout mode test failed\n"
+ RC=$EXIT_FAILURE
+ fi
+ fi
+elif [ $TEST_TYPE -eq $TEST_TYPE_ENDURANCE ]; then
+ iteration=1
+ terminate=0
+ random_file="${TMPDIR}/random_${CHIP_SIZE_KB}K.bin"
+ cmp_file="${TMPDIR}/cmp.bin"
+ # TODO: We can measure how long the tests take on average, throughput, etc.
+ # i.e. { time $NEW_FLASHROM $PRIMARY_OPTS -w $random_file ; } 2>&1 | grep user | cut -f2
+
+ # For this test we want to run clobber mode until failure
+ while [ $terminate -eq 0 ]
+ do
+ print_and_log "Running iteration #${iteration}\n"
+
+ scmd $DO_REMOTE "dd if=/dev/urandom of=${random_file} bs=1k count=${CHIP_SIZE_KB}"
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -w $random_file" "endurance_write_${iteration}"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $cmp_file" "endurance_verify_${iteration}"
+ scmd $DO_REMOTE "cmp $random_file $cmp_file"
+ if [ $? -ne 0 ]; then
+ terminate=1
+ fi
+ scmd $DO_REMOTE "rm -f $cmp_file $random_file"
+
+ iteration=$(($iteration + 1))
+ done
+
+ # TODO: Determine what to return for the endurance test exit status
+ # i.e. what constitutes a test pass and what constitutes a test fail?
+ print_and_log "Failed on iteration $iteration\n"
+ # TODO - Print performance metrics?
+elif [ $TEST_TYPE -eq $TEST_TYPE_WRITEPROTECT ]; then
+ random_file_protect="${TMPDIR}/random_${CHIP_SIZE_KB}K_protect.bin"
+ random_file_clobber1="${TMPDIR}/random_${CHIP_SIZE_KB}K_clobber1.bin"
+ random_file_clobber2="${TMPDIR}/random_${CHIP_SIZE_KB}K_clobber2.bin"
+ cmp_file="${TMPDIR}/cmp.bin"
+
+ # generate random files
+ scmd $DO_REMOTE "dd if=/dev/urandom of=$random_file_protect bs=1k count=${CHIP_SIZE_KB}"
+ scmd $DO_REMOTE "dd if=/dev/urandom of=$random_file_clobber1 bs=1k count=${CHIP_SIZE_KB}"
+ scmd $DO_REMOTE "dd if=/dev/urandom of=$random_file_clobber2 bs=1k count=${CHIP_SIZE_KB}"
+
+ save_wp_state
+ set_wp_state $WP_DISABLE 0 0
+
+ # clobber ROM with an initial file
+ print_and_log "Clobbering ROM with random initial content\n"
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -w $random_file_protect" "writeprotect_initial_write"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $cmp_file" "writeprotect_initial_verify"
+ scmd $DO_REMOTE "cmp $random_file_protect $cmp_file"
+ if [ $? -ne 0 ]; then
+ wp_test_fail "Failed to clobber ROM initially."
+ fi
+ scmd $DO_REMOTE "rm -f $cmp_file"
+
+ # Protect lower half of ROM, then try clobbering.
+ print_and_log "Starting lower half test\n"
+ set_wp_state $WP_ENABLE 0 $CHIP_SIZE_HALF
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -n -w $random_file_clobber1" "writeprotect_enable_lower_write"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $cmp_file" "writeprotect_enable_lower_verify"
+ scmd $DO_REMOTE "cmp --bytes=$CHIP_SIZE_HALF $random_file_protect $cmp_file"
+ if [ $? -ne 0 ]; then
+ wp_test_fail "Failed to protect lower half of ROM - exiting writeprotect test."
+ fi
+ scmd $DO_REMOTE "cmp --ignore-initial=$CHIP_SIZE_HALF --bytes=$CHIP_SIZE_HALF $random_file_clobber1 $cmp_file"
+ if [ $? -ne 0 ]; then
+ wp_test_fail "Failed to clobber upper half of ROM - exiting writeprotect test."
+ fi
+ scmd $DO_REMOTE "rm -f $cmp_file"
+
+ # Protect upper half of ROM, then try clobbering.
+ print_and_log "Starting upper half test\n"
+ set_wp_state $WP_ENABLE $CHIP_SIZE_HALF $CHIP_SIZE_HALF
+ flashrom_log_scmd $DO_REMOTE "$NEW_FLASHROM $PRIMARY_OPTS -n -w $random_file_clobber2" "writeprotect_enable_upper_write"
+ flashrom_log_scmd $DO_REMOTE "$OLD_FLASHROM $PRIMARY_OPTS -r $cmp_file" "writeprotect_enable_upper_verify"
+ scmd $DO_REMOTE "cmp --bytes=$CHIP_SIZE_HALF $random_file_clobber2 $cmp_file"
+ if [ $? -ne 0 ]; then
+ wp_test_fail "Failed to clobber lower half of ROM - exiting writeprotect test."
+ fi
+ scmd $DO_REMOTE "cmp --ignore-initial=$CHIP_SIZE_HALF --bytes=$CHIP_SIZE_HALF $random_file_clobber1 $cmp_file"
+ if [ $? -ne 0 ]; then
+ wp_test_fail "Failed to protect upper half of ROM - exiting writeprotect test."
+ fi
+ scmd $DO_REMOTE "rm -f $cmp_file"
+
+ set_wp_state $WP_DISABLE 0 0 # completely disable wp so we can write the backup
+fi
+
+# restore and cleanup
+write_backup_image
+if [ $TEST_TYPE -eq $TEST_TYPE_WRITEPROTECT ]; then
+ restore_wp_state # restore the fw and sw writeprotect states to the initial saved states.
+fi
+
+if [ $RC -eq 0 ]; then
+ print_and_log "Test status: PASS\n"
+else
+ print_and_log "Test status: FAIL\n"
+fi
+do_cleanup
+
+exit $RC
--
To view, visit https://review.coreboot.org/23023
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I41bef98d32df61af400ecac46ea9571e722b2ac6
Gerrit-Change-Number: 23023
Gerrit-PatchSet: 1
Gerrit-Owner: David Hendricks <david.hendricks(a)gmail.com>
Philipp Deppenwiese has posted comments on this change. ( https://review.coreboot.org/23003 )
Change subject: internal: Fix #if guards for big-endian mips
......................................................................
Patch Set 2: Code-Review+2
--
To view, visit https://review.coreboot.org/23003
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: 1.0.x
Gerrit-MessageType: comment
Gerrit-Change-Id: Id0508c5241a7bd61b8d92d631cdf42ef7829a8a9
Gerrit-Change-Number: 23003
Gerrit-PatchSet: 2
Gerrit-Owner: Nico Huber <nico.h(a)gmx.de>
Gerrit-Reviewer: David Hendricks <david.hendricks(a)gmail.com>
Gerrit-Reviewer: Patrick Rudolph <siro(a)das-labor.org>
Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki(a)gmail.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org>
Gerrit-Comment-Date: Wed, 27 Dec 2017 23:52:21 +0000
Gerrit-HasComments: No
Gerrit-HasLabels: Yes
Hello David Hendricks, Paul Menzel, build bot (Jenkins),
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/22263
to look at the new patch set (#2).
Change subject: vt_vx: check whether the chipset's MMIO range is configured
......................................................................
vt_vx: check whether the chipset's MMIO range is configured
Avoid attempting to read the SPI bases from the location 0x00000000, all
zeroes mean that the chipset's MMIO area is not enabled.
Change-Id: I5d3a1ba695153e854e0979ae634f8ed97e6b6293
Signed-off-by: Lubomir Rintel <lkundrak(a)v3.sk>
---
M chipset_enable.c
1 file changed, 8 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/63/22263/2
--
To view, visit https://review.coreboot.org/22263
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: staging
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I5d3a1ba695153e854e0979ae634f8ed97e6b6293
Gerrit-Change-Number: 22263
Gerrit-PatchSet: 2
Gerrit-Owner: Lubomir Rintel <lkundrak(a)v3.sk>
Gerrit-Reviewer: David Hendricks <david.hendricks(a)gmail.com>
Gerrit-Reviewer: Paul Menzel <paulepanter(a)users.sourceforge.net>
Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org>