summaryrefslogtreecommitdiff
path: root/tests/vboot_nvstorage_test.c
blob: 8f62317bab85bc5855bf20881058b189fb9f127b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Tests for firmware image library.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "test_common.h"
#include "vboot_common.h"
#include "vboot_nvstorage.h"

#if 0

/* Initialize the NV storage library.  This must be called before any
 * other functions in this library. Returns 0 if success, non-zero if
 * error. */
int VbNvSetup(VbNvContext* context);

/* Clean up and flush changes back to the raw data.  This must be
 * called after other functions in this library.  Caller must check
 * context.raw_changed after calling tis function.  Returns 0 if
 * success, non-zero if error. */
int VbNvTeardown(VbNvContext* context);

/* Read a NV storage parameter into *dest.  Returns 0 if success,
 * non-zero if error. */
int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest);

/* Set a NV storage param to a new value.  Returns 0 if success,
 * non-zero if error. */
int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value);

typedef struct VbNvContext {
  /* Raw NV data.  Caller must fill this before calling VbNvStart(). */
  uint8_t raw[NV_BLOCK_SIZE];
  /* Flag indicating whether raw data has changed.  Set by VbNvStop() if
   * the raw data has changed and needs to be stored to the underlying
   * non-volatile data store. */
  int raw_changed;

  /* Internal data for NV storage routines.  Caller should not touch
   * these fields. */
  int regenerate_crc;

} VbNvContext;

#endif

static void VbStorageTest(void) {

  VbNvContext c;
  uint8_t goodcrc;
  uint32_t data;

  memset(&c, 0xA6, sizeof(c));

  /* Open with invalid data should set defaults */
  TEST_EQ(VbNvSetup(&c), 0, "VbNvSetup()");
  TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte");
  /* Close then regenerates the CRC */
  TEST_EQ(VbNvTeardown(&c), 0, "VbNvTeardown()");
  TEST_NEQ(c.raw[15], 0, "VbNvTeardown() CRC");
  TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed");
  goodcrc = c.raw[15];
  /* Another open-close pair should not cause further changes */
  VbNvSetup(&c);
  VbNvTeardown(&c);
  TEST_EQ(c.raw_changed, 0, "VbNvTeardown() didn't change");
  TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same");

  /* Perturbing the header should force defaults */
  c.raw[0] ^= 0x40;
  VbNvSetup(&c);
  TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte again");
  /* Close then regenerates the CRC */
  VbNvTeardown(&c);
  TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again");
  TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again");

  /* So should perturbing some other byte */
  TEST_EQ(c.raw[11], 0, "Kernel byte starts at 0");
  c.raw[11] = 12;
  VbNvSetup(&c);
  TEST_EQ(c.raw[11], 0, "VbNvSetup() reset kernel byte");
  /* Close then regenerates the CRC */
  VbNvTeardown(&c);
  TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again");
  TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again");

  /* Clear the kernel and firmware flags */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data), 0,
          "Get firmware settings reset");
  TEST_EQ(data, 1, "Firmware settings are reset");
  TEST_EQ(VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 0), 0,
          "Clear firmware settings reset");
  VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data);
  TEST_EQ(data, 0, "Firmware settings are clear");

  TEST_EQ(VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data), 0,
          "Get kernel settings reset");
  TEST_EQ(data, 1, "Kernel settings are reset");
  TEST_EQ(VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 0), 0,
          "Clear kernel settings reset");
  VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data);
  TEST_EQ(data, 0, "Kernel settings are clear");
  TEST_EQ(c.raw[0], 0x40, "Header byte now just has the header bit");
  VbNvTeardown(&c);
  /* That should have changed the CRC */
  TEST_NEQ(c.raw[15], goodcrc, "VbNvTeardown() CRC changed due to flags clear");

  /* Test debug reset mode field */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_DEBUG_RESET_MODE, &data), 0,
          "Get debug reset mode");
  TEST_EQ(data, 0, "Debug reset mode default");
  TEST_EQ(VbNvSet(&c, VBNV_DEBUG_RESET_MODE, 1), 0,
          "Set debug reset mode");
  VbNvGet(&c, VBNV_DEBUG_RESET_MODE, &data);
  TEST_EQ(data, 1, "Debug reset mode set");
  VbNvTeardown(&c);

  /* Test try B count */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_TRY_B_COUNT, &data), 0, "Get try b count");
  TEST_EQ(data, 0, "Try b count default");
  TEST_EQ(VbNvSet(&c, VBNV_TRY_B_COUNT, 6), 0, "Set try b count");
  VbNvGet(&c, VBNV_TRY_B_COUNT, &data);
  TEST_EQ(data, 6, "Try b count set");
  VbNvSet(&c, VBNV_TRY_B_COUNT, 15);
  VbNvGet(&c, VBNV_TRY_B_COUNT, &data);
  TEST_EQ(data, 15, "Try b count set 2");
  VbNvTeardown(&c);

  /* Test recovery request */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data), 0, "Get recovery request");
  TEST_EQ(data, 0, "Default recovery request");
  TEST_EQ(VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0x42), 0, "Set recovery request");
  VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data);
  TEST_EQ(data, 0x42, "Set recovery request");
  VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0xED);
  VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data);
  TEST_EQ(data, 0xED, "Set recovery request 2");
  VbNvTeardown(&c);

  /* Test localization index */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data), 0,
          "Get localization index");
  TEST_EQ(data, 0, "Default localization index");
  TEST_EQ(VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0x69), 0,
          "Set localization index");
  VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data);
  TEST_EQ(data, 0x69, "Set localization index");
  VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0xB0);
  VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data);
  TEST_EQ(data, 0xB0, "Set localization index 2");
  VbNvTeardown(&c);

  /* Test kernel field */
  VbNvSetup(&c);
  TEST_EQ(VbNvGet(&c, VBNV_KERNEL_FIELD, &data), 0, "Get kernel field");
  TEST_EQ(data, 0, "Default kernel field");
  TEST_EQ(VbNvSet(&c, VBNV_KERNEL_FIELD, 0x12345678), 0, "Set kernel field");
  VbNvGet(&c, VBNV_KERNEL_FIELD, &data);
  TEST_EQ(data, 0x12345678, "Set kernel field");
  VbNvSet(&c, VBNV_KERNEL_FIELD, 0xFEDCBA98);
  VbNvGet(&c, VBNV_KERNEL_FIELD, &data);
  TEST_EQ(data, 0xFEDCBA98, "Set kernel field 2");
  VbNvTeardown(&c);

  /* None of those changes should have caused a reset to defaults */
  VbNvSetup(&c);
  VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data);
  TEST_EQ(data, 0, "Firmware settings are still clear");
  VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data);
  TEST_EQ(data, 0, "Kernel settings are still clear");
  VbNvTeardown(&c);

  /* Verify writing identical settings doesn't cause the CRC to regenerate */
  VbNvSetup(&c);
  TEST_EQ(c.regenerate_crc, 0, "No regen CRC on open");
  VbNvSet(&c, VBNV_DEBUG_RESET_MODE, 1);
  VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0xED);
  VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0xB0);
  VbNvSet(&c, VBNV_KERNEL_FIELD, 0xFEDCBA98);
  TEST_EQ(c.regenerate_crc, 0, "No regen CRC if data not changed");
  VbNvTeardown(&c);
  TEST_EQ(c.raw_changed, 0, "No raw change if data not changed");
}


/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))

int main(int argc, char* argv[]) {
  int error_code = 0;

  VbStorageTest();

  if (!gTestSuccess)
    error_code = 255;

  return error_code;
}