1/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6/* Non-volatile storage routines.
7 */
8#include "sysincludes.h"
9
10#include "crc8.h"
11#include "utility.h"
12#include "vboot_common.h"
13#include "vboot_nvstorage.h"
14#include "rollback_index.h"
15
16/* These are the fields of the nvram that we want to back up. */
17static const VbNvParam backup_params[] = {
18	VBNV_KERNEL_FIELD,
19	VBNV_LOCALIZATION_INDEX,
20	VBNV_DEV_BOOT_USB,
21	VBNV_DEV_BOOT_LEGACY,
22	VBNV_DEV_BOOT_SIGNED_ONLY,
23};
24
25/* We can't back things up if there isn't enough storage. */
26BUILD_ASSERT(VBNV_BLOCK_SIZE <= BACKUP_NV_SIZE);
27
28int RestoreNvFromBackup(VbNvContext *vnc)
29{
30	VbNvContext bvnc;
31	uint32_t value;
32	int i;
33
34	VBDEBUG(("TPM: %s()\n", __func__));
35
36	if (TPM_SUCCESS != RollbackBackupRead(bvnc.raw))
37		return 1;
38
39	VbNvSetup(&bvnc);
40	if (bvnc.regenerate_crc) {
41		VBDEBUG(("TPM: Oops, backup is no good.\n"));
42		return 1;
43	}
44
45	for (i = 0; i < ARRAY_SIZE(backup_params); i++) {
46		VbNvGet(&bvnc, backup_params[i], &value);
47		VbNvSet(vnc, backup_params[i], value);
48	}
49
50	/* VbNvTeardown(&bvnc); is not needed. We're done with it. */
51	return 0;
52}
53
54int SaveNvToBackup(VbNvContext *vnc)
55{
56	VbNvContext bvnc;
57	uint32_t value;
58	int i;
59
60	VBDEBUG(("TPM: %s()\n", __func__));
61
62	/* Read it first. No point in writing the same data. */
63	if (TPM_SUCCESS != RollbackBackupRead(bvnc.raw))
64		return 1;
65
66	VbNvSetup(&bvnc);
67	VBDEBUG(("TPM: existing backup is %s\n",
68		 bvnc.regenerate_crc ? "bad" : "good"));
69
70	for (i = 0; i < ARRAY_SIZE(backup_params); i++) {
71		VbNvGet(vnc, backup_params[i], &value);
72		VbNvSet(&bvnc, backup_params[i], value);
73	}
74
75	VbNvTeardown(&bvnc);
76
77	if (!bvnc.raw_changed) {
78		VBDEBUG(("TPM: Nothing's changed, not writing backup\n"));
79		/* Clear the request flag, since we're happy. */
80		VbNvSet(vnc, VBNV_BACKUP_NVRAM_REQUEST, 0);
81		return 0;
82	}
83
84	if (TPM_SUCCESS == RollbackBackupWrite(bvnc.raw)) {
85		/* Clear the request flag if we wrote successfully too */
86		VbNvSet(vnc, VBNV_BACKUP_NVRAM_REQUEST, 0);
87		return 0;
88	}
89
90	VBDEBUG(("TPM: Sorry, couldn't write backup.\n"));
91	return 1;
92}
93