Skip to content

Commit

Permalink
Secure Memory Manager implementation
Browse files Browse the repository at this point in the history
Support to update and manage the memory window list
Opening of HB Dump window in istep 5.1
Enabled memory filtering in mem access chip-ops

Change-Id: I72b68ac099371babe47a64689fa38927934625b7
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43929
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: AMIT J. TENDOLKAR <amit.tendolkar@in.ibm.com>
Reviewed-by: RAJA DAS <rajadas2@in.ibm.com>
Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
  • Loading branch information
Shakeebbk authored and sgupta2m committed Sep 6, 2017
1 parent 736117b commit 708be51
Show file tree
Hide file tree
Showing 15 changed files with 770 additions and 302 deletions.
186 changes: 186 additions & 0 deletions src/sbefw/sbeSecureMemRegionManager.C
@@ -0,0 +1,186 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
/* $Source: src/sbefw/sbeSecureMemRegionManager.C $ */
/* */
/* OpenPOWER sbe Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2017 */
/* */
/* */
/* 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 "sbeSecureMemRegionManager.H"
#include "sbetrace.H"
#include "sbeutil.H"

#ifndef __SBEFW_SEEPROM__

SBESecureMemRegionManager* SBESecMemRegionManager =
&SBESecureMemRegionManager::getInstance();

SBESecureMemRegionManager& SBESecureMemRegionManager::getInstance()
{
static SBESecureMemRegionManager iv_instance;
return iv_instance;
}

secureMemRegion_t SBESecureMemRegionManager::getPartialRegionSize(
const secureMemRegion_t i_region)
{
secureMemRegion_t ret = {};
for(size_t i = 0; i < iv_regionsOpenCnt; i++)
{
uint64_t minStartAddr = i_region.startAddress < iv_memRegions[i].startAddress ?
i_region.startAddress : iv_memRegions[i].startAddress;
uint64_t iRegionEndAddress = i_region.startAddress + i_region.size - 1;
uint64_t existingRegionEndAddress = iv_memRegions[i].startAddress + iv_memRegions[i].size - 1;
uint64_t maxEndAddr = iRegionEndAddress >= existingRegionEndAddress ?
iRegionEndAddress : existingRegionEndAddress;

// detect overlap
if((maxEndAddr - minStartAddr + 1) < (i_region.size + iv_memRegions[i].size))
{
ret = iv_memRegions[i];
// Give preference to first region
if(i_region.startAddress >= iv_memRegions[i].startAddress &&
i_region.startAddress < (iv_memRegions[i].startAddress +
iv_memRegions[i].size))
{
// Return the existing window to the extent of input window
ret.startAddress = i_region.startAddress;
ret.size = iv_memRegions[i].startAddress + iv_memRegions[i].size
- i_region.startAddress;
if(ret.size > i_region.size)
ret.size = i_region.size;
break;
}
}
}
return ret;
}

#endif //__SBEFW_SEEPROM__
#ifdef __SBEFW_SEEPROM__

// Public functions
sbeSecondaryResponse SBESecureMemRegionManager::add(const uint64_t i_startAddr,
const uint32_t i_size,
const uint8_t i_mode)
{
#define SBE_FUNC "SBESecureMemRegionManager::add"
sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
do
{
if(getPartialRegionSize({i_startAddr, i_size, i_mode}).mode)
{
SBE_ERROR(SBE_FUNC" SBE_SEC_MEM_REGION_AMEND_ATTEMPTED");
rc = SBE_SEC_MEM_REGION_AMEND_ATTEMPTED;
break;
}
if(iv_regionsOpenCnt >= MAX_NONSECURE_MEM_REGIONS)
{
SBE_ERROR(SBE_FUNC" SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED");
rc = SBE_SEC_MAXIMUM_MEM_REGION_EXCEEDED;
break;
}
SBE_INFO(SBE_FUNC" Adding region Mem[0x%08X%08X], size[0x%08X]",
SBE::higher32BWord(i_startAddr),
SBE::lower32BWord(i_startAddr),
i_size);
iv_memRegions[iv_regionsOpenCnt++] = {i_startAddr, i_size, i_mode};
SBE_INFO(SBE_FUNC" after addition iv_regionsOpenCnt [%d]",
iv_regionsOpenCnt);
} while(0);
return rc;
#undef SBE_FUNC
}

sbeSecondaryResponse SBESecureMemRegionManager::remove(const uint64_t i_startAddr)
{
#define SBE_FUNC "SBESecureMemRegionManager::remove";
size_t i = 0;
sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
for(; i < iv_regionsOpenCnt; i++)
{
if(i_startAddr == iv_memRegions[i].startAddress)
{
break;
}
}
if(i < iv_regionsOpenCnt)
{
SBE_INFO(SBE_FUNC" Deleting region i[%d], Mem[0x%08X%08X], size[0x%08X]",
i,
SBE::higher32BWord(iv_memRegions[i].startAddress),
SBE::lower32BWord(iv_memRegions[i].startAddress),
iv_memRegions[i].size);
// Remove the empty slot and maintain contiguous list
for(size_t j = i; j < iv_regionsOpenCnt-1; j++)
{
iv_memRegions[j].startAddress = iv_memRegions[j+1].startAddress;
iv_memRegions[j].size = iv_memRegions[j+1].size;
iv_memRegions[j].mode = iv_memRegions[j+1].mode;
}

iv_regionsOpenCnt--;
SBE_INFO(SBE_FUNC" After deletion : iv_regionsOpenCnt[%d]", iv_regionsOpenCnt);
}
else
{
SBE_ERROR(SBE_FUNC" SBE_SEC_MEM_REGION_NOT_FOUND");
rc = SBE_SEC_MEM_REGION_NOT_FOUND;
}
return rc;
#undef SBE_FUNC
}

#endif //__SBEFW_SEEPROM__
#ifndef __SBEFW_SEEPROM__

sbeSecondaryResponse SBESecureMemRegionManager::isAccessAllowed(
secureMemRegion_t i_region)
{
#define SBE_FUNC "SBESecureMemRegionManager::isAccessAllowed"
sbeSecondaryResponse rc = SBE_SEC_OPERATION_SUCCESSFUL;
while(i_region.size > 0)
{
secureMemRegion_t foundregion = getPartialRegionSize(i_region);
// Check if the found region has allowable access level
// and that the region overlap is from the beginning itself
if((i_region.mode & foundregion.mode) &&
(i_region.startAddress == foundregion.startAddress))
{
SBE_INFO(SBE_FUNC" foundRegion Mem[0x%08X%08X], size[0x%08X]",
SBE::higher32BWord(foundregion.startAddress),
SBE::lower32BWord(foundregion.startAddress),
foundregion.size);
i_region.size -= foundregion.size;
i_region.startAddress += foundregion.size;
}
else
{
SBE_ERROR(SBE_FUNC" Non secure access to memory blocked "
"Addr[0x%08X%08X] Size[0x%08X]",
SBE::higher32BWord(i_region.startAddress),
SBE::lower32BWord(i_region.startAddress),
i_region.size);
rc = SBE_SEC_BLACKLISTED_MEM_ACCESS;
break;
}
}
return rc;
#undef SBE_FUNC
}
#endif //__SBEFW_SEEPROM__
113 changes: 113 additions & 0 deletions src/sbefw/sbeSecureMemRegionManager.H
@@ -0,0 +1,113 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
/* $Source: src/sbefw/sbeSecureMemRegionManager.H $ */
/* */
/* OpenPOWER sbe Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2017 */
/* */
/* */
/* 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 */
#pragma once

