summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot/base/securerom.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/secureboot/base/securerom.C')
-rw-r--r--src/usr/secureboot/base/securerom.C510
1 files changed, 510 insertions, 0 deletions
diff --git a/src/usr/secureboot/base/securerom.C b/src/usr/secureboot/base/securerom.C
new file mode 100644
index 000000000..af12b365b
--- /dev/null
+++ b/src/usr/secureboot/base/securerom.C
@@ -0,0 +1,510 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/base/securerom.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <secureboot/service.H>
+#include <secureboot/secure_reasoncodes.H>
+#include <sys/mmio.h>
+#include <kernel/pagemgr.H>
+#include <limits.h>
+#include <targeting/common/commontargeting.H>
+#include <targeting/common/targetservice.H>
+#include <devicefw/driverif.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+
+#include "securerom.H"
+#include "../settings.H"
+
+extern trace_desc_t* g_trac_secure;
+
+// Quick change for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+
+// Hardcode define for Secure ROM code (bootrom.bin) in system
+// Secure ROM has 16KB reserved address space
+#define SECUREROM_MEMORY_SIZE (16 * KILOBYTE)
+// 4 pages * (PAGESIZE=4K) = 16K
+#define SECUREROM_NUM_PAGES (SECUREROM_MEMORY_SIZE / PAGESIZE)
+
+namespace SECUREBOOT
+{
+
+
+/**
+ * @brief Initialize Secure Rom by loading it into memory and
+ * retrieving Hash Keys
+ */
+errlHndl_t initializeSecureROM(void)
+{
+ return Singleton<SecureROM>::instance().initialize();
+}
+
+/**
+ * @brief Verify Signed Container
+ */
+errlHndl_t verifyContainer(void * i_container, size_t i_size)
+{
+ TRACUCOMP(g_trac_secure, "verifyContainer(): i_container=%p, size=0x%x",
+ i_container, i_size);
+
+ return Singleton<SecureROM>::instance().verifyContainer(i_container,
+ i_size);
+}
+
+/**
+ * @brief Hash Signed Blob
+ *
+ */
+errlHndl_t hashBlob(void * i_blob, size_t i_size)
+{
+ return Singleton<SecureROM>::instance().hashBlob(i_blob, i_size);
+
+}
+
+}; //end SECUREBOOT namespace
+
+
+/********************
+ Public Methods
+ ********************/
+
+
+/**
+ * @brief Initialize Secure Rom by loading it into memory and
+ * getting Hash Keys
+ */
+errlHndl_t SecureROM::initialize()
+{
+ TRACDCOMP(g_trac_secure,ENTER_MRK"SecureROM::initialize()");
+
+ errlHndl_t l_errl = NULL;
+ bool l_cleanup = false;
+ uint32_t l_rc = 0;
+
+ do{
+
+ // Check to see if ROM has already been initialized
+ if (iv_device_ptr != NULL)
+ {
+ // The Secure ROM has already been initialized
+ TRACUCOMP(g_trac_secure,"SecureROM::initialize(): Already "
+ "Loaded: iv_device_ptr=%p", iv_device_ptr);
+
+ // Can skip the rest of this function
+ break;
+ }
+
+
+ /*********************************************************************/
+ /* Find base address of Secure ROM via TBROM_BASE_REG scom register */
+ /*********************************************************************/
+
+ const uint32_t tbrom_reg_addr = 0x02020017;
+ uint64_t tbrom_reg_data;
+ size_t op_size = sizeof(uint64_t);
+
+ l_errl = deviceRead( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &(tbrom_reg_data),
+ op_size,
+ DEVICE_SCOM_ADDRESS(tbrom_reg_addr) );
+
+ if (l_errl != NULL)
+ {
+ TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():"
+ " Fail SCOM Read of tbrom_reg_addr (0x%x)", tbrom_reg_addr);
+
+ break;
+ }
+
+
+ TRACUCOMP(g_trac_secure,INFO_MRK"SecureROM::initialize(): "
+ "tbrom_reg_data = 0x%016llx", tbrom_reg_data);
+
+
+ // This register contains the starting address of the bootrom device
+ void * l_rom_baseAddr = reinterpret_cast<void*>(tbrom_reg_data);
+
+
+ /*******************************************************************/
+ /* Map the bootrom code into virtual memory */
+ /*******************************************************************/
+ void * l_rom_virtAddr = mmio_dev_map(l_rom_baseAddr, THIRTYTWO_GB);
+
+ if (l_rom_virtAddr == NULL)
+ {
+ TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():"
+ " mmio_dev_map failed: l_rom_virtAddr=%p, l_rom_baseAddr=%p",
+ l_rom_virtAddr, l_rom_baseAddr);
+
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_ROM_INIT
+ * @reasoncode SECUREBOOT::RC_DEV_MAP_FAIL
+ * @userdata1 TBROM Register Address
+ * @userdata2 TBROM Register Data
+ * @devdesc mmio_dev_map() failed for Secure ROM
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SECUREBOOT::MOD_SECURE_ROM_INIT,
+ SECUREBOOT::RC_DEV_MAP_FAIL,
+ TO_UINT64(tbrom_reg_addr),
+ tbrom_reg_data);
+
+ l_errl->collectTrace("SECURE",256);
+ break;
+
+ }
+
+ /**********************************************************************/
+ /* Allocate Memory: Request full SECUREROM_MEMORY_SIZE */
+ /**********************************************************************/
+
+ // Using malloc() rather than allocatePage because malloc() will
+ // handle error path
+ iv_device_ptr = malloc(SECUREROM_MEMORY_SIZE);
+
+ // Pages are now allocated, so free below if necessary
+ l_cleanup = true;
+
+ /***************************************************************/
+ /* Copy and setup ROM code in allocated memory */
+ /***************************************************************/
+
+ // memcpy from mapped device to allocated pages
+ memcpy( iv_device_ptr, l_rom_virtAddr, SECUREROM_MEMORY_SIZE );
+
+ // invalidate icache to make sure that bootrom code in memory is used
+ size_t l_icache_invalid_size = (SECUREROM_MEMORY_SIZE /
+ sizeof(uint64_t));
+
+ mm_icache_invalidate( iv_device_ptr, l_icache_invalid_size);
+
+ // Make this address space executable
+ uint64_t l_access_type = EXECUTABLE;
+ l_rc = mm_set_permission( iv_device_ptr,
+ SECUREROM_MEMORY_SIZE,
+ l_access_type);
+
+
+ if (l_rc != 0)
+ {
+ TRACFCOMP(g_trac_secure,EXIT_MRK"SecureROM::initialize():"
+ " Fail from mm_set_permission(EXECUTABLE): l_rc=0x%x, ptr=%p, "
+ "size=0x%x, access=0x%x", l_rc, iv_device_ptr,
+ SECUREROM_MEMORY_SIZE, l_access_type);
+
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_ROM_INIT
+ * @reasoncode SECUREBOOT::RC_SET_PERMISSION_FAIL_EXE
+ * @userdata1 l_rc
+ * @userdata2 iv_device_ptr
+ * @devdesc mm_set_permission(EXECUTABLE) failed for Secure ROM
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SECUREBOOT::MOD_SECURE_ROM_INIT,
+ SECUREBOOT::RC_SET_PERMISSION_FAIL_EXE,
+ TO_UINT64(l_rc),
+ reinterpret_cast<uint64_t>(iv_device_ptr));
+
+ l_errl->collectTrace("SECURE",256);
+ break;
+
+ }
+
+
+ /***************************************************************/
+ /* Retrieve HW Hash Keys From The System */
+ /***************************************************************/
+
+ // @todo RTC:RTC:34080 - Support for SecureROM::getHwHashKeys()
+ l_errl = SecureROM::getHwHashKeys();
+
+ if (l_errl != NULL)
+ {
+ TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():"
+ " SecureROM::getHwHashKeys() returned an error");
+
+ l_errl->collectTrace("SECURE",256);
+ break;
+
+ }
+
+
+ /***************************************************************/
+ /* Secure ROM successfully initialized */
+ /***************************************************************/
+ // If we've made it this far without an error, than Secure ROM
+ // is properly initialized and pages shouldn't be de-allocated
+ l_cleanup = false;
+ TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::initialize(): SUCCESSFUL:"
+ " iv_device_ptr=%p", iv_device_ptr);
+
+
+ }while(0);
+
+ // Check to see if we should free pages
+ if (l_cleanup == true)
+ {
+ SecureROM::_cleanup();
+ }
+
+ TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::initialize() - %s",
+ ((NULL == l_errl) ? "No Error" : "With Error") );
+
+ return l_errl;
+
+}
+
+
+/**
+ * @brief Verify Container against system hash keys
+ */
+errlHndl_t SecureROM::verifyContainer(void * i_container, size_t i_size)
+{
+ TRACDCOMP(g_trac_secure,ENTER_MRK"SecureROM::verifyContainer(): "
+ "i_container=%p, size=0x%x", i_container, i_size);
+
+
+ errlHndl_t l_errl = NULL;
+ uint64_t l_rc = 0;
+
+ do{
+
+ // Check to see if ROM has already been initialized
+ // This should have been done early in IPL so assert if this
+ // is not the case as system is in a bad state
+ assert(iv_device_ptr != NULL);
+
+
+ // Declare local input struct
+ ROM_hw_params l_hw_parms;
+
+ // Clear/zero-out the struct since we want 0 ('zero') values for
+ // struct elements my_ecid, entry_point and log
+ memset(&l_hw_parms, 0, sizeof(ROM_hw_params));
+
+ // Now set hw_key_hash, which is of type sha2_hash_t, to iv_hash_key
+ memcpy (&l_hw_parms.hw_key_hash, &iv_hash_key, sizeof(sha2_hash_t));
+
+
+ /*******************************************************************/
+ /* Call ROM_verify() function via an assembly call */
+ /*******************************************************************/
+
+ // Set startAddr to ROM_verify() function at an offset of Secure ROM
+ uint64_t l_rom_verify_startAddr = reinterpret_cast<uint64_t>(
+ iv_device_ptr)
+ + ROM_VERIFY_FUNCTION_OFFSET;
+
+ TRACUCOMP(g_trac_secure,"SecureROM::verifyContainer(): "
+ " Calling ROM_verify() via call_rom_verify: l_rc=0x%x, "
+ "l_hw_parms.log=0x%x (&l_hw_parms=%p) addr=%p (iv_d_p=%p)",
+ l_rc, l_hw_parms.log, &l_hw_parms, l_rom_verify_startAddr,
+ iv_device_ptr);
+
+
+ l_rc = call_rom_verify(reinterpret_cast<void*>
+ (l_rom_verify_startAddr),
+ reinterpret_cast<ROM_container_raw*>
+ (i_container),
+ &l_hw_parms);
+
+
+ TRACUCOMP(g_trac_secure,"SecureROM::verifyContainer(): "
+ "Back from ROM_verify() via call_rom_verify: l_rc=0x%x, "
+ "l_hw_parms.log=0x%x (&l_hw_parms=%p) addr=%p (iv_d_p=%p)",
+ l_rc, l_hw_parms.log, &l_hw_parms, l_rom_verify_startAddr,
+ iv_device_ptr);
+
+
+
+ if (l_rc != 0)
+ {
+ TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::verifyContainer():"
+ " ROM_verify() FAIL: l_rc=0x%x, l_hw_parms.log=0x%x "
+ "addr=%p (iv_d_p=%p)", l_rc, l_hw_parms.log,
+ l_rom_verify_startAddr, iv_device_ptr);
+
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_ROM_VERIFY
+ * @reasoncode SECUREBOOT::RC_ROM_VERIFY
+ * @userdata1 l_rc
+ * @userdata2 l_hw_parms.log
+ * @devdesc ROM_verify() Call Failed
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SECUREBOOT::MOD_SECURE_ROM_VERIFY,
+ SECUREBOOT::RC_ROM_VERIFY,
+ l_rc,
+ l_hw_parms.log);
+
+ l_errl->collectTrace("SECURE",256);
+ break;
+
+ }
+
+ }while(0);
+
+
+ TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::verifyContainer() - %s",
+ ((NULL == l_errl) ? "No Error" : "With Error") );
+
+ return l_errl;
+}
+
+
+/**
+ * @brief Hash Blob
+ */
+errlHndl_t SecureROM::hashBlob(void * i_blob, size_t i_size)
+{
+
+ TRACDCOMP(g_trac_secure,INFO_MRK"SecureROM::hashBlob() NOT "
+ "supported, but not returning error log");
+
+ // @todo RTC:34080 - Add support for this function
+
+ errlHndl_t l_errl = NULL;
+
+ TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::hashBlob() - %s",
+ ((NULL == l_errl) ? "No Error" : "With Error") );
+
+ return l_errl;
+
+}
+
+
+/********************
+ Internal Methods
+ ********************/
+
+/**
+ * @brief Constructor
+ */
+SecureROM::SecureROM()
+:iv_device_ptr(NULL)
+{
+ TRACDCOMP(g_trac_secure, "SecureROM::SecureROM()>");
+
+ // Clear out iv_hash_keys, which is of type sha2_hash_t
+ memset(&iv_hash_key, 0, sizeof(sha2_hash_t) );
+
+}
+
+/**
+ * @brief Destructor
+ */
+SecureROM::~SecureROM() { SecureROM::_cleanup(); };
+
+void SecureROM::_cleanup()
+{
+ // deallocate pages
+ if ( iv_device_ptr != NULL )
+ {
+
+ // Make this address space writable before sending it back
+ // to the Page Manager via free, otherwise PM will crash trying to
+ // update the previously-defined-as-excutable memory space
+ uint64_t l_access_type = WRITABLE;
+ uint64_t l_rc = mm_set_permission( iv_device_ptr,
+ SECUREROM_NUM_PAGES,
+ l_access_type );
+
+ if (l_rc != 0)
+ {
+ TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM:::_cleanup():"
+ " Fail from mm_set_permission(WRITABLE): l_rc=0x%x, ptr=%p, "
+ "size=0x%x, pages=%d, access=0x%x", l_rc, iv_device_ptr,
+ SECUREROM_MEMORY_SIZE, SECUREROM_NUM_PAGES, l_access_type);
+
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_ROM_CLEANUP
+ * @reasoncode SECUREBOOT::RC_SET_PERMISSION_FAIL_WRITE
+ * @userdata1 l_rc
+ * @userdata2 iv_device_ptr
+ * @devdesc mm_set_permission(WRITABLE) failed for Secure ROM
+ */
+ errlHndl_t l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SECUREBOOT::MOD_SECURE_ROM_CLEANUP,
+ SECUREBOOT::RC_SET_PERMISSION_FAIL_WRITE,
+ TO_UINT64(l_rc),
+ reinterpret_cast<uint64_t>(iv_device_ptr));
+
+ l_errl->collectTrace("SECURE",256);
+
+ // Commit here because funtion doesn't return error handle
+ errlCommit(l_errl, SECURE_COMP_ID);
+
+ // NOTE: Purposely not calling free() here -
+ // prefer to have a memory leak than have another task crash
+ // due to pages still being excutable or in a bad state
+
+ }
+ else
+ {
+ // Safe to free allocated pages
+ free(iv_device_ptr);
+
+ TRACDCOMP(g_trac_secure,INFO_MRK
+ "SecureROM::_cleanup(): pages set to "
+ "WRITABLE (rc=0x%x) and free called", l_rc);
+
+
+ // Reset device ptr
+ iv_device_ptr = NULL;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Retrieves HW Keys from the system
+ */
+errlHndl_t SecureROM::getHwHashKeys()
+{
+
+ errlHndl_t l_errl = NULL;
+
+ TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::getHwHashKeys() NOT supported");
+
+ // @todo RTC:34080 - Add support for getting HW Hash Keys from System
+
+ return l_errl;
+}
+
+/**
+ * @brief Static instance function for testcase only
+ */
+SecureROM& SecureROM::getInstance()
+{
+ return Singleton<SecureROM>::instance();
+}
+
+
OpenPOWER on IntegriCloud