summaryrefslogtreecommitdiffstats
path: root/src/bootloader
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootloader')
-rw-r--r--src/bootloader/bl_pnor_ecc.C4
-rw-r--r--src/bootloader/bl_pnor_utils.C59
-rw-r--r--src/bootloader/bl_start.S154
-rw-r--r--src/bootloader/bootloader.C220
-rw-r--r--src/bootloader/makefile8
5 files changed, 341 insertions, 104 deletions
diff --git a/src/bootloader/bl_pnor_ecc.C b/src/bootloader/bl_pnor_ecc.C
index df7e9d6ee..97e92c2d8 100644
--- a/src/bootloader/bl_pnor_ecc.C
+++ b/src/bootloader/bl_pnor_ecc.C
@@ -29,9 +29,9 @@
#include <stdio.h>
#include <endian.h>
-#include <usr/pnor/ecc.H>
+#include <ecc.H>
-#include <../usr/pnor/ecc.C>
+#include <ecc.C>
#undef bl_pnor_ecc_C
diff --git a/src/bootloader/bl_pnor_utils.C b/src/bootloader/bl_pnor_utils.C
new file mode 100644
index 000000000..cca6f25d1
--- /dev/null
+++ b/src/bootloader/bl_pnor_utils.C
@@ -0,0 +1,59 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/bootloader/bl_pnor_utils.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <bootloader/bootloader.H>
+
+#define bl_pnor_utils_C
+
+#include <stdio.h>
+#include <endian.h>
+
+int strcmp(const char *str1, const char *str2)
+{
+ for(uint32_t strcmp_index = 0;
+ strcmp_index < 12;
+ strcmp_index++)
+ {
+ if((str1[strcmp_index] == '\0') && (str2[strcmp_index] == '\0'))
+ {
+ return 0;
+ }
+ else if(str1[strcmp_index] == str2[strcmp_index])
+ {
+ continue;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#include <pnor_utils.C>
+
+#undef bl_pnor_utils_C
+
+
diff --git a/src/bootloader/bl_start.S b/src/bootloader/bl_start.S
index 9f190b11f..9af07a45f 100644
--- a/src/bootloader/bl_start.S
+++ b/src/bootloader/bl_start.S
@@ -41,7 +41,6 @@ _start:
mtsrr1 r2
li r2, _start_postmsr@l
mtsrr0 r2
- b _start_postmsr
_start_postmsr:
@@ -59,63 +58,6 @@ _start_postmsr:
bne 1b ;// Loop until sucessful at stwcx.
isync
- b _main
-
-
-/* @TODO RTC:133821 might not be needed
- ;// Relocate code
- bl pre_relocate ;// fill LR with address
-pre_relocate:
- mflr r2
- lis r1,0x0010
- cmpl cr0,r2,r1 ;// Check LR is less than 1MB
- blt finished_relocate ;// No need to relocate if less than 1MB
-
- ;// Get addresses for relocation.
- ;// Write address in r5
- ;// Read address in r1
- li r5,0
- lis r1, -1 ;// fill r1 with ffff..ff0000
-
- and r1,r1,r2 ;// and with pre_relocate's address from r2 to get start of
- ;// rom section.
-
- ;// Update LR to low address.
- clrldi r2,r2,48 ;// Equiv to ~(0x0FFFF)
- mtlr 2
-
- ;// Moving 1MB , so load r2 with (1MB / 8 bytes per word)
- lis r2, 0x2
- mtctr r2
-relocate_loop:
- ;// The dcbst/sync/icbi/isync sequence comes from PowerISA
- ld r4, 0(r1)
- std r4, 0(r5)
- dcbst 0,r5
- sync
- icbi 0,r5
- isync
- addi r1,r1,8
- addi r5,r5,8
- bdnz+ relocate_loop
-
- ;// Now that we've relocated, erase exception prefix.
- mfmsr r11
-
- rldicl r11,r11,57,1 ;// Erase bit 6 ( equiv to r11 & ~(0x40))
- rotldi r11,r11,7
-
- mtmsr r11
-
- ;// Jump to low address.
- blr
-
-finished_relocate:
- ;// Jump to main.
- b _main
-@TODO RTC:133821 might not be needed */
-
-
;// _main:
;// Set up stack and TOC and call kernel's main.
_main:
@@ -124,10 +66,22 @@ _main:
ori r2, r2, main@l
ld r2,8(r2)
- ;// Set up initial stack, space for 8 double-words
- lis r1, kernel_stack@h
- ori r1, r1, kernel_stack@l
- addi r1, r1, 16320
+ ;// Set up initial stack just before scratch space at 64k offset into HBBL
+ lis r1, _start@h
+ addis r1, r1, 1 ;// 64k (1 * 0x10000)
+
+ ;// Zero space from end of load to bottom of stack
+ lis r3, end_load_address@h
+ ori r3, r3, end_load_address@l
+ li r4, 7
+ add r3, r3, r4
+ andc r3, r3, r4
+ li r4, 0
+_zero_space_loop:
+ std r4, 0(r3)
+ addi r3, r3, 8
+ cmpld cr7, r3, r1
+ blt cr7, _zero_space_loop
;// Call main.
bl main
@@ -161,22 +115,76 @@ task_end_stub:
sc
-.section .data
+ ;// @fn enterHBB
+ ;// Leave the Bootloader and switch to the Hostboot Base (HBB).
+ ;//
+ ;// Steps:
+ ;// Retrieve existing HRMOR.
+ ;// Determine physical address of EA[0]=1 mode instruction.
+ ;// Jump to enter EA[0]=1 mode.
+ ;// Update HRMOR.
+ ;// Execute isync.
+ ;// Enter Hostboot Base (HBB).
+ ;//
+ ;// @param[in] r3 - Hostboot HRMOR
+ ;// @param[in] r4 - Hostboot Entry
+ ;//
+.global enterHBB
+enterHBB:
+ ;// Set R10 to 0x8000000000000000 so we can set "EA[0]=1" for addrs.
+ li r10, 1
+ rotldi r10, r10, 63
+
+ ;// Retrieve existing HRMOR.
+ mfspr r0, HRMOR
+
+ ;// Determine physical address of EA[0]=1 mode instruction.
+ lis r9, switchToHBB@h
+ ori r9, r9, switchToHBB@l
+ or r9, r9, r0 ;// Apply HRMOR.
+ or r9, r9, r10 ;// Apply EA[0]=1.
+
+ ;// Jump to enter EA[0]=1
+ mtlr r9
+ blr
- .balign 1024
-kernel_stack:
- .space 4*1024
+switchToHBB:
+ ;// Update HRMOR
+ mtspr HRMOR, r3
+
+ ;// Execute isync
+ isync
+
+ ;// Enter Hostboot Base (HBB).
+ mtsrr0 r4
+ rfid
- .balign 8
-.global data_sandbox
-data_sandbox:
- .space 64
+.section .data
+
+ .balign 8
.global kernel_other_thread_spinlock
kernel_other_thread_spinlock:
.space 8
-.global g_blScratchSpace
-g_blScratchSpace:
- .space 8
+ ;// @name bootloader_trace_index
+ ;// @brief Index for Bootloader Trace entries
+ ;// One-byte index for next entry to use in bootloader_trace.
+.global bootloader_trace_index
+bootloader_trace_index:
+ .space 1
+
+ .balign 16
+ ;// @name bootloader_trace
+ ;// @brief Buffer for Bootloader Trace data
+ ;// Buffer with bootloader trace entries. There are 64 one-byte entries
+ ;// in the buffer. They are used to track events that have occurred in
+ ;// the bootloader code. After all entries have been used, the buffer
+ ;// wraps and the oldest entry is overwritten by the newest trace data.
+.global bootloader_trace
+bootloader_trace:
+ .space 64
+.global bootloader_hbbSection
+bootloader_hbbSection:
+ .space 32
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
-
diff --git a/src/bootloader/makefile b/src/bootloader/makefile
index cf5fe04a6..2513e7089 100644
--- a/src/bootloader/makefile
+++ b/src/bootloader/makefile
@@ -24,8 +24,16 @@
# IBM_PROLOG_END_TAG
ROOTPATH = ../..
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pnor/
+EXTRAINCDIR += ${ROOTPATH}/src/usr/lpc/
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/pnor/
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/lpc/
+
OBJS += bl_start.o
OBJS += bootloader.o
+OBJS += bl_pnorAccess.o
+OBJS += bl_pnor_utils.o
OBJS += bl_pnor_ecc.o
OBJS += bl_builtins.o
OpenPOWER on IntegriCloud