#include <stdint.h>
#include <stddef.h>
#include "sbe_sp_intf.H"

enum class memRegionMode:uint8_t
{
READ = 0x01,
WRITE = 0x02,
};

// Structure to define a mem region
typedef struct
{
uint64_t startAddress;
uint32_t size;
uint32_t mode;
} secureMemRegion_t;

constexpr size_t MAX_NONSECURE_MEM_REGIONS = 8;

class SBESecureMemRegionManager
{
secureMemRegion_t iv_memRegions[MAX_NONSECURE_MEM_REGIONS];
size_t iv_regionsOpenCnt;

SBESecureMemRegionManager():iv_memRegions{0}
{
}

/*
* @brief getPartialRegionSize - get the overlapping region
* if it exists.
* Also if the overlap is from the beginning,
* first region is returned
*
*
* @param[in] i_region region to check for overlap
*
* @return overlapping region
*/
secureMemRegion_t getPartialRegionSize(const secureMemRegion_t i_region);

public:
// Disable copy constructors
SBESecureMemRegionManager(const SBESecureMemRegionManager&) = delete;
SBESecureMemRegionManager& operator=(const SBESecureMemRegionManager&) = delete;

static SBESecureMemRegionManager& getInstance();

/*
* @brief add - Open a new memory region
*
* @param[in] i_startAddr Start address of the memory region
* @param[in] i_size Size of the memory region
* @param[in] i_mode Bit mapped access mode of the memory region
*
* @return SBE secondary RC
*/
sbeSecondaryResponse add(const uint64_t i_startAddr,
const uint32_t i_size,
const uint8_t i_mode);
/*
* @brief remove - Close a memory region
*
* @param[in] i_startAddr Start address of the memory region
*
* @return SBE secondary RC
*/
sbeSecondaryResponse remove(const uint64_t i_startAddr);
/*
* @brief isAccessAllowed - Check if the access is allowed
*
* @param[in] i_region region to check the access for
*
* @return SBE secondary RC
*/
sbeSecondaryResponse isAccessAllowed(secureMemRegion_t i_region);

/*
* @brief closeAllRegions - close all non-secure regions
*/
void closeAllRegions()
{
iv_regionsOpenCnt = 0;
}
};

