blob: 05126214a050c2f21353fab9f0f32544d849c052 [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
19#include "host_common.h"
20
21#include "crossystem.h"
Randall Spanglereb591952011-04-07 10:02:00 -070022#include "crossystem_arch.h"
Duncan Lauriee98431f2016-03-30 09:35:20 -070023#include "crossystem_vbnv.h"
Randall Spangler54218662011-02-07 11:20:20 -080024#include "utility.h"
25#include "vboot_common.h"
Randall Spanglere73302c2011-02-18 14:53:01 -080026#include "vboot_nvstorage.h"
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070027#include "vboot_struct.h"
Randall Spangler54218662011-02-07 11:20:20 -080028
Randall Spangler196e1772011-03-10 11:31:06 -080029/* Filename for kernel command line */
30#define KERNEL_CMDLINE_PATH "/proc/cmdline"
31
Duncan Lauriee98431f2016-03-30 09:35:20 -070032#define MOSYS_CROS_PATH "/usr/sbin/mosys"
33#define MOSYS_ANDROID_PATH "/system/bin/mosys"
34
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070035/* Fields that GetVdatString() can get */
36typedef enum VdatStringField {
Randall Spanglerfb267152016-10-11 15:28:16 -070037 VDAT_STRING_TIMERS = 0, /* Timer values */
38 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 */
49 VDAT_INT_DEVSW_VIRTUAL, /* Dev switch is virtual */
50 VDAT_INT_RECSW_BOOT, /* Recovery switch position at boot */
51 VDAT_INT_HW_WPSW_BOOT, /* Hardware WP switch position at boot */
52 VDAT_INT_SW_WPSW_BOOT, /* Flash chip's WP setting at boot */
Randall Spanglerda8d32d2012-08-03 12:48:24 -070053
Randall Spanglerfb267152016-10-11 15:28:16 -070054 VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
55 VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */
56 VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */
57 VDAT_INT_KERNEL_KEY_VERIFIED, /* Kernel key verified using
58 * signature, not just hash */
59 VDAT_INT_RECOVERY_REASON, /* Recovery reason for current boot */
60 VDAT_INT_FW_BOOT2 /* Firmware selection by vboot2 */
Randall Spanglerf4ba19d2011-03-17 16:10:21 -070061} VdatIntField;
62
63
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070064/* Description of build options that may be specified on the
65 * kernel command line. */
66typedef enum VbBuildOption {
Randall Spanglerfb267152016-10-11 15:28:16 -070067 VB_BUILD_OPTION_UNKNOWN,
68 VB_BUILD_OPTION_DEBUG,
69 VB_BUILD_OPTION_NODEBUG
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070070} VbBuildOption;
71
Randall Spangler9e1da782014-06-24 15:31:04 -070072static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
Mary Ruthven12a55f22015-10-06 10:42:31 -070073static const char *default_boot[] = {"disk", "usb", "legacy"};
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -070074
Randall Spanglerff3f0002011-07-26 10:43:53 -070075/* Masks for kern_nv usage by kernel. */
Randall Spanglerd7728232011-04-08 14:04:21 -070076#define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
Bill Richardson850b74f2014-04-30 16:30:36 -070077#define KERN_NV_BLOCK_DEVMODE_FLAG 0x00000010
Luigi Semenzatof80ceeb2015-03-19 16:45:52 -070078#define KERN_NV_TPM_ATTACK_FLAG 0x00000020
Randall Spanglerff3f0002011-07-26 10:43:53 -070079/* If you want to use the remaining currently-unused bits in kern_nv
80 * for something kernel-y, define a new field (the way we did for
81 * fwupdate_tries). Don't just modify kern_nv directly, because that
82 * makes it too easy to accidentally corrupt other sub-fields. */
Luigi Semenzatof80ceeb2015-03-19 16:45:52 -070083#define KERN_NV_CURRENTLY_UNUSED 0xFFFFFFC0
Randall Spanglerd7728232011-04-08 14:04:21 -070084
Randall Spanglerc80fe652011-02-17 11:06:47 -080085/* Return true if the FWID starts with the specified string. */
Randall Spanglerfb267152016-10-11 15:28:16 -070086int FwidStartsWith(const char *start)
87{
88 char fwid[VB_MAX_STRING_PROPERTY];
89 if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid)))
90 return 0;
Randall Spanglerc80fe652011-02-17 11:06:47 -080091
Randall Spanglerfb267152016-10-11 15:28:16 -070092 return 0 == strncmp(fwid, start, strlen(start));
Randall Spanglerc80fe652011-02-17 11:06:47 -080093}
94
Vadim Bendebury38201fe2014-11-07 17:25:09 -080095static int vnc_read;
Randall Spanglerc80fe652011-02-17 11:06:47 -080096
Randall Spanglerfb267152016-10-11 15:28:16 -070097int VbGetNvStorage(VbNvParam param)
98{
99 uint32_t value;
100 int retval;
101 static VbNvContext cached_vnc;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800102
Randall Spanglerfb267152016-10-11 15:28:16 -0700103 /* TODO: locking around NV access */
104 if (!vnc_read) {
105 if (0 != VbReadNvStorage(&cached_vnc))
106 return -1;
107 vnc_read = 1;
108 }
Randall Spanglereb591952011-04-07 10:02:00 -0700109
Randall Spanglerfb267152016-10-11 15:28:16 -0700110 if (0 != VbNvSetup(&cached_vnc))
111 return -1;
112 retval = VbNvGet(&cached_vnc, param, &value);
113 if (0 != VbNvTeardown(&cached_vnc))
114 return -1;
115 if (0 != retval)
116 return -1;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800117
Randall Spanglerfb267152016-10-11 15:28:16 -0700118 /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and
119 * save the new defaults. If we're able to, log. */
120 /* TODO: release lock */
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800121
Randall Spanglerfb267152016-10-11 15:28:16 -0700122 return (int)value;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800123}
124
Randall Spanglerfb267152016-10-11 15:28:16 -0700125int VbSetNvStorage(VbNvParam param, int value)
126{
127 VbNvContext vnc;
128 int retval = -1;
129 int i;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800130
Randall Spanglerfb267152016-10-11 15:28:16 -0700131 if (0 != VbReadNvStorage(&vnc))
132 return -1;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800133
Randall Spanglerfb267152016-10-11 15:28:16 -0700134 if (0 != VbNvSetup(&vnc))
135 goto VbSetNvCleanup;
136 i = VbNvSet(&vnc, param, (uint32_t)value);
137 if (0 != VbNvTeardown(&vnc))
138 goto VbSetNvCleanup;
139 if (0 != i)
140 goto VbSetNvCleanup;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800141
Randall Spanglerfb267152016-10-11 15:28:16 -0700142 if (vnc.raw_changed) {
143 vnc_read = 0;
144 if (0 != VbWriteNvStorage(&vnc))
145 goto VbSetNvCleanup;
146 }
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800147
Randall Spanglerfb267152016-10-11 15:28:16 -0700148 /* Success */
149 retval = 0;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800150
151VbSetNvCleanup:
Randall Spanglerfb267152016-10-11 15:28:16 -0700152 /* TODO: release lock */
153 return retval;
Randall Spangler0f8ffb12011-02-25 09:50:54 -0800154}
155
Bill Richardsonb64f0972014-05-28 15:49:23 -0700156/*
157 * Set a param value, and try to flag it for persistent backup.
158 * It's okay if backup isn't supported. It's best-effort only.
159 */
160static int VbSetNvStorage_WithBackup(VbNvParam param, int value)
161{
Randall Spanglerfb267152016-10-11 15:28:16 -0700162 int retval;
163 retval = VbSetNvStorage(param, value);
164 if (!retval)
165 VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, 1);
166 return retval;
Bill Richardsonb64f0972014-05-28 15:49:23 -0700167}
168
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700169/* Find what build/debug status is specified on the kernel command
170 * line, if any. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700171static VbBuildOption VbScanBuildOption(void)
172{
173 FILE* f = NULL;
174 char buf[4096] = "";
175 char *t, *saveptr;
176 const char *delimiters = " \r\n";
Randall Spangler196e1772011-03-10 11:31:06 -0800177
Randall Spanglerfb267152016-10-11 15:28:16 -0700178 f = fopen(KERNEL_CMDLINE_PATH, "r");
179 if (NULL != f) {
180 if (NULL == fgets(buf, sizeof(buf), f))
181 buf[0] = 0;
182 fclose(f);
183 }
184 for (t = strtok_r(buf, delimiters, &saveptr); t;
185 t = strtok_r(NULL, delimiters, &saveptr)) {
186 if (0 == strcmp(t, "cros_debug"))
187 return VB_BUILD_OPTION_DEBUG;
188 else if (0 == strcmp(t, "cros_nodebug"))
189 return VB_BUILD_OPTION_NODEBUG;
190 }
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700191
Randall Spanglerfb267152016-10-11 15:28:16 -0700192 return VB_BUILD_OPTION_UNKNOWN;
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700193}
194
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700195/* Determine whether the running OS image was built for debugging.
196 * Returns 1 if yes, 0 if no or indeterminate. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700197int VbGetDebugBuild(void)
198{
199 return VB_BUILD_OPTION_DEBUG == VbScanBuildOption();
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700200}
201
J. Richard Barnette92cbd5d2013-10-22 16:21:14 -0700202/* Determine whether OS-level debugging should be allowed.
203 * Returns 1 if yes, 0 if no or indeterminate. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700204int VbGetCrosDebug(void)
205{
206 /* If the currently running system specifies its debug status, use
207 * that in preference to other indicators. */
208 VbBuildOption option = VbScanBuildOption();
209 if (VB_BUILD_OPTION_DEBUG == option) {
210 return 1;
211 } else if (VB_BUILD_OPTION_NODEBUG == option) {
212 return 0;
213 }
Randall Spangler196e1772011-03-10 11:31:06 -0800214
Randall Spanglerfb267152016-10-11 15:28:16 -0700215 /* Command line is silent; allow debug if the dev switch is on. */
216 if (1 == VbGetSystemPropertyInt("devsw_boot"))
217 return 1;
Randall Spangler196e1772011-03-10 11:31:06 -0800218
Randall Spanglerfb267152016-10-11 15:28:16 -0700219 /* All other cases disallow debug. */
220 return 0;
Randall Spangler196e1772011-03-10 11:31:06 -0800221}
222
Randall Spanglerfb267152016-10-11 15:28:16 -0700223char *GetVdatLoadFirmwareDebug(char *dest, int size,
224 const VbSharedDataHeader *sh)
225{
226 snprintf(dest, size,
227 "Check A result=%d\n"
228 "Check B result=%d\n"
229 "Firmware index booted=0x%02x\n"
230 "TPM combined version at start=0x%08x\n"
231 "Lowest combined version from firmware=0x%08x\n",
232 sh->check_fw_a_result,
233 sh->check_fw_b_result,
234 sh->firmware_index,
235 sh->fw_version_tpm_start,
236 sh->fw_version_lowest);
237 return dest;
Randall Spangler71415712011-03-21 11:04:50 -0700238}
239
Randall Spangler71415712011-03-21 11:04:50 -0700240#define TRUNCATED "\n(truncated)\n"
241
Randall Spanglerfb267152016-10-11 15:28:16 -0700242char *GetVdatLoadKernelDebug(char *dest, int size,
243 const VbSharedDataHeader *sh)
244{
245 int used = 0;
246 int first_call_tracked = 0;
247 int call;
Randall Spangler71415712011-03-21 11:04:50 -0700248
Randall Spanglerfb267152016-10-11 15:28:16 -0700249 /* Make sure we have space for truncation warning */
250 if (size < strlen(TRUNCATED) + 1)
251 return NULL;
252 size -= strlen(TRUNCATED) + 1;
Randall Spangler71415712011-03-21 11:04:50 -0700253
Randall Spanglerfb267152016-10-11 15:28:16 -0700254 used += snprintf(
255 dest + used, size - used,
256 "Calls to LoadKernel()=%d\n",
257 sh->lk_call_count);
258 if (used > size)
259 goto LoadKernelDebugExit;
Randall Spangler71415712011-03-21 11:04:50 -0700260
Randall Spanglerfb267152016-10-11 15:28:16 -0700261 /* Report on the last calls */
262 if (sh->lk_call_count > VBSD_MAX_KERNEL_CALLS)
263 first_call_tracked = sh->lk_call_count - VBSD_MAX_KERNEL_CALLS;
264 for (call = first_call_tracked; call < sh->lk_call_count; call++) {
265 const VbSharedDataKernelCall* shc = sh->lk_calls +
266 (call & (VBSD_MAX_KERNEL_CALLS - 1));
267 int first_part_tracked = 0;
268 int part;
Randall Spangler71415712011-03-21 11:04:50 -0700269
Randall Spanglerfb267152016-10-11 15:28:16 -0700270 used += snprintf(dest + used, size - used,
271 "Call %d:\n"
272 " Boot flags=0x%02x\n"
273 " Boot mode=%d\n"
274 " Test error=%d\n"
275 " Return code=%d\n"
276 " Debug flags=0x%02x\n"
277 " Drive sectors=%" PRIu64 "\n"
278 " Sector size=%d\n"
279 " Check result=%d\n"
280 " Kernel partitions found=%d\n",
281 call + 1,
282 shc->boot_flags,
283 shc->boot_mode,
284 shc->test_error_num,
285 shc->return_code,
286 shc->flags,
287 shc->sector_count,
288 shc->sector_size,
289 shc->check_result,
290 shc->kernel_parts_found);
291 if (used > size)
292 goto LoadKernelDebugExit;
Randall Spangler71415712011-03-21 11:04:50 -0700293
Randall Spanglerfb267152016-10-11 15:28:16 -0700294 /* If we found too many partitions, only prints ones where the
295 * structure has info. */
296 if (shc->kernel_parts_found > VBSD_MAX_KERNEL_PARTS)
297 first_part_tracked = shc->kernel_parts_found -
298 VBSD_MAX_KERNEL_PARTS;
Randall Spangler71415712011-03-21 11:04:50 -0700299
Randall Spanglerfb267152016-10-11 15:28:16 -0700300 /* Report on the partitions checked */
301 for (part = first_part_tracked; part < shc->kernel_parts_found;
302 part++) {
303 const VbSharedDataKernelPart* shp = shc->parts +
304 (part & (VBSD_MAX_KERNEL_PARTS - 1));
Randall Spangler71415712011-03-21 11:04:50 -0700305
Randall Spanglerfb267152016-10-11 15:28:16 -0700306 used += snprintf(dest + used, size - used,
307 " Kernel %d:\n"
308 " GPT index=%d\n"
309 " Start sector=%" PRIu64 "\n"
310 " Sector count=%" PRIu64 "\n"
311 " Combined version=0x%08x\n"
312 " Check result=%d\n"
313 " Debug flags=0x%02x\n",
314 part + 1,
315 shp->gpt_index,
316 shp->sector_start,
317 shp->sector_count,
318 shp->combined_version,
319 shp->check_result,
320 shp->flags);
321 if (used > size)
322 goto LoadKernelDebugExit;
323 }
324 }
Randall Spangler71415712011-03-21 11:04:50 -0700325
326LoadKernelDebugExit:
327
Randall Spanglerfb267152016-10-11 15:28:16 -0700328 /* Warn if data was truncated; we left space for this above. */
329 if (used > size)
330 strcat(dest, TRUNCATED);
Randall Spangler71415712011-03-21 11:04:50 -0700331
Randall Spanglerfb267152016-10-11 15:28:16 -0700332 return dest;
Randall Spangler71415712011-03-21 11:04:50 -0700333}
334
Randall Spanglerfb267152016-10-11 15:28:16 -0700335char *GetVdatString(char *dest, int size, VdatStringField field)
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700336{
Randall Spanglerfb267152016-10-11 15:28:16 -0700337 VbSharedDataHeader *sh = VbSharedDataRead();
338 char *value = dest;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700339
Randall Spanglerfb267152016-10-11 15:28:16 -0700340 if (!sh)
341 return NULL;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700342
Randall Spanglerfb267152016-10-11 15:28:16 -0700343 switch (field) {
344 case VDAT_STRING_TIMERS:
345 snprintf(dest, size,
346 "LFS=%" PRIu64 ",%" PRIu64
347 " LF=%" PRIu64 ",%" PRIu64
348 " LK=%" PRIu64 ",%" PRIu64,
349 sh->timer_vb_init_enter,
350 sh->timer_vb_init_exit,
351 sh->timer_vb_select_firmware_enter,
352 sh->timer_vb_select_firmware_exit,
353 sh->timer_vb_select_and_load_kernel_enter,
354 sh->timer_vb_select_and_load_kernel_exit);
355 break;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700356
Randall Spanglerfb267152016-10-11 15:28:16 -0700357 case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
358 value = GetVdatLoadFirmwareDebug(dest, size, sh);
359 break;
Randall Spangler71415712011-03-21 11:04:50 -0700360
Randall Spanglerfb267152016-10-11 15:28:16 -0700361 case VDAT_STRING_LOAD_KERNEL_DEBUG:
362 value = GetVdatLoadKernelDebug(dest, size, sh);
363 break;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700364
Randall Spanglerfb267152016-10-11 15:28:16 -0700365 case VDAT_STRING_MAINFW_ACT:
366 switch(sh->firmware_index) {
367 case 0:
368 StrCopy(dest, "A", size);
369 break;
370 case 1:
371 StrCopy(dest, "B", size);
372 break;
373 case 0xFF:
374 StrCopy(dest, "recovery", size);
375 break;
376 default:
377 value = NULL;
378 }
379 break;
Randall Spanglera185b8d2011-07-15 16:28:38 -0700380
Randall Spanglerfb267152016-10-11 15:28:16 -0700381 default:
382 value = NULL;
383 break;
384 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700385
Randall Spanglerfb267152016-10-11 15:28:16 -0700386 free(sh);
387 return value;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700388}
389
Randall Spanglerfb267152016-10-11 15:28:16 -0700390int GetVdatInt(VdatIntField field)
391{
392 VbSharedDataHeader* sh = VbSharedDataRead();
393 int value = -1;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700394
Randall Spanglerfb267152016-10-11 15:28:16 -0700395 if (!sh)
396 return -1;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700397
Randall Spanglerfb267152016-10-11 15:28:16 -0700398 /* Fields supported in version 1 */
399 switch (field) {
400 case VDAT_INT_FLAGS:
401 value = (int)sh->flags;
402 break;
403 case VDAT_INT_HEADER_VERSION:
404 value = sh->struct_version;
405 break;
406 case VDAT_INT_TRIED_FIRMWARE_B:
407 value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0);
408 break;
409 case VDAT_INT_KERNEL_KEY_VERIFIED:
410 value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
411 break;
412 case VDAT_INT_FW_VERSION_TPM:
413 value = (int)sh->fw_version_tpm;
414 break;
415 case VDAT_INT_KERNEL_VERSION_TPM:
416 value = (int)sh->kernel_version_tpm;
417 break;
418 case VDAT_INT_FW_BOOT2:
419 value = (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2 ? 1 : 0);
420 default:
421 break;
422 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700423
Randall Spanglerfb267152016-10-11 15:28:16 -0700424 /* Fields added in struct version 2 */
425 if (sh->struct_version >= 2) {
426 switch(field) {
427 case VDAT_INT_DEVSW_BOOT:
428 value = (sh->flags &
429 VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
430 break;
431 case VDAT_INT_DEVSW_VIRTUAL:
432 value = (sh->flags &
433 VBSD_HONOR_VIRT_DEV_SWITCH ? 1 : 0);
434 break;
435 case VDAT_INT_RECSW_BOOT:
436 value = (sh->flags &
437 VBSD_BOOT_REC_SWITCH_ON ? 1 : 0);
438 break;
439 case VDAT_INT_HW_WPSW_BOOT:
440 value = (sh->flags &
441 VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0);
442 break;
443 case VDAT_INT_SW_WPSW_BOOT:
444 value = (sh->flags &
445 VBSD_BOOT_FIRMWARE_SW_WP_ENABLED ?
446 1 : 0);
447 break;
448 case VDAT_INT_RECOVERY_REASON:
449 value = sh->recovery_reason;
450 break;
451 default:
452 break;
453 }
454 }
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700455
Randall Spanglerfb267152016-10-11 15:28:16 -0700456 free(sh);
457 return value;
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700458}
459
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700460/* Return version of VbSharedData struct or -1 if not found. */
Randall Spanglerfb267152016-10-11 15:28:16 -0700461int VbSharedDataVersion(void)
462{
463 return GetVdatInt(VDAT_INT_HEADER_VERSION);
Randall Spanglerda8d32d2012-08-03 12:48:24 -0700464}
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700465
Randall Spanglerfb267152016-10-11 15:28:16 -0700466int VbGetSystemPropertyInt(const char *name)
467{
468 int value = -1;
Randall Spangler54218662011-02-07 11:20:20 -0800469
Randall Spanglerfb267152016-10-11 15:28:16 -0700470 /* Check architecture-dependent properties first */
471 value = VbGetArchPropertyInt(name);
472 if (-1 != value)
473 return value;
Randall Spanglereb591952011-04-07 10:02:00 -0700474
Randall Spanglerfb267152016-10-11 15:28:16 -0700475 /* NV storage values */
476 else if (!strcasecmp(name,"kern_nv")) {
477 value = VbGetNvStorage(VBNV_KERNEL_FIELD);
478 } else if (!strcasecmp(name,"nvram_cleared")) {
479 value = VbGetNvStorage(VBNV_KERNEL_SETTINGS_RESET);
480 } else if (!strcasecmp(name,"recovery_request")) {
481 value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
482 } else if (!strcasecmp(name,"dbg_reset")) {
483 value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
484 } else if (!strcasecmp(name,"disable_dev_request")) {
485 value = VbGetNvStorage(VBNV_DISABLE_DEV_REQUEST);
486 } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
487 value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST);
488 } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
489 value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE);
490 } else if (!strcasecmp(name,"tpm_rebooted")) {
491 value = VbGetNvStorage(VBNV_TPM_REQUESTED_REBOOT);
492 } else if (!strcasecmp(name,"fwb_tries")) {
493 value = VbGetNvStorage(VBNV_TRY_B_COUNT);
494 } else if (!strcasecmp(name,"fw_vboot2")) {
495 value = GetVdatInt(VDAT_INT_FW_BOOT2);
496 } else if (!strcasecmp(name,"fw_try_count")) {
497 value = VbGetNvStorage(VBNV_FW_TRY_COUNT);
498 } else if (!strcasecmp(name,"fwupdate_tries")) {
499 value = VbGetNvStorage(VBNV_KERNEL_FIELD);
500 if (value != -1)
501 value &= KERN_NV_FWUPDATE_TRIES_MASK;
502 } else if (!strcasecmp(name,"block_devmode")) {
503 value = VbGetNvStorage(VBNV_KERNEL_FIELD);
504 if (value != -1) {
505 value &= KERN_NV_BLOCK_DEVMODE_FLAG;
506 value = !!value;
507 }
508 } else if (!strcasecmp(name,"tpm_attack")) {
509 value = VbGetNvStorage(VBNV_KERNEL_FIELD);
510 if (value != -1) {
511 value &= KERN_NV_TPM_ATTACK_FLAG;
512 value = !!value;
513 }
514 } else if (!strcasecmp(name,"loc_idx")) {
515 value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
516 } else if (!strcasecmp(name,"backup_nvram_request")) {
517 value = VbGetNvStorage(VBNV_BACKUP_NVRAM_REQUEST);
518 } else if (!strcasecmp(name,"dev_boot_usb")) {
519 value = VbGetNvStorage(VBNV_DEV_BOOT_USB);
520 } else if (!strcasecmp(name,"dev_boot_legacy")) {
521 value = VbGetNvStorage(VBNV_DEV_BOOT_LEGACY);
522 } else if (!strcasecmp(name,"dev_boot_signed_only")) {
523 value = VbGetNvStorage(VBNV_DEV_BOOT_SIGNED_ONLY);
524 } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
525 value = VbGetNvStorage(VBNV_DEV_BOOT_FASTBOOT_FULL_CAP);
526 } else if (!strcasecmp(name,"oprom_needed")) {
527 value = VbGetNvStorage(VBNV_OPROM_NEEDED);
528 } else if (!strcasecmp(name,"recovery_subcode")) {
529 value = VbGetNvStorage(VBNV_RECOVERY_SUBCODE);
530 } else if (!strcasecmp(name,"wipeout_request")) {
531 value = VbGetNvStorage(VBNV_FW_REQ_WIPEOUT);
532 }
533 /* Other parameters */
534 else if (!strcasecmp(name,"cros_debug")) {
535 value = VbGetCrosDebug();
536 } else if (!strcasecmp(name,"debug_build")) {
537 value = VbGetDebugBuild();
538 } else if (!strcasecmp(name,"devsw_boot")) {
539 value = GetVdatInt(VDAT_INT_DEVSW_BOOT);
540 } else if (!strcasecmp(name,"devsw_virtual")) {
541 value = GetVdatInt(VDAT_INT_DEVSW_VIRTUAL);
542 } else if (!strcasecmp(name, "recoverysw_boot")) {
543 value = GetVdatInt(VDAT_INT_RECSW_BOOT);
544 } else if (!strcasecmp(name, "wpsw_boot")) {
545 value = GetVdatInt(VDAT_INT_HW_WPSW_BOOT);
546 } else if (!strcasecmp(name, "sw_wpsw_boot")) {
547 value = GetVdatInt(VDAT_INT_SW_WPSW_BOOT);
548 } 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);
558 } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
559 value = VbGetNvStorage(VBNV_FASTBOOT_UNLOCK_IN_FW);
560 } else if (!strcasecmp(name, "boot_on_ac_detect")) {
561 value = VbGetNvStorage(VBNV_BOOT_ON_AC_DETECT);
562 } else if (!strcasecmp(name, "try_ro_sync")) {
563 value = VbGetNvStorage(VBNV_TRY_RO_SYNC);
564 } else if (!strcasecmp(name, "battery_cutoff_request")) {
565 value = VbGetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST);
566 } else if (!strcasecmp(name, "inside_vm")) {
567 /* Detect if the host is a VM. If there is no HWID and the
568 * firmware type is "nonchrome", then assume it is a VM. If
569 * HWID is present, it is a baremetal Chrome OS machine. Other
570 * cases are errors. */
571 char hwid[VB_MAX_STRING_PROPERTY];
572 if (!VbGetSystemPropertyString("hwid", hwid, sizeof(hwid))) {
573 char fwtype_buf[VB_MAX_STRING_PROPERTY];
574 const char *fwtype = VbGetSystemPropertyString(
575 "mainfw_type", fwtype_buf, sizeof(fwtype_buf));
576 if (fwtype && !strcasecmp(fwtype, "nonchrome")) {
577 value = 1;
578 }
579 } else {
580 value = 0;
581 }
582 }
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,
588 size_t size)
589{
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);
605 } else if (!strcasecmp(name, "vdat_timers")) {
606 return GetVdatString(dest, size, VDAT_STRING_TIMERS);
607 } else if (!strcasecmp(name, "vdat_lfdebug")) {
608 return GetVdatString(dest, size,
609 VDAT_STRING_LOAD_FIRMWARE_DEBUG);
610 } else if (!strcasecmp(name, "vdat_lkdebug")) {
611 return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
612 } else if (!strcasecmp(name, "fw_try_next")) {
613 return VbGetNvStorage(VBNV_FW_TRY_NEXT) ? "B" : "A";
614 } else if (!strcasecmp(name, "fw_tried")) {
615 return VbGetNvStorage(VBNV_FW_TRIED) ? "B" : "A";
616 } else if (!strcasecmp(name, "fw_result")) {
617 int v = VbGetNvStorage(VBNV_FW_RESULT);
618 if (v < ARRAY_SIZE(fw_results))
619 return fw_results[v];
620 else
621 return "unknown";
622 } else if (!strcasecmp(name, "fw_prev_tried")) {
623 return VbGetNvStorage(VBNV_FW_PREV_TRIED) ? "B" : "A";
624 } else if (!strcasecmp(name, "fw_prev_result")) {
625 int v = VbGetNvStorage(VBNV_FW_PREV_RESULT);
626 if (v < ARRAY_SIZE(fw_results))
627 return fw_results[v];
628 else
629 return "unknown";
630 } else if (!strcasecmp(name,"dev_default_boot")) {
631 int v = VbGetNvStorage(VBNV_DEV_DEFAULT_BOOT);
632 if (v < ARRAY_SIZE(default_boot))
633 return default_boot[v];
634 else
635 return "unknown";
636 }
637
638 return NULL;
Randall Spangler54218662011-02-07 11:20:20 -0800639}
640
Randall Spangler54218662011-02-07 11:20:20 -0800641
Randall Spanglerfb267152016-10-11 15:28:16 -0700642int VbSetSystemPropertyInt(const char *name, int value)
643{
644 /* Check architecture-dependent properties first */
Randall Spanglereb591952011-04-07 10:02:00 -0700645
Randall Spanglerfb267152016-10-11 15:28:16 -0700646 if (0 == VbSetArchPropertyInt(name, value))
647 return 0;
Randall Spanglereb591952011-04-07 10:02:00 -0700648
Randall Spanglerfb267152016-10-11 15:28:16 -0700649 /* NV storage values */
650 if (!strcasecmp(name,"nvram_cleared")) {
651 /* Can only clear this flag; it's set inside the NV storage
652 * library. */
653 return VbSetNvStorage(VBNV_KERNEL_SETTINGS_RESET, 0);
654 } else if (!strcasecmp(name,"recovery_request")) {
655 return VbSetNvStorage(VBNV_RECOVERY_REQUEST, value);
656 } else if (!strcasecmp(name,"recovery_subcode")) {
657 return VbSetNvStorage(VBNV_RECOVERY_SUBCODE, value);
658 } else if (!strcasecmp(name,"dbg_reset")) {
659 return VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value);
660 } else if (!strcasecmp(name,"disable_dev_request")) {
661 return VbSetNvStorage(VBNV_DISABLE_DEV_REQUEST, value);
662 } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
663 return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST, value);
664 } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
665 /* Can only clear this flag; it's set by firmware. */
666 return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE, 0);
667 } else if (!strcasecmp(name,"fwb_tries")) {
668 return VbSetNvStorage(VBNV_TRY_B_COUNT, value);
669 } else if (!strcasecmp(name,"fw_try_count")) {
670 return VbSetNvStorage(VBNV_FW_TRY_COUNT, value);
671 } else if (!strcasecmp(name,"oprom_needed")) {
672 return VbSetNvStorage(VBNV_OPROM_NEEDED, value);
673 } else if (!strcasecmp(name,"wipeout_request")) {
674 /* Can only clear this flag, set only by firmware. */
675 return VbSetNvStorage(VBNV_FW_REQ_WIPEOUT, 0);
676 } else if (!strcasecmp(name,"backup_nvram_request")) {
677 /* Best-effort only, since it requires firmware and TPM
678 * support. */
679 return VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, value);
680 } else if (!strcasecmp(name,"fwupdate_tries")) {
681 int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
682 if (kern_nv == -1)
683 return -1;
684 kern_nv &= ~KERN_NV_FWUPDATE_TRIES_MASK;
685 kern_nv |= (value & KERN_NV_FWUPDATE_TRIES_MASK);
686 return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
687 } else if (!strcasecmp(name,"block_devmode")) {
688 int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
689 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;
694 return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
695 } else if (!strcasecmp(name,"tpm_attack")) {
696 /* This value should only be read and cleared, but we allow
697 * setting it to 1 for testing. */
698 int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
699 if (kern_nv == -1)
700 return -1;
701 kern_nv &= ~KERN_NV_TPM_ATTACK_FLAG;
702 if (value)
703 kern_nv |= KERN_NV_TPM_ATTACK_FLAG;
704 return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
705 } else if (!strcasecmp(name,"loc_idx")) {
706 return VbSetNvStorage_WithBackup(VBNV_LOCALIZATION_INDEX,
707 value);
708 } else if (!strcasecmp(name,"dev_boot_usb")) {
709 return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_USB, value);
710 } else if (!strcasecmp(name,"dev_boot_legacy")) {
711 return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_LEGACY, value);
712 } else if (!strcasecmp(name,"dev_boot_signed_only")) {
713 return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_SIGNED_ONLY,
714 value);
715 } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
716 return VbSetNvStorage_WithBackup(
717 VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, value);
718 } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
719 return VbSetNvStorage_WithBackup(VBNV_FASTBOOT_UNLOCK_IN_FW,
720 value);
721 } else if (!strcasecmp(name, "boot_on_ac_detect")) {
722 return VbSetNvStorage_WithBackup(VBNV_BOOT_ON_AC_DETECT, value);
723 } else if (!strcasecmp(name, "try_ro_sync")) {
724 return VbSetNvStorage_WithBackup(VBNV_TRY_RO_SYNC, value);
725 } else if (!strcasecmp(name, "battery_cutoff_request")) {
726 return VbSetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST, value);
727 }
728
729 return -1;
Randall Spangler54218662011-02-07 11:20:20 -0800730}
731
Randall Spanglerfb267152016-10-11 15:28:16 -0700732int VbSetSystemPropertyString(const char* name, const char* value)
733{
734 /* Chain to architecture-dependent properties */
735 if (0 == VbSetArchPropertyString(name, value))
736 return 0;
Randall Spangler54218662011-02-07 11:20:20 -0800737
Randall Spanglerfb267152016-10-11 15:28:16 -0700738 if (!strcasecmp(name, "fw_try_next")) {
739 if (!strcasecmp(value, "A"))
740 return VbSetNvStorage(VBNV_FW_TRY_NEXT, 0);
741 else if (!strcasecmp(value, "B"))
742 return VbSetNvStorage(VBNV_FW_TRY_NEXT, 1);
743 else
744 return -1;
Randall Spanglerd7728232011-04-08 14:04:21 -0700745
Randall Spanglerfb267152016-10-11 15:28:16 -0700746 } else if (!strcasecmp(name, "fw_result")) {
747 int i;
Randall Spangler54218662011-02-07 11:20:20 -0800748
Randall Spanglerfb267152016-10-11 15:28:16 -0700749 for (i = 0; i < ARRAY_SIZE(fw_results); i++) {
750 if (!strcasecmp(value, fw_results[i]))
751 return VbSetNvStorage(VBNV_FW_RESULT, i);
752 }
753 return -1;
754 } else if (!strcasecmp(name, "dev_default_boot")) {
755 int i;
Randall Spanglere73302c2011-02-18 14:53:01 -0800756
Randall Spanglerfb267152016-10-11 15:28:16 -0700757 for (i = 0; i < ARRAY_SIZE(default_boot); i++) {
758 if (!strcasecmp(value, default_boot[i]))
759 return VbSetNvStorage(VBNV_DEV_DEFAULT_BOOT, i);
760 }
761 return -1;
762 }
763
764 return -1;
Randall Spangler54218662011-02-07 11:20:20 -0800765}
766
Randall Spangler770202f2016-09-28 11:54:20 -0700767static int InAndroid(void)
768{
769 int fd;
770 struct stat s;
771 int retval = 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700772
Randall Spangler770202f2016-09-28 11:54:20 -0700773 /*
774 * In Android, mosys utility located in /system/bin check if file
775 * exists. Using fstat because for some reason, stat() was seg
776 * faulting in Android
777 */
778 fd = open(MOSYS_ANDROID_PATH, O_RDONLY);
779 if (fd != -1) {
780 if (fstat(fd, &s) == 0)
781 retval = 1;
782 close(fd);
783 }
784 return retval;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700785}
786
Randall Spanglerfb267152016-10-11 15:28:16 -0700787static int ExecuteMosys(char * const argv[], char *buf, size_t bufsize)
788{
789 int status, mosys_to_crossystem[2];
790 pid_t pid;
791 ssize_t n;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700792
Randall Spanglerfb267152016-10-11 15:28:16 -0700793 if (pipe(mosys_to_crossystem) < 0) {
794 VBDEBUG(("pipe() error\n"));
795 return -1;
796 }
Duncan Lauriee98431f2016-03-30 09:35:20 -0700797
Randall Spanglerfb267152016-10-11 15:28:16 -0700798 if ((pid = fork()) < 0) {
799 VBDEBUG(("fork() error\n"));
800 close(mosys_to_crossystem[0]);
801 close(mosys_to_crossystem[1]);
802 return -1;
803 } else if (!pid) { /* Child */
804 close(mosys_to_crossystem[0]);
805 /* Redirect pipe's write-end to mosys' stdout */
806 if (STDOUT_FILENO != mosys_to_crossystem[1]) {
807 if (dup2(mosys_to_crossystem[1], STDOUT_FILENO)
808 != STDOUT_FILENO) {
809 VBDEBUG(("stdout dup2() failed (mosys)\n"));
810 close(mosys_to_crossystem[1]);
811 exit(1);
812 }
813 }
814 /* Execute mosys */
815 execv(InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH, argv);
816 /* We shouldn't be here; exit now! */
817 VBDEBUG(("execv() of mosys failed\n"));
818 close(mosys_to_crossystem[1]);
819 exit(1);
820 } else { /* Parent */
821 close(mosys_to_crossystem[1]);
822 if (bufsize) {
823 bufsize--; /* Reserve 1 byte for '\0' */
824 while ((n = read(mosys_to_crossystem[0],
825 buf, bufsize)) > 0) {
826 buf += n;
827 bufsize -= n;
828 }
829 *buf = '\0';
830 } else {
831 n = 0;
832 }
833 close(mosys_to_crossystem[0]);
834 if (n < 0)
835 VBDEBUG(("read() error reading output from mosys\n"));
836 if (waitpid(pid, &status, 0) < 0 || status) {
837 VBDEBUG(("waitpid() or mosys error\n"));
838 fprintf(stderr, "waitpid() or mosys error\n");
839 return -1;
840 }
841 if (n < 0)
842 return -1;
843 }
844 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700845}
846
Randall Spanglerfb267152016-10-11 15:28:16 -0700847int VbReadNvStorage_mosys(VbNvContext *vnc)
848{
849 char hexstring[VBNV_BLOCK_SIZE * 2 + 32]; /* Reserve extra 32 bytes */
850 char * const argv[] = {
851 InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
852 "nvram", "vboot", "read", NULL
853 };
854 char hexdigit[3];
855 int i;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700856
Randall Spanglerfb267152016-10-11 15:28:16 -0700857 if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
858 return -1;
859 hexdigit[2] = '\0';
860 for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
861 hexdigit[0] = hexstring[i * 2];
862 hexdigit[1] = hexstring[i * 2 + 1];
863 vnc->raw[i] = strtol(hexdigit, NULL, 16);
864 }
865 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700866}
867
Randall Spanglerfb267152016-10-11 15:28:16 -0700868int VbWriteNvStorage_mosys(VbNvContext* vnc)
869{
870 char hexstring[VBNV_BLOCK_SIZE * 2 + 1];
871 char * const argv[] = {
872 InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
873 "nvram", "vboot", "write", hexstring, NULL
874 };
875 int i;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700876
Randall Spanglerfb267152016-10-11 15:28:16 -0700877 for (i = 0; i < VBNV_BLOCK_SIZE; i++)
878 snprintf(hexstring + i * 2, 3, "%02x", vnc->raw[i]);
879 hexstring[sizeof(hexstring) - 1] = '\0';
880 if (ExecuteMosys(argv, NULL, 0))
881 return -1;
882 return 0;
Duncan Lauriee98431f2016-03-30 09:35:20 -0700883}