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