Software APIs
rom_ext.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/rom_ext.h"
6 
13 #include "sw/device/silicon_creator/lib/base/boot_measurements.h"
16 #include "sw/device/silicon_creator/lib/boot_data.h"
17 #include "sw/device/silicon_creator/lib/boot_log.h"
18 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_empty.h"
19 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_header.h"
20 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
21 #include "sw/device/silicon_creator/lib/cert/dice_chain.h"
22 #include "sw/device/silicon_creator/lib/dbg_print.h"
23 #include "sw/device/silicon_creator/lib/drivers/ast.h"
24 #include "sw/device/silicon_creator/lib/drivers/epmp.h"
25 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
26 #include "sw/device/silicon_creator/lib/drivers/hmac.h"
27 #include "sw/device/silicon_creator/lib/drivers/ibex.h"
28 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
29 #include "sw/device/silicon_creator/lib/drivers/otp.h"
30 #include "sw/device/silicon_creator/lib/drivers/pinmux.h"
31 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
32 #include "sw/device/silicon_creator/lib/drivers/rnd.h"
33 #include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
34 #include "sw/device/silicon_creator/lib/drivers/uart.h"
35 #include "sw/device/silicon_creator/lib/epmp_state.h"
36 #include "sw/device/silicon_creator/lib/manifest.h"
37 #include "sw/device/silicon_creator/lib/manifest_def.h"
38 #include "sw/device/silicon_creator/lib/ownership/ownership.h"
39 #include "sw/device/silicon_creator/lib/ownership/ownership_activate.h"
40 #include "sw/device/silicon_creator/lib/ownership/ownership_key.h"
41 #include "sw/device/silicon_creator/lib/ownership/ownership_unlock.h"
42 #include "sw/device/silicon_creator/lib/shutdown.h"
43 #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h"
44 #include "sw/device/silicon_creator/lib/sigverify/rsa_verify.h"
45 #include "sw/device/silicon_creator/lib/sigverify/sigverify.h"
46 #include "sw/device/silicon_creator/rom_ext/rescue.h"
47 #include "sw/device/silicon_creator/rom_ext/rom_ext_boot_policy.h"
48 #include "sw/device/silicon_creator/rom_ext/rom_ext_boot_policy_ptrs.h"
49 #include "sw/device/silicon_creator/rom_ext/rom_ext_manifest.h"
50 #include "sw/device/silicon_creator/rom_ext/sigverify_keys.h"
51 
52 #include "flash_ctrl_regs.h" // Generated.
53 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
54 #include "sram_ctrl_regs.h" // Generated.
55 
56 // Declaration for the ROM_EXT manifest start address, populated by the linker
57 extern char _rom_ext_start_address[];
58 // Declaration for the chip_info structure stored in ROM.
59 extern const char _rom_chip_info_start[];
60 
61 // Life cycle state of the chip.
62 lifecycle_state_t lc_state;
63 
64 // Owner configuration details parsed from the onwer info pages.
66 
67 // Owner application keys.
69 
70 // Verifying key index
71 size_t verify_key;
72 
74 static rom_error_t rom_ext_irq_error(void) {
75  uint32_t mcause;
76  CSR_READ(CSR_REG_MCAUSE, &mcause);
77 
78  // TODO(opentitan#22947): Remove this debug print prior to a formal release.
79  uint32_t mepc, mtval;
80  CSR_READ(CSR_REG_MEPC, &mepc);
81  CSR_READ(CSR_REG_MTVAL, &mtval);
82  dbg_printf("MCAUSE=%x MEPC=%x MTVAL=%x\r\n", mcause, mepc, mtval);
83 
84  // Shuffle the mcause bits into the uppermost byte of the word and report
85  // the cause as kErrorRomExtInterrupt.
86  // Based on the ibex verilog, it appears that the most significant bit
87  // indicates whether the cause is an exception (0) or external interrupt (1),
88  // and the 5 least significant bits indicate which exception/interrupt.
89  //
90  // Preserve the MSB and shift the 7 LSBs into the upper byte.
91  // (we preserve 7 instead of 5 because the verilog hardcodes the unused bits
92  // as zero and those would be the next bits used should the number of
93  // interrupt causes increase).
94  mcause = (mcause & 0x80000000) | ((mcause & 0x7f) << 24);
95  return kErrorRomExtInterrupt + mcause;
96 }
97 
99 static uint32_t rom_ext_current_slot(void) {
100  uint32_t pc = ibex_addr_remap_get(0);
101  if (pc == 0) {
102  // If the remap window has address zero, we're running from flash and we can
103  // simply read the program counter.
104  asm("auipc %[pc], 0;" : [pc] "=r"(pc));
105  }
106 
107  const uint32_t kFlashSlotA = TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR;
108  const uint32_t kFlashSlotB =
109  kFlashSlotA + TOP_EARLGREY_FLASH_CTRL_MEM_SIZE_BYTES / 2;
110  const uint32_t kFlashSlotEnd =
112  uint32_t side = 0;
113  if (pc >= kFlashSlotA && pc < kFlashSlotB) {
114  // Running in Slot A.
115  side = kBootSlotA;
116  } else if (pc >= kFlashSlotB && pc < kFlashSlotEnd) {
117  // Running in Slot B.
118  side = kBootSlotB;
119  } else {
120  // Not running in flash: impossible.
121  HARDENED_TRAP();
122  }
123  return side;
124 }
125 
126 void rom_ext_check_rom_expectations(void) {
127  // Check the ePMP state.
128  SHUTDOWN_IF_ERROR(epmp_state_check());
129  // Check sec_mmio expectations.
130  // We don't check the counters since we don't want to tie ROM_EXT to a
131  // specific ROM version.
132  sec_mmio_check_values(rnd_uint32());
133 }
134 
136 static rom_error_t rom_ext_init(boot_data_t *boot_data) {
138  lc_state = lifecycle_state_get();
139  pinmux_init();
140  // Configure UART0 as stdout.
141  uart_init(kUartNCOValue);
142 
143  // Reclaim entries 0 ~ 7 from ROM and ROM_EXT IMM_SECTION.
144  for (int8_t i = 7; i >= 0; --i) {
145  epmp_clear((uint8_t)i);
146  }
147  HARDENED_RETURN_IF_ERROR(epmp_state_check());
148 
149  // Conditionally patch AST and check that it is in the expected state.
150  HARDENED_RETURN_IF_ERROR(ast_patch(lc_state));
151 
152  // Check that the retention RAM is initialized.
153  // TODO(lowrisc#22387): Check if return-if-error here is a potential
154  // boot-loop.
155  HARDENED_RETURN_IF_ERROR(retention_sram_check_version());
156 
157  // Get the boot_data record
158  HARDENED_RETURN_IF_ERROR(boot_data_read(lc_state, boot_data));
159 
160  return kErrorOk;
161 }
162 
163 void rom_ext_sram_exec(owner_sram_exec_mode_t mode) {
164  switch (mode) {
165  case kOwnerSramExecModeEnabled:
166  // In enabled mode, we do not lock the register so owner code can disable
167  // SRAM exec at some later time.
168  HARDENED_CHECK_EQ(mode, kOwnerSramExecModeEnabled);
170  SRAM_CTRL_EXEC_REG_OFFSET,
171  kMultiBitBool4True);
172  break;
173  case kOwnerSramExecModeDisabled:
174  // In disabled mode, we do not lock the register so owner code can enable
175  // SRAM exec at some later time.
176  HARDENED_CHECK_EQ(mode, kOwnerSramExecModeDisabled);
178  SRAM_CTRL_EXEC_REG_OFFSET,
179  kMultiBitBool4False);
180  break;
181  case kOwnerSramExecModeDisabledLocked:
182  default:
183  // In disabled locked mode, we lock the register so the mode cannot be
184  // changed.
186  SRAM_CTRL_EXEC_REG_OFFSET,
187  kMultiBitBool4False);
189  SRAM_CTRL_EXEC_REGWEN_REG_OFFSET,
190  0);
191  break;
192  }
193 }
194 
196 static rom_error_t rom_ext_verify(const manifest_t *manifest,
197  const boot_data_t *boot_data) {
198  RETURN_IF_ERROR(rom_ext_boot_policy_manifest_check(manifest, boot_data));
199  ownership_key_alg_t key_alg = kOwnershipKeyAlgEcdsaP256;
200  RETURN_IF_ERROR(owner_keyring_find_key(
201  &keyring, key_alg,
202  sigverify_ecdsa_p256_key_id_get(&manifest->ecdsa_public_key),
203  &verify_key));
204 
205  dbg_printf("app_verify: key=%u alg=%C domain=%C\r\n", verify_key,
206  keyring.key[verify_key]->key_alg,
207  keyring.key[verify_key]->key_domain);
208 
209  memset(boot_measurements.bl0.data, (int)rnd_uint32(),
210  sizeof(boot_measurements.bl0.data));
211 
212  hmac_sha256_init();
213  // Hash usage constraints.
214  manifest_usage_constraints_t usage_constraints_from_hw;
215  sigverify_usage_constraints_get(manifest->usage_constraints.selector_bits |
216  keyring.key[verify_key]->usage_constraint,
217  &usage_constraints_from_hw);
218  hmac_sha256_update(&usage_constraints_from_hw,
219  sizeof(usage_constraints_from_hw));
220  // Hash the remaining part of the image.
221  manifest_digest_region_t digest_region = manifest_digest_region_get(manifest);
222  hmac_sha256_update(digest_region.start, digest_region.length);
223  // TODO(#19596): add owner configuration block to measurement.
224  // Verify signature
225  hmac_sha256_process();
226  hmac_digest_t act_digest;
227  hmac_sha256_final(&act_digest);
228 
229  static_assert(sizeof(boot_measurements.bl0) == sizeof(act_digest),
230  "Unexpected BL0 digest size.");
231  memcpy(&boot_measurements.bl0, &act_digest, sizeof(boot_measurements.bl0));
232 
233  uint32_t flash_exec = 0;
234  return sigverify_ecdsa_p256_verify(&manifest->ecdsa_signature,
235  &keyring.key[verify_key]->data.ecdsa,
236  &act_digest, &flash_exec);
237 }
238 
239 /**
240  * These symbols are defined in
241  * `opentitan/sw/device/silicon_creator/rom_ext/rom_ext.ld`, and describe the
242  * location of the flash header.
243  */
244 extern char _owner_virtual_start_address[];
245 extern char _owner_virtual_size[];
246 
247 /**
248  * Compute the virtual address corresponding to the physical address `lma_addr`.
249  *
250  * @param manifest Pointer to the current manifest.
251  * @param lma_addr Load address or physical address.
252  * @return the computed virtual address.
253  */
255 static uintptr_t owner_vma_get(const manifest_t *manifest, uintptr_t lma_addr) {
256  return (lma_addr - (uintptr_t)manifest +
257  (uintptr_t)_owner_virtual_start_address + CHIP_ROM_EXT_SIZE_MAX);
258 }
259 
261 static rom_error_t rom_ext_boot(boot_data_t *boot_data, boot_log_t *boot_log,
262  const manifest_t *manifest) {
263  // Determine which owner block the key came from and measure that block.
264  hmac_digest_t owner_measurement;
265  const owner_application_key_t *key = keyring.key[verify_key];
266  owner_block_measurement(owner_block_key_page(key), &owner_measurement);
267 
268  keymgr_binding_value_t sealing_binding;
269  if (boot_data->ownership_state == kOwnershipStateLockedOwner) {
270  HARDENED_CHECK_EQ(boot_data->ownership_state, kOwnershipStateLockedOwner);
271  // If we're in LockedOwner, initialize the sealing binding with the
272  // diversification constant associated with key applicaiton key that
273  // validated the owner firmware payload.
274  static_assert(
275  sizeof(key->raw_diversifier) == sizeof(keymgr_binding_value_t),
276  "Expect the keymgr binding value to be the same size as an application "
277  "key diversifier");
278  memcpy(&sealing_binding, key->raw_diversifier, sizeof(sealing_binding));
279  } else {
280  // If we're not in LockedOwner state, we don't want to derive any valid
281  // sealing keys, so set the binding constant to a nonsense value.
282  memset(&sealing_binding, 0x55, sizeof(sealing_binding));
283  }
284 
285  // Generate CDI_1 attestation keys and certificate.
286  HARDENED_RETURN_IF_ERROR(dice_chain_attestation_owner(
287  manifest, &boot_measurements.bl0, &owner_measurement, &sealing_binding,
288  key->key_domain));
289 
290  // Write the DICE certs to flash if they have been updated.
291  HARDENED_RETURN_IF_ERROR(dice_chain_flush_flash());
292 
293  // Remove write and erase access to the certificate pages before handing over
294  // execution to the owner firmware (owner firmware can still read).
295  flash_ctrl_cert_info_page_owner_restrict(&kFlashCtrlInfoPageDiceCerts);
296 
297  // Disable access to silicon creator info pages, the OTP creator partition
298  // and the OTP direct access interface until the next reset.
299  flash_ctrl_creator_info_pages_lockdown();
300  otp_creator_sw_cfg_lockdown();
301  SEC_MMIO_WRITE_INCREMENT(kFlashCtrlSecMmioCreatorInfoPagesLockdown +
302  kOtpSecMmioCreatorSwCfgLockDown);
303 
304  epmp_clear_lock_bits();
305 
306  HARDENED_RETURN_IF_ERROR(epmp_state_check());
307 
308  // Configure address translation, compute the epmp regions and the entry
309  // point for the virtual address in case the address translation is enabled.
310  // Otherwise, compute the epmp regions and the entry point for the load
311  // address.
312  //
313  // We'll map the owner code TOR region as ePMP entries 2/3. If using address
314  // translation, we'll configure ePMP entry 4 as the read-only region.
315  epmp_region_t text_region = manifest_code_region_get(manifest);
316  uintptr_t entry_point = manifest_entry_point_get(manifest);
317  switch (launder32(manifest->address_translation)) {
318  case kHardenedBoolTrue:
320  ibex_addr_remap_1_set((uintptr_t)_owner_virtual_start_address,
321  (uintptr_t)manifest, (size_t)_owner_virtual_size);
322  SEC_MMIO_WRITE_INCREMENT(kAddressTranslationSecMmioConfigure);
323 
324  // Unlock read-only for the whole rom_ext virtual memory.
325  HARDENED_RETURN_IF_ERROR(epmp_state_check());
326  epmp_set_napot(
327  4,
328  (epmp_region_t){.start = (uintptr_t)_owner_virtual_start_address,
329  .end = (uintptr_t)_owner_virtual_start_address +
330  (uintptr_t)_owner_virtual_size},
331  kEpmpPermReadOnly);
332  HARDENED_RETURN_IF_ERROR(epmp_state_check());
333 
334  // Move the ROM_EXT execution section from the load address to the virtual
335  // address.
336  // TODO(#13513): Harden these calculations.
337  text_region.start = owner_vma_get(manifest, text_region.start);
338  text_region.end = owner_vma_get(manifest, text_region.end);
339  entry_point = owner_vma_get(manifest, entry_point);
340  break;
341  case kHardenedBoolFalse:
343  // Normally we'd want to clear the ROM region since we aren't using it
344  // anymore and since it isn't being used to encode access to the virtual
345  // window. However, for SiVal, we want to keep low entries locked to
346  // prevent using low entries to override policy in higher entries.
347  // epmp_clear_rom_region();
348  break;
349  default:
350  HARDENED_TRAP();
351  }
352 
353  // Allow execution of owner stage executable code (text) sections,
354  // unlock the ROM_EXT code regions so the next stage can re-use those
355  // entries and clear RLB to prevent further changes to locked ePMP regions.
356  HARDENED_RETURN_IF_ERROR(epmp_state_check());
357  epmp_set_tor(2, text_region, kEpmpPermReadExecute);
358 
359  // Now that we're done reconfiguring the ePMP, we'll clear the RLB bit to
360  // prevent any modification to locked entries.
361  epmp_clear_rlb();
362  HARDENED_RETURN_IF_ERROR(epmp_state_check());
363 
364  // Lock the address translation windows.
365  ibex_addr_remap_lockdown(0);
366  ibex_addr_remap_lockdown(1);
367 
368  // Lock the flash according to the ownership configuration.
369  HARDENED_RETURN_IF_ERROR(
370  ownership_flash_lockdown(boot_data, boot_log->bl0_slot, &owner_config));
371 
372  dbg_print_epmp();
373 
374  // Verify expectations before jumping to owner code.
375  // TODO: we really want to call rnd_uint32 here to select a random starting
376  // location for checking expectations. However, rnd_uint32 read from OTP
377  // to know if it's allowed to used the CSRNG and OTP is locked down.
378  sec_mmio_check_values_except_otp(/*rnd_uint32()*/ 0,
380  // Jump to OWNER entry point.
381  dbg_printf("entry: 0x%x\r\n", (unsigned int)entry_point);
382  ((owner_stage_entry_point *)entry_point)();
383 
384  return kErrorRomExtBootFailed;
385 }
386 
388 static rom_error_t boot_svc_next_boot_bl0_slot_handler(
390  boot_log_t *boot_log) {
391  uint32_t active_slot = boot_data->primary_bl0_slot;
392  uint32_t primary_slot = boot_svc_msg->next_boot_bl0_slot_req.primary_bl0_slot;
393  rom_error_t error = kErrorOk;
394 
395  // If the requested primary slot is the same as the active slot, this request
396  // is a no-op.
397  if (active_slot != primary_slot) {
398  switch (primary_slot) {
399  case kBootSlotA:
400  case kBootSlotB:
401  boot_data->primary_bl0_slot = primary_slot;
402  // Write boot data, updating relevant fields and recomputing the digest.
403  HARDENED_RETURN_IF_ERROR(boot_data_write(boot_data));
404  // Read the boot data back to ensure the correct slot is booted this
405  // time.
406  HARDENED_RETURN_IF_ERROR(boot_data_read(lc_state, boot_data));
407  // Update the boot log.
409  break;
410  case kBootSlotUnspecified:
411  // Do nothing.
412  break;
413  default:
414  error = kErrorBootSvcBadSlot;
415  }
416  }
417 
418  // Record the new primary slot for use in the response message.
419  active_slot = boot_data->primary_bl0_slot;
420 
421  uint32_t next_slot = boot_svc_msg->next_boot_bl0_slot_req.next_bl0_slot;
422  switch (launder32(next_slot)) {
423  case kBootSlotA:
424  case kBootSlotB:
425  // We overwrite the RAM copy of the primary slot to the requested next
426  // slot. This will cause a one-time boot of the requested side.
427  boot_data->primary_bl0_slot = next_slot;
428  break;
429  case kBootSlotUnspecified:
430  // Do nothing.
431  break;
432  default:
433  error = kErrorBootSvcBadSlot;
434  }
435 
436  boot_svc_next_boot_bl0_slot_res_init(error, active_slot,
437  &boot_svc_msg->next_boot_bl0_slot_res);
438  // We always return OK here because we've logged any error status in the boot
439  // services response message and we want the boot flow to continue.
440  return kErrorOk;
441 }
442 
444 static rom_error_t boot_svc_min_sec_ver_handler(boot_svc_msg_t *boot_svc_msg,
446  const uint32_t current_min_sec_ver = boot_data->min_security_version_bl0;
447  const uint32_t requested_min_sec_ver =
448  boot_svc_msg->next_boot_bl0_slot_req.next_bl0_slot;
449 
450  // Ensure the requested minimum security version isn't lower than the current
451  // minimum security version.
452  if (launder32(requested_min_sec_ver) > current_min_sec_ver) {
453  HARDENED_CHECK_GT(requested_min_sec_ver, current_min_sec_ver);
454  uint32_t max_sec_ver = current_min_sec_ver;
455 
456  // Check the two flash slots for valid manifests and determine the maximum
457  // value of the new minimum_security_version. This prevents a malicious
458  // MinBl0SecVer request from making the chip un-bootable.
459  const manifest_t *manifest = rom_ext_boot_policy_manifest_a_get();
460  rom_error_t error = rom_ext_verify(manifest, boot_data);
461  if (error == kErrorOk && manifest->security_version > max_sec_ver) {
462  max_sec_ver = manifest->security_version;
463  }
464  manifest = rom_ext_boot_policy_manifest_b_get();
465  error = rom_ext_verify(manifest, boot_data);
466  if (error == kErrorOk && manifest->security_version > max_sec_ver) {
467  max_sec_ver = manifest->security_version;
468  }
469 
470  if (requested_min_sec_ver <= max_sec_ver) {
471  HARDENED_CHECK_LE(requested_min_sec_ver, max_sec_ver);
472  // Update boot data to the requested minimum BL0 security version.
473  boot_data->min_security_version_bl0 = requested_min_sec_ver;
474 
475  // Write boot data, updating relevant fields and recomputing the digest.
476  HARDENED_RETURN_IF_ERROR(boot_data_write(boot_data));
477  // Read the boot data back to ensure the correct policy is used this boot.
478  HARDENED_RETURN_IF_ERROR(boot_data_read(lc_state, boot_data));
479 
480  boot_svc_min_bl0_sec_ver_res_init(boot_data->min_security_version_bl0,
481  kErrorOk,
482  &boot_svc_msg->min_bl0_sec_ver_res);
483 
484  HARDENED_CHECK_EQ(requested_min_sec_ver,
486  return kErrorOk;
487  }
488  }
489  boot_svc_min_bl0_sec_ver_res_init(current_min_sec_ver, kErrorBootSvcBadSecVer,
490  &boot_svc_msg->min_bl0_sec_ver_res);
491  return kErrorOk;
492 }
493 
495 static rom_error_t handle_boot_svc(boot_data_t *boot_data,
496  boot_log_t *boot_log) {
497  boot_svc_msg_t *boot_svc_msg = &retention_sram_get()->creator.boot_svc_msg;
498  // TODO(lowRISC#22387): Examine the boot_svc code paths for boot loops.
499  if (boot_svc_msg->header.identifier == kBootSvcIdentifier) {
500  HARDENED_RETURN_IF_ERROR(boot_svc_header_check(&boot_svc_msg->header));
501  uint32_t msg_type = boot_svc_msg->header.type;
502  switch (launder32(msg_type)) {
503  case kBootSvcEmptyReqType:
504  HARDENED_CHECK_EQ(msg_type, kBootSvcEmptyReqType);
505  boot_svc_empty_res_init(&boot_svc_msg->empty);
506  break;
507  case kBootSvcNextBl0SlotReqType:
508  HARDENED_CHECK_EQ(msg_type, kBootSvcNextBl0SlotReqType);
509  return boot_svc_next_boot_bl0_slot_handler(boot_svc_msg, boot_data,
510  boot_log);
511  case kBootSvcMinBl0SecVerReqType:
512  HARDENED_CHECK_EQ(msg_type, kBootSvcMinBl0SecVerReqType);
513  return boot_svc_min_sec_ver_handler(boot_svc_msg, boot_data);
514  case kBootSvcOwnershipUnlockReqType:
515  HARDENED_CHECK_EQ(msg_type, kBootSvcOwnershipUnlockReqType);
516  return ownership_unlock_handler(boot_svc_msg, boot_data);
517  case kBootSvcOwnershipActivateReqType:
518  HARDENED_CHECK_EQ(msg_type, kBootSvcOwnershipActivateReqType);
519  return ownership_activate_handler(boot_svc_msg, boot_data);
520  case kBootSvcEmptyResType:
521  case kBootSvcNextBl0SlotResType:
522  case kBootSvcMinBl0SecVerResType:
523  case kBootSvcOwnershipUnlockResType:
524  case kBootSvcOwnershipActivateResType:
525  // For response messages left in ret-ram we do nothing.
526  break;
527  default:
528  // For messages with an unknown msg_type, we do nothing.
529  ;
530  }
531  }
532  return kErrorOk;
533 }
534 
536 static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data,
537  boot_log_t *boot_log) {
539  rom_ext_boot_policy_manifests_get(boot_data);
540  rom_error_t error = kErrorRomExtBootFailed;
541  rom_error_t slot[2] = {0, 0};
542  for (size_t i = 0; i < ARRAYSIZE(manifests.ordered); ++i) {
543  error = rom_ext_verify(manifests.ordered[i], boot_data);
544  slot[i] = error;
545  if (error != kErrorOk) {
546  continue;
547  }
548 
549  if (manifests.ordered[i] == rom_ext_boot_policy_manifest_a_get()) {
550  boot_log->bl0_slot = kBootSlotA;
551  } else if (manifests.ordered[i] == rom_ext_boot_policy_manifest_b_get()) {
552  boot_log->bl0_slot = kBootSlotB;
553  } else {
554  return kErrorRomExtBootFailed;
555  }
556  boot_log_digest_update(boot_log);
557 
558  // Boot fails if a verified ROM_EXT cannot be booted.
559  RETURN_IF_ERROR(rom_ext_boot(boot_data, boot_log, manifests.ordered[i]));
560  // `rom_ext_boot()` should never return `kErrorOk`, but if it does
561  // we must shut down the chip instead of trying the next ROM_EXT.
562  return kErrorRomExtBootFailed;
563  }
564 
565  // If we get here, the loop exited after trying both slots.
566  // If we see kErrorBootPolicyBadIdentifier as the error, we probably have an
567  // empty slot. In that case, the "bad identifier" error is not helpful, so
568  // maybe choose the error from the other slot.
569  if (error == kErrorBootPolicyBadIdentifier && error == slot[1]) {
570  // If the bad identifier error comes from the non-primary slot, prefer
571  // the error from the primary slot.
572  error = slot[0];
573  }
574  return error;
575 }
576 
577 static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) {
578  HARDENED_RETURN_IF_ERROR(rom_ext_init(boot_data));
579  const manifest_t *self = rom_ext_manifest();
580  dbg_printf("Starting ROM_EXT %u.%u\r\n", self->version_major,
581  self->version_minor);
582 
583  // Prepare dice chain builder for CDI_1.
584  HARDENED_RETURN_IF_ERROR(dice_chain_init());
585 
586  // Initialize the boot_log in retention RAM.
587  const chip_info_t *rom_chip_info = (const chip_info_t *)_rom_chip_info_start;
588  boot_log_check_or_init(boot_log, rom_ext_current_slot(), rom_chip_info);
589  boot_log->rom_ext_major = self->version_major;
590  boot_log->rom_ext_minor = self->version_minor;
591  boot_log->rom_ext_size = CHIP_ROM_EXT_SIZE_MAX;
592  // Even though `primary_bl0_slot` can be changed by boot svc, we initialize
593  // it here so the "SetNextBl0" can do a one-time override of the RAM copy
594  // of `boot_data`.
596 
597  // Initialize the chip ownership state.
598  rom_error_t error;
599  error = ownership_init(boot_data, &owner_config, &keyring);
600  if (error == kErrorWriteBootdataThenReboot) {
601  return error;
602  }
603  // TODO(cfrantz): evaluate permissible ownership init failure conditions
604  // and change this to HARDENED_RETURN_IF_ERROR.
605  if (error != kErrorOk) {
606  dbg_printf("ownership_init: %x\r\n", error);
607  }
608 
609  // Configure SRAM execution as the owner requested.
610  rom_ext_sram_exec(owner_config.sram_exec);
611 
612  // Handle any pending boot_svc commands.
613  uint32_t reset_reasons = retention_sram_get()->creator.reset_reasons;
614  uint32_t skip_boot_svc = reset_reasons & (1 << kRstmgrReasonLowPowerExit);
615  if (skip_boot_svc == 0) {
616  error = handle_boot_svc(boot_data, boot_log);
617  if (error == kErrorWriteBootdataThenReboot) {
618  // Boot services reports errors by writing a status code into the reply
619  // messages. Regardless of whether a boot service request produced an
620  // error, we want to continue booting unless the error specifically asks
621  // for a reboot.
622  return error;
623  }
624  }
625 
626  // Synchronize the boot_log entries that could be changed by boot services.
632  boot_log_digest_update(boot_log);
633 
634  if (uart_break_detect(kRescueDetectTime) == kHardenedBoolTrue) {
635  dbg_printf("rescue: remember to clear break\r\n");
636  uart_enable_receiver();
637  ownership_pages_lockdown(boot_data, /*rescue=*/kHardenedBoolTrue);
638  // TODO: update rescue protocol to accept boot data and rescue
639  // config from the owner_config.
640  error = rescue_protocol(boot_data, owner_config.rescue);
641  } else {
642  ownership_pages_lockdown(boot_data, /*rescue=*/kHardenedBoolFalse);
643  error = rom_ext_try_next_stage(boot_data, boot_log);
644  }
645  return error;
646 }
647 
648 void rom_ext_main(void) {
649  rom_ext_check_rom_expectations();
651  boot_log_t *boot_log = &retention_sram_get()->creator.boot_log;
652 
653  rom_error_t error = rom_ext_start(&boot_data, boot_log);
654  if (error == kErrorWriteBootdataThenReboot) {
655  HARDENED_CHECK_EQ(error, kErrorWriteBootdataThenReboot);
656  error = boot_data_write(&boot_data);
657  }
658  shutdown_finalize(error);
659 }
660 
661 OT_USED
662 void rom_ext_interrupt_handler(void) { shutdown_finalize(rom_ext_irq_error()); }
663 
664 // We only need a single handler for all ROM_EXT interrupts, but we want to
665 // keep distinct symbols to make writing tests easier. In the ROM_EXT,
666 // alias all interrupt handler symbols to the single handler.
667 OT_USED
668 OT_ALIAS("rom_ext_interrupt_handler")
669 void rom_ext_exception_handler(void);
670 
671 OT_USED
672 OT_ALIAS("rom_ext_interrupt_handler")
673 void rom_ext_nmi_handler(void);