summaryrefslogtreecommitdiffstats
path: root/src/bootloader/bootloader.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootloader/bootloader.C')
-rw-r--r--src/bootloader/bootloader.C220
1 files changed, 191 insertions, 29 deletions
diff --git a/src/bootloader/bootloader.C b/src/bootloader/bootloader.C
index 462217d76..8f63ae925 100644
--- a/src/bootloader/bootloader.C
+++ b/src/bootloader/bootloader.C
@@ -22,63 +22,225 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+#define __BOOT_LOADER_C
+
#include <stdint.h>
#include <bootloader/bootloader.H>
-#include <util/singleton.H>
-#include <kernel/cpu.H>
+#include <bootloader/bootloader_trace.H>
+#include <bootloader/bl_pnorAccess.H>
-#include <kernel/intmsghandler.H> // @TODO RTC:133821 might not be needed long-term
+#include <lpc_const.H>
+#include <pnor_utils.H>
-#include <usr/pnor/ecc.H>
+#include <ecc.H>
#include <stdlib.h>
extern uint64_t kernel_other_thread_spinlock;
-extern uint32_t data_sandbox[16]; // @TODO RTC:133821 temporary bringup
+extern PNOR::SectionData_t bootloader_hbbSection;
namespace Bootloader{
+ /**
+ * @brief Pointer to bootloader scratch space
+ *
+ * Pointer to location in main storage which bootloader uses as
+ * scratch space
+ */
+ uint8_t *g_blScratchSpace;
+
+ /** Apply Secure Signature Validation function.
+ *
+ * @note Currently just a stub.
+ */
+ void applySecureSignatureValidation()
+ {
+ // (just an empty stub function for now) @TODO RTC:143902
+ }
+
+
+ /** Bootloader main function to work with and start HBB.
+ *
+ * @return 0.
+ *
+ * @note Should branch to HBB and never return.
+ */
extern "C"
int main()
{
- // cppBootstrap(); @TODO RTC:133821 might not be needed long-term
- // cv_blScratchSpace = ??? @TODO RTC:133821
+ // Initialization
+ bootloader_trace_index = 0;
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_START);
+ g_blScratchSpace = reinterpret_cast<uint8_t*>(HBBL_SCRATCH_SPACE_ADDR);
- // @TODO RTC:134064 Get location of HB base code in PNOR from TOC
+ // Set variables needed for getting location of HB base code
+ // @TODO RTC:138268 Support multiple sides of PNOR in bootloader
+ uint64_t l_pnorStart = LPC::LPC_PHYS_BASE + LPC::LPCHC_FW_SPACE
+ + PNOR::LPC_SFC_MMIO_OFFSET;
+ uint32_t l_errCode = PNOR::NO_ERROR;
+ uint8_t l_tocUsed = 0;
- // @TODO RTC:133821 Copy HB base code from PNOR to 0x200000
+ // Get location of HB base code in PNOR from TOC
+ // @TODO RTC:138268 Support multiple sides of PNOR in bootloader
+ bl_pnorAccess::getHBBSection(l_pnorStart,
+ bootloader_hbbSection,
+ l_errCode,
+ l_tocUsed);
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_GETHBBSECTION_RTN );
- // Remove ECC from HB base code at 0x200000 and store result at 0x300000
- PNOR::ECC::eccStatus rc = PNOR::ECC::CLEAN;
-// PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>(0x200000),
-// reinterpret_cast<uint8_t*>(0x300000),
-// 0x100000); // @TODO RTC:133821 determine size
-
- if (rc != PNOR::ECC::UNCORRECTABLE)
+ if(PNOR::NO_ERROR == l_errCode)
{
-// memcpy(reinterpret_cast<void*>(0x300000),
-// reinterpret_cast<void*>(0),
-// 0x100000); // @TODO RTC:133821 determine size // replace with asm cache inhibited instructions
- }
+ // get hbbFlashOffset
+ uint64_t l_hbbFlashOffset = bootloader_hbbSection.flashAddr;
+ // get hbbLength without size of ECC data
+ uint32_t l_hbbLength = bootloader_hbbSection.size;
+ // get hbbEcc
+ bool l_hbbEcc =
+ ( bootloader_hbbSection.integrity == FFS_INTEG_ECC_PROTECT);
+ // set hbbSbeHeaderSize @TODO RTC:137480 subject to future removal
+ uint64_t l_hbbSbeHeaderSize = (l_hbbEcc)
+ ? (0x18 * LENGTH_W_ECC) / LENGTH_WO_ECC
+ : 0x18;
+
+ // Copy HB base code from PNOR to working location
+ handleMMIO(l_pnorStart + l_hbbFlashOffset + l_hbbSbeHeaderSize,
+ (l_hbbEcc) ? HBB_ECC_WORKING_ADDR : HBB_WORKING_ADDR,
+ (l_hbbEcc) ? (l_hbbLength * LENGTH_W_ECC)/LENGTH_WO_ECC
+ : l_hbbLength,
+ BYTESIZE);
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_WORKING_HANDLEMMIO_RTN);
- // Ready to let the other CPUs go. @TODO RTC:133821 actually need to start relocated HB base code
- lwsync();
- kernel_other_thread_spinlock = 1;
+ PNOR::ECC::eccStatus rc = PNOR::ECC::CLEAN;
+ if(l_hbbEcc)
+ {
+ // Remove ECC from HB base code at in working location and
+ // store result in new working location
+ rc = PNOR::ECC::removeECC(
+ reinterpret_cast<uint8_t*>(HBB_ECC_WORKING_ADDR |
+ IGNORE_HRMOR_MASK),
+ reinterpret_cast<uint8_t*>(HBB_WORKING_ADDR |
+ IGNORE_HRMOR_MASK),
+ l_hbbLength);
+ if (rc != PNOR::ECC::CLEAN)
+ {
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_REMOVEECC_RTN);
+ }
+ else if (rc != PNOR::ECC::CORRECTED)
+ {
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_REMOVEECC_CORRECTED);
+ }
+ }
- data_sandbox[8] = 0x12345678; // @TODO RTC:133821 temporary bringup
+ if (rc != PNOR::ECC::UNCORRECTABLE)
+ {
+ // Apply secure signature validation @TODO RTC:143902
+ applySecureSignatureValidation();
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_APPLYSECSIGVAL_RTN);
- MAGIC_INSTRUCTION(MAGIC_BREAK); // @TODO RTC:133821 temporary bringup
+ // Copy HBB image into address where it executes
+ uint64_t *l_src_addr =
+ reinterpret_cast<uint64_t*>(HBB_WORKING_ADDR |
+ IGNORE_HRMOR_MASK);
+ uint64_t *l_dest_addr =
+ reinterpret_cast<uint64_t*>(HBB_RUNNING_ADDR |
+ IGNORE_HRMOR_MASK);
+ for(uint32_t i = 0;
+ i < l_hbbLength / sizeof(uint64_t);
+ i++)
+ {
+ l_dest_addr[i] = l_src_addr[i];
+ }
+ BOOTLOADER_TRACE(BTLDR_TRC_MAIN_COPY_HBB_DONE);
+
+ // Start executing HBB
+ enterHBB(HBB_HRMOR, HBB_RUNNING_OFFSET);
+ }
+ else
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_MAIN_REMOVEECC_FAIL);
+ }
+ }
+ else
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_MAIN_GETHBBSECTION_FAIL);
+ }
- while(1); // @TODO
- task_end_stub(); // @TODO
return 0;
}
+
+ /** Handle MMIO to copy code/data from location to another.
+ *
+ * @param[in] i_srcAddr - The source location.
+ * @param[in] i_destAddr - The destination location.
+ * @param[in] i_size - The size of the code/data.
+ * @param[in] i_ld_st_size - The size of each load/store operation.
+ *
+ * @return void.
+ */
void handleMMIO(uint64_t i_srcAddr,
uint64_t i_destAddr,
uint32_t i_size,
MMIOLoadStoreSizes i_ld_st_size)
{
- // @TODO RTC:133821
+ BOOTLOADER_TRACE(BTLDR_TRC_HANDLEMMIO_START);
+
+ // Set base addresses, Ignore HRMOR setting
+ uint64_t l_srcAddr_base = i_srcAddr | IGNORE_HRMOR_MASK;
+ uint64_t l_destAddr_base = i_destAddr | IGNORE_HRMOR_MASK;
+
+ uint32_t l_targetGPR = 0;
+
+ for(uint32_t i = 0;
+ i < i_size;
+ i += i_ld_st_size)
+ {
+ // Set addresses
+ uint64_t l_srcAddr = l_srcAddr_base + i;
+ uint64_t l_destAddr = l_destAddr_base + i;
+
+ if(i_ld_st_size == BYTESIZE)
+ {
+ // Cache-inhibited load byte from hypervisor state.
+ // lbzcix BOP1,Ref_G0,BOP2
+ asm volatile("lbzcix %0, 0, %1"
+ : "=r" (l_targetGPR) // output, %0
+ : "r" (l_srcAddr) // input, %1
+ : ); // no impacts
+
+ // Cache-inhibited store byte.
+ // stbcix BOP1,Ref_G0,BOP2
+ asm volatile("stbcix %0,0,%1"
+ :: "r" (l_targetGPR) , "r" (l_destAddr));
+ }
+ else if(i_ld_st_size == WORDSIZE)
+ {
+ // Cache-inhibited load word from hypervisor state.
+ // lwzcix BOP1,Ref_G0,BOP2
+ asm volatile("lwzcix %0, 0, %1"
+ : "=r" (l_targetGPR) // output, %0
+ : "r" (l_srcAddr) // input, %1
+ : ); // no impacts
+
+ // Cache-inhibited store word.
+ // stwcix BOP1,Ref_G0,BOP2
+ asm volatile("stwcix %0,0,%1"
+ :: "r" (l_targetGPR) , "r" (l_destAddr));
+ }
+ else
+ {
+ // Cache-inhibited load double word from hypervisor state.
+ // ldcix BOP1,Ref_G0,BOP2
+ asm volatile("ldcix %0, 0, %1"
+ : "=r" (l_targetGPR) // output, %0
+ : "r" (l_srcAddr) // input, %1
+ : ); // no impacts
+
+ // Cache-inhibited store double word.
+ // stdcix BOP1,Ref_G0,BOP2
+ asm volatile("stdcix %0,0,%1"
+ :: "r" (l_targetGPR) , "r" (l_destAddr));
+ }
+ }
}
} // end namespace Bootloader
-
OpenPOWER on IntegriCloud