summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChe-Liang Chiou <clchiou@chromium.org>2012-09-11 15:27:03 -0700
committerGerrit <chrome-bot@google.com>2012-09-18 15:05:03 -0700
commit770c1b772c0aa9241bc2923354092a14e1c68661 (patch)
treef3fd739696b6b3560a66a4af3f1c9677392fc7c4
parent46c01a2d2bceaf6948c53ca8946ed19b900190b3 (diff)
downloadvboot-770c1b772c0aa9241bc2923354092a14e1c68661.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>
-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;