summaryrefslogtreecommitdiffstats
path: root/src/sbefw/core/sbecmdgeneric.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbefw/core/sbecmdgeneric.C')
-rw-r--r--src/sbefw/core/sbecmdgeneric.C532
1 files changed, 532 insertions, 0 deletions
diff --git a/src/sbefw/core/sbecmdgeneric.C b/src/sbefw/core/sbecmdgeneric.C
new file mode 100644
index 00000000..593e012f
--- /dev/null
+++ b/src/sbefw/core/sbecmdgeneric.C
@@ -0,0 +1,532 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/core/sbecmdgeneric.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,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 */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdgeneric.C
+ *
+ * @brief This file contains the SBE generic Commands
+ *
+ */
+
+#include "sbecmdgeneric.H"
+#include "sbefifo.H"
+#include "sbetrace.H"
+#include "sbe_sp_intf.H"
+#include "sbe_build_info.H"
+#include "sbeFifoMsgUtils.H"
+#include "sbeFFDC.H"
+#include "sberegaccess.H"
+#include "sbestates.H"
+#include "sbeHostMsg.H"
+#include "sbeHostUtils.H"
+#include "sbeglobals.H"
+#include "sbeXipUtils.H"
+
+#include "fapi2.H"
+//#include "p9_xip_image.h"
+
+using namespace fapi2;
+
+#ifdef __SBEFW_SEEPROM__
+// Forward declaration
+sbeCapabilityRespMsg::sbeCapabilityRespMsg()
+{
+ verMajor= SBE_FW_MAJOR_VERSION;
+ verMinor = SBE_FW_MINOR_VERSION;
+ fwCommitId = SBE_COMMIT_ID;
+ // Get hbbl section
+ P9XipHeader *hdr = getXipHdr();
+ for(uint32_t idx=0; idx<sizeof(hdr->iv_buildTag); idx++)
+ {
+ buildTag[idx] = hdr->iv_buildTag[idx];
+ }
+
+ // We can remove this for llop once all capabilities
+ // are supported
+ for(uint32_t idx = 0; idx < SBE_MAX_CAPABILITIES; idx++ )
+ {
+ capability[idx] = 0;
+ }
+ // @TODO via RTC : 160602
+ // Update Capability flags based on lastes spec.
+ capability[IPL_CAPABILITY_START_IDX] =
+ EXECUTE_ISTEP_SUPPPORTED |
+ SUSPEND_IO_SUPPPORTED;
+
+ capability[SCOM_CAPABILITY_START_IDX] =
+ GET_SCOM_SUPPPORTED |
+ PUT_SCOM_SUPPPORTED |
+ MODIFY_SCOM_SUPPPORTED |
+ PUT_SCOM_UNDER_MASK_SUPPPORTED ;
+
+ capability[GENERIC_CHIPOP_CAPABILITY_START_IDX] =
+ GET_SBE_FFDC_SUPPPORTED |
+ GET_SBE_CAPABILITIES_SUPPPORTED|
+ SBE_QUIESCE;
+
+ capability[MEMORY_CAPABILITY_START_IDX] =
+ GET_MEMORY_SUPPPORTED |
+ PUT_MEMORY_SUPPPORTED |
+ GET_SRAM_OCC_SUPPPORTED |
+ PUT_SRAM_OCC_SUPPPORTED;
+
+ capability[INSTRUCTION_CTRL_CAPABILITY_START_IDX] =
+ CONTROL_INSTRUCTIONS_SUPPPORTED;
+
+ capability[REGISTER_CAPABILITY_START_IDX] =
+ GET_REGISTER_SUPPPORTED |
+ PUT_REGISTER_SUPPPORTED ;
+
+ capability[RING_CAPABILITY_START_IDX] =
+ GET_RING_SUPPPORTED |
+ PUT_RING_SUPPPORTED;
+}
+// Functions
+//----------------------------------------------------------------------------
+uint32_t sbeGetCapabilities (uint8_t *i_pArg)
+{
+ #define SBE_FUNC "sbeGetCapabilities "
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t len = 0;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+ sbeCapabilityRespMsg_t capMsg;
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ rc = sbeUpFifoDeq_mult (len, NULL);
+ // @TODO via RTC : 130575
+ // Optimize both the RC handling and
+ // FIFO operation infrastructure.
+ if ( rc != SBE_SEC_OPERATION_SUCCESSFUL )
+ {
+ // Let command processor routine to handle the RC
+ break;
+ }
+
+ len = sizeof(capMsg)/sizeof(uint32_t);
+ rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &capMsg);
+ if (rc)
+ {
+ break;
+ }
+
+ rc = sbeDsSendRespHdr(respHdr);
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+// Functions
+//----------------------------------------------------------------------------
+uint32_t sbeGetFfdc (uint8_t *i_pArg)
+{
+ #define SBE_FUNC "sbeGetFfdc "
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t len = 0;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ rc = sbeUpFifoDeq_mult (len, NULL);
+
+ if ( rc != SBE_SEC_OPERATION_SUCCESSFUL )
+ {
+ // Let command processor routine to handle the RC
+ break;
+ }
+
+ SbeFFDCPackage sbeFfdcPack;
+ sbeResponseFfdc_t l_ffdc;
+
+ // If need be, force collect HWP FFDC async to the real HWP fail.
+ // Else, just send back what the SBE already has.
+ sbeFfdcPack.collectAsyncHwpFfdc ();
+
+ l_ffdc.setRc(g_FfdcData.fapiRc);
+ SBE_INFO(SBE_FUNC"FAPI RC is %x", g_FfdcData.fapiRc);
+ // If no ffdc , exit;
+ if( (l_ffdc.getRc() != FAPI2_RC_SUCCESS))
+ {
+ // making sure ffdc length is multiples of uint32_t
+ assert((g_FfdcData.ffdcLength % sizeof(uint32_t)) == 0);
+ uint32_t ffdcDataLenInWords = g_FfdcData.ffdcLength
+ / sizeof(uint32_t);
+ // Set failed command information
+ // Sequence Id is 0 by default for Fifo interface
+ // @TODO via RTC : 149074
+ // primary and secondary status should be picked
+ // from the globals.
+ l_ffdc.setCmdInfo(0, respHdr.cmdClass, respHdr.command);
+ // Add HWP specific ffdc data length
+ l_ffdc.lenInWords += ffdcDataLenInWords;
+ len = sizeof(sbeResponseFfdc_t)/sizeof(uint32_t);
+ rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &l_ffdc);
+ if (rc)
+ {
+ break;
+ }
+ //Send HWP internal Data
+ rc = sbeDownFifoEnq_mult ( ffdcDataLenInWords,
+ ( uint32_t *) &g_FfdcData.ffdcData);
+ if (rc)
+ {
+ break;
+ }
+
+ }
+ //Send the FFDC data over FIFO.
+ // @TODO via RTC : 149074
+ // primary and secondary status should be picked
+ // from the globals.
+ // Check for Primary and Secondary Status from Globals and then send
+ // internal FFDC.
+ rc = sbeFfdcPack.sendOverFIFO(respHdr,
+ SBE_FFDC_ALL_DUMP,
+ len,
+ true);
+ if (rc)
+ {
+ break;
+ }
+ rc = sbeDsSendRespHdr(respHdr);
+
+ if (rc)
+ {
+ break;
+ }
+ // If we are able to send ffdc, turn off async ffdc bit
+ (void)SbeRegAccess::theSbeRegAccess().updateAsyncFFDCBit(false);
+ SBE_GLOBAL->asyncFfdcRC = FAPI2_RC_SUCCESS;
+
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//---------------------------------------------------------------------------
+uint32_t sbeSetFFDCAddr(uint8_t *i_pArg)
+{
+#define SBE_FUNC "sbeSetFFDCAddr"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+ sbeSetFFDCAddrReq_t l_req = {};
+
+ do
+ {
+ // Extract the request
+ // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(l_req)/sizeof(uint64_t)),
+ (uint64_t*)&l_req,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ l_req.getFFDCAddr(SBE_GLOBAL->hostFFDCAddr);
+ l_req.getPassThroughCmdAddr(SBE_GLOBAL->hostPassThroughCmdAddr);
+
+ SBE_INFO(SBE_FUNC" Global hostFFDCAddr size[0x%08X] Address[0x%08X%08X]",
+ static_cast<uint32_t>(SBE_GLOBAL->hostFFDCAddr.size),
+ static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostFFDCAddr.addr)),
+ static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostFFDCAddr.addr)));
+ SBE_INFO(SBE_FUNC" Global hostPassCmdAddr size[0x%08X] Address[0x%08X%08X]",
+ static_cast<uint32_t>(SBE_GLOBAL->hostPassThroughCmdAddr.size),
+ static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr)),
+ static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr)));
+
+ } while(false);
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, rc);
+
+ return rc;
+ SBE_EXIT(SBE_FUNC);
+#undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeStashKeyAddrPair( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeStashKeyAddrPair"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t fapiRc = FAPI2_RC_SUCCESS;
+ do
+ {
+ stashMsg_t l_stashMsg;
+ // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1, once both
+ // key/addr is extracted out of MBOX_REG1 and MBOX_REG2
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(stashMsg_t)/sizeof(uint64_t)),
+ (uint64_t*)&l_stashMsg, true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract "
+ "SBE_HOST_PSU_MBOX_REG1/SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC "Key[0x%08X] Addr[0x%08X %08X]",
+ l_stashMsg.key, SBE::higher32BWord(l_stashMsg.addr),
+ SBE::lower32BWord(l_stashMsg.addr));
+
+ // Update the Key-Addr Pair in local Memory
+ bool update = SBE_GLOBAL->sbeKeyAddrPair.updatePair(l_stashMsg.key,
+ l_stashMsg.addr);
+ if(false == update)
+ {
+ // Update RC to indicate Host that Stash memory is full
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(
+ SBE_PRI_GENERIC_EXECUTION_FAILURE,
+ SBE_SEC_INPUT_BUFFER_OVERFLOW);
+ break;
+ }
+ }while(0);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeSetSystemFabricMap( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeSetSystemFabricMap"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t l_fapiRc = FAPI2_RC_SUCCESS;
+
+ do
+ {
+ uint64_t l_sysFabricMap = 0;
+ //send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(l_sysFabricMap)/sizeof(uint64_t)),
+ &l_sysFabricMap, true);
+
+ if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1");
+ break;
+ }
+
+ SBE_INFO(SBE_FUNC "Sytem Fabric Map [0x%08X][%08X]",
+ SBE::higher32BWord(l_sysFabricMap),
+ SBE::lower32BWord(l_sysFabricMap));
+
+ PLAT_ATTR_INIT(fapi2::ATTR_SBE_SYS_CONFIG,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_sysFabricMap);
+ }while(0);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+#endif //__SBEFW_SEEPROM__
+
+#ifndef __SBEFW_SEEPROM__
+//----------------------------------------------------------------------------
+uint32_t sbeFifoQuiesce( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeFifoQuiesce"
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t len = 0;
+ sbeRespGenHdr_t respHdr;
+ respHdr.init();
+
+ do
+ {
+ // Dequeue the EOT entry as no more data is expected.
+ rc = sbeUpFifoDeq_mult (len, NULL);
+ CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc);
+
+ // Set Quiesce State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_QUIESCE_EVENT);
+
+ rc = sbeDsSendRespHdr(respHdr);
+ if(rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC "sbeDsSendRespHdr failed");
+ // Not Breaking here since we can't revert back on the set state
+ }
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbePsuQuiesce( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbePsuQuiesce"
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ do
+ {
+ // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ // This util method will check internally on the mbox0 register if
+ // ACK is requested.
+ rc = sbeAcknowledgeHost();
+ if (rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over "
+ "SBE_SBE2PSU_DOORBELL_SET_BIT1");
+ break;
+ }
+
+ // Set Quiesce State
+ (void)SbeRegAccess::theSbeRegAccess().stateTransition(
+ SBE_QUIESCE_EVENT);
+
+ rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4,
+ (uint64_t*)(&SBE_GLOBAL->sbeSbe2PsuRespHdr),
+ (sizeof(SBE_GLOBAL->sbeSbe2PsuRespHdr)/sizeof(uint64_t)),
+ true);
+ if(rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ SBE_ERROR(SBE_FUNC" Failed to write SBE_HOST_PSU_MBOX_REG4");
+ // Not Breaking here since we can't revert back on the set state
+ }
+ }while(0);
+
+ if( rc )
+ {
+ SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc);
+ }
+ return rc;
+ #undef SBE_FUNC
+}
+
+//----------------------------------------------------------------------------
+uint32_t sbeReadMem( uint8_t *i_pArg )
+{
+ #define SBE_FUNC "sbeReadMem"
+ SBE_ENTER(SBE_FUNC);
+ uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ uint32_t fapiRc = FAPI2_RC_SUCCESS;
+ sbeReadMemReq_t req = {};
+
+ do
+ {
+ // Extract the request
+ // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1
+ rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1,
+ (sizeof(req)/sizeof(uint64_t)),
+ (uint64_t*)&req,
+ true);
+ if(SBE_SEC_OPERATION_SUCCESSFUL != rc)
+ {
+ SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and "
+ "SBE_HOST_PSU_MBOX_REG2");
+ break;
+ }
+
+ if(!( req.validateReq()) )
+ {
+ SBE_ERROR(SBE_FUNC"Invalid data. offset:0x%08X size:0x%08X",
+ req.offset, req.size );
+ SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_USER_ERROR,
+ SBE_SEC_INVALID_PARAMS);
+ break;
+ }
+
+ // Default EX Target Init. As its not LCO mode, ex does not matter.
+ fapi2::Target<fapi2::TARGET_TYPE_EX> l_ex(
+ fapi2::plat_getTargetHandleByChipletNumber<fapi2::TARGET_TYPE_EX>(
+ sbeMemAccessInterface::PBA_DEFAULT_EX_CHIPLET_ID));
+ p9_PBA_oper_flag l_myPbaFlag;
+ l_myPbaFlag.setOperationType(p9_PBA_oper_flag::INJ);
+
+ sbeMemAccessInterface pbaInterface(
+ SBE_MEM_ACCESS_PBA,
+ req.responseAddr,
+ &l_myPbaFlag,
+ SBE_MEM_ACCESS_WRITE,
+ sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES,
+ l_ex);
+ uint32_t len = req.size;
+ uint64_t *seepromAddr = req.getEffectiveAddr();
+ while( len > 0)
+ {
+ uint64_t *dataBuffer = static_cast<uint64_t*>
+ (pbaInterface.getBuffer());
+ for(size_t idx=0;
+ idx < (sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES/
+ sizeof(uint64_t));
+ idx++)
+ {
+ *dataBuffer = *seepromAddr;
+ dataBuffer++;
+ seepromAddr++;
+ }
+
+ fapi2::ReturnCode fapiRc = pbaInterface.accessGranule(
+ len == sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES);
+ if( fapiRc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ len = len - sbeMemAccessInterface::PBA_GRAN_SIZE_BYTES;
+ }
+ } while(false);
+
+ // Send the response
+ sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc);
+
+ SBE_EXIT(SBE_FUNC);
+ return rc;
+ #undef SBE_FUNC
+}
+#endif //not __SBEFW_SEEPROM__
+
OpenPOWER on IntegriCloud