blob: c126707cd58fd42b68c5ae9016831373589da296 [file] [log] [blame]
Randall Spanglerc0e37422012-06-08 12:30:17 -07001/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Randall Spangler54218662011-02-07 11:20:20 -08002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
J. Richard Barnettea3d70a32013-10-30 11:36:45 -07006#include <stddef.h>
Randall Spangler54218662011-02-07 11:20:20 -08007#include <stdio.h>
8#include <string.h>
Vadim Bendebury20084232011-03-15 09:29:48 -07009#include <sys/types.h>
10#include <sys/stat.h>
11#include <unistd.h>
12#include <ctype.h>
Duncan Lauriee98431f2016-03-30 09:35:20 -070013#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/wait.h>
16#include <fcntl.h>
17#include <unistd.h>
Randall Spangler54218662011-02-07 11:20:20 -080018
Randall Spanglerdff58522017-11-27 15:37:13 -080019#include "2api.h"
Joel Kitching98b00ae2019-06-25 16:11:45 +080020#include "2common.h"
Randall Spanglerdff58522017-11-27 15:37:13 -080021#include "2nvstorage.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +080022#include "2sysincludes.h"
Randall Spanglereb591952011-04-07 10:02:00 -070023#include "crossystem_arch.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +080024#include "crossystem.h"
Duncan Lauriee98431f2016-03-30 09:35:20 -070025#include "crossystem_vbnv.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +080026#include "host_common.h"
Randall Spangler54218662011-02-07 11:20:20 -080027#include "utility.h"
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070028#include "vboot_struct.h"
Randall Spangler54218662011-02-07 11:20:20 -080029
Randall Spangler196e1772011-03-10 11:31:06 -080030/* Filename for kernel command line */
31#define KERNEL_CMDLINE_PATH "/proc/cmdline"
32
Jack Rosenthalfde6a342019-12-03 14:53:27 -070033#define MOSYS_PATH "/usr/sbin/mosys"
Duncan Lauriee98431f2016-03-30 09:35:20 -070034
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070035/* Fields that GetVdatString() can get */
36typedef enum VdatStringField {
Joel Kitching77dff642019-10-14 23:14:59 +080037 VDAT_STRING_DEPRECATED_TIMERS = 0, /* Timer values */
Randall Spanglerfb267152016-10-11 15:28:16 -070038 VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */
39 VDAT_STRING_LOAD_KERNEL_DEBUG, /* LoadKernel() debug information */
40 VDAT_STRING_MAINFW_ACT /* Active main firmware */
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070041} VdatStringField;
42
43
44/* Fields that GetVdatInt() can get */
45typedef enum VdatIntField {
Randall Spanglerfb267152016-10-11 15:28:16 -070046 VDAT_INT_FLAGS = 0, /* Flags */
47 VDAT_INT_HEADER_VERSION, /* Header version for VbSharedData */
48 VDAT_INT_DEVSW_BOOT, /* Dev switch position at boot */
Joel Kitchingf9a2fa12019-03-18 16:46:39 +080049 VDAT_INT_DEPRECATED_DEVSW_VIRTUAL, /* Dev switch is virtual;
50 * deprecated: chromium:942901 */
Randall Spanglerfb267152016-10-11 15:28:16 -070051 VDAT_INT_RECSW_BOOT, /* Recovery switch position at boot */
Tudor Brindusc2393742018-07-31 16:25:26 -070052 VDAT_INT_RECSW_VIRTUAL, /* Recovery switch is virtual */
Randall Spanglerfb267152016-10-11 15:28:16 -070053 VDAT_INT_HW_WPSW_BOOT, /* Hardware WP switch position at boot */
Randall Spanglerda8d32d2012-08-03 12:48:24 -070054
Randall Spanglerfb267152016-10-11 15:28:16 -070055 VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
56 VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */
57 VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */
58 VDAT_INT_KERNEL_KEY_VERIFIED, /* Kernel key verified using
59 * signature, not just hash */
60 VDAT_INT_RECOVERY_REASON, /* Recovery reason for current boot */
61 VDAT_INT_FW_BOOT2 /* Firmware selection by vboot2 */
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070062} VdatIntField;
63
64
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070065/* Description of build options that may be specified on the
66 * kernel command line. */
67typedef enum VbBuildOption {
Randall Spanglerfb267152016-10-11 15:28:16 -070068 VB_BUILD_OPTION_UNKNOWN,
69 VB_BUILD_OPTION_DEBUG,
70 VB_BUILD_OPTION_NODEBUG
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070071} VbBuildOption;
72
Randall Spangler9e1da782014-06-24 15:31:04 -070073static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
Mary Ruthven12a55f22015-10-06 10:42:31 -070074static const char *default_boot[] = {"disk", "usb", "legacy"};
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070075
Randall Spanglerff3f0002011-07-26 10:43:53 -070076/* Masks for kern_nv usage by kernel. */
Randall Spangler4aaaeca2017-10-20 12:38:40 -070077#define KERN_NV_FWUPDATE_TRIES_MASK 0x000F
78#define KERN_NV_BLOCK_DEVMODE_FLAG 0x0010
79#define KERN_NV_TPM_ATTACK_FLAG 0x0020
Randall Spanglerff3f0002011-07-26 10:43:53 -070080/* If you want to use the remaining currently-unused bits in kern_nv
81 * for something kernel-y, define a new field (the way we did for
82 * fwupdate_tries). Don't just modify kern_nv directly, because that
83 * makes it too easy to accidentally corrupt other sub-fields. */
Randall Spangler4aaaeca2017-10-20 12:38:40 -070084#define KERN_NV_CURRENTLY_UNUSED 0xFFC0
Randall Spanglerd7728232011-04-08 14:04:21 -070085
Randall Spanglerc80fe652011-02-17 11:06:47 -080086/* Return true if the FWID starts with the specified string. */
Randall Spanglerfb267152016-10-11 15:28:16 -070087int FwidStartsWith(const char *start)
88{
89 char fwid[VB_MAX_STRING_PROPERTY];
90 if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid)))
91 return 0;
Randall Spanglerc80fe652011-02-17 11:06:47 -080092
Randall Spanglerfb267152016-10-11 15:28:16 -070093 return 0 == strncmp(fwid, start, strlen(start));
Randall Spanglerc80fe652011-02-17 11:06:47 -080094}
95
Julius Werner49428f42019-11-14 09:48:34 -080096static struct vb2_context *get_fake_context(void)
97{
98 static uint8_t fake_workbuf[sizeof(struct vb2_shared_data) + 16]
99 __attribute__((aligned(VB2_WORKBUF_ALIGN)));
100 static struct vb2_context *fake_ctx;
101
102 if (fake_ctx)
103 return fake_ctx;
104
105 vb2api_init(fake_workbuf, sizeof(fake_workbuf), &fake_ctx);
106
107 return fake_ctx;
108}
109
Vadim Bendebury38201fe2014-11-07 17:25:09 -0800110static int vnc_read;
Randall Spanglerc80fe652011-02-17 11:06:47 -0800111
Randall Spanglerdff58522017-11-27 15:37:13 -0800112int vb2_get_nv_storage(enum vb2_nv_param param)
Randall Spanglerfb267152016-10-11 15:28:16 -0700113{
Randall Spanglera80a79f2018-02-26 17:01:24 -0800114 VbSharedDataHeader* sh = VbSharedDataRead();
Julius Werner49428f42019-11-14 09:48:34 -0800115 struct vb2_context *ctx = get_fake_context();
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800116
Patrick Georgid12e6da2019-08-27 17:18:03 +0200117 if (!sh)
118 return -1;
119
Randall Spanglerfb267152016-10-11 15:28:16 -0700120 /* TODO: locking around NV access */
121 if (!vnc_read) {
Randall Spangler0bdb8712018-03-07 21:06:15 -0800122 if (sh && sh->flags & VBSD_NVDATA_V2)
Julius Werner49428f42019-11-14 09:48:34 -0800123 ctx->flags |= VB2_CONTEXT_NVDATA_V2;
124 if (0 != vb2_read_nv_storage(ctx)) {
Patrick Georgid12e6da2019-08-27 17:18:03 +0200125 free(sh);
Randall Spanglerfb267152016-10-11 15:28:16 -0700126 return -1;
Patrick Georgid12e6da2019-08-27 17:18:03 +0200127 }
Julius Werner49428f42019-11-14 09:48:34 -0800128 vb2_nv_init(ctx);
Randall Spanglerdff58522017-11-27 15:37:13 -0800129
130 /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write
131 * and save the new defaults. If we're able to, log. */
132
Randall Spanglerfb267152016-10-11 15:28:16 -0700133 vnc_read = 1;
134 }
Randall Spanglereb591952011-04-07 10:02:00 -0700135
Patrick Georgid12e6da2019-08-27 17:18:03 +0200136 free(sh);
Julius Werner49428f42019-11-14 09:48:34 -0800137 return (int)vb2_nv_get(ctx, param);
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800138}
139
Randall Spanglerdff58522017-11-27 15:37:13 -0800140int vb2_set_nv_storage(enum vb2_nv_param param, int value)
Randall Spanglerfb267152016-10-11 15:28:16 -0700141{
Randall Spanglera80a79f2018-02-26 17:01:24 -0800142 VbSharedDataHeader* sh = VbSharedDataRead();
Julius Werner49428f42019-11-14 09:48:34 -0800143 struct vb2_context *ctx = get_fake_context();
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800144
Patrick Georgid12e6da2019-08-27 17:18:03 +0200145 if (!sh)
146 return -1;
147
Randall Spanglerdff58522017-11-27 15:37:13 -0800148 /* TODO: locking around NV access */
Randall Spangler0bdb8712018-03-07 21:06:15 -0800149 if (sh && sh->flags & VBSD_NVDATA_V2)
Julius Werner49428f42019-11-14 09:48:34 -0800150 ctx->flags |= VB2_CONTEXT_NVDATA_V2;
151 if (0 != vb2_read_nv_storage(ctx)) {
Patrick Georgid12e6da2019-08-27 17:18:03 +0200152 free(sh);
Randall Spanglerfb267152016-10-11 15:28:16 -0700153 return -1;
Patrick Georgid12e6da2019-08-27 17:18:03 +0200154 }
Julius Werner49428f42019-11-14 09:48:34 -0800155 vb2_nv_init(ctx);
156 vb2_nv_set(ctx, param, (uint32_t)value);
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800157
Julius Werner49428f42019-11-14 09:48:34 -0800158 if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
Randall Spanglerfb267152016-10-11 15:28:16 -0700159 vnc_read = 0;
Julius Werner49428f42019-11-14 09:48:34 -0800160 if (0 != vb2_write_nv_storage(ctx)) {
Patrick Georgid12e6da2019-08-27 17:18:03 +0200161 free(sh);
Randall Spanglerdff58522017-11-27 15:37:13 -0800162 return -1;
Patrick Georgid12e6da2019-08-27 17:18:03 +0200163 }
Randall Spanglerfb267152016-10-11 15:28:16 -0700164 }
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800165
Randall Spanglerfb267152016-10-11 15:28:16 -0700166 /* Success */
Patrick Georgid12e6da2019-08-27 17:18:03 +0200167 free(sh);
Randall Spanglerdff58522017-11-27 15:37:13 -0800168 return 0;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800169}
170
Bill Richardsonb64f0972014-05-28 15:49:23 -0700171/*
Randall Spanglerdff58522017-11-27 15:37:13 -0800172 * Set a param value, and try to flag it for persistent backup. It's okay if
173 * backup isn't supported (which it isn't, in current designs). It's
174 * best-effort only.
Bill Richardsonb64f0972014-05-28 15:49:23 -0700175 */
Randall Spanglerdff58522017-11-27 15:37:13 -0800176static int vb2_set_nv_storage_with_backup(enum vb2_nv_param param, int value)
Bill Richardsonb64f0972014-05-28 15:49:23 -0700177{
Randall Spanglerfb267152016-10-11 15:28:16 -0700178 int retval;
Randall Spanglerdff58522017-11-27 15:37:13 -0800179 retval = vb2_set_nv_storage(param, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700180 if (!retval)
Randall Spanglerdff58522017-11-27 15:37:13 -0800181 vb2_set_nv_storage(VB2_NV_BACKUP_NVRAM_REQUEST, 1);
Randall Spanglerfb267152016-10-11 15:28:16 -0700182 return retval;
Bill Richardsonb64f0972014-05-28 15:49:23 -0700183}
184
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700185/* Find what build/debug status is specified on the kernel command
186 * line, if any. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700187static VbBuildOption VbScanBuildOption(void)
188{
189 FILE* f = NULL;
190 char buf[4096] = "";
191 char *t, *saveptr;
192 const char *delimiters = " \r\n";
Randall Spangler196e1772011-03-10 11:31:06 -0800193
Randall Spanglerfb267152016-10-11 15:28:16 -0700194 f = fopen(KERNEL_CMDLINE_PATH, "r");
195 if (NULL != f) {
196 if (NULL == fgets(buf, sizeof(buf), f))
197 buf[0] = 0;
198 fclose(f);
199 }
200 for (t = strtok_r(buf, delimiters, &saveptr); t;
201 t = strtok_r(NULL, delimiters, &saveptr)) {
202 if (0 == strcmp(t, "cros_debug"))
203 return VB_BUILD_OPTION_DEBUG;
204 else if (0 == strcmp(t, "cros_nodebug"))
205 return VB_BUILD_OPTION_NODEBUG;
206 }
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700207
Randall Spanglerfb267152016-10-11 15:28:16 -0700208 return VB_BUILD_OPTION_UNKNOWN;
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700209}
210
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700211/* Determine whether the running OS image was built for debugging.
212 * Returns 1 if yes, 0 if no or indeterminate. */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800213static vb2_error_t VbGetDebugBuild(void)
Randall Spanglerfb267152016-10-11 15:28:16 -0700214{
215 return VB_BUILD_OPTION_DEBUG == VbScanBuildOption();
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700216}
217
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700218/* Determine whether OS-level debugging should be allowed.
219 * Returns 1 if yes, 0 if no or indeterminate. */
Julius Werner52fa8c12019-05-07 12:59:47 -0700220static int VbGetCrosDebug(void)
Randall Spanglerfb267152016-10-11 15:28:16 -0700221{
222 /* If the currently running system specifies its debug status, use
223 * that in preference to other indicators. */
224 VbBuildOption option = VbScanBuildOption();
225 if (VB_BUILD_OPTION_DEBUG == option) {
226 return 1;
227 } else if (VB_BUILD_OPTION_NODEBUG == option) {
228 return 0;
229 }
Randall Spangler196e1772011-03-10 11:31:06 -0800230
Randall Spanglerfb267152016-10-11 15:28:16 -0700231 /* Command line is silent; allow debug if the dev switch is on. */
232 if (1 == VbGetSystemPropertyInt("devsw_boot"))
233 return 1;
Randall Spangler196e1772011-03-10 11:31:06 -0800234
Randall Spanglerfb267152016-10-11 15:28:16 -0700235 /* All other cases disallow debug. */
236 return 0;
Randall Spangler196e1772011-03-10 11:31:06 -0800237}
238
Julius Werner52fa8c12019-05-07 12:59:47 -0700239static char *GetVdatLoadFirmwareDebug(char *dest, int size,
240 const VbSharedDataHeader *sh)
Randall Spanglerfb267152016-10-11 15:28:16 -0700241{
242 snprintf(dest, size,
243 "Check A result=%d\n"
244 "Check B result=%d\n"
245 "Firmware index booted=0x%02x\n"
246 "TPM combined version at start=0x%08x\n"
247 "Lowest combined version from firmware=0x%08x\n",
248 sh->check_fw_a_result,
249 sh->check_fw_b_result,
250 sh->firmware_index,
251 sh->fw_version_tpm_start,
252 sh->fw_version_lowest);
253 return dest;
Randall Spangler71415712011-03-21 11:04:50 -0700254}
255
Randall Spangler71415712011-03-21 11:04:50 -0700256#define TRUNCATED "\n(truncated)\n"
257
Julius Werner52fa8c12019-05-07 12:59:47 -0700258static char *GetVdatLoadKernelDebug(char *dest, int size,
259 const VbSharedDataHeader *sh)
Randall Spanglerfb267152016-10-11 15:28:16 -0700260{
261 int used = 0;
262 int first_call_tracked = 0;
263 int call;
Randall Spangler71415712011-03-21 11:04:50 -0700264
Randall Spanglerfb267152016-10-11 15:28:16 -0700265 /* Make sure we have space for truncation warning */
266 if (size < strlen(TRUNCATED) + 1)
267 return NULL;
268 size -= strlen(TRUNCATED) + 1;
Randall Spangler71415712011-03-21 11:04:50 -0700269
Randall Spanglerfb267152016-10-11 15:28:16 -0700270 used += snprintf(
271 dest + used, size - used,
272 "Calls to LoadKernel()=%d\n",
273 sh->lk_call_count);
274 if (used > size)
275 goto LoadKernelDebugExit;
Randall Spangler71415712011-03-21 11:04:50 -0700276
Randall Spanglerfb267152016-10-11 15:28:16 -0700277 /* Report on the last calls */
278 if (sh->lk_call_count > VBSD_MAX_KERNEL_CALLS)
279 first_call_tracked = sh->lk_call_count - VBSD_MAX_KERNEL_CALLS;
280 for (call = first_call_tracked; call < sh->lk_call_count; call++) {
281 const VbSharedDataKernelCall* shc = sh->lk_calls +
282 (call & (VBSD_MAX_KERNEL_CALLS - 1));
283 int first_part_tracked = 0;
284 int part;
Randall Spangler71415712011-03-21 11:04:50 -0700285
Randall Spanglerfb267152016-10-11 15:28:16 -0700286 used += snprintf(dest + used, size - used,
287 "Call %d:\n"
288 " Boot flags=0x%02x\n"
289 " Boot mode=%d\n"
290 " Test error=%d\n"
291 " Return code=%d\n"
292 " Debug flags=0x%02x\n"
293 " Drive sectors=%" PRIu64 "\n"
294 " Sector size=%d\n"
295 " Check result=%d\n"
296 " Kernel partitions found=%d\n",
297 call + 1,
298 shc->boot_flags,
299 shc->boot_mode,
300 shc->test_error_num,
301 shc->return_code,
302 shc->flags,
303 shc->sector_count,
304 shc->sector_size,
305 shc->check_result,
306 shc->kernel_parts_found);
307 if (used > size)
308 goto LoadKernelDebugExit;
Randall Spangler71415712011-03-21 11:04:50 -0700309
Randall Spanglerfb267152016-10-11 15:28:16 -0700310 /* If we found too many partitions, only prints ones where the
311 * structure has info. */
312 if (shc->kernel_parts_found > VBSD_MAX_KERNEL_PARTS)
313 first_part_tracked = shc->kernel_parts_found -
314 VBSD_MAX_KERNEL_PARTS;
Randall Spangler71415712011-03-21 11:04:50 -0700315
Randall Spanglerfb267152016-10-11 15:28:16 -0700316 /* Report on the partitions checked */
317 for (part = first_part_tracked; part < shc->kernel_parts_found;
318 part++) {
319 const VbSharedDataKernelPart* shp = shc->parts +
320 (part & (VBSD_MAX_KERNEL_PARTS - 1));
Randall Spangler71415712011-03-21 11:04:50 -0700321
Randall Spanglerfb267152016-10-11 15:28:16 -0700322 used += snprintf(dest + used, size - used,
323 " Kernel %d:\n"
324 " GPT index=%d\n"
325 " Start sector=%" PRIu64 "\n"
326 " Sector count=%" PRIu64 "\n"
327 " Combined version=0x%08x\n"
328 " Check result=%d\n"
329 " Debug flags=0x%02x\n",
330 part + 1,
331 shp->gpt_index,
332 shp->sector_start,
333 shp->sector_count,
334 shp->combined_version,
335 shp->check_result,
336 shp->flags);
337 if (used > size)
338 goto LoadKernelDebugExit;
339 }
340 }
Randall Spangler71415712011-03-21 11:04:50 -0700341
342LoadKernelDebugExit:
343
Randall Spanglerfb267152016-10-11 15:28:16 -0700344 /* Warn if data was truncated; we left space for this above. */
345 if (used > size)
346 strcat(dest, TRUNCATED);
Randall Spangler71415712011-03-21 11:04:50 -0700347
Randall Spanglerfb267152016-10-11 15:28:16 -0700348 return dest;
Randall Spangler71415712011-03-21 11:04:50 -0700349}
350
Julius Werner52fa8c12019-05-07 12:59:47 -0700351static char *GetVdatString(char *dest, int size, VdatStringField field)
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700352{
Randall Spanglerfb267152016-10-11 15:28:16 -0700353 VbSharedDataHeader *sh = VbSharedDataRead();
354 char *value = dest;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700355
Randall Spanglerfb267152016-10-11 15:28:16 -0700356 if (!sh)
357 return NULL;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700358
Randall Spanglerfb267152016-10-11 15:28:16 -0700359 switch (field) {
Randall Spanglerfb267152016-10-11 15:28:16 -0700360 case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
361 value = GetVdatLoadFirmwareDebug(dest, size, sh);
362 break;
Randall Spangler71415712011-03-21 11:04:50 -0700363
Randall Spanglerfb267152016-10-11 15:28:16 -0700364 case VDAT_STRING_LOAD_KERNEL_DEBUG:
365 value = GetVdatLoadKernelDebug(dest, size, sh);
366 break;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700367
Randall Spanglerfb267152016-10-11 15:28:16 -0700368 case VDAT_STRING_MAINFW_ACT:
369 switch(sh->firmware_index) {
370 case 0:
371 StrCopy(dest, "A", size);
372 break;
373 case 1:
374 StrCopy(dest, "B", size);
375 break;
376 case 0xFF:
377 StrCopy(dest, "recovery", size);
378 break;
379 default:
380 value = NULL;
381 }
382 break;
Randall Spanglera185b8d2011-07-15 16:28:38 -0700383
Randall Spanglerfb267152016-10-11 15:28:16 -0700384 default:
385 value = NULL;
386 break;
387 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700388
Randall Spanglerfb267152016-10-11 15:28:16 -0700389 free(sh);
390 return value;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700391}
392
Julius Werner52fa8c12019-05-07 12:59:47 -0700393static int GetVdatInt(VdatIntField field)
Randall Spanglerfb267152016-10-11 15:28:16 -0700394{
395 VbSharedDataHeader* sh = VbSharedDataRead();
396 int value = -1;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700397
Randall Spanglerfb267152016-10-11 15:28:16 -0700398 if (!sh)
399 return -1;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700400
Randall Spanglerfb267152016-10-11 15:28:16 -0700401 /* Fields supported in version 1 */
402 switch (field) {
403 case VDAT_INT_FLAGS:
404 value = (int)sh->flags;
405 break;
406 case VDAT_INT_HEADER_VERSION:
407 value = sh->struct_version;
408 break;
409 case VDAT_INT_TRIED_FIRMWARE_B:
Joel Kitching3c001802019-10-02 12:53:21 +0800410 value = (sh->flags & VBSD_DEPRECATED_FWB_TRIED ? 1 : 0);
Randall Spanglerfb267152016-10-11 15:28:16 -0700411 break;
412 case VDAT_INT_KERNEL_KEY_VERIFIED:
413 value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
414 break;
415 case VDAT_INT_FW_VERSION_TPM:
416 value = (int)sh->fw_version_tpm;
417 break;
418 case VDAT_INT_KERNEL_VERSION_TPM:
419 value = (int)sh->kernel_version_tpm;
420 break;
421 case VDAT_INT_FW_BOOT2:
422 value = (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2 ? 1 : 0);
Mathew Kinged8390e2019-11-05 22:21:33 +0000423 VBOOT_FALLTHROUGH;
Randall Spanglerfb267152016-10-11 15:28:16 -0700424 default:
425 break;
426 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700427
Randall Spanglerfb267152016-10-11 15:28:16 -0700428 /* Fields added in struct version 2 */
429 if (sh->struct_version >= 2) {
430 switch(field) {
431 case VDAT_INT_DEVSW_BOOT:
432 value = (sh->flags &
433 VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
434 break;
Randall Spanglerfb267152016-10-11 15:28:16 -0700435 case VDAT_INT_RECSW_BOOT:
436 value = (sh->flags &
437 VBSD_BOOT_REC_SWITCH_ON ? 1 : 0);
438 break;
Tudor Brindusc2393742018-07-31 16:25:26 -0700439 case VDAT_INT_RECSW_VIRTUAL:
440 value = (sh->flags &
441 VBSD_BOOT_REC_SWITCH_VIRTUAL ? 1 : 0);
442 break;
Randall Spanglerfb267152016-10-11 15:28:16 -0700443 case VDAT_INT_HW_WPSW_BOOT:
444 value = (sh->flags &
445 VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0);
446 break;
Randall Spanglerfb267152016-10-11 15:28:16 -0700447 case VDAT_INT_RECOVERY_REASON:
448 value = sh->recovery_reason;
449 break;
450 default:
451 break;
452 }
453 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700454
Randall Spanglerfb267152016-10-11 15:28:16 -0700455 free(sh);
456 return value;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700457}
458
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700459/* Return version of VbSharedData struct or -1 if not found. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700460int VbSharedDataVersion(void)
461{
462 return GetVdatInt(VDAT_INT_HEADER_VERSION);
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700463}
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700464
Randall Spanglerfb267152016-10-11 15:28:16 -0700465int VbGetSystemPropertyInt(const char *name)
466{
467 int value = -1;
Randall Spangler54218662011-02-07 11:20:20 -0800468
Randall Spanglerfb267152016-10-11 15:28:16 -0700469 /* Check architecture-dependent properties first */
470 value = VbGetArchPropertyInt(name);
471 if (-1 != value)
472 return value;
Randall Spanglereb591952011-04-07 10:02:00 -0700473
Randall Spanglerfb267152016-10-11 15:28:16 -0700474 /* NV storage values */
475 else if (!strcasecmp(name,"kern_nv")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800476 value = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700477 } else if (!strcasecmp(name,"nvram_cleared")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800478 value = vb2_get_nv_storage(VB2_NV_KERNEL_SETTINGS_RESET);
Randall Spanglerfb267152016-10-11 15:28:16 -0700479 } else if (!strcasecmp(name,"recovery_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800480 value = vb2_get_nv_storage(VB2_NV_RECOVERY_REQUEST);
Matt Delco90a95ea2019-03-05 16:54:23 -0800481 } else if (!strcasecmp(name,"diagnostic_request")) {
482 value = vb2_get_nv_storage(VB2_NV_DIAG_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700483 } else if (!strcasecmp(name,"dbg_reset")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800484 value = vb2_get_nv_storage(VB2_NV_DEBUG_RESET_MODE);
Randall Spanglerfb267152016-10-11 15:28:16 -0700485 } else if (!strcasecmp(name,"disable_dev_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800486 value = vb2_get_nv_storage(VB2_NV_DISABLE_DEV_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700487 } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800488 value = vb2_get_nv_storage(VB2_NV_CLEAR_TPM_OWNER_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700489 } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800490 value = vb2_get_nv_storage(VB2_NV_CLEAR_TPM_OWNER_DONE);
Randall Spanglerfb267152016-10-11 15:28:16 -0700491 } else if (!strcasecmp(name,"tpm_rebooted")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800492 value = vb2_get_nv_storage(VB2_NV_TPM_REQUESTED_REBOOT);
493 } else if (!strcasecmp(name,"fwb_tries") ||
494 !strcasecmp(name,"fw_try_count")) {
495 value = vb2_get_nv_storage(VB2_NV_TRY_COUNT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700496 } else if (!strcasecmp(name,"fw_vboot2")) {
497 value = GetVdatInt(VDAT_INT_FW_BOOT2);
Randall Spanglerfb267152016-10-11 15:28:16 -0700498 } else if (!strcasecmp(name,"fwupdate_tries")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800499 value = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700500 if (value != -1)
501 value &= KERN_NV_FWUPDATE_TRIES_MASK;
502 } else if (!strcasecmp(name,"block_devmode")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800503 value = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700504 if (value != -1) {
505 value &= KERN_NV_BLOCK_DEVMODE_FLAG;
506 value = !!value;
507 }
508 } else if (!strcasecmp(name,"tpm_attack")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800509 value = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700510 if (value != -1) {
511 value &= KERN_NV_TPM_ATTACK_FLAG;
512 value = !!value;
513 }
514 } else if (!strcasecmp(name,"loc_idx")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800515 value = vb2_get_nv_storage(VB2_NV_LOCALIZATION_INDEX);
Randall Spanglerfb267152016-10-11 15:28:16 -0700516 } else if (!strcasecmp(name,"backup_nvram_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800517 value = vb2_get_nv_storage(VB2_NV_BACKUP_NVRAM_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700518 } else if (!strcasecmp(name,"dev_boot_usb")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800519 value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_USB);
Randall Spanglerfb267152016-10-11 15:28:16 -0700520 } else if (!strcasecmp(name,"dev_boot_legacy")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800521 value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_LEGACY);
Randall Spanglerfb267152016-10-11 15:28:16 -0700522 } else if (!strcasecmp(name,"dev_boot_signed_only")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800523 value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_SIGNED_ONLY);
Duncan Laurie534194e2018-04-12 10:20:16 -0700524 } else if (!strcasecmp(name,"dev_enable_udc")) {
525 value = vb2_get_nv_storage(VB2_NV_DEV_ENABLE_UDC);
Joel Kitching43f6cab2019-05-10 12:17:18 +0800526 } else if (!strcasecmp(name,"display_request")) {
527 value = vb2_get_nv_storage(VB2_NV_DISPLAY_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700528 } else if (!strcasecmp(name,"recovery_subcode")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800529 value = vb2_get_nv_storage(VB2_NV_RECOVERY_SUBCODE);
Randall Spanglerfb267152016-10-11 15:28:16 -0700530 } else if (!strcasecmp(name,"wipeout_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800531 value = vb2_get_nv_storage(VB2_NV_REQ_WIPEOUT);
Randall Spangler4aaaeca2017-10-20 12:38:40 -0700532 } else if (!strcasecmp(name,"kernel_max_rollforward")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800533 value = vb2_get_nv_storage(VB2_NV_KERNEL_MAX_ROLLFORWARD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700534 }
535 /* Other parameters */
536 else if (!strcasecmp(name,"cros_debug")) {
537 value = VbGetCrosDebug();
538 } else if (!strcasecmp(name,"debug_build")) {
539 value = VbGetDebugBuild();
540 } else if (!strcasecmp(name,"devsw_boot")) {
541 value = GetVdatInt(VDAT_INT_DEVSW_BOOT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700542 } else if (!strcasecmp(name, "recoverysw_boot")) {
543 value = GetVdatInt(VDAT_INT_RECSW_BOOT);
Tudor Brindusc2393742018-07-31 16:25:26 -0700544 } else if (!strcasecmp(name, "recoverysw_is_virtual")) {
545 value = GetVdatInt(VDAT_INT_RECSW_VIRTUAL);
Randall Spanglerfb267152016-10-11 15:28:16 -0700546 } else if (!strcasecmp(name, "wpsw_boot")) {
547 value = GetVdatInt(VDAT_INT_HW_WPSW_BOOT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700548 } else if (!strcasecmp(name,"vdat_flags")) {
549 value = GetVdatInt(VDAT_INT_FLAGS);
550 } else if (!strcasecmp(name,"tpm_fwver")) {
551 value = GetVdatInt(VDAT_INT_FW_VERSION_TPM);
552 } else if (!strcasecmp(name,"tpm_kernver")) {
553 value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
554 } else if (!strcasecmp(name,"tried_fwb")) {
555 value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B);
556 } else if (!strcasecmp(name,"recovery_reason")) {
557 value = GetVdatInt(VDAT_INT_RECOVERY_REASON);
Randall Spanglerfb267152016-10-11 15:28:16 -0700558 } else if (!strcasecmp(name, "boot_on_ac_detect")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800559 value = vb2_get_nv_storage(VB2_NV_BOOT_ON_AC_DETECT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700560 } else if (!strcasecmp(name, "try_ro_sync")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800561 value = vb2_get_nv_storage(VB2_NV_TRY_RO_SYNC);
Randall Spanglerfb267152016-10-11 15:28:16 -0700562 } else if (!strcasecmp(name, "battery_cutoff_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800563 value = vb2_get_nv_storage(VB2_NV_BATTERY_CUTOFF_REQUEST);
Randall Spanglerfb267152016-10-11 15:28:16 -0700564 } else if (!strcasecmp(name, "inside_vm")) {
565 /* Detect if the host is a VM. If there is no HWID and the
566 * firmware type is "nonchrome", then assume it is a VM. If
567 * HWID is present, it is a baremetal Chrome OS machine. Other
568 * cases are errors. */
569 char hwid[VB_MAX_STRING_PROPERTY];
570 if (!VbGetSystemPropertyString("hwid", hwid, sizeof(hwid))) {
571 char fwtype_buf[VB_MAX_STRING_PROPERTY];
572 const char *fwtype = VbGetSystemPropertyString(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800573 "mainfw_type", fwtype_buf, sizeof(fwtype_buf));
Randall Spanglerfb267152016-10-11 15:28:16 -0700574 if (fwtype && !strcasecmp(fwtype, "nonchrome")) {
575 value = 1;
576 }
577 } else {
578 value = 0;
579 }
Joel Kitching0f777982018-10-02 20:54:07 +0800580 } else if (!strcasecmp(name, "post_ec_sync_delay")) {
581 value = vb2_get_nv_storage(VB2_NV_POST_EC_SYNC_DELAY);
Randall Spanglerfb267152016-10-11 15:28:16 -0700582 }
Randall Spangler54218662011-02-07 11:20:20 -0800583
Randall Spanglerfb267152016-10-11 15:28:16 -0700584 return value;
585}
586
587const char *VbGetSystemPropertyString(const char *name, char *dest,
Joel Kitching9ad8a412018-08-02 16:21:17 +0800588 size_t size)
Randall Spanglerfb267152016-10-11 15:28:16 -0700589{
590 /* Check architecture-dependent properties first */
591 if (VbGetArchPropertyString(name, dest, size))
592 return dest;
593
594 if (!strcasecmp(name,"kernkey_vfy")) {
595 switch(GetVdatInt(VDAT_INT_KERNEL_KEY_VERIFIED)) {
596 case 0:
597 return "hash";
598 case 1:
599 return "sig";
600 default:
601 return NULL;
602 }
603 } else if (!strcasecmp(name, "mainfw_act")) {
604 return GetVdatString(dest, size, VDAT_STRING_MAINFW_ACT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700605 } else if (!strcasecmp(name, "vdat_lfdebug")) {
606 return GetVdatString(dest, size,
607 VDAT_STRING_LOAD_FIRMWARE_DEBUG);
608 } else if (!strcasecmp(name, "vdat_lkdebug")) {
609 return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
610 } else if (!strcasecmp(name, "fw_try_next")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800611 return vb2_get_nv_storage(VB2_NV_TRY_NEXT) ? "B" : "A";
Randall Spanglerfb267152016-10-11 15:28:16 -0700612 } else if (!strcasecmp(name, "fw_tried")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800613 return vb2_get_nv_storage(VB2_NV_FW_TRIED) ? "B" : "A";
Randall Spanglerfb267152016-10-11 15:28:16 -0700614 } else if (!strcasecmp(name, "fw_result")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800615 int v = vb2_get_nv_storage(VB2_NV_FW_RESULT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700616 if (v < ARRAY_SIZE(fw_results))
617 return fw_results[v];
618 else
619 return "unknown";
620 } else if (!strcasecmp(name, "fw_prev_tried")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800621 return vb2_get_nv_storage(VB2_NV_FW_PREV_TRIED) ? "B" : "A";
Randall Spanglerfb267152016-10-11 15:28:16 -0700622 } else if (!strcasecmp(name, "fw_prev_result")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800623 int v = vb2_get_nv_storage(VB2_NV_FW_PREV_RESULT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700624 if (v < ARRAY_SIZE(fw_results))
625 return fw_results[v];
626 else
627 return "unknown";
628 } else if (!strcasecmp(name,"dev_default_boot")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800629 int v = vb2_get_nv_storage(VB2_NV_DEV_DEFAULT_BOOT);
Randall Spanglerfb267152016-10-11 15:28:16 -0700630 if (v < ARRAY_SIZE(default_boot))
631 return default_boot[v];
632 else
633 return "unknown";
634 }
635
636 return NULL;
Randall Spangler54218662011-02-07 11:20:20 -0800637}
638
Randall Spangler54218662011-02-07 11:20:20 -0800639
Randall Spanglerfb267152016-10-11 15:28:16 -0700640int VbSetSystemPropertyInt(const char *name, int value)
641{
642 /* Check architecture-dependent properties first */
Randall Spanglereb591952011-04-07 10:02:00 -0700643
Randall Spanglerfb267152016-10-11 15:28:16 -0700644 if (0 == VbSetArchPropertyInt(name, value))
645 return 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700646
Randall Spanglerfb267152016-10-11 15:28:16 -0700647 /* NV storage values */
648 if (!strcasecmp(name,"nvram_cleared")) {
649 /* Can only clear this flag; it's set inside the NV storage
650 * library. */
Randall Spanglerdff58522017-11-27 15:37:13 -0800651 return vb2_set_nv_storage(VB2_NV_KERNEL_SETTINGS_RESET, 0);
Randall Spanglerfb267152016-10-11 15:28:16 -0700652 } else if (!strcasecmp(name,"recovery_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800653 return vb2_set_nv_storage(VB2_NV_RECOVERY_REQUEST, value);
Matt Delco90a95ea2019-03-05 16:54:23 -0800654 } else if (!strcasecmp(name,"diagnostic_request")) {
655 return vb2_set_nv_storage(VB2_NV_DIAG_REQUEST, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700656 } else if (!strcasecmp(name,"recovery_subcode")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800657 return vb2_set_nv_storage(VB2_NV_RECOVERY_SUBCODE, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700658 } else if (!strcasecmp(name,"dbg_reset")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800659 return vb2_set_nv_storage(VB2_NV_DEBUG_RESET_MODE, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700660 } else if (!strcasecmp(name,"disable_dev_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800661 return vb2_set_nv_storage(VB2_NV_DISABLE_DEV_REQUEST, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700662 } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800663 return vb2_set_nv_storage(VB2_NV_CLEAR_TPM_OWNER_REQUEST, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700664 } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
665 /* Can only clear this flag; it's set by firmware. */
Randall Spanglerdff58522017-11-27 15:37:13 -0800666 return vb2_set_nv_storage(VB2_NV_CLEAR_TPM_OWNER_DONE, 0);
667 } else if (!strcasecmp(name,"fwb_tries") ||
668 !strcasecmp(name,"fw_try_count")) {
669 return vb2_set_nv_storage(VB2_NV_TRY_COUNT, value);
Joel Kitching43f6cab2019-05-10 12:17:18 +0800670 } else if (!strcasecmp(name,"display_request")) {
671 return vb2_set_nv_storage(VB2_NV_DISPLAY_REQUEST, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700672 } else if (!strcasecmp(name,"wipeout_request")) {
673 /* Can only clear this flag, set only by firmware. */
Randall Spanglerdff58522017-11-27 15:37:13 -0800674 return vb2_set_nv_storage(VB2_NV_REQ_WIPEOUT, 0);
Randall Spanglerfb267152016-10-11 15:28:16 -0700675 } else if (!strcasecmp(name,"backup_nvram_request")) {
676 /* Best-effort only, since it requires firmware and TPM
677 * support. */
Randall Spanglerdff58522017-11-27 15:37:13 -0800678 return vb2_set_nv_storage(VB2_NV_BACKUP_NVRAM_REQUEST, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700679 } else if (!strcasecmp(name,"fwupdate_tries")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800680 int kern_nv = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700681 if (kern_nv == -1)
682 return -1;
683 kern_nv &= ~KERN_NV_FWUPDATE_TRIES_MASK;
684 kern_nv |= (value & KERN_NV_FWUPDATE_TRIES_MASK);
Joel Kitching9ad8a412018-08-02 16:21:17 +0800685 return vb2_set_nv_storage_with_backup(
686 VB2_NV_KERNEL_FIELD, kern_nv);
Randall Spanglerfb267152016-10-11 15:28:16 -0700687 } else if (!strcasecmp(name,"block_devmode")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800688 int kern_nv = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700689 if (kern_nv == -1)
690 return -1;
691 kern_nv &= ~KERN_NV_BLOCK_DEVMODE_FLAG;
692 if (value)
693 kern_nv |= KERN_NV_BLOCK_DEVMODE_FLAG;
Joel Kitching9ad8a412018-08-02 16:21:17 +0800694 return vb2_set_nv_storage_with_backup(
695 VB2_NV_KERNEL_FIELD, kern_nv);
Randall Spanglerfb267152016-10-11 15:28:16 -0700696 } else if (!strcasecmp(name,"tpm_attack")) {
697 /* This value should only be read and cleared, but we allow
698 * setting it to 1 for testing. */
Randall Spanglerdff58522017-11-27 15:37:13 -0800699 int kern_nv = vb2_get_nv_storage(VB2_NV_KERNEL_FIELD);
Randall Spanglerfb267152016-10-11 15:28:16 -0700700 if (kern_nv == -1)
701 return -1;
702 kern_nv &= ~KERN_NV_TPM_ATTACK_FLAG;
703 if (value)
704 kern_nv |= KERN_NV_TPM_ATTACK_FLAG;
Randall Spanglerdff58522017-11-27 15:37:13 -0800705 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800706 VB2_NV_KERNEL_FIELD, kern_nv);
Randall Spanglerfb267152016-10-11 15:28:16 -0700707 } else if (!strcasecmp(name,"loc_idx")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800708 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800709 VB2_NV_LOCALIZATION_INDEX, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700710 } else if (!strcasecmp(name,"dev_boot_usb")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800711 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800712 VB2_NV_DEV_BOOT_USB, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700713 } else if (!strcasecmp(name,"dev_boot_legacy")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800714 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800715 VB2_NV_DEV_BOOT_LEGACY, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700716 } else if (!strcasecmp(name,"dev_boot_signed_only")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800717 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800718 VB2_NV_DEV_BOOT_SIGNED_ONLY, value);
Duncan Laurie534194e2018-04-12 10:20:16 -0700719 } else if (!strcasecmp(name, "dev_enable_udc")) {
720 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800721 VB2_NV_DEV_ENABLE_UDC, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700722 } else if (!strcasecmp(name, "boot_on_ac_detect")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800723 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800724 VB2_NV_BOOT_ON_AC_DETECT, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700725 } else if (!strcasecmp(name, "try_ro_sync")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800726 return vb2_set_nv_storage_with_backup(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800727 VB2_NV_TRY_RO_SYNC, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700728 } else if (!strcasecmp(name, "battery_cutoff_request")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800729 return vb2_set_nv_storage(VB2_NV_BATTERY_CUTOFF_REQUEST, value);
Randall Spangler4aaaeca2017-10-20 12:38:40 -0700730 } else if (!strcasecmp(name,"kernel_max_rollforward")) {
Randall Spanglerdff58522017-11-27 15:37:13 -0800731 return vb2_set_nv_storage(VB2_NV_KERNEL_MAX_ROLLFORWARD, value);
Joel Kitching0f777982018-10-02 20:54:07 +0800732 } else if (!strcasecmp(name, "post_ec_sync_delay")) {
733 return vb2_set_nv_storage(VB2_NV_POST_EC_SYNC_DELAY, value);
Randall Spanglerfb267152016-10-11 15:28:16 -0700734 }
735
736 return -1;
Randall Spangler54218662011-02-07 11:20:20 -0800737}
738
Randall Spanglerfb267152016-10-11 15:28:16 -0700739int VbSetSystemPropertyString(const char* name, const char* value)
740{
741 /* Chain to architecture-dependent properties */
742 if (0 == VbSetArchPropertyString(name, value))
743 return 0;
Randall Spangler54218662011-02-07 11:20:20 -0800744
Randall Spanglerfb267152016-10-11 15:28:16 -0700745 if (!strcasecmp(name, "fw_try_next")) {
746 if (!strcasecmp(value, "A"))
Randall Spanglerdff58522017-11-27 15:37:13 -0800747 return vb2_set_nv_storage(VB2_NV_TRY_NEXT, 0);
Randall Spanglerfb267152016-10-11 15:28:16 -0700748 else if (!strcasecmp(value, "B"))
Randall Spanglerdff58522017-11-27 15:37:13 -0800749 return vb2_set_nv_storage(VB2_NV_TRY_NEXT, 1);
Randall Spanglerfb267152016-10-11 15:28:16 -0700750 else
751 return -1;
Randall Spanglerd7728232011-04-08 14:04:21 -0700752
Randall Spanglerfb267152016-10-11 15:28:16 -0700753 } else if (!strcasecmp(name, "fw_result")) {
754 int i;
Randall Spangler54218662011-02-07 11:20:20 -0800755
Randall Spanglerfb267152016-10-11 15:28:16 -0700756 for (i = 0; i < ARRAY_SIZE(fw_results); i++) {
757 if (!strcasecmp(value, fw_results[i]))
Randall Spanglerdff58522017-11-27 15:37:13 -0800758 return vb2_set_nv_storage(VB2_NV_FW_RESULT, i);
Randall Spanglerfb267152016-10-11 15:28:16 -0700759 }
760 return -1;
761 } else if (!strcasecmp(name, "dev_default_boot")) {
762 int i;
Randall Spanglere73302c2011-02-18 14:53:01 -0800763
Randall Spanglerfb267152016-10-11 15:28:16 -0700764 for (i = 0; i < ARRAY_SIZE(default_boot); i++) {
765 if (!strcasecmp(value, default_boot[i]))
Randall Spanglerdff58522017-11-27 15:37:13 -0800766 return vb2_set_nv_storage(
Joel Kitching9ad8a412018-08-02 16:21:17 +0800767 VB2_NV_DEV_DEFAULT_BOOT, i);
Randall Spanglerfb267152016-10-11 15:28:16 -0700768 }
769 return -1;
770 }
771
772 return -1;
Randall Spangler54218662011-02-07 11:20:20 -0800773}
774
Julius Werner52fa8c12019-05-07 12:59:47 -0700775static int ExecuteMosys(const char * const argv[], char *buf, size_t bufsize)
Randall Spanglerfb267152016-10-11 15:28:16 -0700776{
777 int status, mosys_to_crossystem[2];
778 pid_t pid;
779 ssize_t n;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700780
Randall Spanglerfb267152016-10-11 15:28:16 -0700781 if (pipe(mosys_to_crossystem) < 0) {
Randall Spangler21015892017-01-03 13:49:18 -0800782 fprintf(stderr, "pipe() error\n");
Randall Spanglerfb267152016-10-11 15:28:16 -0700783 return -1;
784 }
Duncan Lauriee98431f2016-03-30 09:35:20 -0700785
Randall Spanglerfb267152016-10-11 15:28:16 -0700786 if ((pid = fork()) < 0) {
Randall Spangler21015892017-01-03 13:49:18 -0800787 fprintf(stderr, "fork() error\n");
Randall Spanglerfb267152016-10-11 15:28:16 -0700788 close(mosys_to_crossystem[0]);
789 close(mosys_to_crossystem[1]);
790 return -1;
791 } else if (!pid) { /* Child */
792 close(mosys_to_crossystem[0]);
793 /* Redirect pipe's write-end to mosys' stdout */
794 if (STDOUT_FILENO != mosys_to_crossystem[1]) {
795 if (dup2(mosys_to_crossystem[1], STDOUT_FILENO)
796 != STDOUT_FILENO) {
Randall Spangler21015892017-01-03 13:49:18 -0800797 fprintf(stderr, "stdout dup2() failed (mosys)\n");
Randall Spanglerfb267152016-10-11 15:28:16 -0700798 close(mosys_to_crossystem[1]);
799 exit(1);
800 }
801 }
Julius Werner52fa8c12019-05-07 12:59:47 -0700802 /* Execute mosys (needs cast because POSIX is stupid) */
Jack Rosenthalfde6a342019-12-03 14:53:27 -0700803 execv(MOSYS_PATH, (char * const *)argv);
Randall Spanglerfb267152016-10-11 15:28:16 -0700804 /* We shouldn't be here; exit now! */
Randall Spangler21015892017-01-03 13:49:18 -0800805 fprintf(stderr, "execv() of mosys failed\n");
Randall Spanglerfb267152016-10-11 15:28:16 -0700806 close(mosys_to_crossystem[1]);
807 exit(1);
808 } else { /* Parent */
809 close(mosys_to_crossystem[1]);
810 if (bufsize) {
811 bufsize--; /* Reserve 1 byte for '\0' */
812 while ((n = read(mosys_to_crossystem[0],
813 buf, bufsize)) > 0) {
814 buf += n;
815 bufsize -= n;
816 }
817 *buf = '\0';
818 } else {
819 n = 0;
820 }
821 close(mosys_to_crossystem[0]);
822 if (n < 0)
Randall Spangler21015892017-01-03 13:49:18 -0800823 fprintf(stderr, "read() error on output from mosys\n");
Randall Spanglerfb267152016-10-11 15:28:16 -0700824 if (waitpid(pid, &status, 0) < 0 || status) {
Randall Spanglerfb267152016-10-11 15:28:16 -0700825 fprintf(stderr, "waitpid() or mosys error\n");
826 return -1;
827 }
828 if (n < 0)
829 return -1;
830 }
831 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700832}
833
Randall Spanglerdff58522017-11-27 15:37:13 -0800834int vb2_read_nv_storage_mosys(struct vb2_context *ctx)
Randall Spanglerfb267152016-10-11 15:28:16 -0700835{
Randall Spanglera80a79f2018-02-26 17:01:24 -0800836 /* Reserve extra 32 bytes */
837 char hexstring[VB2_NVDATA_SIZE_V2 * 2 + 32];
838 /*
839 * TODO(rspangler): mosys doesn't know how to read anything but 16-byte
840 * records yet. When it grows a command line option to do that, call
841 * it here when needed.
842 *
843 * It's possible mosys won't need that. For example, if if examines
844 * the header byte to determine the records size, or if it calls back
845 * to crossystem to read the VBSD flag.
846 */
Julius Werner52fa8c12019-05-07 12:59:47 -0700847 const char * const argv[] = {
Jack Rosenthalfde6a342019-12-03 14:53:27 -0700848 MOSYS_PATH, "nvram", "vboot", "read", NULL
Randall Spanglerfb267152016-10-11 15:28:16 -0700849 };
850 char hexdigit[3];
Randall Spanglera80a79f2018-02-26 17:01:24 -0800851 const int nvsize = vb2_nv_get_size(ctx);
Randall Spanglerfb267152016-10-11 15:28:16 -0700852 int i;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700853
Randall Spanglerfb267152016-10-11 15:28:16 -0700854 if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
855 return -1;
Randall Spangler4c84e072018-03-11 09:56:06 -0700856 if (strlen(hexstring) < 2 * nvsize) {
Randall Spanglera80a79f2018-02-26 17:01:24 -0800857 fprintf(stderr, "mosys returned hex nvdata size %d"
Randall Spangler4c84e072018-03-11 09:56:06 -0700858 " (need %d)\n", (int)strlen(hexstring), 2 * nvsize);
Randall Spanglera80a79f2018-02-26 17:01:24 -0800859 return -1;
860 }
Randall Spanglerfb267152016-10-11 15:28:16 -0700861 hexdigit[2] = '\0';
Randall Spanglera80a79f2018-02-26 17:01:24 -0800862 for (i = 0; i < nvsize; i++) {
Randall Spanglerfb267152016-10-11 15:28:16 -0700863 hexdigit[0] = hexstring[i * 2];
864 hexdigit[1] = hexstring[i * 2 + 1];
Randall Spanglerdff58522017-11-27 15:37:13 -0800865 ctx->nvdata[i] = strtol(hexdigit, NULL, 16);
Randall Spanglerfb267152016-10-11 15:28:16 -0700866 }
867 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700868}
869
Randall Spanglerdff58522017-11-27 15:37:13 -0800870int vb2_write_nv_storage_mosys(struct vb2_context *ctx)
Randall Spanglerfb267152016-10-11 15:28:16 -0700871{
Randall Spanglera80a79f2018-02-26 17:01:24 -0800872 char hexstring[VB2_NVDATA_SIZE_V2 * 2 + 1];
Julius Werner52fa8c12019-05-07 12:59:47 -0700873 const char * const argv[] = {
Jack Rosenthalfde6a342019-12-03 14:53:27 -0700874 MOSYS_PATH, "nvram", "vboot", "write", hexstring, NULL
Randall Spanglerfb267152016-10-11 15:28:16 -0700875 };
Randall Spanglera80a79f2018-02-26 17:01:24 -0800876 const int nvsize = vb2_nv_get_size(ctx);
Randall Spanglerfb267152016-10-11 15:28:16 -0700877 int i;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700878
Randall Spanglera80a79f2018-02-26 17:01:24 -0800879 for (i = 0; i < nvsize; i++)
Randall Spanglerdff58522017-11-27 15:37:13 -0800880 snprintf(hexstring + i * 2, 3, "%02x", ctx->nvdata[i]);
Randall Spanglerfb267152016-10-11 15:28:16 -0700881 hexstring[sizeof(hexstring) - 1] = '\0';
882 if (ExecuteMosys(argv, NULL, 0))
883 return -1;
884 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700885}