Software APIs
boot_svc_primary_test.c
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/lib/base/status.h"
8 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
9 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_next_boot_bl0_slot.h"
10 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
11 #include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
12 #include "sw/device/silicon_creator/rom_ext/e2e/boot_svc/boot_svc_test_lib.h"
13 
14 OTTF_DEFINE_TEST_CONFIG();
15 
16 static status_t initialize(retention_sram_t *retram, boot_svc_retram_t *state) {
17  boot_svc_msg_t msg = {0};
18  TRY_CHECK(state->primary_side == 'A');
19  boot_svc_next_boot_bl0_slot_req_init(
20  /*primary_slot=*/kBootSlotB,
21  /*next_slot=*/kBootSlotUnspecified, &msg.next_boot_bl0_slot_req);
22 
23  retram->creator.boot_svc_msg = msg;
24  state->state = kBootSvcTestStateNextSideB;
25  rstmgr_reset();
26  return INTERNAL();
27 }
28 
29 static status_t check_side_b(retention_sram_t *retram,
30  boot_svc_retram_t *state) {
31  boot_svc_msg_t msg = retram->creator.boot_svc_msg;
32  TRY(boot_svc_header_check(&msg.header));
33  TRY_CHECK(msg.header.type == kBootSvcNextBl0SlotResType);
34  TRY_CHECK(msg.next_boot_bl0_slot_res.status == kErrorOk);
35  TRY_CHECK(msg.next_boot_bl0_slot_res.primary_bl0_slot == kBootSlotB);
36  TRY_CHECK(state->current_side == 'B');
37  TRY_CHECK(state->primary_side == 'B');
38  if (state->boots == 4) {
39  // When we reach 4 boots, transition back to SlotA.
40  boot_svc_next_boot_bl0_slot_req_init(
41  /*primary_slot=*/kBootSlotA,
42  /*next_slot=*/kBootSlotUnspecified, &msg.next_boot_bl0_slot_req);
43  retram->creator.boot_svc_msg = msg;
44  state->state = kBootSvcTestStateReturnSideA;
45  }
46  rstmgr_reset();
47  return INTERNAL();
48 }
49 
50 static status_t check_return_side_a(retention_sram_t *retram,
51  boot_svc_retram_t *state) {
52  boot_svc_msg_t msg = retram->creator.boot_svc_msg;
53  TRY(boot_svc_header_check(&msg.header));
54  TRY_CHECK(msg.header.type == kBootSvcNextBl0SlotResType);
55  TRY_CHECK(state->current_side == 'A');
56  TRY_CHECK(state->primary_side == 'A');
57  TRY_CHECK(msg.next_boot_bl0_slot_res.primary_bl0_slot == kBootSlotA);
58  state->state = kBootSvcTestStateFinal;
59  return OK_STATUS();
60 }
61 
62 static status_t next_boot_bl0_slot_test(void) {
63  retention_sram_t *retram = retention_sram_get();
64  TRY(boot_svc_test_init(retram, kBootSvcTestPrimaryBl0));
65  boot_svc_retram_t *state = (boot_svc_retram_t *)&retram->owner;
66 
67  for (;;) {
68  LOG_INFO("Test state = %d", state->state);
69  LOG_INFO("CurrentBootLog: %d:%s", state->boots, state->partition);
70  switch (state->state) {
71  case kBootSvcTestStateInit:
72  TRY(initialize(retram, state));
73  break;
74  case kBootSvcTestStateNextSideB:
75  TRY(check_side_b(retram, state));
76  break;
77  case kBootSvcTestStateReturnSideA:
78  TRY(check_return_side_a(retram, state));
79  break;
80  case kBootSvcTestStateFinal:
81  LOG_INFO("FinalBootLog: %d:%s", state->boots, state->partition);
82  return OK_STATUS();
83  default:
84  LOG_ERROR("Unknown state: %d", state->state);
85  return UNKNOWN();
86  }
87  }
88 }
89 
90 bool test_main(void) {
91  status_t sts = next_boot_bl0_slot_test();
92  if (status_err(sts)) {
93  LOG_ERROR("next_boot_bl0_slot_test: %r", sts);
94  }
95  return status_ok(sts);
96 }