Software APIs
rescue.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/silicon_creator/rom_ext/rescue.h"
6 
9 #include "sw/device/silicon_creator/lib/boot_data.h"
10 #include "sw/device/silicon_creator/lib/dbg_print.h"
11 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
12 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
13 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
14 #include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
15 #include "sw/device/silicon_creator/lib/drivers/uart.h"
16 #include "sw/device/silicon_creator/lib/ownership/datatypes.h"
17 #include "sw/device/silicon_creator/lib/ownership/owner_block.h"
18 #include "sw/device/silicon_creator/lib/xmodem.h"
19 
20 #include "flash_ctrl_regs.h"
21 
22 // All of the xmodem functions accept an opaque iohandle pointer.
23 // The iohandle is used to facilitate unit tests and doesn't have
24 // any function in real firmware.
25 #define iohandle NULL
26 
27 const uint32_t kFlashPageSize = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
28 const uint32_t kFlashBankSize =
29  kFlashPageSize * FLASH_CTRL_PARAM_REG_PAGES_PER_BANK;
30 static rescue_state_t rescue_state;
31 
32 rom_error_t flash_firmware_block(rescue_state_t *state) {
33  uint32_t bank_offset =
34  state->mode == kRescueModeFirmwareSlotB ? kFlashBankSize : 0;
35  if (state->flash_offset == 0) {
36  // TODO(#24428): Make sure we interact correctly with owner flash region
37  // configuration.
38  flash_ctrl_data_default_perms_set((flash_ctrl_perms_t){
39  .read = kMultiBitBool4True,
40  .write = kMultiBitBool4True,
41  .erase = kMultiBitBool4True,
42  });
43  for (uint32_t addr = state->flash_start; addr < state->flash_limit;
44  addr += kFlashPageSize) {
45  HARDENED_RETURN_IF_ERROR(
46  flash_ctrl_data_erase(bank_offset + addr, kFlashCtrlEraseTypePage));
47  }
48  state->flash_offset = state->flash_start;
49  }
50  if (state->flash_offset < state->flash_limit) {
51  HARDENED_RETURN_IF_ERROR(flash_ctrl_data_write(
52  bank_offset + state->flash_offset,
53  sizeof(state->data) / sizeof(uint32_t), state->data));
54  state->flash_offset += sizeof(state->data);
55  } else {
56  xmodem_cancel(iohandle);
57  return kErrorRescueImageTooBig;
58  }
59  return kErrorOk;
60 }
61 
62 rom_error_t flash_owner_block(rescue_state_t *state, boot_data_t *bootdata) {
63  if (bootdata->ownership_state == kOwnershipStateUnlockedAny ||
64  bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
65  bootdata->ownership_state == kOwnershipStateUnlockedEndorsed ||
66  (bootdata->ownership_state == kOwnershipStateLockedOwner &&
67  owner_block_newversion_mode() == kHardenedBoolTrue)) {
68  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(
69  &kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage));
70  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write(
71  &kFlashCtrlInfoPageOwnerSlot1, 0,
72  sizeof(state->data) / sizeof(uint32_t), state->data));
73  } else {
74  dbg_printf("error: cannot accept owner_block in current state\r\n");
75  }
76  return kErrorOk;
77 }
78 
79 static void change_speed(void) {
80  dbg_printf("ok: waiting for baudrate\r\n");
81  uint32_t speed = 0;
82  OT_DISCARD(uart_read((uint8_t *)&speed, sizeof(speed), 10000));
83  uint32_t nco;
84  switch (speed) {
85  case kRescueBaud115K:
86  nco = kUartBaud115K;
87  break;
88  case kRescueBaud230K:
89  nco = kUartBaud230K;
90  break;
91  case kRescueBaud460K:
92  nco = kUartBaud460K;
93  break;
94  case kRescueBaud921K:
95  nco = kUartBaud921K;
96  break;
97  case kRescueBaud1M33:
98  nco = kUartBaud1M33;
99  break;
100  case kRescueBaud1M50:
101  nco = kUartBaud1M50;
102  break;
103  default:
104  nco = 0;
105  }
106  if (nco) {
107  dbg_printf("ok: new baudrate %C\r\n", speed);
108  uart_init(nco);
109  uart_enable_receiver();
110  } else {
111  dbg_printf("error: unsupported baudrate %C\r\n", speed);
112  }
113 }
114 
115 #ifdef ROM_EXT_KLOBBER_ALLOWED
116 // In order to facilitate debuging and manual test flows for ownerhsip transfer,
117 // we allow the owner pages to be erased if and only if the chip is in the DEV
118 // lifecycle state AND the ROM_EXT was specifically built to allow owner erase.
119 //
120 // In the general case, the `KLBR` command does not exist. It can only be
121 // enabled by silicon_creator and only for DEV chips.
122 static void ownership_erase(void) {
123  lifecycle_state_t lc_state = lifecycle_state_get();
124  if (lc_state == kLcStateDev) {
125  OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0,
126  kFlashCtrlEraseTypePage));
127  OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot1,
128  kFlashCtrlEraseTypePage));
129  dbg_printf("ok: erased owner blocks\r\n");
130  } else {
131  dbg_printf("error: erase not allowed in state %x\r\n", lc_state);
132  }
133 }
134 #endif
135 
136 static void validate_mode(uint32_t mode, rescue_state_t *state,
137  boot_data_t *bootdata) {
138  dbg_printf("\r\nmode: %C\r\n", bitfield_byteswap32(mode));
139 
140  // The following commands are always allowed and are not subject to
141  // the "command allowed" check.
142  switch (mode) {
143  case kRescueModeBaud:
144  change_speed();
145  goto exitproc;
146  case kRescueModeReboot:
147  dbg_printf("ok: reboot\r\n");
148  state->mode = (rescue_mode_t)mode;
149  goto exitproc;
150  case kRescueModeWait:
151  dbg_printf("ok: wait after upload\r\n");
152  state->reboot = false;
153  goto exitproc;
154 #ifdef ROM_EXT_KLOBBER_ALLOWED
155  case kRescueModeKlobber:
156  ownership_erase();
157  goto exitproc;
158 #endif
159  default:
160  /* do nothing */;
161  }
162 
163  hardened_bool_t allow = owner_rescue_command_allowed(state->config, mode);
164  if (allow == kHardenedBoolTrue) {
165  switch (mode) {
166  case kRescueModeBootLog:
167  dbg_printf("ok: receive boot_log via xmodem-crc\r\n");
168  break;
169  case kRescueModeBootSvcRsp:
170  dbg_printf("ok: receive boot_svc response via xmodem-crc\r\n");
171  break;
172  case kRescueModeBootSvcReq:
173  dbg_printf("ok: send boot_svc request via xmodem-crc\r\n");
174  break;
175  case kRescueModeOwnerBlock:
176  if (bootdata->ownership_state == kOwnershipStateUnlockedAny ||
177  bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
178  bootdata->ownership_state == kOwnershipStateUnlockedEndorsed ||
179  (bootdata->ownership_state == kOwnershipStateLockedOwner &&
180  owner_block_newversion_mode() == kHardenedBoolTrue)) {
181  dbg_printf("ok: send owner_block via xmodem-crc\r\n");
182  } else {
183  dbg_printf("error: cannot accept owner_block in current state\r\n");
184  return;
185  }
186  break;
187  case kRescueModeFirmware:
188  case kRescueModeFirmwareSlotB:
189  dbg_printf("ok: send firmware via xmodem-crc\r\n");
190  break;
191  case kRescueModeOwnerPage0:
192  case kRescueModeOwnerPage1:
193  dbg_printf("ok: receive owner page via xmodem-crc\r\n");
194  break;
195  case kRescueModeOpenTitanID:
196  dbg_printf("ok: receive device ID via xmodem-crc\r\n");
197  break;
198  default:
199  // User input error. Do not change modes.
200  dbg_printf("error: unrecognized mode\r\n");
201  return;
202  }
203  state->mode = (rescue_mode_t)mode;
204  } else {
205  dbg_printf("error: mode not allowed\r\n");
206  }
207 exitproc:
208  state->frame = 1;
209  state->offset = 0;
210  state->flash_offset = 0;
211 }
212 
213 static rom_error_t handle_send_modes(rescue_state_t *state,
214  boot_data_t *bootdata) {
215  hardened_bool_t allow =
216  owner_rescue_command_allowed(state->config, state->mode);
217  if (allow != kHardenedBoolTrue) {
218  return kErrorRescueBadMode;
219  }
220 
221  const retention_sram_t *rr = retention_sram_get();
222  switch (state->mode) {
223  case kRescueModeBootLog:
224  HARDENED_RETURN_IF_ERROR(xmodem_send(iohandle, &rr->creator.boot_log,
225  sizeof(rr->creator.boot_log)));
226  break;
227  case kRescueModeBootSvcRsp:
228  HARDENED_RETURN_IF_ERROR(xmodem_send(iohandle, &rr->creator.boot_svc_msg,
229  sizeof(rr->creator.boot_svc_msg)));
230  break;
231  case kRescueModeOpenTitanID: {
233  lifecycle_device_id_get(&id);
234  HARDENED_RETURN_IF_ERROR(xmodem_send(iohandle, &id, sizeof(id)));
235  break;
236  }
237  case kRescueModeOwnerPage0:
238  case kRescueModeOwnerPage1:
239  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_read(
240  state->mode == kRescueModeOwnerPage0 ? &kFlashCtrlInfoPageOwnerSlot0
241  : &kFlashCtrlInfoPageOwnerSlot1,
242  0, sizeof(state->data) / sizeof(uint32_t), state->data));
243  HARDENED_RETURN_IF_ERROR(
244  xmodem_send(iohandle, state->data, sizeof(state->data)));
245  break;
246 
247  case kRescueModeBootSvcReq:
248  case kRescueModeOwnerBlock:
249  case kRescueModeFirmware:
250  case kRescueModeFirmwareSlotB:
251  // Nothing to do for receive modes.
252  return kErrorOk;
253  case kRescueModeReboot:
254  // If a reboot was requested, return an error and go through the normal
255  // shutdown process.
256  return kErrorRescueReboot;
257  default:
258  // This state should be impossible.
259  return kErrorRescueBadMode;
260  }
261  validate_mode(kRescueModeFirmware, state, bootdata);
262  return kErrorOk;
263 }
264 
265 static rom_error_t handle_recv_modes(rescue_state_t *state,
266  boot_data_t *bootdata) {
267  hardened_bool_t allow =
268  owner_rescue_command_allowed(state->config, state->mode);
269  if (allow != kHardenedBoolTrue) {
270  xmodem_cancel(iohandle);
271  return kErrorRescueBadMode;
272  }
273 
274  retention_sram_t *rr = retention_sram_get();
275  switch (state->mode) {
276  case kRescueModeBootLog:
277  case kRescueModeBootSvcRsp:
278  case kRescueModeOpenTitanID:
279  case kRescueModeOwnerPage0:
280  case kRescueModeOwnerPage1:
281  // Nothing to do for send modes.
282  break;
283  case kRescueModeBootSvcReq:
284  if (state->offset >= sizeof(rr->creator.boot_svc_msg)) {
285  const boot_svc_msg_t *msg = (const boot_svc_msg_t *)state->data;
286  allow = owner_rescue_command_allowed(state->config, msg->header.type);
287  if (allow != kHardenedBoolTrue) {
288  xmodem_cancel(iohandle);
289  return kErrorRescueBadMode;
290  }
291  memcpy(&rr->creator.boot_svc_msg, state->data,
292  sizeof(rr->creator.boot_svc_msg));
293  state->offset = 0;
294  }
295  break;
296  case kRescueModeOwnerBlock:
297  if (state->offset == sizeof(state->data)) {
298  HARDENED_RETURN_IF_ERROR(flash_owner_block(state, bootdata));
299  state->offset = 0;
300  }
301  break;
302  case kRescueModeFirmware:
303  case kRescueModeFirmwareSlotB:
304  if (state->offset == sizeof(state->data)) {
305  HARDENED_RETURN_IF_ERROR(flash_firmware_block(state));
306  state->offset = 0;
307  }
308  break;
309  case kRescueModeReboot:
310  default:
311  // This state should be impossible.
312  return kErrorRescueBadMode;
313  }
314  return kErrorOk;
315 }
316 
317 static rom_error_t protocol(rescue_state_t *state, boot_data_t *bootdata) {
318  rom_error_t result;
319  size_t rxlen;
320  uint8_t command;
321  uint32_t next_mode = 0;
322 
323  state->reboot = true;
324  validate_mode(kRescueModeFirmware, &rescue_state, bootdata);
325 
326  xmodem_recv_start(iohandle);
327  while (true) {
328  HARDENED_RETURN_IF_ERROR(handle_send_modes(&rescue_state, bootdata));
329  result = xmodem_recv_frame(iohandle, state->frame,
330  state->data + state->offset, &rxlen, &command);
331  if (state->frame == 1 && result == kErrorXModemTimeoutStart) {
332  xmodem_recv_start(iohandle);
333  continue;
334  }
335  switch (result) {
336  case kErrorOk:
337  // Packet ok.
338  state->offset += rxlen;
339  HARDENED_RETURN_IF_ERROR(handle_recv_modes(&rescue_state, bootdata));
340  xmodem_ack(iohandle, true);
341  break;
342  case kErrorXModemEndOfFile:
343  if (state->offset % 2048 != 0) {
344  // If there is unhandled residue, extend out to a full block and
345  // then handle it.
346  while (state->offset % 2048 != 0) {
347  state->data[state->offset++] = 0xFF;
348  }
349  HARDENED_RETURN_IF_ERROR(handle_recv_modes(&rescue_state, bootdata));
350  }
351  xmodem_ack(iohandle, true);
352  if (!state->reboot) {
353  state->frame = 1;
354  state->offset = 0;
355  state->flash_offset = 0;
356  continue;
357  }
358  return kErrorRescueReboot;
359  case kErrorXModemCrc:
360  xmodem_ack(iohandle, false);
361  continue;
362  case kErrorXModemCancel:
363  return result;
364  case kErrorXModemUnknown:
365  if (state->frame == 1) {
366  if (command == '\r') {
367  validate_mode(next_mode, &rescue_state, bootdata);
368  next_mode = 0;
369  } else {
370  next_mode = (next_mode << 8) | command;
371  }
372  continue;
373  }
375  default:
376  return result;
377  }
378  state->frame += 1;
379  }
380 }
381 
382 rom_error_t rescue_protocol(boot_data_t *bootdata,
383  const owner_rescue_config_t *config) {
384  rescue_state.config = config;
385  if ((hardened_bool_t)config == kHardenedBoolFalse) {
387  // If there is no rescue config, then the rescue region starts immediately
388  // after the ROM_EXT and ends at the end of the flash bank.
389  rescue_state.flash_start = CHIP_ROM_EXT_SIZE_MAX;
390  rescue_state.flash_limit = kFlashBankSize;
391  } else {
392  rescue_state.flash_start = (uint32_t)config->start * kFlashPageSize;
393  rescue_state.flash_limit =
394  (uint32_t)(config->start + config->size) * kFlashPageSize;
395  }
396  rom_error_t result = protocol(&rescue_state, bootdata);
397  if (result == kErrorRescueReboot) {
398  rstmgr_reset();
399  }
400  return result;
401 }