Software APIs
shutdown_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/silicon_creator/lib/shutdown.h"
6 
7 #include <array>
8 
9 #include "gtest/gtest.h"
10 #include "sw/device/lib/base/global_mock.h"
13 #include "sw/device/lib/base/mock_abs_mmio.h"
14 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
15 #include "sw/device/silicon_creator/lib/drivers/mock_alert.h"
16 #include "sw/device/silicon_creator/lib/drivers/mock_otp.h"
17 #include "sw/device/silicon_creator/lib/error.h"
18 #include "sw/device/silicon_creator/testing/rom_test.h"
19 
20 #include "alert_handler_regs.h"
21 #include "flash_ctrl_regs.h"
23 #include "lc_ctrl_regs.h"
24 #include "otp_ctrl_regs.h"
25 #include "rv_core_ibex_regs.h"
26 
27 namespace shutdown_unittest {
28 
29 using ::testing::ElementsAre;
30 using ::testing::Invoke;
31 using ::testing::Return;
32 using ::testing::Test;
33 
34 namespace {
35 
36 namespace internal {
37 // Create a mock for internal shutdown functions.
38 class MockShutdownImpl : public ::global_mock::GlobalMock<MockShutdownImpl> {
39  public:
40  MOCK_METHOD(void, shutdown_report_error, (rom_error_t));
41  MOCK_METHOD(void, shutdown_software_escalate, ());
42  MOCK_METHOD(void, shutdown_keymgr_kill, ());
43  MOCK_METHOD(void, shutdown_reset, ());
44  MOCK_METHOD(void, shutdown_flash_kill, ());
45  MOCK_METHOD(void, shutdown_hang, ());
46 };
47 
48 } // namespace internal
49 using MockShutdownImpl = testing::StrictMock<internal::MockShutdownImpl>;
50 extern "C" {
51 void shutdown_report_error(rom_error_t error) {
52  return MockShutdownImpl::Instance().shutdown_report_error(error);
53 }
54 void shutdown_software_escalate(void) {
55  return MockShutdownImpl::Instance().shutdown_software_escalate();
56 }
57 void shutdown_keymgr_kill(void) {
58  return MockShutdownImpl::Instance().shutdown_keymgr_kill();
59 }
60 void shutdown_reset(void) {
61  return MockShutdownImpl::Instance().shutdown_reset();
62 }
63 void shutdown_flash_kill(void) {
64  return MockShutdownImpl::Instance().shutdown_flash_kill();
65 }
66 void shutdown_hang(void) {
67  return MockShutdownImpl::Instance().shutdown_hang();
68 }
69 
70 // Real implementations of the above mocks.
71 extern void unmocked_shutdown_flash_kill(void);
72 extern void unmocked_shutdown_software_escalate(void);
73 } // extern "C"
74 
75 constexpr uint32_t Pack32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
76  uint32_t result = (a << 0) | (b << 8) | (c << 16) | (d << 24);
77  return result;
78 }
79 
80 #define FULL(name, prod, prodend, dev, rma) \
81  { \
82  name, kAlertClass##prod, kAlertClass##prodend, kAlertClass##dev, \
83  kAlertClass##rma \
84  }
85 
86 #define CLASSIFY(name, prod, prodend, dev, rma) \
87  Pack32(kAlertClass##prod, kAlertClass##prodend, kAlertClass##dev, \
88  kAlertClass##rma)
89 
90 // This alert configuration is described in the ROM Shutdown specification:
91 // https://docs.google.com/document/d/1V8hRvQnJhsvddieJbRHS3azbPZvoBWxfxPZV_0YA1QU/edit#
92 // Dummy alerts have been added to prevent the tests breaking when new alerts
93 // are added (see #7183). These lists of alerts and local alerts are for test
94 // purposes only and may not be complete and/or up to date.
95 // clang-format off
96 #define ALERTS(Xmacro) \
97  Xmacro("Uart0FatalFault", C, C, X, X), \
98  Xmacro("Uart1FatalFault", C, C, X, X), \
99  Xmacro("Uart2FatalFault", C, C, X, X), \
100  Xmacro("Uart3FatalFault", C, C, X, X), \
101  Xmacro("GpioFatalFault", C, C, X, X), \
102  Xmacro("SpiDeviceFatalFault", C, C, X, X), \
103  Xmacro("SpiHost0FatalFault", C, C, X, X), \
104  Xmacro("SpiHost1FatalFault", C, C, X, X), \
105  Xmacro("I2c0FatalFault", C, C, X, X), \
106  Xmacro("I2c1FatalFault", C, C, X, X), \
107  Xmacro("I2c2FatalFault", C, C, X, X), \
108  Xmacro("PattgenFatalFault", C, C, X, X), \
109  Xmacro("OtpCtrlFatalMacroError", A, A, X, X), \
110  Xmacro("OtpCtrlFatalCheckError", A, A, X, X), \
111  Xmacro("LcCtrlFatalProgError", A, A, X, X), \
112  Xmacro("LcCtrlFatalStateError", A, A, X, X), \
113  Xmacro("LcCtrlFatalBusIntegError", A, A, X, X), \
114  Xmacro("PwrmgrAonFatalFault", C, C, X, X), \
115  Xmacro("RstmgrAonFatalFault", C, C, X, X), \
116  Xmacro("ClkmgrAonFatalFault", C, C, X, X), \
117  Xmacro("SysrstCtrlAonFatalFault", C, C, X, X), \
118  Xmacro("AdcCtrlAonFatalFault", C, C, X, X), \
119  Xmacro("PwmAonFatalFault", C, C, X, X), \
120  Xmacro("PinmuxAonFatalFault", C, C, X, X), \
121  Xmacro("AonTimerAonFatalFault", C, C, X, X), \
122  Xmacro("SensorCtrlAonRecovAs", B, B, X, X), \
123  Xmacro("SensorCtrlAonRecovCg", C, C, X, X), \
124  Xmacro("SensorCtrlAonRecovGd", C, C, X, X), \
125  Xmacro("SensorCtrlAonRecovTsHi", C, C, X, X), \
126  Xmacro("SensorCtrlAonRecovTsLo", C, C, X, X), \
127  Xmacro("SensorCtrlAonRecovFla", C, C, X, X), \
128  Xmacro("SensorCtrlAonRecovOtp", C, C, X, X), \
129  Xmacro("SensorCtrlAonRecovOt0", C, C, X, X), \
130  Xmacro("SensorCtrlAonRecovOt1", C, C, X, X), \
131  Xmacro("SensorCtrlAonRecovOt2", C, C, X, X), \
132  Xmacro("SensorCtrlAonRecovOt3", C, C, X, X), \
133  Xmacro("SensorCtrlAonRecovOt4", C, C, X, X), \
134  Xmacro("SensorCtrlAonRecovOt5", C, C, X, X), \
135  Xmacro("SramCtrlRetAonFatalIntgError", B, B, X, X), \
136  Xmacro("SramCtrlRetAonFatalParityError", B, B, X, X), \
137  Xmacro("FlashCtrlRecovErr", D, D, X, X), \
138  Xmacro("FlashCtrlRecovMpErr", D, D, X, X), \
139  Xmacro("FlashCtrlRecovEccErr", D, D, X, X), \
140  Xmacro("FlashCtrlFatalIntgErr", A, A, X, X), \
141  Xmacro("RvPlicFatalFault", A, A, X, X), \
142  Xmacro("AesRecovCtrlUpdateErr", D, D, X, X), \
143  Xmacro("AesFatalFault", A, A, X, X), \
144  Xmacro("HmacFatalFault", A, A, X, X), \
145  Xmacro("KmacFatalFault", A, A, X, X), \
146  Xmacro("KeymgrFatalFaultErr", A, A, X, X), \
147  Xmacro("KeymgrRecovOperationErr", D, D, X, X), \
148  Xmacro("CsrngFatalAlert", A, A, X, X), \
149  Xmacro("EntropySrcRecovAlert", D, D, X, X), \
150  Xmacro("EntropySrcFatalAlert", A, A, X, X), \
151  Xmacro("Edn0FatalAlert", A, A, X, X), \
152  Xmacro("Edn1FatalAlert", A, A, X, X), \
153  Xmacro("SramCtrlMainFatalIntgError", A, A, X, X), \
154  Xmacro("SramCtrlMainFatalParityError", A, A, X, X), \
155  Xmacro("OtbnFatal", A, A, X, X), \
156  Xmacro("OtbnRecov", D, D, X, X), \
157  Xmacro("RomCtrlFatal", A, A, X, X), \
158  Xmacro("Dummy61", X, X, X, X), \
159  Xmacro("Dummy62", X, X, X, X), \
160  Xmacro("Dummy63", X, X, X, X), \
161  Xmacro("Dummy64", X, X, X, X), \
162  Xmacro("Dummy65", X, X, X, X), \
163  Xmacro("Dummy66", X, X, X, X), \
164  Xmacro("Dummy67", X, X, X, X), \
165  Xmacro("Dummy68", X, X, X, X), \
166  Xmacro("Dummy69", X, X, X, X), \
167  Xmacro("Dummy70", X, X, X, X), \
168  Xmacro("Dummy71", X, X, X, X), \
169  Xmacro("Dummy72", X, X, X, X), \
170  Xmacro("Dummy73", X, X, X, X), \
171  Xmacro("Dummy74", X, X, X, X), \
172  Xmacro("Dummy75", X, X, X, X), \
173  Xmacro("Dummy76", X, X, X, X), \
174  Xmacro("Dummy77", X, X, X, X), \
175  Xmacro("Dummy78", X, X, X, X), \
176  Xmacro("Dummy79", X, X, X, X)
177 
178 #define LOC_ALERTS(Xmacro) \
179  Xmacro("LocAlertPingFail", A, A, X, X), \
180  Xmacro("LocEscPingFail", A, A, X, X), \
181  Xmacro("LocAlertIntegrityFail", A, A, X, X), \
182  Xmacro("LocEscIntegrityFail", A, A, X, X), \
183  Xmacro("LocBusIntegrityFail", A, A, X, X), \
184  Xmacro("LocShadowRegUpdateFail", A, A, X, X), \
185  Xmacro("LocShadowRegStorageError", A, A, X, X), \
186  Xmacro("LocDummy7", X, X, X, X), \
187  Xmacro("LocDummy8", X, X, X, X), \
188  Xmacro("LocDummy9", X, X, X, X), \
189  Xmacro("LocDummy10", X, X, X, X), \
190  Xmacro("LocDummy11", X, X, X, X), \
191  Xmacro("LocDummy12", X, X, X, X), \
192  Xmacro("LocDummy13", X, X, X, X), \
193  Xmacro("LocDummy14", X, X, X, X), \
194  Xmacro("LocDummy15", X, X, X, X),
195 // clang-format on
196 
198  uint32_t rom_error_reporting;
199  uint32_t rom_bootstrap_en;
200  uint32_t rom_alert_class_en;
201  uint32_t rom_alert_escalation;
202  uint32_t rom_alert_classification[80];
203  uint32_t rom_local_alert_classification[16];
204  uint32_t rom_alert_accum_thresh[4];
205  uint32_t rom_alert_timeout_cycles[4];
206  uint32_t rom_alert_phase_cycles[4][4];
207 };
208 
210  const char *name;
211  alert_class_t prod;
212  alert_class_t prodend;
213  alert_class_t dev;
214  alert_class_t rma;
215 };
216 
217 constexpr OtpConfiguration kOtpConfig = {
218  .rom_error_reporting = (uint32_t)kShutdownErrorRedactNone,
219  .rom_bootstrap_en = 1,
220  .rom_alert_class_en = Pack32(kAlertEnableLocked, kAlertEnableEnabled,
221  kAlertEnableNone, kAlertEnableNone),
222  .rom_alert_escalation = Pack32(kAlertEscalatePhase3, kAlertEscalatePhase3,
223  kAlertEscalateNone, kAlertEscalateNone),
224  .rom_alert_classification = {ALERTS(CLASSIFY)},
225  .rom_local_alert_classification = {LOC_ALERTS(CLASSIFY)},
226  .rom_alert_accum_thresh = {0, 0, 0, 0},
227  .rom_alert_timeout_cycles = {0, 0, 0, 0},
228  .rom_alert_phase_cycles =
229  {
230  {0, 10, 10, 0xFFFFFFFF}, // Class A
231  {0, 10, 10, 0xFFFFFFFF}, // Class B
232  {0, 0, 0, 0}, // Class C
233  {0, 0, 0, 0}, // Class D
234  },
235 };
236 
237 constexpr DefaultAlertClassification kDefaultAlertClassification[] = {
238  ALERTS(FULL),
239 };
240 static_assert(ARRAYSIZE(kDefaultAlertClassification) <=
241  (OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_ALERT_CLASSIFICATION_SIZE /
242  4),
243  "The default alert classification must be less than or equal to "
244  "the number of reserved OTP words");
245 
246 static_assert(kTopEarlgreyAlertIdLast < ARRAYSIZE(kDefaultAlertClassification),
247  "The number of alert sources must be smaller than the alert "
248  "classification");
249 
250 constexpr DefaultAlertClassification kDefaultLocAlertClassification[] = {
251  LOC_ALERTS(FULL)};
252 static_assert(
253  ARRAYSIZE(kDefaultLocAlertClassification) <=
254  (OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_LOCAL_ALERT_CLASSIFICATION_SIZE / 4),
255  "The default local alert classification must be less than or "
256  "equal to the number of reserved OTP words");
257 
258 constexpr alert_class_t kClasses[] = {
259  kAlertClassA,
260  kAlertClassB,
261  kAlertClassC,
262  kAlertClassD,
263 };
264 
265 alert_enable_t RomAlertClassEnable(alert_class_t cls) {
266  // Note: these need to match with `rom_alert_class_en` above.
267  switch (cls) {
268  case kAlertClassA:
269  return kAlertEnableLocked;
270  case kAlertClassB:
271  return kAlertEnableEnabled;
272  case kAlertClassC:
273  return kAlertEnableNone;
274  case kAlertClassD:
275  return kAlertEnableNone;
276  // Class X (and all other invalid classes) default to class A's enable
277  // status.
278  default:
279  return kAlertEnableLocked;
280  }
281 }
282 
283 alert_escalate_t RomAlertClassEscalation(alert_class_t cls) {
284  // Note: these need to match with `rom_alert_class_escalation` above.
285  switch (cls) {
286  case kAlertClassA:
287  return kAlertEscalatePhase3;
288  case kAlertClassB:
289  return kAlertEscalatePhase3;
290  case kAlertClassC:
291  return kAlertEscalateNone;
292  case kAlertClassD:
293  return kAlertEscalateNone;
294  // Class X (and all other invalid classes) default to class A's escalate
295  // setting.
296  default:
297  return kAlertEscalatePhase3;
298  }
299 }
300 
302  protected:
303  void SetupOtpReads() {
304  // Make OTP reads retrieve their values from `otp_config_`.
305  ON_CALL(otp_, read32(::testing::_)).WillByDefault([this](uint32_t address) {
306  // Must be aligned and in the SW_CFG partition.
307  EXPECT_EQ(address % 4, 0);
308  EXPECT_GE(address, OTP_CTRL_PARAM_OWNER_SW_CFG_OFFSET);
309  EXPECT_LT(address,
310  OTP_CTRL_PARAM_OWNER_SW_CFG_OFFSET + sizeof(this->otp_config_));
311  // Convert the address to a word index.
312  uint32_t index = (address - OTP_CTRL_PARAM_OWNER_SW_CFG_OFFSET) / 4;
313  const uint32_t *words =
314  reinterpret_cast<const uint32_t *>(&this->otp_config_);
315  return words[index];
316  });
317  }
318 
319  void ExpectClassConfigure() {
320  ExpectClassConfigure(0);
321  ExpectClassConfigure(1);
322  ExpectClassConfigure(2);
323  ExpectClassConfigure(3);
324  }
325 
326  void ExpectClassConfigure(size_t i) {
327  alert_class_t expected_cls = kClasses[i];
328  EXPECT_CALL(alert_, alert_class_configure(expected_cls, ::testing::_))
329  .WillOnce(Invoke([this, i](alert_class_t cls,
330  const alert_class_config_t *config) {
331  alert_class_t expected_cls = kClasses[i];
332  // Would like to use testing::FiledsAre, but we need a gtest upgrade
333  // for that.
334  EXPECT_EQ(cls, expected_cls);
335  EXPECT_EQ(config->enabled, RomAlertClassEnable(expected_cls));
336  EXPECT_EQ(config->escalation, RomAlertClassEscalation(expected_cls));
337  EXPECT_EQ(config->accum_threshold,
338  otp_config_.rom_alert_accum_thresh[i]);
339  EXPECT_EQ(config->timeout_cycles,
340  otp_config_.rom_alert_timeout_cycles[i]);
341  EXPECT_THAT(config->phase_cycles,
342  ElementsAre(otp_config_.rom_alert_phase_cycles[i][0],
343  otp_config_.rom_alert_phase_cycles[i][1],
344  otp_config_.rom_alert_phase_cycles[i][2],
345  otp_config_.rom_alert_phase_cycles[i][3]));
346  return kErrorOk;
347  }));
348  }
349 
350  // Expect a call to `shutdown_finalize`.
351  void ExpectFinalize(rom_error_t error) {
352  // In the RV32 environment, finalize should never return.
353  // In the X86_64 unittest environment, verify that all of the various
354  // kill functions were called.
355  EXPECT_CALL(shutdown_, shutdown_report_error(error));
356  EXPECT_CALL(shutdown_, shutdown_software_escalate());
357  EXPECT_CALL(shutdown_, shutdown_keymgr_kill());
358  EXPECT_CALL(shutdown_, shutdown_reset());
359  EXPECT_CALL(shutdown_, shutdown_flash_kill());
360  EXPECT_CALL(shutdown_, shutdown_hang());
361  }
362 
363  OtpConfiguration otp_config_ = kOtpConfig;
364  // Use NiceMock because we aren't interested in the specifics of OTP reads,
365  // but we want to mock out calls to otp_read32.
366  rom_test::NiceMockOtp otp_;
367  MockShutdownImpl shutdown_;
368  rom_test::MockAlert alert_;
369  rom_test::MockAbsMmio mmio_;
370 };
371 
372 TEST_F(ShutdownTest, InitializeProd) {
373  SetupOtpReads();
374  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
375  ++i) {
376  const auto &c = kDefaultAlertClassification[i];
377  alert_class_t cls = c.prod;
378  alert_enable_t en = RomAlertClassEnable(cls);
379  EXPECT_CALL(alert_, alert_configure(i, cls, en)).WillOnce(Return(kErrorOk));
380  }
381  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
382  ++i) {
383  const auto &c = kDefaultLocAlertClassification[i];
384  alert_class_t cls = c.prod;
385  alert_enable_t en = RomAlertClassEnable(cls);
386  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
387  .WillOnce(Return(kErrorOk));
388  }
389  ExpectClassConfigure();
390  EXPECT_EQ(shutdown_init(kLcStateProd), kErrorOk);
391 }
392 
393 TEST_F(ShutdownTest, InitializeProdWithAlertError) {
394  SetupOtpReads();
395  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
396  ++i) {
397  const auto &c = kDefaultAlertClassification[i];
398  alert_class_t cls = c.prod;
399  alert_enable_t en = RomAlertClassEnable(cls);
400  // Return an error on i zero. The error should not cause alert
401  // configuation to abort early (ie: still expect the rest of the
402  // alerts to get configured).
403  EXPECT_CALL(alert_, alert_configure(i, cls, en))
404  .WillOnce(Return(i == 0 ? kErrorUnknown : kErrorOk));
405  }
406  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
407  ++i) {
408  const auto &c = kDefaultLocAlertClassification[i];
409  alert_class_t cls = c.prod;
410  alert_enable_t en = RomAlertClassEnable(cls);
411  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
412  .WillOnce(Return(kErrorOk));
413  }
414  ExpectClassConfigure();
415  // We expect to get the error from alert configuration.
416  EXPECT_EQ(shutdown_init(kLcStateProd), kErrorUnknown);
417 }
418 
419 TEST_F(ShutdownTest, InitializeProdWithLocalAlertError) {
420  SetupOtpReads();
421  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
422  ++i) {
423  const auto &c = kDefaultAlertClassification[i];
424  alert_class_t cls = c.prod;
425  alert_enable_t en = RomAlertClassEnable(cls);
426  EXPECT_CALL(alert_, alert_configure(i, cls, en)).WillOnce(Return(kErrorOk));
427  }
428  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
429  ++i) {
430  const auto &c = kDefaultLocAlertClassification[i];
431  alert_class_t cls = c.prod;
432  alert_enable_t en = RomAlertClassEnable(cls);
433  // Return an error on i zero. The error should not cause alert
434  // configuation to abort early (ie: still expect the rest of the
435  // alerts to get configured).
436  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
437  .WillOnce(Return(i == 0 ? kErrorUnknown : kErrorOk));
438  }
439  ExpectClassConfigure();
440  // We expect to get the error from alert configuration.
441  EXPECT_EQ(shutdown_init(kLcStateProd), kErrorUnknown);
442 }
443 
444 TEST_F(ShutdownTest, InitializeProdEnd) {
445  SetupOtpReads();
446  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
447  ++i) {
448  const auto &c = kDefaultAlertClassification[i];
449  alert_class_t cls = c.prodend;
450  alert_enable_t en = RomAlertClassEnable(cls);
451  EXPECT_CALL(alert_, alert_configure(i, cls, en)).WillOnce(Return(kErrorOk));
452  }
453  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
454  ++i) {
455  const auto &c = kDefaultLocAlertClassification[i];
456  alert_class_t cls = c.prodend;
457  alert_enable_t en = RomAlertClassEnable(cls);
458  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
459  .WillOnce(Return(kErrorOk));
460  }
461  ExpectClassConfigure();
462  EXPECT_EQ(shutdown_init(kLcStateProdEnd), kErrorOk);
463 }
464 
465 TEST_F(ShutdownTest, InitializeDev) {
466  SetupOtpReads();
467  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
468  ++i) {
469  const auto &c = kDefaultAlertClassification[i];
470  alert_class_t cls = c.dev;
471  alert_enable_t en = RomAlertClassEnable(cls);
472  EXPECT_CALL(alert_, alert_configure(i, cls, en)).WillOnce(Return(kErrorOk));
473  }
474  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
475  ++i) {
476  const auto &c = kDefaultLocAlertClassification[i];
477  alert_class_t cls = c.dev;
478  alert_enable_t en = RomAlertClassEnable(cls);
479  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
480  .WillOnce(Return(kErrorOk));
481  }
482  ExpectClassConfigure();
483  EXPECT_EQ(shutdown_init(kLcStateDev), kErrorOk);
484 }
485 
486 TEST_F(ShutdownTest, InitializeRma) {
487  SetupOtpReads();
488  for (size_t i = 0; i < ALERT_HANDLER_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
489  ++i) {
490  const auto &c = kDefaultAlertClassification[i];
491  alert_class_t cls = c.rma;
492  alert_enable_t en = RomAlertClassEnable(cls);
493  EXPECT_CALL(alert_, alert_configure(i, cls, en)).WillOnce(Return(kErrorOk));
494  }
495  for (size_t i = 0; i < ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_MULTIREG_COUNT;
496  ++i) {
497  const auto &c = kDefaultLocAlertClassification[i];
498  alert_class_t cls = c.rma;
499  alert_enable_t en = RomAlertClassEnable(cls);
500  EXPECT_CALL(alert_, alert_local_configure(i, cls, en))
501  .WillOnce(Return(kErrorOk));
502  }
503  ExpectClassConfigure();
504  EXPECT_EQ(shutdown_init(kLcStateRma), kErrorOk);
505 }
506 
507 TEST_F(ShutdownTest, RedactPolicyManufacturing) {
508  // Devices in manufacturing or RMA states should not redact errors regardless
509  // of the redaction level set by OTP.
510  constexpr std::array<uint32_t, 9> kManufacturingStates = {
511  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0,
512  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1,
513  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2,
514  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3,
515  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4,
516  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5,
517  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6,
518  LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7,
519  LC_CTRL_LC_STATE_STATE_VALUE_RMA,
520  };
521  for (const auto state : kManufacturingStates) {
522  EXPECT_ABS_READ32(
523  TOP_EARLGREY_LC_CTRL_REGS_BASE_ADDR + LC_CTRL_LC_STATE_REG_OFFSET,
524  static_cast<uint32_t>(state));
525  EXPECT_EQ(shutdown_redact_policy(), kShutdownErrorRedactNone);
526  }
527 }
528 
529 TEST_F(ShutdownTest, RedactPolicyProduction) {
530  // Production states should read redaction level from OTP.
531  constexpr std::array<uint32_t, 3> kProductionStates = {
532  LC_CTRL_LC_STATE_STATE_VALUE_DEV,
533  LC_CTRL_LC_STATE_STATE_VALUE_PROD,
534  LC_CTRL_LC_STATE_STATE_VALUE_PROD_END,
535  };
536  for (const auto state : kProductionStates) {
537  EXPECT_ABS_READ32(
538  TOP_EARLGREY_LC_CTRL_REGS_BASE_ADDR + LC_CTRL_LC_STATE_REG_OFFSET,
539  static_cast<uint32_t>(state));
540  EXPECT_ABS_READ32(
542  OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET +
543  OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_ERROR_REPORTING_OFFSET,
544  static_cast<uint32_t>(kShutdownErrorRedactModule));
545  EXPECT_EQ(shutdown_redact_policy(), kShutdownErrorRedactModule);
546  }
547 }
548 
549 TEST_F(ShutdownTest, RedactPolicyInvalid) {
550  // Invalid states should result in the highest redaction level regardless of
551  // the redaction level set by OTP.
552  EXPECT_ABS_READ32(
553  TOP_EARLGREY_LC_CTRL_REGS_BASE_ADDR + LC_CTRL_LC_STATE_REG_OFFSET, 0);
554  EXPECT_EQ(shutdown_redact_policy(), kShutdownErrorRedactAll);
555 }
556 
557 TEST_F(ShutdownTest, InitializeManufacturing) {
558  // OTP reads and alert setup should be skipped in the TEST_UNLOCKED lifecycle
559  // states.
560  EXPECT_EQ(shutdown_init(kLcStateTest), kErrorOk);
561 }
562 
563 class ShutdownDeathTest : public ShutdownTest {};
564 
565 TEST_F(ShutdownDeathTest, InitializeInvalid) {
566  EXPECT_DEATH(
567  {
568  SetupOtpReads();
569  OT_DISCARD(shutdown_init(static_cast<lifecycle_state_t>(0)));
570  },
571  "");
572 }
573 
574 TEST(ShutdownModule, RedactErrors) {
575  EXPECT_EQ(shutdown_redact(kErrorOk, kShutdownErrorRedactNone), 0);
576  EXPECT_EQ(shutdown_redact(kErrorOk, kShutdownErrorRedactError), 0);
577  EXPECT_EQ(shutdown_redact(kErrorOk, kShutdownErrorRedactModule), 0);
578  EXPECT_EQ(shutdown_redact(kErrorOk, kShutdownErrorRedactAll), 0);
579 
580  rom_error_t error = static_cast<rom_error_t>(0xaabbccdd);
581  EXPECT_EQ(shutdown_redact(error, kShutdownErrorRedactNone), 0xaabbccdd);
582  EXPECT_EQ(shutdown_redact(error, kShutdownErrorRedactError), 0x00bbccdd);
583  EXPECT_EQ(shutdown_redact(error, kShutdownErrorRedactModule), 0x000000dd);
584  EXPECT_EQ(shutdown_redact(error, kShutdownErrorRedactAll), 0xffffffff);
585 }
586 
587 TEST_F(ShutdownTest, ShutdownFinalize) {
588  SetupOtpReads();
589  ExpectFinalize(kErrorUnknown);
590  shutdown_finalize(kErrorUnknown);
591 }
592 
593 TEST_F(ShutdownTest, FlashKill) {
594  EXPECT_ABS_WRITE32(
595  TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR + FLASH_CTRL_DIS_REG_OFFSET, 0);
596  unmocked_shutdown_flash_kill();
597 }
598 
599 TEST_F(ShutdownTest, ShutdownIfErrorOk) { SHUTDOWN_IF_ERROR(kErrorOk); }
600 
601 TEST_F(ShutdownTest, ShutdownIfErrorUnknown) {
602  EXPECT_DEATH(
603  {
604  ExpectFinalize(kErrorUnknown);
605  SHUTDOWN_IF_ERROR(kErrorUnknown);
606  },
607  "");
608 }
609 
610 TEST_F(ShutdownTest, SoftwareEscalate) {
611  EXPECT_ABS_WRITE32(TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR +
612  RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET,
613  0);
614  unmocked_shutdown_software_escalate();
615 }
616 } // namespace
617 } // namespace shutdown_unittest