extern SBESecureMemRegionManager* SBESecMemRegionManager;
56 changes: 50 additions & 6 deletions src/sbefw/sbecmdiplcontrol.C
Expand Up @@ -109,6 +109,9 @@

#include "sbeXipUtils.H" // For getting hbbl offset
#include "sbeutil.H" // For getting SBE_TO_NEST_FREQ_FACTOR

#include "p9_fbc_utils.H"
#include "sbeSecureMemRegionManager.H"
// Forward declaration
using namespace fapi2;

Expand Down Expand Up @@ -828,6 +831,7 @@ ReturnCode istepWithCoreConditional( sbeIstepHwp_t i_hwp)
}

//----------------------------------------------------------------------------
constexpr uint32_t HB_MEM_WINDOW_SIZE = 32*1024*1024; //32 MB
ReturnCode istepLoadBootLoader( sbeIstepHwp_t i_hwp)
{
ReturnCode rc = FAPI2_RC_SUCCESS;
Expand All @@ -842,12 +846,50 @@ ReturnCode istepLoadBootLoader( sbeIstepHwp_t i_hwp)
P9XipHeader *hdr = getXipHdr();
P9XipSection *hbblSection = &(hdr->iv_section[P9_XIP_SECTION_SBE_HBBL]);

// Update the ATTR_SBE_ADDR_KEY_STASH_ADDR before calling the bootloader,
// since it is going to access these data from inside.
uint64_t addr = SBE_GLOBAL->sbeKeyAddrPair.fetchStashAddrAttribute();
FAPI_ATTR_SET(fapi2::ATTR_SBE_ADDR_KEY_STASH_ADDR, sysTgt, addr);
SBE_EXEC_HWP(rc, p9_sbe_load_bootloader, proc, exTgt, hbblSection->iv_size,
getSectionAddr(hbblSection))
uint64_t drawer_base_address_nm0, drawer_base_address_nm1;
uint64_t drawer_base_address_m;
uint64_t drawer_base_address_mmio;
uint64_t l_hostboot_hrmor_offset;
do
{
// Update the ATTR_SBE_ADDR_KEY_STASH_ADDR before calling the bootloader,
// since it is going to access these data from inside.
uint64_t addr = SBE_GLOBAL->sbeKeyAddrPair.fetchStashAddrAttribute();
FAPI_ATTR_SET(fapi2::ATTR_SBE_ADDR_KEY_STASH_ADDR, sysTgt, addr);
SBE_EXEC_HWP(rc, p9_sbe_load_bootloader, proc, exTgt, hbblSection->iv_size,
getSectionAddr(hbblSection))
if(rc != FAPI2_RC_SUCCESS)
{
SBE_ERROR(" p9_sbe_load_bootloader failed");
break;
}

// Open HB Dump memory Region
fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
FAPI_ATTR_GET(fapi2::ATTR_HOSTBOOT_HRMOR_OFFSET,
FAPI_SYSTEM,
l_hostboot_hrmor_offset);
rc = p9_fbc_utils_get_chip_base_address(
proc,
ABS_FBC_GRP_ID_ONLY,
drawer_base_address_nm0,
drawer_base_address_nm1,
drawer_base_address_m,
drawer_base_address_mmio);
if(rc != FAPI2_RC_SUCCESS)
{
SBE_ERROR(" p9_fbc_utils_get_chip_base_address failed");
break;
}
drawer_base_address_nm0 += l_hostboot_hrmor_offset;
SBE_INFO("istep 5.1 HB Dump mem Region [0x%08X%08X]",
SBE::higher32BWord(drawer_base_address_nm0),
SBE::lower32BWord(drawer_base_address_nm0));
SBESecMemRegionManager->add(drawer_base_address_nm0,
HB_MEM_WINDOW_SIZE,
static_cast<uint8_t>(memRegionMode::READ));

} while(0);
return rc;
}

Expand Down Expand Up @@ -1172,6 +1214,8 @@ ReturnCode istepStartMpipl( sbeIstepHwp_t i_hwp)
SBE_ENTER_MPIPL_EVENT);
// Set MPIPL mode bit in Scratch Reg 3
(void)SbeRegAccess::theSbeRegAccess().setMpIplMode(true);
// Close all non-secure memory regions
SBESecMemRegionManager->closeAllRegions();

do
{
Expand Down

0 comments on commit 708be51

Please sign in to comment.