blob: e805e2a9cba66b21f93a9b678c8177783a805e27 [file] [log] [blame]
Randall Spanglerda8d32d2012-08-03 12:48:24 -07001/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Randall Spanglereb591952011-04-07 10:02:00 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Bill Richardson1a4d03d2011-08-31 12:01:13 -07006#include <ctype.h>
7#include <dirent.h>
Gabe Black29efa172011-11-08 22:57:38 -08008#include <errno.h>
Patrick Georgi8a966452019-09-20 22:03:58 +02009#include <fcntl.h>
Idwer Volleringb384db32021-05-10 21:15:45 +020010#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
Gabe Black29efa172011-11-08 22:57:38 -080011#include <linux/nvram.h>
Lukasz Majczak5859c782020-04-17 16:37:02 +020012#include <linux/version.h>
Idwer Volleringade61512020-08-28 23:16:28 +020013#endif
J. Richard Barnettea3d70a32013-10-30 11:36:45 -070014#include <stddef.h>
Bill Richardson0c3ba242013-03-29 11:09:30 -070015#include <stdint.h>
Randall Spanglereb591952011-04-07 10:02:00 -070016#include <stdio.h>
17#include <string.h>
Gabe Black29efa172011-11-08 22:57:38 -080018#include <sys/ioctl.h>
Randall Spanglereb591952011-04-07 10:02:00 -070019#include <sys/stat.h>
Bill Richardson1a4d03d2011-08-31 12:01:13 -070020#include <sys/types.h>
Lukasz Majczak5859c782020-04-17 16:37:02 +020021#include <sys/utsname.h>
Randall Spanglereb591952011-04-07 10:02:00 -070022#include <unistd.h>
Randall Spanglereb591952011-04-07 10:02:00 -070023
Randall Spanglereb591952011-04-07 10:02:00 -070024#include "crossystem_arch.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +080025#include "crossystem.h"
Duncan Laurieeb0c8cc2016-03-30 09:38:54 -070026#include "crossystem_vbnv.h"
Bill Richardson0c3ba242013-03-29 11:09:30 -070027#include "host_common.h"
Randall Spanglereb591952011-04-07 10:02:00 -070028#include "vboot_struct.h"
29
Randall Spanglereb591952011-04-07 10:02:00 -070030/* ACPI constants from Chrome OS Main Processor Firmware Spec */
31/* Boot reasons from BINF.0, from early H2C firmware */
32/* Unknown */
33#define BINF0_UNKNOWN 0
34/* Normal boot to Chrome OS */
35#define BINF0_NORMAL 1
36/* Developer mode boot (developer mode warning displayed) */
37#define BINF0_DEVELOPER 2
38/* Recovery initiated by user, using recovery button */
39#define BINF0_RECOVERY_BUTTON 3
40/* Recovery initiated by user pressing a key at developer mode warning
41 * screen */
42#define BINF0_RECOVERY_DEV_SCREEN_KEY 4
43/* Recovery caused by BIOS failed signature check (neither rewritable
44 * firmware was valid) */
45#define BINF0_RECOVERY_RW_FW_BAD 5
46/* Recovery caused by no OS kernel detected */
47#define BINF0_RECOVERY_NO_OS 6
48/* Recovery caused by OS kernel failed signature check */
49#define BINF0_RECOVERY_BAD_OS 7
50/* Recovery initiated by OS */
51#define BINF0_RECOVERY_OS_INITIATED 8
52/* OS-initiated S3 diagnostic path (debug mode boot) */
53#define BINF0_S3_DIAGNOSTIC_PATH 9
54/* S3 resume failed */
55#define BINF0_S3_RESUME_FAILED 10
56/* Recovery caused by TPM error */
57#define BINF0_RECOVERY_TPM_ERROR 11
Randall Spanglereb591952011-04-07 10:02:00 -070058/* CHSW bitflags */
59#define CHSW_RECOVERY_BOOT 0x00000002
60#define CHSW_RECOVERY_EC_BOOT 0x00000004
61#define CHSW_DEV_BOOT 0x00000020
Randall Spanglereb591952011-04-07 10:02:00 -070062/* CMOS reboot field bitflags */
63#define CMOSRF_RECOVERY 0x80
64#define CMOSRF_DEBUG_RESET 0x40
65#define CMOSRF_TRY_B 0x20
66/* GPIO signal types */
67#define GPIO_SIGNAL_TYPE_RECOVERY 1
Joel Kitchingf70c35d2019-03-27 18:29:20 +080068#define GPIO_SIGNAL_TYPE_DEPRECATED_DEV 2 /* Deprecated; see chromium:942901 */
Randall Spanglereb591952011-04-07 10:02:00 -070069#define GPIO_SIGNAL_TYPE_WP 3
Aaron Durbin8bb1c3b2016-12-12 14:15:12 -060070#define GPIO_SIGNAL_TYPE_PHASE_ENFORCEMENT 4
Randall Spanglereb591952011-04-07 10:02:00 -070071
72/* Base name for ACPI files */
73#define ACPI_BASE_PATH "/sys/devices/platform/chromeos_acpi"
74/* Paths for frequently used ACPI files */
75#define ACPI_BINF_PATH ACPI_BASE_PATH "/BINF"
76#define ACPI_CHNV_PATH ACPI_BASE_PATH "/CHNV"
77#define ACPI_CHSW_PATH ACPI_BASE_PATH "/CHSW"
Randall Spanglereb591952011-04-07 10:02:00 -070078#define ACPI_GPIO_PATH ACPI_BASE_PATH "/GPIO"
79#define ACPI_VBNV_PATH ACPI_BASE_PATH "/VBNV"
80#define ACPI_VDAT_PATH ACPI_BASE_PATH "/VDAT"
81
82/* Base name for GPIO files */
83#define GPIO_BASE_PATH "/sys/class/gpio"
84#define GPIO_EXPORT_PATH GPIO_BASE_PATH "/export"
85
86/* Filename for NVRAM file */
87#define NVRAM_PATH "/dev/nvram"
88
Randall Spangler07f34842011-04-11 13:35:06 -070089/* Filename for legacy firmware update tries */
90#define NEED_FWUPDATE_PATH "/mnt/stateful_partition/.need_firmware_update"
91
Bernie Thompson0b5789f2011-12-28 07:40:48 -080092/* Filenames for PCI Vendor and Device IDs */
93#define PCI_VENDOR_ID_PATH "/sys/bus/pci/devices/0000:00:00.0/vendor"
94#define PCI_DEVICE_ID_PATH "/sys/bus/pci/devices/0000:00:00.0/device"
95
John Zhao5f16cce2015-04-02 10:24:51 -070096typedef struct {
Randall Spanglerfb267152016-10-11 15:28:16 -070097 unsigned int base;
98 unsigned int uid;
John Zhao5f16cce2015-04-02 10:24:51 -070099} Basemapping;
100
Randall Spanglerfb267152016-10-11 15:28:16 -0700101static void VbFixCmosChecksum(FILE* file)
102{
Idwer Volleringb384db32021-05-10 21:15:45 +0200103#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
Randall Spanglerfb267152016-10-11 15:28:16 -0700104 int fd = fileno(file);
105 ioctl(fd, NVRAM_SETCKS);
Idwer Volleringade61512020-08-28 23:16:28 +0200106#endif
Gabe Black29efa172011-11-08 22:57:38 -0800107}
108
109
Randall Spanglerfb267152016-10-11 15:28:16 -0700110static int VbCmosRead(unsigned offs, size_t size, void *ptr)
111{
112 size_t res;
113 FILE* f;
Gabe Black29efa172011-11-08 22:57:38 -0800114
Randall Spanglerfb267152016-10-11 15:28:16 -0700115 f = fopen(NVRAM_PATH, "rb");
116 if (!f)
117 return -1;
Gabe Black29efa172011-11-08 22:57:38 -0800118
Randall Spanglerfb267152016-10-11 15:28:16 -0700119 if (0 != fseek(f, offs, SEEK_SET)) {
120 fclose(f);
121 return -1;
122 }
Gabe Black29efa172011-11-08 22:57:38 -0800123
Randall Spanglerfb267152016-10-11 15:28:16 -0700124 res = fread(ptr, size, 1, f);
125 if (1 != res && errno == EIO && ferror(f)) {
126 VbFixCmosChecksum(f);
127 res = fread(ptr, size, 1, f);
128 }
Gabe Black29efa172011-11-08 22:57:38 -0800129
Randall Spanglerfb267152016-10-11 15:28:16 -0700130 fclose(f);
131 return (1 == res) ? 0 : -1;
Gabe Black29efa172011-11-08 22:57:38 -0800132}
133
134
Randall Spanglerfb267152016-10-11 15:28:16 -0700135static int VbCmosWrite(unsigned offs, size_t size, const void *ptr)
136{
137 size_t res;
138 FILE* f;
Gabe Black29efa172011-11-08 22:57:38 -0800139
Randall Spanglerfb267152016-10-11 15:28:16 -0700140 f = fopen(NVRAM_PATH, "w+b");
141 if (!f)
142 return -1;
Gabe Black29efa172011-11-08 22:57:38 -0800143
Randall Spanglerfb267152016-10-11 15:28:16 -0700144 if (0 != fseek(f, offs, SEEK_SET)) {
145 fclose(f);
146 return -1;
147 }
Hung-Te Lin6a6f85d2011-11-16 17:31:19 +0800148
Randall Spanglerfb267152016-10-11 15:28:16 -0700149 res = fwrite(ptr, size, 1, f);
150 if (1 != res && errno == EIO && ferror(f)) {
151 VbFixCmosChecksum(f);
152 res = fwrite(ptr, size, 1, f);
153 }
Gabe Black29efa172011-11-08 22:57:38 -0800154
Randall Spanglerfb267152016-10-11 15:28:16 -0700155 fclose(f);
156 return (1 == res) ? 0 : -1;
Gabe Black29efa172011-11-08 22:57:38 -0800157}
158
159
Randall Spanglerdff58522017-11-27 15:37:13 -0800160int vb2_read_nv_storage(struct vb2_context *ctx)
Randall Spanglerfb267152016-10-11 15:28:16 -0700161{
162 unsigned offs, blksz;
Randall Spanglera80a79f2018-02-26 17:01:24 -0800163 unsigned expectsz = vb2_nv_get_size(ctx);
Randall Spanglereb591952011-04-07 10:02:00 -0700164
Randall Spanglerfb267152016-10-11 15:28:16 -0700165 /* Get the byte offset from VBNV */
166 if (ReadFileInt(ACPI_VBNV_PATH ".0", &offs) < 0)
167 return -1;
168 if (ReadFileInt(ACPI_VBNV_PATH ".1", &blksz) < 0)
169 return -1;
Randall Spanglera80a79f2018-02-26 17:01:24 -0800170 if (expectsz > blksz)
Randall Spanglerfb267152016-10-11 15:28:16 -0700171 return -1; /* NV storage block is too small */
Randall Spanglereb591952011-04-07 10:02:00 -0700172
Randall Spanglera80a79f2018-02-26 17:01:24 -0800173 if (0 != VbCmosRead(offs, expectsz, ctx->nvdata))
Randall Spanglerfb267152016-10-11 15:28:16 -0700174 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700175
Randall Spanglerfb267152016-10-11 15:28:16 -0700176 return 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700177}
178
179
Randall Spanglerdff58522017-11-27 15:37:13 -0800180int vb2_write_nv_storage(struct vb2_context *ctx)
Randall Spanglerd8a9ede2016-09-02 12:25:27 -0700181{
Randall Spanglerfb267152016-10-11 15:28:16 -0700182 unsigned offs, blksz;
Randall Spanglera80a79f2018-02-26 17:01:24 -0800183 unsigned expectsz = vb2_nv_get_size(ctx);
Randall Spanglereb591952011-04-07 10:02:00 -0700184
Randall Spanglerdff58522017-11-27 15:37:13 -0800185 if (!(ctx->flags & VB2_CONTEXT_NVDATA_CHANGED))
Randall Spanglerfb267152016-10-11 15:28:16 -0700186 return 0; /* Nothing changed, so no need to write */
Randall Spanglereb591952011-04-07 10:02:00 -0700187
Randall Spanglerfb267152016-10-11 15:28:16 -0700188 /* Get the byte offset from VBNV */
189 if (ReadFileInt(ACPI_VBNV_PATH ".0", &offs) < 0)
190 return -1;
191 if (ReadFileInt(ACPI_VBNV_PATH ".1", &blksz) < 0)
192 return -1;
Randall Spanglera80a79f2018-02-26 17:01:24 -0800193 if (expectsz > blksz)
Randall Spanglerfb267152016-10-11 15:28:16 -0700194 return -1; /* NV storage block is too small */
Randall Spanglereb591952011-04-07 10:02:00 -0700195
Randall Spanglera80a79f2018-02-26 17:01:24 -0800196 if (0 != VbCmosWrite(offs, expectsz, ctx->nvdata))
Randall Spanglerfb267152016-10-11 15:28:16 -0700197 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700198
Jack Rosenthal15651692020-05-27 09:06:41 -0600199 /* Also attempt to write using flashrom if using vboot2 */
Randall Spanglerfb267152016-10-11 15:28:16 -0700200 VbSharedDataHeader *sh = VbSharedDataRead();
201 if (sh) {
202 if (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2)
Jack Rosenthal15651692020-05-27 09:06:41 -0600203 vb2_write_nv_storage_flashrom(ctx);
Randall Spanglerfb267152016-10-11 15:28:16 -0700204 free(sh);
205 }
Duncan Laurieeb0c8cc2016-03-30 09:38:54 -0700206
Randall Spanglerfb267152016-10-11 15:28:16 -0700207 return 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700208}
209
210
211/*
212 * Get buffer data from ACPI.
213 *
214 * Buffer data is expected to be represented by a file which is a text dump of
215 * the buffer, representing each byte by two hex numbers, space and newline
216 * separated.
217 *
218 * On success, stores the amount of data read in bytes to *buffer_size; on
219 * erros, sets *buffer_size=0.
220 *
221 * Input - ACPI file name to get data from.
222 *
223 * Output: a pointer to AcpiBuffer structure containing the binary
224 * representation of the data. The caller is responsible for
225 * deallocating the pointer, this will take care of both the structure
226 * and the buffer. Null in case of error.
227 */
Randall Spanglerfb267152016-10-11 15:28:16 -0700228static uint8_t* VbGetBuffer(const char* filename, int* buffer_size)
229{
230 FILE* f = NULL;
231 char* file_buffer = NULL;
232 uint8_t* output_buffer = NULL;
233 uint8_t* return_value = NULL;
Randall Spanglereb591952011-04-07 10:02:00 -0700234
Randall Spanglerfb267152016-10-11 15:28:16 -0700235 /* Assume error until proven otherwise */
236 if (buffer_size)
237 *buffer_size = 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700238
Randall Spanglerfb267152016-10-11 15:28:16 -0700239 do {
240 struct stat fs;
241 uint8_t* output_ptr;
242 int rv, i, real_size;
243 int parsed_size = 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700244
Patrick Georgi8a966452019-09-20 22:03:58 +0200245 int fd = open(filename, O_RDONLY);
246 if (fd == -1)
247 break;
248
249 rv = fstat(fd, &fs);
Patrick Georgi3a62b652019-09-26 18:21:01 +0200250 if (rv || !S_ISREG(fs.st_mode)) {
251 close(fd);
Randall Spanglerfb267152016-10-11 15:28:16 -0700252 break;
Patrick Georgi3a62b652019-09-26 18:21:01 +0200253 }
Randall Spanglereb591952011-04-07 10:02:00 -0700254
Patrick Georgi8a966452019-09-20 22:03:58 +0200255 f = fdopen(fd, "r");
Patrick Georgi3a62b652019-09-26 18:21:01 +0200256 if (!f) {
257 close(fd);
Randall Spanglerfb267152016-10-11 15:28:16 -0700258 break;
Patrick Georgi3a62b652019-09-26 18:21:01 +0200259 }
Randall Spanglereb591952011-04-07 10:02:00 -0700260
Randall Spanglerfb267152016-10-11 15:28:16 -0700261 file_buffer = malloc(fs.st_size + 1);
262 if (!file_buffer)
263 break;
Randall Spanglereb591952011-04-07 10:02:00 -0700264
Randall Spanglerfb267152016-10-11 15:28:16 -0700265 real_size = fread(file_buffer, 1, fs.st_size, f);
266 if (!real_size)
267 break;
268 file_buffer[real_size] = '\0';
Randall Spanglereb591952011-04-07 10:02:00 -0700269
Randall Spanglerfb267152016-10-11 15:28:16 -0700270 /* Each byte in the output will replace two characters and a
271 * space in the input, so the output size does not exceed input
272 * side/3 (a little less if account for newline characters). */
273 output_buffer = malloc(real_size/3);
274 if (!output_buffer)
275 break;
276 output_ptr = output_buffer;
Randall Spanglereb591952011-04-07 10:02:00 -0700277
Randall Spanglerfb267152016-10-11 15:28:16 -0700278 /* process the file contents */
279 for (i = 0; i < real_size; i++) {
280 char* base, *end;
Randall Spanglereb591952011-04-07 10:02:00 -0700281
Randall Spanglerfb267152016-10-11 15:28:16 -0700282 base = file_buffer + i;
Randall Spanglereb591952011-04-07 10:02:00 -0700283
Randall Spanglerfb267152016-10-11 15:28:16 -0700284 if (!isxdigit(*base))
285 continue;
Randall Spanglereb591952011-04-07 10:02:00 -0700286
Randall Spanglerfb267152016-10-11 15:28:16 -0700287 output_ptr[parsed_size++] =
288 strtol(base, &end, 16) & 0xff;
Randall Spanglereb591952011-04-07 10:02:00 -0700289
Randall Spanglerfb267152016-10-11 15:28:16 -0700290 if ((end - base) != 2)
291 /* Input file format error */
292 break;
Randall Spanglereb591952011-04-07 10:02:00 -0700293
Randall Spanglerfb267152016-10-11 15:28:16 -0700294 /* skip the second character and the following space */
295 i += 2;
296 }
Randall Spanglereb591952011-04-07 10:02:00 -0700297
Randall Spanglerfb267152016-10-11 15:28:16 -0700298 if (i == real_size) {
299 /* all is well */
300 return_value = output_buffer;
301 output_buffer = NULL; /* prevent it from deallocating */
302 if (buffer_size)
303 *buffer_size = parsed_size;
304 }
305 } while(0);
Randall Spanglereb591952011-04-07 10:02:00 -0700306
Randall Spanglerfb267152016-10-11 15:28:16 -0700307 /* wrap up */
308 if (f)
309 fclose(f);
Randall Spanglereb591952011-04-07 10:02:00 -0700310
Randall Spanglerfb267152016-10-11 15:28:16 -0700311 if (file_buffer)
312 free(file_buffer);
Randall Spanglereb591952011-04-07 10:02:00 -0700313
Randall Spanglerfb267152016-10-11 15:28:16 -0700314 if (output_buffer)
315 free(output_buffer);
Randall Spanglereb591952011-04-07 10:02:00 -0700316
Randall Spanglerfb267152016-10-11 15:28:16 -0700317 return return_value;
Randall Spanglereb591952011-04-07 10:02:00 -0700318}
319
320
Randall Spanglerfb267152016-10-11 15:28:16 -0700321VbSharedDataHeader* VbSharedDataRead(void)
322{
323 VbSharedDataHeader* sh;
324 int got_size = 0;
325 int expect_size;
Randall Spanglereb591952011-04-07 10:02:00 -0700326
Randall Spanglerfb267152016-10-11 15:28:16 -0700327 sh = (VbSharedDataHeader*)VbGetBuffer(ACPI_VDAT_PATH, &got_size);
328 if (!sh)
329 return NULL;
Randall Spangler7adcc602011-06-24 16:11:45 -0700330
Randall Spanglerfb267152016-10-11 15:28:16 -0700331 /* Make sure the size is sufficient for the struct version we got.
332 * Check supported old versions first. */
333 if (1 == sh->struct_version)
334 expect_size = VB_SHARED_DATA_HEADER_SIZE_V1;
335 else {
336 /* There'd better be enough data for the current header size. */
337 expect_size = sizeof(VbSharedDataHeader);
338 }
Randall Spangler7adcc602011-06-24 16:11:45 -0700339
Randall Spanglerfb267152016-10-11 15:28:16 -0700340 if (got_size < expect_size) {
341 free(sh);
342 return NULL;
343 }
344 if (sh->data_size > got_size)
345 sh->data_size = got_size; /* Truncated read */
Randall Spanglereb591952011-04-07 10:02:00 -0700346
Randall Spanglerfb267152016-10-11 15:28:16 -0700347 return sh;
Randall Spanglereb591952011-04-07 10:02:00 -0700348}
349
350
351/* Read the CMOS reboot field in NVRAM.
352 *
353 * Returns 0 if the mask is clear in the field, 1 if set, or -1 if error. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700354static int VbGetCmosRebootField(uint8_t mask)
355{
356 unsigned chnv;
357 uint8_t nvbyte;
Randall Spanglereb591952011-04-07 10:02:00 -0700358
Randall Spanglerfb267152016-10-11 15:28:16 -0700359 /* Get the byte offset from CHNV */
360 if (ReadFileInt(ACPI_CHNV_PATH, &chnv) < 0)
361 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700362
Randall Spanglerfb267152016-10-11 15:28:16 -0700363 if (0 != VbCmosRead(chnv, 1, &nvbyte))
364 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700365
Randall Spanglerfb267152016-10-11 15:28:16 -0700366 return (nvbyte & mask ? 1 : 0);
Randall Spanglereb591952011-04-07 10:02:00 -0700367}
368
369
370/* Write the CMOS reboot field in NVRAM.
371 *
372 * Sets (value=0) or clears (value!=0) the mask in the byte.
373 *
374 * Returns 0 if success, or -1 if error. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700375static int VbSetCmosRebootField(uint8_t mask, int value)
376{
377 unsigned chnv;
378 uint8_t nvbyte;
Randall Spanglereb591952011-04-07 10:02:00 -0700379
Randall Spanglerfb267152016-10-11 15:28:16 -0700380 /* Get the byte offset from CHNV */
381 if (ReadFileInt(ACPI_CHNV_PATH, &chnv) < 0)
382 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700383
Randall Spanglerfb267152016-10-11 15:28:16 -0700384 if (0 != VbCmosRead(chnv, 1, &nvbyte))
385 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700386
Randall Spanglerfb267152016-10-11 15:28:16 -0700387 /* Set/clear the mask */
388 if (value)
389 nvbyte |= mask;
390 else
391 nvbyte &= ~mask;
Randall Spanglereb591952011-04-07 10:02:00 -0700392
Randall Spanglerfb267152016-10-11 15:28:16 -0700393 /* Write the byte back */
394 if (0 != VbCmosWrite(chnv, 1, &nvbyte))
395 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700396
Randall Spanglerfb267152016-10-11 15:28:16 -0700397 /* Success */
398 return 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700399}
400
401
402/* Read the active main firmware type into the destination buffer.
403 * Passed the destination and its size. Returns the destination, or
404 * NULL if error. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700405static const char* VbReadMainFwType(char* dest, int size)
406{
407 unsigned value;
Randall Spanglereb591952011-04-07 10:02:00 -0700408
Randall Spanglerfb267152016-10-11 15:28:16 -0700409 /* Try reading type from BINF.3 */
410 if (ReadFileInt(ACPI_BINF_PATH ".3", &value) == 0) {
411 switch(value) {
Hung-Te Linecda1152018-05-22 17:17:21 +0800412 case BINF3_LEGACY:
413 return StrCopy(dest, "legacy", size);
Randall Spanglerfb267152016-10-11 15:28:16 -0700414 case BINF3_NETBOOT:
415 return StrCopy(dest, "netboot", size);
416 case BINF3_RECOVERY:
417 return StrCopy(dest, "recovery", size);
418 case BINF3_NORMAL:
419 return StrCopy(dest, "normal", size);
420 case BINF3_DEVELOPER:
421 return StrCopy(dest, "developer", size);
422 default:
423 break; /* Fall through to legacy handling */
424 }
425 }
Randall Spanglereb591952011-04-07 10:02:00 -0700426
Randall Spanglerfb267152016-10-11 15:28:16 -0700427 /* Fall back to BINF.0 for legacy systems like Mario. */
428 if (ReadFileInt(ACPI_BINF_PATH ".0", &value) < 0)
429 /* Both BINF.0 and BINF.3 are missing, so this isn't Chrome OS
430 * firmware. */
431 return StrCopy(dest, "nonchrome", size);
Duncan Lauried241fff2014-10-13 08:11:09 -0700432
Randall Spanglerfb267152016-10-11 15:28:16 -0700433 switch(value) {
434 case BINF0_NORMAL:
435 return StrCopy(dest, "normal", size);
436 case BINF0_DEVELOPER:
437 return StrCopy(dest, "developer", size);
438 case BINF0_RECOVERY_BUTTON:
439 case BINF0_RECOVERY_DEV_SCREEN_KEY:
440 case BINF0_RECOVERY_RW_FW_BAD:
441 case BINF0_RECOVERY_NO_OS:
442 case BINF0_RECOVERY_BAD_OS:
443 case BINF0_RECOVERY_OS_INITIATED:
444 case BINF0_RECOVERY_TPM_ERROR:
445 /* Assorted flavors of recovery boot reason. */
446 return StrCopy(dest, "recovery", size);
447 default:
448 /* Other values don't map cleanly to firmware type. */
449 return NULL;
450 }
Randall Spanglereb591952011-04-07 10:02:00 -0700451}
452
453
454/* Read the recovery reason. Returns the reason code or -1 if error. */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800455static vb2_error_t VbGetRecoveryReason(void)
Randall Spanglerfb267152016-10-11 15:28:16 -0700456{
457 unsigned value;
Randall Spangler7adcc602011-06-24 16:11:45 -0700458
Randall Spanglerfb267152016-10-11 15:28:16 -0700459 /* Try reading type from BINF.4 */
460 if (ReadFileInt(ACPI_BINF_PATH ".4", &value) == 0)
461 return value;
Randall Spanglereb591952011-04-07 10:02:00 -0700462
Randall Spanglerfb267152016-10-11 15:28:16 -0700463 /* Fall back to BINF.0 for legacy systems like Mario. */
464 if (ReadFileInt(ACPI_BINF_PATH ".0", &value) < 0)
465 return -1;
466 switch(value) {
467 case BINF0_NORMAL:
468 case BINF0_DEVELOPER:
Randall Spanglerdff58522017-11-27 15:37:13 -0800469 return VB2_RECOVERY_NOT_REQUESTED;
Randall Spanglerfb267152016-10-11 15:28:16 -0700470 case BINF0_RECOVERY_BUTTON:
Randall Spanglerdff58522017-11-27 15:37:13 -0800471 return VB2_RECOVERY_RO_MANUAL;
Randall Spanglerfb267152016-10-11 15:28:16 -0700472 case BINF0_RECOVERY_RW_FW_BAD:
Randall Spanglerdff58522017-11-27 15:37:13 -0800473 return VB2_RECOVERY_RO_INVALID_RW;
Randall Spanglerfb267152016-10-11 15:28:16 -0700474 case BINF0_RECOVERY_NO_OS:
Julius Wernerddc84582019-10-15 14:37:35 -0700475 return VB2_RECOVERY_RW_NO_KERNEL;
Randall Spanglerfb267152016-10-11 15:28:16 -0700476 case BINF0_RECOVERY_BAD_OS:
Randall Spanglerdff58522017-11-27 15:37:13 -0800477 return VB2_RECOVERY_RW_INVALID_OS;
Randall Spanglerfb267152016-10-11 15:28:16 -0700478 case BINF0_RECOVERY_OS_INITIATED:
Randall Spanglerdff58522017-11-27 15:37:13 -0800479 return VB2_RECOVERY_LEGACY;
Randall Spanglerfb267152016-10-11 15:28:16 -0700480 default:
481 /* Other values don't map cleanly to firmware type. */
482 return -1;
483 }
Randall Spanglereb591952011-04-07 10:02:00 -0700484}
485
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700486/* Physical GPIO number <N> may be accessed through /sys/class/gpio/gpio<M>/,
487 * but <N> and <M> may differ by some offset <O>. To determine that constant,
488 * we look for a directory named /sys/class/gpio/gpiochip<O>/. If there's not
489 * exactly one match for that, we're SOL.
490 */
Duncan Laurie8bb36892014-10-17 14:35:33 -0700491static int FindGpioChipOffset(unsigned *gpio_num, unsigned *offset,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800492 const char *name)
Randall Spanglerfb267152016-10-11 15:28:16 -0700493{
494 DIR *dir;
495 struct dirent *ent;
496 int match = 0;
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700497
Randall Spanglerfb267152016-10-11 15:28:16 -0700498 dir = opendir(GPIO_BASE_PATH);
499 if (!dir) {
500 return 0;
501 }
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700502
Randall Spanglerfb267152016-10-11 15:28:16 -0700503 while(0 != (ent = readdir(dir))) {
504 if (1 == sscanf(ent->d_name, "gpiochip%u", offset)) {
505 match++;
506 }
507 }
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700508
Randall Spanglerfb267152016-10-11 15:28:16 -0700509 closedir(dir);
510 return (1 == match);
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700511}
512
Duncan Laurie8bb36892014-10-17 14:35:33 -0700513/* Physical GPIO number <N> may be accessed through /sys/class/gpio/gpio<M>/,
514 * but <N> and <M> may differ by some offset <O>. To determine that constant,
515 * we look for a directory named /sys/class/gpio/gpiochip<O>/ and check for
516 * a 'label' file inside of it to find the expected the controller name.
517 */
518static int FindGpioChipOffsetByLabel(unsigned *gpio_num, unsigned *offset,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800519 const char *name)
Randall Spanglerfb267152016-10-11 15:28:16 -0700520{
521 DIR *dir;
522 struct dirent *ent;
523 char filename[128];
524 char chiplabel[128];
525 int match = 0;
526 unsigned controller_offset = 0;
Duncan Laurie8bb36892014-10-17 14:35:33 -0700527
Randall Spanglerfb267152016-10-11 15:28:16 -0700528 dir = opendir(GPIO_BASE_PATH);
529 if (!dir) {
530 return 0;
531 }
Duncan Laurie8bb36892014-10-17 14:35:33 -0700532
Randall Spanglerfb267152016-10-11 15:28:16 -0700533 while(0 != (ent = readdir(dir))) {
534 if (1 == sscanf(ent->d_name, "gpiochip%u",
535 &controller_offset)) {
536 /*
537 * Read the file at gpiochip<O>/label to get the
538 * identifier for this bank of GPIOs.
539 */
540 snprintf(filename, sizeof(filename),
541 "%s/gpiochip%u/label",
542 GPIO_BASE_PATH, controller_offset);
543 if (ReadFileString(chiplabel, sizeof(chiplabel),
544 filename)) {
545 if (!strncasecmp(chiplabel, name,
546 strlen(name))) {
547 /*
548 * Store offset when chip label is
549 * matched.
550 */
551 *offset = controller_offset;
552 match++;
553 }
554 }
555 }
556 }
Duncan Laurie8bb36892014-10-17 14:35:33 -0700557
Randall Spanglerfb267152016-10-11 15:28:16 -0700558 closedir(dir);
559 return (1 == match);
Duncan Laurie8bb36892014-10-17 14:35:33 -0700560}
561
John Zhao5f16cce2015-04-02 10:24:51 -0700562static int FindGpioChipOffsetByNumber(unsigned *gpio_num, unsigned *offset,
Randall Spanglerfb267152016-10-11 15:28:16 -0700563 Basemapping *data)
564{
565 DIR *dir;
566 struct dirent *ent;
567 int match = 0;
Aaron Durbin1aa59b02013-12-10 16:05:30 -0800568
Randall Spanglerfb267152016-10-11 15:28:16 -0700569 /* Obtain relative GPIO number.
570 * The assumption here is the Basemapping
571 * table is arranged in decreasing order of
572 * base address and ends with 0.
573 * A UID with value 0 indicates an invalid range
574 * and causes an early return to avoid the directory
575 * opening code below.
576 */
577 do {
578 if (*gpio_num >= data->base) {
579 *gpio_num -= data->base;
580 break;
581 }
582 data++;
583 } while(1);
John Zhao5f16cce2015-04-02 10:24:51 -0700584
Randall Spanglerfb267152016-10-11 15:28:16 -0700585 if (data->uid == 0) {
586 return 0;
587 }
Aaron Durbin1aa59b02013-12-10 16:05:30 -0800588
Randall Spanglerfb267152016-10-11 15:28:16 -0700589 dir = opendir(GPIO_BASE_PATH);
590 if (!dir) {
591 return 0;
592 }
Aaron Durbin1aa59b02013-12-10 16:05:30 -0800593
Randall Spanglerfb267152016-10-11 15:28:16 -0700594 while(0 != (ent = readdir(dir))) {
595 /* For every gpiochip entry determine uid. */
596 if (1 == sscanf(ent->d_name, "gpiochip%u", offset)) {
597 char uid_file[128];
598 unsigned uid_value;
599 snprintf(uid_file, sizeof(uid_file),
600 "%s/gpiochip%u/device/firmware_node/uid",
601 GPIO_BASE_PATH, *offset);
602 if (ReadFileInt(uid_file, &uid_value) < 0)
603 continue;
604 if (data->uid == uid_value) {
605 match++;
606 break;
607 }
608 }
609 }
Aaron Durbin1aa59b02013-12-10 16:05:30 -0800610
Randall Spanglerfb267152016-10-11 15:28:16 -0700611 closedir(dir);
612 return (1 == match);
Aaron Durbin1aa59b02013-12-10 16:05:30 -0800613}
614
Bill Richardson1a4d03d2011-08-31 12:01:13 -0700615
Randall Spanglerfb267152016-10-11 15:28:16 -0700616/* Braswell has 4 sets of GPIO banks. It is expected the firmware exposes each
617 * bank of gpios using a UID in ACPI. Furthermore the gpio number exposed is
618 * relative to the bank. e.g. gpio MF_ISH_GPIO_4 in the bank specified by UID 3
John Zhao5f16cce2015-04-02 10:24:51 -0700619 * would be encoded as 0x10016.
Randall Spanglerfb267152016-10-11 15:28:16 -0700620 *
John Zhao5f16cce2015-04-02 10:24:51 -0700621 * UID | Bank Offset
622 * ----+------------
623 * 1 | 0x0000
624 * 2 | 0x8000
625 * 3 | 0x10000
626 * 4 | 0x18000
627 */
628static int BraswellFindGpioChipOffset(unsigned *gpio_num, unsigned *offset,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800629 const char *name)
Randall Spanglerfb267152016-10-11 15:28:16 -0700630{
Lukasz Majczak5859c782020-04-17 16:37:02 +0200631 int ret;
632 struct utsname host;
633 unsigned int maj, min;
634 int gpe = 0;
Randall Spanglerfb267152016-10-11 15:28:16 -0700635 static Basemapping data[]={
636 {0x20000, 0},
637 {0x18000, 4},
638 {0x10000, 3},
639 {0x08000, 2},
640 {0x00000, 1}};
John Zhao5f16cce2015-04-02 10:24:51 -0700641
Lukasz Majczak5859c782020-04-17 16:37:02 +0200642 /*
643 * This quirk addresses b:143174998 and is required on kernels >= 4.16
644 * when GPIO numbering has changed with an upstream commit:
645 * 03c4749dd6c7ff948a0ce59a44a1b97c015353c2
646 * "gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation".
647 * With that change gpio ACPI/Linux kernel 1:1 mapping was introduced which
648 * made mismatch for gpio number and backward compatibility for user-space.
649 * Details on review commit review
650 * https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2153155
651 */
652
653 /*
654 * Here we are addressing particular wpsw_cur pin which is connected to
655 * East Community GPIO chip (uid == 3, base == 0x10000). In this case there
656 * is only one gap between 11 and 15 (0..11 15..26). For now crosssystem
657 * is not checking pins in other gpio banks, but it is worth to mention that
658 * there are gaps as well.
659 */
660 if (*gpio_num >= 0x10000 && *gpio_num < 0x18000)
661 gpe = 1;
662
663 ret = FindGpioChipOffsetByNumber(gpio_num, offset, data);
664 if (!ret || !gpe)
665 return ret;
666
667 if (uname(&host) == 0) {
668 if (sscanf(host.release, "%u.%u.", &maj, &min) == 2) {
Idwer Volleringb384db32021-05-10 21:15:45 +0200669#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
Lukasz Majczak5859c782020-04-17 16:37:02 +0200670 if (KERNEL_VERSION(maj, min, 0) >= KERNEL_VERSION(4, 16, 0) &&
671 *offset > 11)
672 *offset += 3;
Idwer Volleringade61512020-08-28 23:16:28 +0200673#endif
Lukasz Majczak5859c782020-04-17 16:37:02 +0200674 } else {
675 printf("Couldn't retrieve kernel version!\n");
676 ret = 0;
677 }
678 } else {
679 perror("uname");
680 ret = 0;
681 }
682
683 return ret;
John Zhao5f16cce2015-04-02 10:24:51 -0700684}
685
686/* BayTrail has 3 sets of GPIO banks. It is expected the firmware exposes
687 * each bank of gpios using a UID in ACPI. Furthermore the gpio number exposed
688 * is relative to the bank. e.g. gpio 6 in the bank specified by UID 3 would
689 * be encoded as 0x2006.
690 * UID | Bank Offset
691 * ----+------------
692 * 1 | 0x0000
693 * 2 | 0x1000
694 * 3 | 0x2000
695 */
696static int BayTrailFindGpioChipOffset(unsigned *gpio_num, unsigned *offset,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800697 const char *name)
Randall Spanglerfb267152016-10-11 15:28:16 -0700698{
699 static Basemapping data[]={
700 {0x3000, 0},
701 {0x2000, 3},
702 {0x1000, 2},
703 {0x0000, 1}};
John Zhao5f16cce2015-04-02 10:24:51 -0700704
Randall Spanglerfb267152016-10-11 15:28:16 -0700705 return FindGpioChipOffsetByNumber(gpio_num, offset, data);
John Zhao5f16cce2015-04-02 10:24:51 -0700706}
707
Aaron Durbin31912b62013-12-10 14:58:03 -0800708struct GpioChipset {
Randall Spanglerfb267152016-10-11 15:28:16 -0700709 const char *name;
710 int (*ChipOffsetAndGpioNumber)(unsigned *gpio_num,
711 unsigned *chip_offset,
712 const char *name);
Aaron Durbin31912b62013-12-10 14:58:03 -0800713};
714
715static const struct GpioChipset chipsets_supported[] = {
Daniel Kurtzcf81b102017-09-26 19:28:28 -0600716 { "AMD0030", FindGpioChipOffset },
Randall Spanglerfb267152016-10-11 15:28:16 -0700717 { "NM10", FindGpioChipOffset },
718 { "CougarPoint", FindGpioChipOffset },
719 { "PantherPoint", FindGpioChipOffset },
720 { "LynxPoint", FindGpioChipOffset },
721 { "PCH-LP", FindGpioChipOffset },
722 { "INT3437:00", FindGpioChipOffsetByLabel },
723 { "INT344B:00", FindGpioChipOffsetByLabel },
724 /* INT3452 are for Apollolake */
725 { "INT3452:00", FindGpioChipOffsetByLabel },
726 { "INT3452:01", FindGpioChipOffsetByLabel },
727 { "INT3452:02", FindGpioChipOffsetByLabel },
728 { "INT3452:03", FindGpioChipOffsetByLabel },
Subrata Banik72836892018-10-30 17:18:33 +0530729 { "INT3455:00", FindGpioChipOffsetByLabel },
Vincent Palatinb739f612018-03-07 14:38:33 +0100730 { "INT34BB:00", FindGpioChipOffsetByLabel },
Usha P39e34fb2019-12-16 11:19:54 +0530731 { "INT34C8:00", FindGpioChipOffsetByLabel },
Srinidhi N Kaushik17a91172019-08-22 14:03:52 -0700732 { "INT34C5:00", FindGpioChipOffsetByLabel },
Subrata Banikb2dca282020-04-27 09:56:47 +0530733 /* INTC105x are for Alderlake */
734 { "INTC1055:00", FindGpioChipOffsetByLabel },
735 { "INTC1056:00", FindGpioChipOffsetByLabel },
Shaunak Sahaf2a16b82017-10-26 16:10:15 -0700736 /* INT3453 are for GLK */
737 { "INT3453:00", FindGpioChipOffsetByLabel },
738 { "INT3453:01", FindGpioChipOffsetByLabel },
739 { "INT3453:02", FindGpioChipOffsetByLabel },
740 { "INT3453:03", FindGpioChipOffsetByLabel },
Randall Spanglerfb267152016-10-11 15:28:16 -0700741 { "BayTrail", BayTrailFindGpioChipOffset },
742 { "Braswell", BraswellFindGpioChipOffset },
743 { NULL },
Aaron Durbin31912b62013-12-10 14:58:03 -0800744};
745
Randall Spanglerfb267152016-10-11 15:28:16 -0700746static const struct GpioChipset *FindChipset(const char *name)
747{
748 const struct GpioChipset *chipset = &chipsets_supported[0];
Aaron Durbin31912b62013-12-10 14:58:03 -0800749
Randall Spanglerfb267152016-10-11 15:28:16 -0700750 while (chipset->name != NULL) {
751 if (!strcmp(name, chipset->name))
752 return chipset;
753 chipset++;
754 }
755 return NULL;
Aaron Durbin31912b62013-12-10 14:58:03 -0800756}
757
Randall Spanglereb591952011-04-07 10:02:00 -0700758/* Read a GPIO of the specified signal type (see ACPI GPIO SignalType).
759 *
760 * Returns 1 if the signal is asserted, 0 if not asserted, or -1 if error. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700761static int ReadGpio(unsigned signal_type)
762{
763 char name[128];
764 int index = 0;
765 unsigned gpio_type;
766 unsigned active_high;
767 unsigned controller_num;
768 unsigned controller_offset = 0;
769 char controller_name[128];
770 unsigned value;
771 const struct GpioChipset *chipset;
Randall Spanglereb591952011-04-07 10:02:00 -0700772
Randall Spanglerfb267152016-10-11 15:28:16 -0700773 /* Scan GPIO.* to find a matching signal type */
774 for (index = 0; ; index++) {
775 snprintf(name, sizeof(name), "%s.%d/GPIO.0", ACPI_GPIO_PATH,
776 index);
777 if (ReadFileInt(name, &gpio_type) < 0)
778 return -1; /* Ran out of GPIOs before finding a match */
779 if (gpio_type == signal_type)
780 break;
781 }
Randall Spanglereb591952011-04-07 10:02:00 -0700782
Randall Spanglerfb267152016-10-11 15:28:16 -0700783 /* Read attributes and controller info for the GPIO */
784 snprintf(name, sizeof(name), "%s.%d/GPIO.1", ACPI_GPIO_PATH, index);
785 if (ReadFileInt(name, &active_high) < 0)
786 return -1;
787 snprintf(name, sizeof(name), "%s.%d/GPIO.2", ACPI_GPIO_PATH, index);
788 if (ReadFileInt(name, &controller_num) < 0)
789 return -1;
790 /* Do not attempt to read GPIO that is set to -1 in ACPI */
791 if (controller_num == 0xFFFFFFFF)
792 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700793
Randall Spanglerfb267152016-10-11 15:28:16 -0700794 /* Check for chipsets we recognize. */
795 snprintf(name, sizeof(name), "%s.%d/GPIO.3", ACPI_GPIO_PATH, index);
796 if (!ReadFileString(controller_name, sizeof(controller_name), name))
797 return -1;
798 chipset = FindChipset(controller_name);
799 if (chipset == NULL)
800 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700801
Randall Spanglerfb267152016-10-11 15:28:16 -0700802 /* Modify GPIO number by driver's offset */
803 if (!chipset->ChipOffsetAndGpioNumber(&controller_num,
804 &controller_offset,
805 chipset->name))
806 return -1;
807 controller_offset += controller_num;
Randall Spanglereb591952011-04-07 10:02:00 -0700808
Randall Spanglerfb267152016-10-11 15:28:16 -0700809 /* Try reading the GPIO value */
810 snprintf(name, sizeof(name), "%s/gpio%d/value",
811 GPIO_BASE_PATH, controller_offset);
812 if (ReadFileInt(name, &value) < 0) {
813 /* Try exporting the GPIO */
814 FILE* f = fopen(GPIO_EXPORT_PATH, "wt");
815 if (!f)
816 return -1;
817 fprintf(f, "%u", controller_offset);
818 fclose(f);
Randall Spanglereb591952011-04-07 10:02:00 -0700819
Randall Spanglerfb267152016-10-11 15:28:16 -0700820 /* Try re-reading the GPIO value */
821 if (ReadFileInt(name, &value) < 0)
822 return -1;
823 }
Randall Spanglereb591952011-04-07 10:02:00 -0700824
Randall Spanglerfb267152016-10-11 15:28:16 -0700825 /* Normalize the value read from the kernel in case it is not always
826 * 1. */
827 value = value ? 1 : 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700828
Randall Spanglerfb267152016-10-11 15:28:16 -0700829 /* Compare the GPIO value with the active value and return 1 if
830 * match. */
831 return (value == active_high ? 1 : 0);
Randall Spanglereb591952011-04-07 10:02:00 -0700832}
833
834
Randall Spanglerfb267152016-10-11 15:28:16 -0700835int VbGetArchPropertyInt(const char* name)
836{
837 int value = -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700838
Randall Spanglerfb267152016-10-11 15:28:16 -0700839 /* Switch positions */
840 if (!strcasecmp(name,"devsw_cur")) {
841 /* Systems with virtual developer switches return at-boot
842 * value */
Joel Kitchinge1761d62019-03-18 16:36:36 +0800843 value = VbGetSystemPropertyInt("devsw_boot");
Randall Spanglerfb267152016-10-11 15:28:16 -0700844 } else if (!strcasecmp(name,"recoverysw_cur")) {
845 value = ReadGpio(GPIO_SIGNAL_TYPE_RECOVERY);
846 } else if (!strcasecmp(name,"wpsw_cur")) {
847 value = ReadGpio(GPIO_SIGNAL_TYPE_WP);
Randall Spanglerfb267152016-10-11 15:28:16 -0700848 } else if (!strcasecmp(name,"recoverysw_ec_boot")) {
849 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_EC_BOOT);
Aaron Durbin8bb1c3b2016-12-12 14:15:12 -0600850 } else if (!strcasecmp(name,"phase_enforcement")) {
851 value = ReadGpio(GPIO_SIGNAL_TYPE_PHASE_ENFORCEMENT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700852 }
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700853
Randall Spanglerfb267152016-10-11 15:28:16 -0700854 /* Fields for old systems which don't have VbSharedData */
855 if (VbSharedDataVersion() < 2) {
856 if (!strcasecmp(name,"recovery_reason")) {
857 value = VbGetRecoveryReason();
858 } else if (!strcasecmp(name,"devsw_boot")) {
859 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT);
860 } else if (!strcasecmp(name,"recoverysw_boot")) {
861 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_BOOT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700862 }
863 }
Randall Spanglereb591952011-04-07 10:02:00 -0700864
Randall Spanglerfb267152016-10-11 15:28:16 -0700865 /* NV storage values. If unable to get from NV storage, fall back to
866 * the CMOS reboot field used by older BIOS (e.g. Mario). */
867 if (!strcasecmp(name,"recovery_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800868 value = vb2_get_nv_storage(VB2_NV_RECOVERY_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700869 if (-1 == value)
870 value = VbGetCmosRebootField(CMOSRF_RECOVERY);
871 } else if (!strcasecmp(name,"dbg_reset")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800872 value = vb2_get_nv_storage(VB2_NV_DEBUG_RESET_MODE);
Randall Spanglerfb267152016-10-11 15:28:16 -0700873 if (-1 == value)
874 value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET);
875 } else if (!strcasecmp(name,"fwb_tries")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800876 value = vb2_get_nv_storage(VB2_NV_TRY_COUNT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700877 if (-1 == value)
878 value = VbGetCmosRebootField(CMOSRF_TRY_B);
879 }
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700880
Randall Spanglerfb267152016-10-11 15:28:16 -0700881 /* Firmware update tries is now stored in the kernel field. On
882 * older systems where it's not, it was stored in a file in the
883 * stateful partition. */
884 if (!strcasecmp(name,"fwupdate_tries")) {
885 unsigned fwupdate_value;
Randall Spanglerdff58522017-11-27 15:37:13 -0800886 if (-1 != vb2_get_nv_storage(VB2_NV_KERNEL_FIELD))
Randall Spanglerfb267152016-10-11 15:28:16 -0700887 return -1; /* NvStorage supported; fail through
888 * arch-specific implementation to normal
889 * implementation. */
890 /* Read value from file; missing file means value=0. */
891 if (ReadFileInt(NEED_FWUPDATE_PATH, &fwupdate_value) < 0)
892 value = 0;
893 else
894 value = (int)fwupdate_value;
895 }
Randall Spanglereb591952011-04-07 10:02:00 -0700896
Randall Spanglerfb267152016-10-11 15:28:16 -0700897 return value;
Randall Spanglereb591952011-04-07 10:02:00 -0700898}
899
900
J. Richard Barnettea3d70a32013-10-30 11:36:45 -0700901const char* VbGetArchPropertyString(const char* name, char* dest,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800902 size_t size)
Randall Spanglerfb267152016-10-11 15:28:16 -0700903{
904 unsigned value;
Randall Spanglereb591952011-04-07 10:02:00 -0700905
Randall Spanglerfb267152016-10-11 15:28:16 -0700906 if (!strcasecmp(name,"arch")) {
907 return StrCopy(dest, "x86", size);
908 } else if (!strcasecmp(name,"hwid")) {
909 return ReadFileString(dest, size, ACPI_BASE_PATH "/HWID");
910 } else if (!strcasecmp(name,"fwid")) {
911 return ReadFileString(dest, size, ACPI_BASE_PATH "/FWID");
912 } else if (!strcasecmp(name,"ro_fwid")) {
913 return ReadFileString(dest, size, ACPI_BASE_PATH "/FRID");
914 } else if (!strcasecmp(name,"mainfw_act")) {
915 if (ReadFileInt(ACPI_BINF_PATH ".1", &value) < 0)
916 return NULL;
917 switch(value) {
918 case 0:
919 return StrCopy(dest, "recovery", size);
920 case 1:
921 return StrCopy(dest, "A", size);
922 case 2:
923 return StrCopy(dest, "B", size);
924 default:
925 return NULL;
926 }
927 } else if (!strcasecmp(name,"mainfw_type")) {
928 return VbReadMainFwType(dest, size);
929 } else if (!strcasecmp(name,"ecfw_act")) {
930 if (ReadFileInt(ACPI_BINF_PATH ".2", &value) < 0)
931 return NULL;
932 switch(value) {
933 case 0:
934 return StrCopy(dest, "RO", size);
935 case 1:
936 return StrCopy(dest, "RW", size);
937 default:
938 return NULL;
939 }
940 }
Randall Spanglereb591952011-04-07 10:02:00 -0700941
Randall Spanglerfb267152016-10-11 15:28:16 -0700942 return NULL;
Randall Spanglereb591952011-04-07 10:02:00 -0700943}
944
945
Randall Spanglerfb267152016-10-11 15:28:16 -0700946int VbSetArchPropertyInt(const char* name, int value)
947{
948 /* NV storage values. If unable to get from NV storage, fall back to
949 * the CMOS reboot field used by older BIOS. */
950 if (!strcasecmp(name,"recovery_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800951 if (0 == vb2_set_nv_storage(VB2_NV_RECOVERY_REQUEST, value))
Randall Spanglerfb267152016-10-11 15:28:16 -0700952 return 0;
953 return VbSetCmosRebootField(CMOSRF_RECOVERY, value);
954 } else if (!strcasecmp(name,"dbg_reset")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800955 if (0 == vb2_set_nv_storage(VB2_NV_DEBUG_RESET_MODE, value))
Randall Spanglerfb267152016-10-11 15:28:16 -0700956 return 0;
957 return VbSetCmosRebootField(CMOSRF_DEBUG_RESET, value);
958 } else if (!strcasecmp(name,"fwb_tries")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800959 if (0 == vb2_set_nv_storage(VB2_NV_TRY_COUNT, value))
Randall Spanglerfb267152016-10-11 15:28:16 -0700960 return 0;
961 return VbSetCmosRebootField(CMOSRF_TRY_B, value);
962 }
963 /* Firmware update tries is now stored in the kernel field. On
964 * older systems where it's not, it was stored in a file in the
965 * stateful partition. */
966 else if (!strcasecmp(name,"fwupdate_tries")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800967 if (-1 != vb2_get_nv_storage(VB2_NV_KERNEL_FIELD))
Randall Spanglerfb267152016-10-11 15:28:16 -0700968 return -1; /* NvStorage supported; fail through
969 * arch-specific implementation to normal
970 * implementation */
Randall Spangler07f34842011-04-11 13:35:06 -0700971
Randall Spanglerfb267152016-10-11 15:28:16 -0700972 if (value) {
973 char buf[32];
974 snprintf(buf, sizeof(buf), "%d", value);
975 return WriteFile(NEED_FWUPDATE_PATH, buf, strlen(buf));
976 } else {
977 /* No update tries, so remove file if it exists. */
978 unlink(NEED_FWUPDATE_PATH);
979 return 0;
980 }
981 }
Randall Spanglereb591952011-04-07 10:02:00 -0700982
Randall Spanglerfb267152016-10-11 15:28:16 -0700983 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700984}
985
Randall Spanglerfb267152016-10-11 15:28:16 -0700986int VbSetArchPropertyString(const char* name, const char* value)
987{
988 /* If there were settable architecture-dependent string properties,
989 * they'd be here. */
990 return -1;
Randall Spanglereb591952011-04-07 10:02:00 -0700991}