summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChe-Liang Chiou <clchiou@chromium.org>2012-09-11 15:27:03 -0700
committerKatie Roberts-Hoffman <katierh@chromium.org>2012-11-02 13:45:41 -0700
commit66eff3172ea0df16f8af595f76deb8ec81ed50e0 (patch)
treed67b2b07817e5c8c06da2042f9185e028a361715
parent3a5c4ee4bfc2f24fe2dbc6df109b541bd03986bf (diff)
downloadvboot-66eff3172ea0df16f8af595f76deb8ec81ed50e0.tar.gz
crossystem should switch on VbNvContext storage type
We may have multiple storage types (disk or mkbp) of VbNvContext. crossystem should switch the type and choose the corresponding device driver. After patching U-Boot, you may check storage type: [ "mkbp" = "$(cat /proc/device-tree/firmware/chromeos/nonvolatile-context-storage)" ] And cross-verify crossystem with mosys: $ mosys nvram vboot read 70000000000000000000000000000020 $ crossystem recovery_request 0 $ crossystem recovery_request=123 $ mosys nvram vboot read 70007b0000000000000000000000005d $ mosys nvram vboot write 70000000000000000000000000000020 $ crossystem recovery_request 0 More importantly, crossystem should also work with older version of firmware, which does not pass down this information. Signed-off-by: Che-Liang Chiou <clchiou@chromium.org> BRANCH=none BUG=chrome-os-partner:13766 TEST=Check storage type on a Snow device: [ "mkbp" = "$(cat /proc/device-tree/firmware/chromeos/nonvolatile-context-storage)" ] Make sure that FAFT is still happy: ./run_remote_tests.sh --remote $ADDR --board daisy 'firmware_TryFwB/control$' ./run_remote_tests.sh --remote $ADDR --board daisy 'firmware_TryFwB/control.dev$' More importantly, check crossystem worked well even when ChromeOS is booted from an older version of firmware. Change-Id: I3989a8c181efe03cd9f06127743763e0ad97e281 Reviewed-on: https://gerrit.chromium.org/gerrit/32470 Reviewed-by: Che-Liang Chiou <clchiou@chromium.org> Tested-by: Che-Liang Chiou <clchiou@chromium.org> Commit-Ready: Che-Liang Chiou <clchiou@chromium.org> (cherry picked from commit 770c1b772c0aa9241bc2923354092a14e1c68661) Reviewed-on: https://gerrit.chromium.org/gerrit/37253 Tested-by: Katie Roberts-Hoffman <katierh@chromium.org>
-rw-r--r--host/arch/arm/lib/crossystem_arch.c119
1 files changed, 117 insertions, 2 deletions
diff --git a/host/arch/arm/lib/crossystem_arch.c b/host/arch/arm/lib/crossystem_arch.c
index f9606745..7120afe4 100644
--- a/host/arch/arm/lib/crossystem_arch.c
+++ b/host/arch/arm/lib/crossystem_arch.c
@@ -5,11 +5,13 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <linux/fs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/ioctl.h>
+#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
@@ -19,6 +21,8 @@
#include "host_common.h"
#include "crossystem_arch.h"
+#define MOSYS_PATH "/usr/sbin/mosys"
+
/* Base name for firmware FDT files */
#define FDT_BASE_PATH "/proc/device-tree/firmware/chromeos"
/* Path to compatible FDT entry */
@@ -253,7 +257,98 @@ out:
return ret;
}
-int VbReadNvStorage(VbNvContext* vnc) {
+static int ExecuteMosys(char * const argv[], char *buf, size_t bufsize) {
+ int status, mosys_to_crossystem[2];
+ pid_t pid;
+ ssize_t n;
+
+ if (pipe(mosys_to_crossystem) < 0) {
+ VBDEBUG(("pipe() error\n"));
+ return -1;
+ }
+
+ if ((pid = fork()) < 0) {
+ VBDEBUG(("fork() error\n"));
+ close(mosys_to_crossystem[0]);
+ close(mosys_to_crossystem[1]);
+ return -1;
+ } else if (!pid) { /* Child */
+ close(mosys_to_crossystem[0]);
+ /* Redirect pipe's write-end to mosys' stdout */
+ if (STDOUT_FILENO != mosys_to_crossystem[1]) {
+ if (dup2(mosys_to_crossystem[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ VBDEBUG(("stdout dup2() failed (mosys)\n"));
+ close(mosys_to_crossystem[1]);
+ exit(1);
+ }
+ }
+ /* Execute mosys */
+ execv(MOSYS_PATH, argv);
+ /* We shouldn't be here; exit now! */
+ VBDEBUG(("execv() of mosys failed\n"));
+ close(mosys_to_crossystem[1]);
+ exit(1);
+ } else { /* Parent */
+ close(mosys_to_crossystem[1]);
+ if (bufsize) {
+ bufsize--; /* Reserve 1 byte for '\0' */
+ while ((n = read(mosys_to_crossystem[0], buf, bufsize)) > 0) {
+ buf += n;
+ bufsize -= n;
+ }
+ *buf = '\0';
+ } else {
+ n = 0;
+ }
+ close(mosys_to_crossystem[0]);
+ if (n < 0)
+ VBDEBUG(("read() error while reading output from mosys\n"));
+ if (waitpid(pid, &status, 0) < 0 || status) {
+ VBDEBUG(("waitpid() or mosys error\n"));
+ fprintf(stderr, "waitpid() or mosys error\n");
+ return -1;
+ }
+ if (n < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int VbReadNvStorage_mkbp(VbNvContext* vnc) {
+ char hexstring[VBNV_BLOCK_SIZE * 2 + 32]; /* Reserve extra 32 bytes */
+ char * const argv[] = {
+ MOSYS_PATH, "nvram", "vboot", "read", NULL
+ };
+ char hexdigit[3];
+ int i;
+
+ if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
+ return -1;
+ hexdigit[2] = '\0';
+ for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
+ hexdigit[0] = hexstring[i * 2];
+ hexdigit[1] = hexstring[i * 2 + 1];
+ vnc->raw[i] = strtol(hexdigit, NULL, 16);
+ }
+ return 0;
+}
+
+static int VbWriteNvStorage_mkbp(VbNvContext* vnc) {
+ char hexstring[VBNV_BLOCK_SIZE * 2 + 1];
+ char * const argv[] = {
+ MOSYS_PATH, "nvram", "vboot", "write", hexstring, NULL
+ };
+ int i;
+
+ for (i = 0; i < VBNV_BLOCK_SIZE; i++)
+ snprintf(hexstring + i * 2, 3, "%02x", vnc->raw[i]);
+ hexstring[sizeof(hexstring) - 1] = '\0';
+ if (ExecuteMosys(argv, NULL, 0))
+ return -1;
+ return 0;
+}
+
+static int VbReadNvStorage_disk(VbNvContext* vnc) {
int nvctx_fd = -1;
uint8_t sector[SECTOR_SIZE];
int rv = -1;
@@ -294,7 +389,7 @@ out:
return rv;
}
-int VbWriteNvStorage(VbNvContext* vnc) {
+static int VbWriteNvStorage_disk(VbNvContext* vnc) {
int nvctx_fd = -1;
uint8_t sector[SECTOR_SIZE];
int rv = -1;
@@ -349,6 +444,26 @@ int VbWriteNvStorage(VbNvContext* vnc) {
return rv;
}
+int VbReadNvStorage(VbNvContext* vnc) {
+ char *media = ReadFdtString("nonvolatile-context-storage");
+ /* Default to disk for older firmware which does not provide storage type */
+ if (!media || !strcmp(media, "disk"))
+ return VbReadNvStorage_disk(vnc);
+ if (!strcmp(media, "mkbp"))
+ return VbReadNvStorage_mkbp(vnc);
+ return -1;
+}
+
+int VbWriteNvStorage(VbNvContext* vnc) {
+ char *media = ReadFdtString("nonvolatile-context-storage");
+ /* Default to disk for older firmware which does not provide storage type */
+ if (!media || !strcmp(media, "disk"))
+ return VbWriteNvStorage_disk(vnc);
+ if (!strcmp(media, "mkbp"))
+ return VbWriteNvStorage_mkbp(vnc);
+ return -1;
+}
+
VbSharedDataHeader *VbSharedDataRead(void) {
void *block = NULL;
size_t size = 0;