diff options
Diffstat (limited to 'src/bootloader')
| -rw-r--r-- | src/bootloader/bl_pnor_ecc.C | 4 | ||||
| -rw-r--r-- | src/bootloader/bl_pnor_utils.C | 59 | ||||
| -rw-r--r-- | src/bootloader/bl_start.S | 154 | ||||
| -rw-r--r-- | src/bootloader/bootloader.C | 220 | ||||
| -rw-r--r-- | src/bootloader/makefile | 8 |
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 |

