summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;