[sw/silicon_creator] Add lifecycle_state_name_get()

Values of the life cycle states were updated in #9319. This change adds
a utility function for getting human-readable state names using the new
state values.

Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/lib/drivers/keymgr_functest.c b/sw/device/silicon_creator/lib/drivers/keymgr_functest.c
index 3f545a8..5b7b077 100644
--- a/sw/device/silicon_creator/lib/drivers/keymgr_functest.c
+++ b/sw/device/silicon_creator/lib/drivers/keymgr_functest.c
@@ -279,7 +279,7 @@
 
   // This test is expected to run in DEV, PROD or PROD_END states.
   lifecycle_state_t lc_state = lifecycle_state_get();
-  LOG_INFO("lifecycle state: %s", lifecycle_state_name[lc_state]);
+  LOG_INFO("lifecycle state: %s", lifecycle_state_name_get(lc_state));
 
   // Initialize pwrmgr
   dif_pwrmgr_t pwrmgr;
diff --git a/sw/device/silicon_creator/lib/drivers/lifecycle.c b/sw/device/silicon_creator/lib/drivers/lifecycle.c
index 05b0535..f925b2b 100644
--- a/sw/device/silicon_creator/lib/drivers/lifecycle.c
+++ b/sw/device/silicon_creator/lib/drivers/lifecycle.c
@@ -14,7 +14,7 @@
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
 #include "lc_ctrl_regs.h"
 
-const char *const lifecycle_state_name[] = {
+static const char *const kStateNames[] = {
     // clang-format off
     "RAW",
     "TEST_UNLOCKED0",
@@ -43,8 +43,8 @@
     // clang-format on
 };
 
-static_assert(ARRAYSIZE(lifecycle_state_name) == kLcStateNumStates,
-              "length of the lifecycle_state_name array doesn't match the "
+static_assert(ARRAYSIZE(kStateNames) == kLcStateNumStates,
+              "length of the kStateNames array doesn't match the "
               "number of states.");
 
 #define LC_ASSERT(a, b) static_assert(a == b, "Bad value for " #a)
@@ -84,6 +84,17 @@
   return (lifecycle_state_t)value;
 }
 
+const char *lifecycle_state_name_get(lifecycle_state_t lc_state) {
+  // Life cycle state value (`lc_state`) is a 32-bit value that repeats the
+  // 5-bit life cycle state index 6 times.
+  enum { kStateIndexMask = 0x1f };
+  size_t state_index = (uint32_t)lc_state & kStateIndexMask;
+  if (state_index >= kLcStateNumStates) {
+    state_index = kLcStateInvalid & kStateIndexMask;
+  }
+  return kStateNames[state_index];
+}
+
 void lifecycle_device_id_get(lifecycle_device_id_t *device_id) {
   static_assert(
       kLifecycleDeviceIdNumWords == LC_CTRL_PARAM_NUM_DEVICE_ID_WORDS,
diff --git a/sw/device/silicon_creator/lib/drivers/lifecycle.h b/sw/device/silicon_creator/lib/drivers/lifecycle.h
index 75762a1..adaf609 100644
--- a/sw/device/silicon_creator/lib/drivers/lifecycle.h
+++ b/sw/device/silicon_creator/lib/drivers/lifecycle.h
@@ -133,11 +133,6 @@
   uint32_t device_id[kLifecycleDeviceIdNumWords];
 } lifecycle_device_id_t;
 
-/*
- * An array of human-readable life cycle state names.
- */
-extern const char *const lifecycle_state_name[];
-
 /**
  * Get the life cycle state.
  *
@@ -146,6 +141,14 @@
 lifecycle_state_t lifecycle_state_get(void);
 
 /**
+ * Get the human-readable name for a life cycle state.
+ *
+ * @param lc_state Life cycle state.
+ * @return Name of the given state.
+ */
+const char *lifecycle_state_name_get(lifecycle_state_t lc_state);
+
+/**
  * Get the device identifier.
  *
  * @param[out] device_id 256-bit device identifier that is stored in the
diff --git a/sw/device/silicon_creator/mask_rom/mask_rom.c b/sw/device/silicon_creator/mask_rom/mask_rom.c
index 7682553..61a79e1 100644
--- a/sw/device/silicon_creator/mask_rom/mask_rom.c
+++ b/sw/device/silicon_creator/mask_rom/mask_rom.c
@@ -197,7 +197,7 @@
   // TODO(lowrisc/opentitan#7894): What (if anything) should we print at
   // startup?
   log_printf("OpenTitan: \"version-tag\"\r\n");
-  log_printf("lc_state: %s\r\n", lifecycle_state_name[lc_state]);
+  log_printf("lc_state: %s\r\n", lifecycle_state_name_get(lc_state));
 
   // TODO(lowrisc/opentitan#1513): Switch to EEPROM SPI device bootstrap
   // protocol.