1da8d32dc8d0fb5ebcfffa305f4a3ecb2dd7c79acRandall Spangler/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler * Use of this source code is governed by a BSD-style license that can be
3eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler * found in the LICENSE file.
4eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler */
5eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
6eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler#include <stdio.h>
7eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler#include <string.h>
8a3d70a3d2b5c052db039d097aaffa42008da24b5J. Richard Barnette#include <stddef.h>
9770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou#include <stdlib.h>
1005987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley#ifndef HAVE_MACOS
113a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson#include <linux/fs.h>
1205987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley#endif
13eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler#include <sys/types.h>
14d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#include <sys/stat.h>
15d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#include <sys/param.h>
163a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson#include <sys/ioctl.h>
17770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou#include <sys/wait.h>
18d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#include <fcntl.h>
19d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#include <unistd.h>
20d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#include <netinet/in.h>
21eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
22eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler#include "vboot_common.h"
23eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler#include "vboot_nvstorage.h"
24c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury#include "host_common.h"
2509a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler#include "crossystem.h"
26c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury#include "crossystem_arch.h"
27eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
28770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou#define MOSYS_PATH "/usr/sbin/mosys"
29770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
30bd00c622e4249b67087a81adb1978a661c7ef8c9Bernie Thompson/* Base name for firmware FDT files */
31d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define FDT_BASE_PATH "/proc/device-tree/firmware/chromeos"
32bd00c622e4249b67087a81adb1978a661c7ef8c9Bernie Thompson/* Path to compatible FDT entry */
33bd00c622e4249b67087a81adb1978a661c7ef8c9Bernie Thompson#define FDT_COMPATIBLE_PATH "/proc/device-tree/compatible"
343afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black/* Path to the chromeos_arm platform device */
353afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black#define PLATFORM_DEV_PATH "/sys/devices/platform/chromeos_arm"
36d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang/* Device for NVCTX write */
37d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define NVCTX_PATH "/dev/mmcblk%d"
38a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang/* Base name for GPIO files */
39a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang#define GPIO_BASE_PATH "/sys/class/gpio"
40a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang#define GPIO_EXPORT_PATH GPIO_BASE_PATH "/export"
41210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou/* Name of NvStorage type property */
42210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou#define FDT_NVSTORAGE_TYPE_PROP "nonvolatile-context-storage"
43d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang/* Errors */
44d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define E_FAIL      -1
45d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define E_FILEOP    -2
46d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define E_MEM       -3
47d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang/* Common constants */
48d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define FNAME_SIZE  80
49d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define SECTOR_SIZE 512
50d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang#define MAX_NMMCBLK 9
51d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
520b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompsontypedef struct PlatformFamily {
530b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  const char* compatible_string; /* Last string in FDT compatible entry */
540b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  const char* platform_string;   /* String to return */
550b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson} PlatformFamily;
560b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
570b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson/* Array of platform family names, terminated with a NULL entry */
580b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompsonconst PlatformFamily platform_family_array[] = {
59435be9873179338d0c4e7b2d823989181a089771Gabe Black  {"nvidia,tegra124", "Tegra5"},
600b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  {"nvidia,tegra250", "Tegra2"},
610b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  {"nvidia,tegra20", "Tegra2"},
620b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  {"ti,omap4", "OMAP4"},
630b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  {"ti,omap3", "OMAP3"},
6458def7454d2c4d085e383a0b73d00670390ddd83Olof Johansson  {"samsung,exynos4210", "EXYNOS4"},
6558def7454d2c4d085e383a0b73d00670390ddd83Olof Johansson  {"samsung,exynos5250", "EXYNOS5"},
66114d54a9e26aad6bfa4564152a3f1daed2e75a9bVadim Bendebury  {"samsung,exynos5420", "EXYNOS5"},
67054c1147989d39a432923cc359d123f0d8e9390aVadim Bendebury  {"qcom,ipq8064", "IPQ8064"},
680b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  /* Terminate with NULL entry */
690b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  {NULL, NULL}
700b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson};
710b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
72d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int FindEmmcDev(void) {
73d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  int mmcblk;
74d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  unsigned value;
75d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char filename[FNAME_SIZE];
76d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  for (mmcblk = 0; mmcblk < MAX_NMMCBLK; mmcblk++) {
77d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    /* Get first non-removable mmc block device */
78d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    snprintf(filename, sizeof(filename), "/sys/block/mmcblk%d/removable",
79d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang              mmcblk);
80d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie    if (ReadFileInt(filename, &value) < 0)
81d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie      continue;
82d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie    if (value == 0)
83d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang      return mmcblk;
84d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  }
85d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  /* eMMC not found */
86d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return E_FAIL;
87d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
88c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
89d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int ReadFdtValue(const char *property, int *value) {
90d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char filename[FNAME_SIZE];
91d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  FILE *file;
92d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  int data = 0;
93c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
94d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", property);
95d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  file = fopen(filename, "rb");
96d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (!file) {
97d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    fprintf(stderr, "Unable to open FDT property %s\n", property);
98d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FILEOP;
99d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  }
100c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
1013401fdcd4125beea1a8cb1cc59ee27df89d4d88aSimon Glass  if (fread(&data, 1, sizeof(data), file) != sizeof(data)) {
1023401fdcd4125beea1a8cb1cc59ee27df89d4d88aSimon Glass    fprintf(stderr, "Unable to read FDT property %s\n", property);
1033401fdcd4125beea1a8cb1cc59ee27df89d4d88aSimon Glass    return E_FILEOP;
1043401fdcd4125beea1a8cb1cc59ee27df89d4d88aSimon Glass  }
105d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  fclose(file);
106c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
107d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (value)
108d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    *value = ntohl(data); /* FDT is network byte order */
109c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
110d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return 0;
111d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
112c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
113d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int ReadFdtInt(const char *property) {
11447779880b28f2c549dd3349d8f28d68a0f784eb4Simon Glass  int value = 0;
115d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (ReadFdtValue(property, &value))
116d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FAIL;
117d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return value;
118d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
119c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
120210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chioustatic void GetFdtPropertyPath(const char *property, char *path, size_t size) {
121210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (property[0] == '/')
122210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    StrCopy(path, property, size);
123210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  else
124210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    snprintf(path, size, FDT_BASE_PATH "/%s", property);
125210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou}
126210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou
127210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chioustatic int FdtPropertyExist(const char *property) {
128210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  char filename[FNAME_SIZE];
129210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  struct stat file_status;
130210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou
131210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  GetFdtPropertyPath(property, filename, sizeof(filename));
132210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (!stat(filename, &file_status))
133210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    return 1; // It exists!
134210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  else
135210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    return 0; // It does not exist or some error happened.
136210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou}
137210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou
138d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int ReadFdtBlock(const char *property, void **block, size_t *size) {
139d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char filename[FNAME_SIZE];
140d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  FILE *file;
141d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  size_t property_size;
142d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char *data;
143d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
144d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (!block)
145d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FAIL;
146d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
147210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  GetFdtPropertyPath(property, filename, sizeof(filename));
148d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  file = fopen(filename, "rb");
149d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (!file) {
150d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    fprintf(stderr, "Unable to open FDT property %s\n", property);
151d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FILEOP;
152c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  }
153c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
154d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  fseek(file, 0, SEEK_END);
155d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  property_size = ftell(file);
156d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  rewind(file);
157d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
158d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  data = malloc(property_size +1);
159d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (!data) {
160d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    fclose(file);
161d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_MEM;
162c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  }
163d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  data[property_size] = 0;
164eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
165d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (1 != fread(data, property_size, 1, file)) {
166d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    fprintf(stderr, "Unable to read from property %s\n", property);
167d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    fclose(file);
168d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    free(data);
169d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FILEOP;
170a3ec5c40f86f4c71305600ea25b58c1862d1c504Vadim Bendebury  }
171d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
172d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  fclose(file);
173d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  *block = data;
174d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (size)
175d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    *size = property_size;
176d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
177d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return 0;
178eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler}
179eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
180d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic char * ReadFdtString(const char *property) {
181d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  void *str = NULL;
182d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  /* Do not need property size */
183d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  ReadFdtBlock(property, &str, 0);
184d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return (char *)str;
185d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
186c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
1870b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompsonstatic char * ReadFdtPlatformFamily(void) {
1880b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  char *compat = NULL;
1890b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  char *s;
1900b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  const PlatformFamily* p;
1910b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  size_t size = 0;
1920b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  int slen;
1930b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
194f47291926afce3235421f73811a04324195f3e13Bill Richardson  if(ReadFdtBlock(FDT_COMPATIBLE_PATH, (void **)&compat, &size))
195885a9774ef469666854a0e4bed7c33733d0396c7Bernie Thompson    return NULL;
1960b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
1970b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  if (size > 0)
1980b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    compat[size-1] = 0;
1990b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
2000b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  /* Check each null separated string in compatible against the family array */
2010b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  s = compat;
2020b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  while ((s-compat) < size) {
2030b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    slen = strlen(s);
2040b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    for (p = platform_family_array; p->compatible_string; p++) {
2050b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson      if (!strcmp(s, p->compatible_string)) {
2060b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson        free(compat);
2070b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson        return strdup(p->platform_string);
2080b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson      }
2090b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    }
2100b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    s += slen + 1;
2110b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  }
2120b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
2130b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  /* No recognized 'compatible' entry found */
2140b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  free(compat);
2150b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  return NULL;
2160b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson}
2170b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
2183afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Blackstatic int VbGetPlatformGpioStatus(const char* name) {
2193afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black  char gpio_name[FNAME_SIZE];
220d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  unsigned value;
2213afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black
2223afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black  snprintf(gpio_name, sizeof(gpio_name), "%s/%s/value",
2233afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black           PLATFORM_DEV_PATH, name);
224d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  if (ReadFileInt(gpio_name, &value) < 0)
225d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie    return -1;
2263afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black
227d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  return (int)value;
2283afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black}
2293afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black
230d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int VbGetGpioStatus(unsigned gpio_number) {
231d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char gpio_name[FNAME_SIZE];
232d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  unsigned value;
233a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang
234a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang  snprintf(gpio_name, sizeof(gpio_name), "%s/gpio%d/value",
235a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang           GPIO_BASE_PATH, gpio_number);
236d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  if (ReadFileInt(gpio_name, &value) < 0) {
237a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    /* Try exporting the GPIO */
238a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    FILE* f = fopen(GPIO_EXPORT_PATH, "wt");
239a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    if (!f)
240a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang      return -1;
241a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    fprintf(f, "%d", gpio_number);
242a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    fclose(f);
243c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
244a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang    /* Try re-reading the GPIO value */
245d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie    if (ReadFileInt(gpio_name, &value) < 0)
246d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie      return -1;
247a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang  }
248a5ef4f98fc30cfae232295464fbc9d846c980fdfRong Chang
249d241fff54c982f2764e6d126a024ab71fa6dd84aDuncan Laurie  return (int)value;
250d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
251eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
252d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changstatic int VbGetVarGpio(const char* name) {
253ffb9233a90fe8f29bb80292a75aed04778b0cda5Che-Liang Chiou  int gpio_num;
2547994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  void *pp = NULL;
2557994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  int *prop;
2567994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  size_t proplen = 0;
2577994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  int ret = 0;
2587994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson
2597994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  /* TODO: This should at some point in the future use the phandle
2607994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson   * to find the gpio chip and thus the base number. Assume 0 now,
2617994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson   * which isn't 100% future-proof (i.e. if one of the switches gets
2627994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson   * moved to an offchip gpio controller.
2637994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson   */
2647994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson
2657994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  ret = ReadFdtBlock(name, &pp, &proplen);
2667994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  if (ret || !pp || proplen != 12) {
267edea097d55771083fd17075f2cc2c8c7a5449914Che-Liang Chiou    ret = 2;
2687994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson    goto out;
2697994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  }
2707994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  prop = pp;
2717994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  gpio_num = ntohl(prop[1]);
272c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
2737ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou  /*
2747ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou   * TODO(chrome-os-partner:11296): Use gpio_num == 0 to denote non-exist
2757ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou   * GPIO for now, at the risk that one day we might actually want to read
2767ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou   * from a GPIO port 0.  We should figure out how to represent "non-exist"
2777ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou   * properly.
2787ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou   */
2797ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou  if (gpio_num)
280ffb9233a90fe8f29bb80292a75aed04778b0cda5Che-Liang Chiou    ret = VbGetGpioStatus(gpio_num);
2817ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou  else
2827ec9f717173ae08571c457bd39a067dd0ce2c471Che-Liang Chiou    ret = -1;
2837994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johanssonout:
2847994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  if (pp)
2857994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson    free(pp);
286c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
2877994d07d565d11557a1701ff16e892d7ab8e0d41Olof Johansson  return ret;
288eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler}
289eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
290770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chioustatic int ExecuteMosys(char * const argv[], char *buf, size_t bufsize) {
291770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  int status, mosys_to_crossystem[2];
292770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  pid_t pid;
293770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  ssize_t n;
294770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
295770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  if (pipe(mosys_to_crossystem) < 0) {
296770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    VBDEBUG(("pipe() error\n"));
297770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return -1;
298770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  }
299770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
300770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  if ((pid = fork()) < 0) {
301770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    VBDEBUG(("fork() error\n"));
302770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[0]);
303770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[1]);
304770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return -1;
305770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  } else if (!pid) {  /* Child */
306770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[0]);
307770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    /* Redirect pipe's write-end to mosys' stdout */
308770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    if (STDOUT_FILENO != mosys_to_crossystem[1]) {
309770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      if (dup2(mosys_to_crossystem[1], STDOUT_FILENO) != STDOUT_FILENO) {
310770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou        VBDEBUG(("stdout dup2() failed (mosys)\n"));
311770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou        close(mosys_to_crossystem[1]);
312770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou        exit(1);
313770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      }
314770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    }
315770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    /* Execute mosys */
316770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    execv(MOSYS_PATH, argv);
317770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    /* We shouldn't be here; exit now! */
318770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    VBDEBUG(("execv() of mosys failed\n"));
319770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[1]);
320770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    exit(1);
321770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  } else {  /* Parent */
322770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[1]);
323770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    if (bufsize) {
324770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      bufsize--;  /* Reserve 1 byte for '\0' */
325770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      while ((n = read(mosys_to_crossystem[0], buf, bufsize)) > 0) {
326770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou        buf += n;
327770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou        bufsize -= n;
328770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      }
329770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      *buf = '\0';
330770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    } else {
331770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      n = 0;
332770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    }
333770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    close(mosys_to_crossystem[0]);
334770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    if (n < 0)
335770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      VBDEBUG(("read() error while reading output from mosys\n"));
336770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    if (waitpid(pid, &status, 0) < 0 || status) {
337770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      VBDEBUG(("waitpid() or mosys error\n"));
338770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      fprintf(stderr, "waitpid() or mosys error\n");
339770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      return -1;
340770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    }
341770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    if (n < 0)
342770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou      return -1;
343770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  }
344770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  return 0;
345770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou}
346770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
347aaa325727a19366f40c84d45bfdbfd2e4fa92de0David Hendricksstatic int VbReadNvStorage_mosys(VbNvContext* vnc) {
348770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  char hexstring[VBNV_BLOCK_SIZE * 2 + 32];  /* Reserve extra 32 bytes */
349770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  char * const argv[] = {
350770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    MOSYS_PATH, "nvram", "vboot", "read", NULL
351770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  };
352770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  char hexdigit[3];
353770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  int i;
354770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
355770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
356770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return -1;
357770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  hexdigit[2] = '\0';
358770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
359770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    hexdigit[0] = hexstring[i * 2];
360770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    hexdigit[1] = hexstring[i * 2 + 1];
361770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    vnc->raw[i] = strtol(hexdigit, NULL, 16);
362770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  }
363770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  return 0;
364770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou}
365770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
366aaa325727a19366f40c84d45bfdbfd2e4fa92de0David Hendricksstatic int VbWriteNvStorage_mosys(VbNvContext* vnc) {
367770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  char hexstring[VBNV_BLOCK_SIZE * 2 + 1];
368770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  char * const argv[] = {
369770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    MOSYS_PATH, "nvram", "vboot", "write", hexstring, NULL
370770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  };
371770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  int i;
372770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
373770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  for (i = 0; i < VBNV_BLOCK_SIZE; i++)
374770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    snprintf(hexstring + i * 2, 3, "%02x", vnc->raw[i]);
375770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  hexstring[sizeof(hexstring) - 1] = '\0';
376770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  if (ExecuteMosys(argv, NULL, 0))
377770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return -1;
378770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  return 0;
379770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou}
380770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
381770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chioustatic int VbReadNvStorage_disk(VbNvContext* vnc) {
3823a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int nvctx_fd = -1;
3833a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  uint8_t sector[SECTOR_SIZE];
3843a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int rv = -1;
3853a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  char nvctx_path[FNAME_SIZE];
3863a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int emmc_dev;
3873a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int lba = ReadFdtInt("nonvolatile-context-lba");
3883a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int offset = ReadFdtInt("nonvolatile-context-offset");
3893a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int size = ReadFdtInt("nonvolatile-context-size");
390d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
3913a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  emmc_dev = FindEmmcDev();
3923a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (emmc_dev < 0)
393d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FAIL;
3943a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  snprintf(nvctx_path, sizeof(nvctx_path), NVCTX_PATH, emmc_dev);
395d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
3963a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (size != sizeof(vnc->raw) || (size + offset > SECTOR_SIZE))
3973a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    return E_FAIL;
3983a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
3993a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  nvctx_fd = open(nvctx_path, O_RDONLY);
4003a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (nvctx_fd == -1) {
4013a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    fprintf(stderr, "%s: failed to open %s\n", __FUNCTION__, nvctx_path);
4023a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    goto out;
4033a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  }
4043a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  lseek(nvctx_fd, lba * SECTOR_SIZE, SEEK_SET);
4053a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
4063a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  rv = read(nvctx_fd, sector, SECTOR_SIZE);
4073a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (size <= 0) {
4083a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    fprintf(stderr, "%s: failed to read nvctx from device %s\n",
4093a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson            __FUNCTION__, nvctx_path);
4103a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    goto out;
4113a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  }
4123a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  Memcpy(vnc->raw, sector+offset, size);
4133a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  rv = 0;
4143a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
4153a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johanssonout:
4163a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (nvctx_fd > 0)
4173a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    close(nvctx_fd);
4183a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
4193a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  return rv;
420c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury}
421c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
422770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chioustatic int VbWriteNvStorage_disk(VbNvContext* vnc) {
423d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  int nvctx_fd = -1;
424d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  uint8_t sector[SECTOR_SIZE];
425c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  int rv = -1;
426d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char nvctx_path[FNAME_SIZE];
427d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  int emmc_dev;
4283a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int lba = ReadFdtInt("nonvolatile-context-lba");
4293a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int offset = ReadFdtInt("nonvolatile-context-offset");
4303a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  int size = ReadFdtInt("nonvolatile-context-size");
431d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
432d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  emmc_dev = FindEmmcDev();
433d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (emmc_dev < 0)
434d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return E_FAIL;
435d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  snprintf(nvctx_path, sizeof(nvctx_path), NVCTX_PATH, emmc_dev);
436c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
4373a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (size != sizeof(vnc->raw) || (size + offset > SECTOR_SIZE))
4383a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    return E_FAIL;
4393a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
440c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  do {
441d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    nvctx_fd = open(nvctx_path, O_RDWR);
442d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    if (nvctx_fd == -1) {
443d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang      fprintf(stderr, "%s: failed to open %s\n", __FUNCTION__, nvctx_path);
444d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang      break;
445d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    }
4463a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    lseek(nvctx_fd, lba * SECTOR_SIZE, SEEK_SET);
4473a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    rv = read(nvctx_fd, sector, SECTOR_SIZE);
4483a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    if (rv <= 0) {
449d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang      fprintf(stderr, "%s: failed to read nvctx from device %s\n",
450d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang              __FUNCTION__, nvctx_path);
451c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury      break;
452c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury    }
4533a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    Memcpy(sector+offset, vnc->raw, size);
4543a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    lseek(nvctx_fd, lba * SECTOR_SIZE, SEEK_SET);
4553a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    rv = write(nvctx_fd, sector, SECTOR_SIZE);
4563a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    if (rv <= 0) {
457d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang      fprintf(stderr,  "%s: failed to write nvctx to device %s\n",
458d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang              __FUNCTION__, nvctx_path);
459c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury      break;
460c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury    }
46105987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley#ifndef HAVE_MACOS
4623a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    /* Must flush buffer cache here to make sure it goes to disk */
4633a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    rv = ioctl(nvctx_fd, BLKFLSBUF, 0);
4643a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    if (rv < 0) {
4653a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson      fprintf(stderr,  "%s: failed to flush nvctx to device %s\n",
4663a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson              __FUNCTION__, nvctx_path);
4673a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson      break;
4683a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    }
46905987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley#endif
470c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury    rv = 0;
471c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  } while (0);
472c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
473d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (nvctx_fd > 0)
474d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    close(nvctx_fd);
475c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
476c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  return rv;
477c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury}
478c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
479770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiouint VbReadNvStorage(VbNvContext* vnc) {
480770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  /* Default to disk for older firmware which does not provide storage type */
481210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  char *media;
482210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (!FdtPropertyExist(FDT_NVSTORAGE_TYPE_PROP))
483210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    return VbReadNvStorage_disk(vnc);
484210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  media = ReadFdtString(FDT_NVSTORAGE_TYPE_PROP);
485210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (!strcmp(media, "disk"))
486770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return VbReadNvStorage_disk(vnc);
4871137139a2e0ea24a5fb7df3b621d4c0ec59daf81David Hendricks  if (!strcmp(media, "mkbp") || !strcmp(media, "flash"))
488aaa325727a19366f40c84d45bfdbfd2e4fa92de0David Hendricks    return VbReadNvStorage_mosys(vnc);
489770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  return -1;
490770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou}
491770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
492770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiouint VbWriteNvStorage(VbNvContext* vnc) {
493770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  /* Default to disk for older firmware which does not provide storage type */
494210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  char *media;
495210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (!FdtPropertyExist(FDT_NVSTORAGE_TYPE_PROP))
496210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou    return VbWriteNvStorage_disk(vnc);
497210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  media = ReadFdtString(FDT_NVSTORAGE_TYPE_PROP);
498210c5ef2d9d060bebf5020da886e2cabd6e05d6dChe-Liang Chiou  if (!strcmp(media, "disk"))
499770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou    return VbWriteNvStorage_disk(vnc);
5001137139a2e0ea24a5fb7df3b621d4c0ec59daf81David Hendricks  if (!strcmp(media, "mkbp") || !strcmp(media, "flash"))
501aaa325727a19366f40c84d45bfdbfd2e4fa92de0David Hendricks    return VbWriteNvStorage_mosys(vnc);
502770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou  return -1;
503770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou}
504770c1b772c0aa9241bc2923354092a14e1c68661Che-Liang Chiou
505c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim BendeburyVbSharedDataHeader *VbSharedDataRead(void) {
506d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  void *block = NULL;
507d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  size_t size = 0;
5083a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (ReadFdtBlock("vboot-shared-data", &block, &size))
509d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return NULL;
51036dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders  VbSharedDataHeader *p = (VbSharedDataHeader *)block;
51136dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders  if (p->magic != VB_SHARED_DATA_MAGIC) {
51236dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders    fprintf(stderr,  "%s: failed to validate magic in "
51336dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders            "VbSharedDataHeader (%x != %x)\n",
51436dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders            __FUNCTION__, p->magic, VB_SHARED_DATA_MAGIC);
51536dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders    return NULL;
51636dccdbad1c88657ee893b794b5aba2feacefaa5Nick Sanders  }
517d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return (VbSharedDataHeader *)block;
518c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury}
519eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
520d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Changint VbGetArchPropertyInt(const char* name) {
52109a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler  if (!strcasecmp(name, "fmap_base")) {
5223a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    return ReadFdtInt("fmap-offset");
52309a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler  } else if (!strcasecmp(name, "devsw_cur")) {
52409a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler    /* Systems with virtual developer switches return at-boot value */
52509a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler    int flags = VbGetSystemPropertyInt("vdat_flags");
52609a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler    if ((flags != -1) && (flags & VBSD_HONOR_VIRT_DEV_SWITCH))
52709a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler      return VbGetSystemPropertyInt("devsw_boot");
52809a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler
529edea097d55771083fd17075f2cc2c8c7a5449914Che-Liang Chiou    return VbGetVarGpio("developer-switch");
53009a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler  } else if (!strcasecmp(name, "recoverysw_cur")) {
531c93ddb60aae37fc06f614a1b79e6f3fee25b97c4Ken Chang    int value;
532c93ddb60aae37fc06f614a1b79e6f3fee25b97c4Ken Chang    value = VbGetPlatformGpioStatus("recovery");
533c93ddb60aae37fc06f614a1b79e6f3fee25b97c4Ken Chang    if (value != -1)
534c93ddb60aae37fc06f614a1b79e6f3fee25b97c4Ken Chang      return value;
535c93ddb60aae37fc06f614a1b79e6f3fee25b97c4Ken Chang
536edea097d55771083fd17075f2cc2c8c7a5449914Che-Liang Chiou    return VbGetVarGpio("recovery-switch");
53709a8447862c7d111d6abdd7891508df1a8f1cc5bRandall Spangler  } else if (!strcasecmp(name, "wpsw_cur")) {
5383afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black    int value;
5393afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black    /* Try finding the GPIO through the chromeos_arm platform device first. */
5403afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black    value = VbGetPlatformGpioStatus("write-protect");
5413afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black    if (value != -1)
5423afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black      return value;
543da8d32dc8d0fb5ebcfffa305f4a3ecb2dd7c79acRandall Spangler    return VbGetVarGpio("write-protect-switch");
5443afe5566ccee0df6c636ab6e9cf882106fe9245bGabe Black  } else if (!strcasecmp(name, "recoverysw_ec_boot"))
545da8d32dc8d0fb5ebcfffa305f4a3ecb2dd7c79acRandall Spangler    /* TODO: read correct value using ectool */
546d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return 0;
5473a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  else
548d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang    return -1;
549d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang}
550c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
551a3d70a3d2b5c052db039d097aaffa42008da24b5J. Richard Barnetteconst char* VbGetArchPropertyString(const char* name, char* dest,
552a3d70a3d2b5c052db039d097aaffa42008da24b5J. Richard Barnette                                    size_t size) {
553d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char *str = NULL;
554d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  char *rv = NULL;
5553a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  char *prop = NULL;
5563a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
5573a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (!strcasecmp(name,"arch"))
5583a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    return StrCopy(dest, "arm", size);
559d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang
560d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  /* Properties from fdt */
5613a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (!strcasecmp(name, "ro_fwid"))
5623a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    prop = "readonly-firmware-version";
5633a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  else if (!strcasecmp(name, "hwid"))
5643a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    prop = "hardware-id";
5653a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  else if (!strcasecmp(name, "fwid"))
5663a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    prop = "firmware-version";
5673a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  else if (!strcasecmp(name, "mainfw_type"))
5683a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    prop = "firmware-type";
5693a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  else if (!strcasecmp(name, "ecfw_act"))
5703a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    prop = "active-ec-firmware";
571d808a43d357371451c8ca4b4ad1a38f2251155c4Tom Wai-Hong Tam  else if (!strcasecmp(name, "ddr_type"))
572d808a43d357371451c8ca4b4ad1a38f2251155c4Tom Wai-Hong Tam    prop = "ddr-type";
5733a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson
5743a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson  if (prop)
5753a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson    str = ReadFdtString(prop);
576eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
5770b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson  if (!strcasecmp(name, "platform_family"))
5780b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson    str = ReadFdtPlatformFamily();
5790b5789fee96b7213a9762c5b2cf7f705a99d95efBernie Thompson
580d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  if (str) {
5813a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson      rv = StrCopy(dest, str, size);
5823a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson      free(str);
5833a6e2f10b279b9b285ae4b832d2df92a05dacd52Olof Johansson      return rv;
584eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler  }
585eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler  return NULL;
586eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler}
587eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
588eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spanglerint VbSetArchPropertyInt(const char* name, int value) {
589c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  /* All is handled in arch independent fashion */
590eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler  return -1;
591eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler}
592eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler
593eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spanglerint VbSetArchPropertyString(const char* name, const char* value) {
594c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury  /* All is handled in arch independent fashion */
595eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler  return -1;
596eb59195473246f8ff3076950f3c3b8d3564d433dRandall Spangler}
597c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury
598c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendeburyint VbArchInit(void)
599c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury{
600d70241f37d87bd7758fc6c5bbb7d5870098ecdfcRong Chang  return 0;
601c3574086a82d04b3584712f7e15a8eb4ea6d40a0Vadim Bendebury}
602