diff --git a/ecmd_plugin/README.md b/ecmd_plugin/README.md new file mode 100644 index 0000000..2a689d0 --- /dev/null +++ b/ecmd_plugin/README.md @@ -0,0 +1,146 @@ + +# **Move eCMD-pdbg Functionality to openpower-proc-control** + +**Author:** Marri Devender Rao +**Primary Assignee:** Marri Devender Rao +**Contributors:** None +**Date Created:** 10 November 2025 + +--- + +## **1. Problem Description** + +Currently, **ecmd-pdbg** is tightly coupled with the **eCMD** repository and cannot be built or maintained independently. +The existing **ecmd-pdbg** recipe pulls the eCMD repository as a submodule and builds both the `ecmd` binaries and DLL. + +Since both **eCMD** and **ecmd-pdbg** reside in the **open-power** layer, they cannot interact with **systemd**, preventing them from creating or committing **PELs (Platform Error Logs)**. + +For next-generation **P12 systems**, which support multiple sleds requiring simultaneous power-on through a **systemd service**, it is essential to move the **ecmd-pdbg** functionality into **openpower-proc-control** (OpenBMC layer). This allows access to systemd and host firmware interfaces. + +By relocating ecmd-pdbg, the new plugin will directly access: +- The **hostfw** repository for hardware access (scoms, cfams) and hardware procedures. + +**Reference Links:** +- [eCMD-pdbg Repository (Internal)](https://github.ibm.com/open-power/ecmd-pdbg) +- [eCMD Repository (Open Source)](https://github.com/open-power/eCMD) +- [openpower-proc-control Repository](https://github.com/ibm-openbmc/openpower-proc-control) + +--- + +## **2. Objective** + +The goal is to **decouple eCMD from ecmd-pdbg ** and build eCMD independently. + +- eCMD will generate the header file `ecmdDllCapi.H`, defining the interface for client plugins. +- Client layers (like openpower-proc-control) will implement this interface. +- When an eCMD command (e.g., `ecmd istep`) is executed, eCMD dynamically loads the plugin defined by the environment variable: + + ```bash + export ECMD_DLL_FILE=/usr/lib/libecmd-plugin.so + ``` + +The implementation of `ecmdDllCapi.H` will now reside within **openpower-proc-control** as an **eCMD plugin**. + +--- + +## **3. Background** + +In the current setup, **ecmd-pdbg** depends on eCMD as a submodule, restricting flexibility and preventing systemd access. +For **P12 multi-sled systems**, **openpower-proc-control** (running under systemd) manages power-on across sleds. +Embedding eCMD integration here allows reuse of existing eCMD command-line functionality and direct access to host firmware APIs. + +--- + +## **4. Requirements** + +- Implement all functions defined in `ecmdDllCapi.H` within **openpower-proc-control** as an `ecmd-plugin`. +- Ensure compatibility with eCMD binary interface and dynamic loading mechanism. +- Support existing eCMD commands such as: + - `getcfam` + - `putscom` + - `query` + - `istep` + +--- + +## **5. Proposed Design** + +### **a. Build System and Recipe Changes** + +- **ecmd bitbake recipe** + - Build **eCMD** as an independent application. + - Generate `ecmdDllCapi.H` for clients. + +- **openpower-proc-control bitbake recipe** + - Add dependency on `ecmd` recipe. + - Include and build the **ecmd-plugin** implementing `ecmdDllCapi.H`. + +--- + +### **b. eCMD Plugin Implementation** + +- Implement all APIs defined in `ecmdDllCapi.H` inside a new module: + ``` + openpower-proc-control/ecmd-plugin/ + ``` +- eCMD dynamically loads this plugin using the `ECMD_DLL_FILE` environment variable. +- The plugin: + - Provides hardware access via **hostfw** (scoms, cfams) and hardware procedures + - Integrates seamlessly with systemd for coordinated sled bring-up +--- + +## **7. Alternatives Considered** + +### **Option 1:** +Re-implement eCMD-like utilities directly inside openpower-proc-control. + +**Drawbacks:** +- Significant development and maintenance overhead +- Loss of mature eCMD CLI features +- Incompatibility with existing tools (e.g., Cronus) + +### **Option 2 (Chosen):** +Reuse eCMD as-is, and re-implement only the plugin interface (`ecmdDllCapi.H`) in openpower-proc-control. + +--- + +## **8. Implementation Details** + +- Add a new module: + ``` + openpower-proc-control/ecmd-plugin/ + ``` +- Implement `ecmdDllCapi.H` API functions. +- Use **hostfw** APIs for SCOM/CFAM access and hardware procedures +- Validate plugin loading through: + ```bash + export ECMD_DLL_FILE=/usr/lib/libecmd-plugin.so + ecmd istep 11.1 + ``` +- Integrate with systemd services for multi-sled bring-up. + +--- + +## **9. Testing Plan** + +| **Test Case** | **Command** | **Expected Result** | +|----------------|-------------|---------------------| +| CFAM Read | `ecmd getcfam` | CFAM register read successful | +| SCOM Write | `ecmd putscom` | SCOM register write successful | +| Target Query | `ecmd query` | Target list displayed correctly | +| ISTEP Execution | `ecmd istep` | ISTEP executed via plugin successfully | + +Successful completion of these validates end-to-end integration of **eCMD → ecmd-plugin → hostfw** under **systemd** orchestration. + +--- + +## **10. Expected Outcome** + +After migration: +- **ecmd-pdbg** functionality will reside in **openpower-proc-control**. +- It will have full access to **systemd**, **hostfw**, and **multi-sled orchestration**. +- The system will maintain eCMD’s command-line flexibility while enabling scalable next-generation bring-up workflows. +--- + +✅ **Final Benefit:** +This refactoring ensures **better modularity, reusability, and integration** with OpenBMC services while preserving the rich eCMD feature set. diff --git a/ecmd_plugin/ecmdDllCapi.H b/ecmd_plugin/ecmdDllCapi.H new file mode 100644 index 0000000..2ed6fda --- /dev/null +++ b/ecmd_plugin/ecmdDllCapi.H @@ -0,0 +1,907 @@ +/* The following has been auto-generated by makedll.pl */ +#ifndef ecmdDllCapi_H +#define ecmdDllCapi_H + +#include +#include +#include +#include +#include +#include + +#include + +extern "C" +{ +/* Dll Common load function - verifies version */ +uint32_t dllLoadDll(const char* i_version, uint32_t debugLevel); +/* Dll Specific load function - used by Cronus/GFW to init variables/object + * models */ +uint32_t dllInitDll(); + +/* Dll Common unload function */ +uint32_t dllUnloadDll(); +/* Dll Specific unload function - deallocates variables/object models */ +uint32_t dllFreeDll(); + +/* Dll version check function */ +uint32_t dllCheckDllVersion(const char* options); +/* Dll Common Command Line Args Function */ +uint32_t dllCommonCommandArgs(int* io_argc, char** io_argv[]); +/* Dll Specific Command Line Args Function */ +uint32_t dllSpecificCommandArgs(int* io_argc, char** io_argv[]); + +/* Dll Specific Return Codes */ +std::string dllSpecificParseReturnCode(uint32_t i_returnCode); + +void dllLoadDllRecovery(std::string i_commandLine, uint32_t& io_rc); + +uint32_t dllLooperInit(ecmdChipTarget& io_target, ecmdLoopType_t i_looptype, + ecmdLooperData& io_state, ecmdLoopMode_t i_mode); + +uint32_t dllConfigLooperInit(ecmdChipTarget& io_target, + ecmdLoopType_t i_looptype, + ecmdLooperData& io_state); + +uint32_t dllExistLooperInit(ecmdChipTarget& io_target, + ecmdLoopType_t i_looptype, + ecmdLooperData& io_state); + +uint32_t dllLooperNext(ecmdChipTarget& io_target, ecmdLooperData& io_state, + ecmdLoopMode_t i_mode); + +uint32_t dllConfigLooperNext(ecmdChipTarget& io_target, + ecmdLooperData& io_state); + +uint32_t dllExistLooperNext(ecmdChipTarget& io_target, + ecmdLooperData& io_state); + +uint32_t dllQueryDllInfo(ecmdDllInfo& o_dllInfo); + +bool dllQueryVersionGreater(const char* version); + +uint32_t dllQueryConfig(const ecmdChipTarget& i_target, + ecmdQueryData& o_queryData, ecmdQueryDetail_t i_detail); + +uint32_t dllQueryExist(const ecmdChipTarget& i_target, + ecmdQueryData& o_queryData, ecmdQueryDetail_t i_detail); + +uint32_t dllQueryConfigSelected(ecmdChipTarget& io_target, + ecmdQueryData& o_queryData, + ecmdLoopType_t i_looptype); + +uint32_t dllQueryExistSelected(ecmdChipTarget& io_target, + ecmdQueryData& o_queryData, + ecmdLoopType_t i_looptype); + +uint32_t dllRelatedTargets(const ecmdChipTarget& i_target, + const std::string i_relatedType, + std::list& o_relatedTargets, + const ecmdLoopMode_t i_mode); + +#ifndef ECMD_REMOVE_RING_FUNCTIONS +uint32_t dllQueryRing(const ecmdChipTarget& i_target, + std::list& o_queryData, + const char* i_ringName, ecmdQueryDetail_t i_detail); + +uint32_t dllQueryRingInversionMask(const ecmdChipTarget& i_target, + const std::string i_ringName, + ecmdDataBuffer& o_inversionMask); + +uint32_t dllQueryRingIgnoreMask(const ecmdChipTarget& i_target, + const std::string i_ringName, + ecmdDataBuffer& o_ignoreMask); + +#endif // ECMD_REMOVE_RING_FUNCTIONS +#ifndef ECMD_REMOVE_LATCH_FUNCTIONS +uint32_t dllQueryLatch(const ecmdChipTarget& i_target, + std::list& o_queryData, + ecmdLatchMode_t i_mode, const char* i_latchName, + const char* i_ringName, ecmdQueryDetail_t i_detail); + +uint32_t dllQueryLatchInfo(const ecmdChipTarget& i_target, + ecmdLatchQueryData& o_queryData, + ecmdLatchMode_t i_mode, const char* i_latchName, + const char* i_ringName, ecmdQueryDetail_t i_detail); + +#endif // ECMD_REMOVE_LATCH_FUNCTIONS +#ifndef ECMD_REMOVE_ARRAY_FUNCTIONS +uint32_t dllQueryArray(const ecmdChipTarget& i_target, + std::list& o_queryData, + const char* i_arrayName, ecmdQueryDetail_t i_detail); + +#endif // ECMD_REMOVE_ARRAY_FUNCTIONS +#ifndef ECMD_REMOVE_SPY_FUNCTIONS +uint32_t dllQuerySpy(const ecmdChipTarget& i_target, + std::list& o_queryData, const char* i_spyName, + ecmdQueryDetail_t i_detail); + +uint32_t dllQuerySpyRings(const ecmdChipTarget& i_target, const char* i_spyName, + std::list& o_ringNames); + +#endif // ECMD_REMOVE_SPY_FUNCTIONS +#ifndef ECMD_REMOVE_SCOM_FUNCTIONS +uint32_t dllQueryScom(const ecmdChipTarget& i_target, + std::list& o_queryData, uint64_t i_address, + ecmdQueryDetail_t i_detail); + +#endif // ECMD_REMOVE_SCOM_FUNCTIONS +#ifndef ECMD_REMOVE_TRACEARRAY_FUNCTIONS +uint32_t dllQueryTraceArray( + const ecmdChipTarget& i_target, std::list& o_queryData, + const char* i_traceArrayName, ecmdQueryDetail_t i_detail); + +#endif // ECMD_REMOVE_TRACEARRAY_FUNCTIONS +uint32_t dllQueryFileLocation( + const ecmdChipTarget& i_target, ecmdFileType_t i_fileType, + std::list& o_fileLocations, std::string& io_version); + +bool dllQueryTargetConfigured(const ecmdChipTarget& i_target, + const ecmdQueryData* i_queryData); + +bool dllQueryTargetExist(const ecmdChipTarget& i_target, + const ecmdQueryData* i_queryData); + +uint32_t dllQueryConnectedTargets(const ecmdChipTarget& i_target, + const char* i_connectionType, + std::list& o_connections); + +uint32_t dllGetChipData(const ecmdChipTarget& i_target, ecmdChipData& o_data); + +uint32_t dllQueryMode(const ecmdChipTarget& i_target, std::string& o_coreMode, + std::string& o_coreChipUnit); + +#ifndef ECMD_REMOVE_RING_FUNCTIONS +uint32_t dllGetRing(const ecmdChipTarget& i_target, const char* i_ringName, + ecmdDataBuffer& o_data, uint32_t i_mode); + +uint32_t dllPutRing(const ecmdChipTarget& i_target, const char* i_ringName, + const ecmdDataBuffer& i_data, uint32_t i_mode); + +uint32_t dllGetRingSparse(const ecmdChipTarget& i_target, + const char* i_ringName, ecmdDataBuffer& o_data, + const ecmdDataBuffer& i_mask, uint32_t i_mode); + +uint32_t dllPutRingSparse(const ecmdChipTarget& i_target, + const char* i_ringName, const ecmdDataBuffer& i_data, + const ecmdDataBuffer& i_mask, uint32_t i_mode); + +uint32_t dllGetRingSparseWithTraceMask( + const ecmdChipTarget& i_target, const char* i_ringName, + ecmdDataBuffer& o_data, const ecmdDataBuffer& i_mask, + const ecmdDataBuffer& i_traceMask, uint32_t i_mode); + +uint32_t dllGetRingWithModifier(const ecmdChipTarget& i_target, + uint32_t i_address, uint32_t i_bitLength, + ecmdDataBuffer& o_data); + +uint32_t dllPutRingWithModifier(const ecmdChipTarget& i_target, + uint32_t i_address, uint32_t i_bitLength, + const ecmdDataBuffer& i_data); + +#endif // ECMD_REMOVE_RING_FUNCTIONS +#ifndef ECMD_REMOVE_SCOM_FUNCTIONS +uint32_t dllGetScom(const ecmdChipTarget& i_target, uint64_t i_address, + ecmdDataBuffer& o_data); + +uint32_t dllPutScom(const ecmdChipTarget& i_target, uint64_t i_address, + const ecmdDataBuffer& i_data); + +uint32_t dllPutScomUnderMask(const ecmdChipTarget& i_target, uint64_t i_address, + const ecmdDataBuffer& i_data, + const ecmdDataBuffer& i_mask); + +uint32_t dllDoScomMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllCreateChipUnitScomAddress(const ecmdChipTarget& i_target, + uint64_t i_address, uint64_t& o_address); + +#endif // ECMD_REMOVE_SCOM_FUNCTIONS +#ifndef ECMD_REMOVE_JTAG_FUNCTIONS +uint32_t dllSendCmd(const ecmdChipTarget& i_target, uint32_t i_instruction, + uint32_t i_modifier, ecmdDataBuffer& o_status); + +#endif // ECMD_REMOVE_JTAG_FUNCTIONS +#ifndef ECMD_REMOVE_FSI_FUNCTIONS +uint32_t dllGetCfamRegister(const ecmdChipTarget& i_target, uint32_t i_address, + ecmdDataBuffer& o_data); + +uint32_t dllPutCfamRegister(const ecmdChipTarget& i_target, uint32_t i_address, + const ecmdDataBuffer& i_data); + +uint32_t dllGetEcid(const ecmdChipTarget& i_target, ecmdDataBuffer& o_ecidData); + +uint32_t dllGetEcidVerbose(const ecmdChipTarget& i_target, + ecmdDataBuffer& o_ecidData, + std::vector& o_additionalInfo); + +#endif // ECMD_REMOVE_FSI_FUNCTIONS +#ifndef ECMD_REMOVE_SPY_FUNCTIONS +uint32_t dllGetSpy(const ecmdChipTarget& i_target, const char* i_spyName, + ecmdDataBuffer& o_data, uint32_t i_flags); + +uint32_t dllGetSpyEnum(const ecmdChipTarget& i_target, const char* i_spyName, + std::string& o_enumValue, uint32_t i_flags); + +uint32_t dllGetSpyEpCheckers( + const ecmdChipTarget& i_target, const char* i_spyEpCheckersName, + ecmdDataBuffer& o_inLatchData, ecmdDataBuffer& o_outLatchData, + ecmdDataBuffer& o_eccErrorMask, uint32_t i_flags); + +uint32_t dllGetSpyGroups(const ecmdChipTarget& i_target, const char* i_spyName, + std::list& o_groups, + uint32_t i_flags); + +uint32_t dllPutSpy(const ecmdChipTarget& i_target, const char* i_spyName, + const ecmdDataBuffer& i_data, uint32_t i_flags); + +uint32_t dllPutSpyEnum(const ecmdChipTarget& i_target, const char* i_spyName, + const std::string i_enumValue, uint32_t i_flags); + +uint32_t dllGetSpyImage(const ecmdChipTarget& i_target, const char* i_spyName, + const ecmdDataBuffer& i_ringImage, + ecmdDataBuffer& o_data); + +uint32_t dllGetSpyEnumImage( + const ecmdChipTarget& i_target, const char* i_spyName, + const ecmdDataBuffer& i_ringImage, std::string& o_enumValue); + +uint32_t dllGetSpyImages( + const ecmdChipTarget& i_target, const char* i_spyName, + const std::map& i_ringImages, + ecmdDataBuffer& o_data); + +uint32_t dllGetSpyEnumImages( + const ecmdChipTarget& i_target, const char* i_spyName, + const std::map& i_ringImages, + std::string& o_enumValue); + +uint32_t dllPutSpyImage(const ecmdChipTarget& i_target, const char* i_spyName, + const ecmdDataBuffer& i_data, + ecmdDataBuffer& io_ringImage); + +uint32_t dllPutSpyEnumImage( + const ecmdChipTarget& i_target, const char* i_spyName, + const std::string i_enumValue, ecmdDataBuffer& io_ringImage); + +uint32_t dllPutSpyImages(const ecmdChipTarget& i_target, const char* i_spyName, + const ecmdDataBuffer& i_data, + std::map& io_ringImages); + +uint32_t dllPutSpyEnumImages( + const ecmdChipTarget& i_target, const char* i_spyName, + const std::string i_enumValue, + std::map& io_ringImages); + +#endif // ECMD_REMOVE_SPY_FUNCTIONS +uint32_t dllEnableRingCache(const ecmdChipTarget& i_target); + +uint32_t dllDisableRingCache(const ecmdChipTarget& i_target); + +uint32_t dllFlushRingCache(const ecmdChipTarget& i_target); + +bool dllIsRingCacheEnabled(const ecmdChipTarget& i_target); + +#ifndef ECMD_REMOVE_ARRAY_FUNCTIONS +uint32_t dllGetArray(const ecmdChipTarget& i_target, const char* i_arrayName, + const ecmdDataBuffer& i_address, ecmdDataBuffer& o_data, + uint32_t i_width); + +uint32_t dllGetArrayMultiple( + const ecmdChipTarget& i_target, const char* i_arrayName, + std::list& io_entries, uint32_t i_width); + +uint32_t dllPutArray(const ecmdChipTarget& i_target, const char* i_arrayName, + const ecmdDataBuffer& i_address, + const ecmdDataBuffer& i_data); + +uint32_t dllPutArrayMultiple(const ecmdChipTarget& i_target, + const char* i_arrayName, + std::list& i_entries); + +#endif // ECMD_REMOVE_ARRAY_FUNCTIONS +#ifndef ECMD_REMOVE_CLOCK_FUNCTIONS +uint32_t dllQueryClockState(const ecmdChipTarget& i_target, + const char* i_clockDomain, + ecmdClockState_t& o_clockState); + +uint32_t dllStartClocks(const ecmdChipTarget& i_target, + const char* i_clockDomain, bool i_forceState); + +uint32_t dllStopClocks(const ecmdChipTarget& i_target, + const char* i_clockDomain, bool i_forceState, + uint32_t i_mode); + +#endif // ECMD_REMOVE_CLOCK_FUNCTIONS +#ifndef ECMD_REMOVE_REFCLOCK_FUNCTIONS +uint32_t dllGetClockSpeed( + const ecmdChipTarget& i_target, ecmdClockType_t i_type, + ecmdClockSpeedType_t i_speedType, uint32_t& o_speed, + ecmdClockFreqMode_t& o_freqMode, uint32_t& o_freqmin, uint32_t& o_freqmax); + +uint32_t dllSetClockSpeed( + const ecmdChipTarget& i_target, ecmdClockType_t i_type, uint32_t i_speed, + ecmdClockSpeedType_t i_speedType, ecmdClockSetMode_t i_mode, + ecmdClockRange_t i_range, ecmdClockFreqMode_t i_freqMode, + uint32_t i_freqMinMhz, uint32_t i_freqMaxMhz); + +uint32_t dllSetClockMultDiv(const ecmdChipTarget& i_target, + ecmdClockType_t i_type, uint32_t i_multiplier, + uint32_t i_divider); + +#endif // ECMD_REMOVE_REFCLOCK_FUNCTIONS +#ifndef ECMD_REMOVE_INIT_FUNCTIONS +uint32_t dllIStepsByNumber(const ecmdDataBuffer& i_steps); + +uint32_t dllIStepsByName(std::string i_stepName); + +uint32_t dllIStepsByNameMultiple(std::list i_stepNames); + +uint32_t dllIStepsByNameRange(std::string i_stepNameBegin, + std::string i_stepNameEnd); + +uint32_t dllInitChipFromFile(const ecmdChipTarget& i_target, + const char* i_initFile, const char* i_initId, + const char* i_mode, uint32_t i_ringMode); + +#endif // ECMD_REMOVE_INIT_FUNCTIONS +#ifndef ECMD_REMOVE_PROCESSOR_FUNCTIONS +uint32_t dllQueryProcRegisterInfo(const ecmdChipTarget& i_target, + const char* i_name, + ecmdProcRegisterInfo& o_data); + +uint32_t dllGetSpr(const ecmdChipTarget& i_target, const char* i_sprName, + ecmdDataBuffer& o_data); + +uint32_t dllGetSprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllPutSpr(const ecmdChipTarget& i_target, const char* i_sprName, + const ecmdDataBuffer& i_data); + +uint32_t dllPutSprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllGetGpr(const ecmdChipTarget& i_target, uint32_t i_gprNum, + ecmdDataBuffer& o_data); + +uint32_t dllGetGprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllPutGpr(const ecmdChipTarget& i_target, uint32_t i_gprNum, + const ecmdDataBuffer& i_data); + +uint32_t dllPutGprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllGetFpr(const ecmdChipTarget& i_target, uint32_t i_fprNum, + ecmdDataBuffer& o_data); + +uint32_t dllGetFprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllPutFpr(const ecmdChipTarget& i_target, uint32_t i_fprNum, + const ecmdDataBuffer& i_data); + +uint32_t dllPutFprMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllGetSlb(const ecmdChipTarget& i_target, uint32_t i_slbNum, + ecmdDataBuffer& o_data); + +uint32_t dllGetSlbMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +uint32_t dllPutSlb(const ecmdChipTarget& i_target, uint32_t i_slbNum, + const ecmdDataBuffer& i_data); + +uint32_t dllPutSlbMultiple(const ecmdChipTarget& i_target, + std::list& io_entries); + +#endif // ECMD_REMOVE_PROCESSOR_FUNCTIONS +#ifndef ECMD_REMOVE_MPIPL_FUNCTIONS +uint32_t dllMpiplClearCheckstop(const std::vector& i_target); + +uint32_t dllMpiplForceWinkle(const ecmdChipTarget& i_target); + +#endif // ECMD_REMOVE_MPIPL_FUNCTIONS +#ifndef ECMD_REMOVE_TRACEARRAY_FUNCTIONS +uint32_t dllGetTraceArray(const ecmdChipTarget& i_target, const char* i_name, + uint32_t i_doTraceStopStart, + ecmdNameVectorEntry& o_data); + +uint32_t dllGetTraceArrayMultiple(const ecmdChipTarget& i_target, + uint32_t i_doTraceStopStart, + std::list& o_data); + +#endif // ECMD_REMOVE_TRACEARRAY_FUNCTIONS +#ifndef ECMD_REMOVE_MEMORY_FUNCTIONS +uint32_t dllGetMemProc(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, ecmdDataBuffer& o_data, + uint32_t i_mode); + +uint32_t dllPutMemProc(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, const ecmdDataBuffer& i_data, + uint32_t i_mode); + +uint32_t dllGetMemDma(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, ecmdDataBuffer& o_data); + +uint32_t dllPutMemDma(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, const ecmdDataBuffer& i_data); + +uint32_t dllGetMemMemCtrl(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, ecmdDataBuffer& o_data); + +uint32_t dllPutMemMemCtrl(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, const ecmdDataBuffer& i_data); + +uint32_t dllGetSram(const ecmdChipTarget& i_target, uint32_t i_mode, + uint64_t i_address, uint32_t i_bytes, + ecmdDataBuffer& o_data); + +uint32_t dllPutSram(const ecmdChipTarget& i_target, uint32_t i_mode, + uint64_t i_address, uint32_t i_bytes, + const ecmdDataBuffer& i_data); + +uint32_t dllQueryCache(const ecmdChipTarget& i_target, + ecmdCacheType_t i_cacheType, ecmdCacheData& o_data); + +uint32_t dllCacheFlush(const ecmdChipTarget& i_target, + ecmdCacheType_t i_cacheType); + +uint32_t dllGetMemPba(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, ecmdDataBuffer& o_data, + uint32_t i_mode); + +uint32_t dllPutMemPba(const ecmdChipTarget& i_target, uint64_t i_address, + uint32_t i_bytes, const ecmdDataBuffer& i_data, + uint32_t i_mode); + +uint32_t dllQueryHostMemInfo(const std::vector& i_targets, + ecmdChipTarget& o_target, uint64_t& o_address, + uint64_t& o_size, const uint32_t i_mode); + +uint32_t dllQueryHostMemInfoRanges( + const std::vector& i_targets, ecmdChipTarget& o_target, + std::vector>& o_ranges, + const uint32_t i_mode); + +#endif // ECMD_REMOVE_MEMORY_FUNCTIONS +std::string dllGetErrorMsg(uint32_t i_returnCode, bool i_parseReturnCode, + bool i_deleteMessage, bool i_messageBorder); + +uint32_t dllRegisterErrorMsg(uint32_t i_returnCode, const char* i_whom, + const char* i_message); + +uint32_t dllFlushRegisteredErrorMsgs(uint32_t i_returnCode); + +uint32_t dllFlushRegisteredErrorMsgsString(uint32_t i_returnCode, + std::string i_searchString); + +uint32_t dllGetErrorTarget(uint32_t i_returnCode, + std::list& o_errorTargets, + bool i_deleteTarget); + +uint32_t dllRegisterErrorTarget(uint32_t i_returnCode, + const ecmdChipTarget& i_errorTarget); + +uint32_t dllFlushRegisteredErrorTargets(uint32_t i_returnCode); + +std::string dllParseReturnCode(uint32_t i_returnCode); + +std::string dllLastError(); + +#ifndef ECMD_REMOVE_BLOCK_FUNCTIONS +uint32_t dllQueryBlock(const ecmdChipTarget& i_target, + std::vector& o_metadataBlockEntry, + const std::string& i_metadataHWPName); + +uint32_t dllGetBlock(const ecmdChipTarget& i_target, + const std::string& i_metadataBlockEntry, + std::vector& o_data); + +#endif // ECMD_REMOVE_BLOCK_FUNCTIONS +void dllOutputError(const char* i_message); + +void dllOutputWarning(const char* i_message); + +void dllOutput(const char* i_message); + +#ifndef ECMD_REMOVE_FSI_FUNCTIONS +uint32_t dllGetGpRegister(const ecmdChipTarget& i_target, uint32_t i_gpRegister, + ecmdDataBuffer& o_data); + +uint32_t dllPutGpRegister(const ecmdChipTarget& i_target, uint32_t i_gpRegister, + const ecmdDataBuffer& i_data); + +uint32_t dllPutGpRegisterUnderMask( + const ecmdChipTarget& i_target, uint32_t i_gpRegister, + const ecmdDataBuffer& i_data, const ecmdDataBuffer& i_mask); + +#endif // ECMD_REMOVE_FSI_FUNCTIONS +uint32_t dllGetGlobalVar(ecmdGlobalVarType_t i_type); + +uint32_t dllSetGlobalVar(ecmdGlobalVarType_t i_type, uint32_t i_value); + +void dllSetTraceMode(ecmdTraceType_t i_type, bool i_enable); + +bool dllQueryTraceMode(ecmdTraceType_t i_type); + +uint32_t dllDelay(uint32_t i_simCycles, uint32_t i_msDelay); + +#ifndef ECMD_REMOVE_SP_FUNCTIONS +uint32_t dllQuerySP(const ecmdChipTarget& i_target, std::string i_commandStr, + std::string& o_result); + +uint32_t dllMakeSPSystemCall(const ecmdChipTarget& i_target, + const std::string& i_command, + std::string& o_stdout); + +#endif // ECMD_REMOVE_SP_FUNCTIONS +uint32_t dllSyncPluginState(const ecmdChipTarget& i_target); + +#ifndef ECMD_REMOVE_INIT_FUNCTIONS +uint32_t dllSyncIplMode(int i_unused); + +#endif // ECMD_REMOVE_INIT_FUNCTIONS +uint32_t dllChipCleanup(const ecmdChipTarget& i_target, uint32_t i_mode); + +uint32_t dllGetConfiguration(const ecmdChipTarget& i_target, std::string i_name, + ecmdConfigValid_t& o_validOutput, + std::string& o_valueAlpha, + uint32_t& o_valueNumeric); + +uint32_t dllGetConfigurationComplex(const ecmdChipTarget& i_target, + std::string i_name, + ecmdConfigData& o_configData); + +uint32_t dllSetConfiguration(const ecmdChipTarget& i_target, std::string i_name, + ecmdConfigValid_t i_validInput, + std::string i_valueAlpha, uint32_t i_valueNumeric); + +uint32_t dllSetConfigurationComplex(const ecmdChipTarget& i_target, + std::string i_name, + ecmdConfigData i_configData); + +uint32_t dllDeconfigureTarget(const ecmdChipTarget& i_target); + +uint32_t dllConfigureTarget(const ecmdChipTarget& i_target); + +#ifndef ECMD_REMOVE_UNITID_FUNCTIONS +uint32_t dllTargetToUnitId(ecmdChipTarget& io_target); + +uint32_t dllUnitIdStringToTarget(std::string i_unitId, + std::list& o_targetList); + +uint32_t dllUnitIdToTarget(uint32_t i_unitId, + std::list& o_targetList); + +uint32_t dllUnitIdToString(uint32_t i_unitId, std::string& o_unitIdStr); + +uint32_t dllGetUnitIdVersion(uint32_t& o_unitIdVersion); + +uint32_t dllSequenceIdToTarget(uint32_t i_core_seq_num, + ecmdChipTarget& io_target, + uint32_t i_thread_seq_num); + +uint32_t dllTargetToSequenceId(const ecmdChipTarget& i_target, + uint32_t& o_core_seq_num, + uint32_t& o_thread_seq_num); + +#endif // ECMD_REMOVE_UNITID_FUNCTIONS +#ifndef ECMD_REMOVE_VPD_FUNCTIONS +uint32_t dllGetModuleVpdKeyword( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, uint32_t i_bytes, ecmdDataBuffer& o_data); + +uint32_t dllPutModuleVpdKeyword( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, const ecmdDataBuffer& i_data); + +uint32_t dllGetModuleVpdImage(const ecmdChipTarget& i_target, uint32_t i_bytes, + ecmdDataBuffer& o_data); + +uint32_t dllPutModuleVpdImage(const ecmdChipTarget& i_target, + const ecmdDataBuffer& i_data); + +uint32_t dllGetModuleVpdKeywordFromImage( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, uint32_t i_bytes, const ecmdDataBuffer& i_image_data, + ecmdDataBuffer& o_keyword_data); + +uint32_t dllPutModuleVpdKeywordToImage( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, ecmdDataBuffer& io_image_data, + const ecmdDataBuffer& i_keyword_data); + +#endif // ECMD_REMOVE_VPD_FUNCTIONS +#ifndef ECMD_REMOVE_VPD_FUNCTIONS +uint32_t dllGetFruVpdKeyword(const ecmdChipTarget& i_target, + const char* i_record_name, const char* i_keyword, + uint32_t i_bytes, ecmdDataBuffer& o_data); + +uint32_t dllGetFruVpdKeywordWithRid(uint32_t i_rid, const char* i_record_name, + const char* i_keyword, uint32_t i_bytes, + ecmdDataBuffer& o_data); + +uint32_t dllPutFruVpdKeyword(const ecmdChipTarget& i_target, + const char* i_record_name, const char* i_keyword, + const ecmdDataBuffer& i_data); + +uint32_t dllPutFruVpdKeywordWithRid(uint32_t i_rid, const char* i_record_name, + const char* i_keyword, + const ecmdDataBuffer& i_data); + +uint32_t dllGetFruVpdImage(const ecmdChipTarget& i_target, uint32_t i_bytes, + ecmdDataBuffer& o_data); + +uint32_t dllPutFruVpdImage(const ecmdChipTarget& i_target, + const ecmdDataBuffer& i_data); + +uint32_t dllGetFruVpdKeywordFromImage( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, uint32_t i_bytes, const ecmdDataBuffer& i_image_data, + ecmdDataBuffer& o_keyword_data); + +uint32_t dllPutFruVpdKeywordToImage( + const ecmdChipTarget& i_target, const char* i_record_name, + const char* i_keyword, ecmdDataBuffer& io_image_data, + const ecmdDataBuffer& i_keyword_data); + +#endif // ECMD_REMOVE_VPD_FUNCTIONS +#ifndef ECMD_REMOVE_I2C_FUNCTIONS +uint32_t dllI2cReset(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_port); + +uint32_t dllI2cRead(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_port, uint32_t i_slaveAddress, + ecmdI2cBusSpeed_t i_busSpeed, uint32_t i_bytes, + ecmdDataBuffer& o_data, uint32_t i_flags); + +uint32_t dllI2cReadOffset(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_port, uint32_t i_slaveAddress, + ecmdI2cBusSpeed_t i_busSpeed, uint64_t i_offset, + uint32_t i_offsetFieldSize, uint32_t i_bytes, + ecmdDataBuffer& o_data, uint32_t i_flags); + +uint32_t dllI2cWrite(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_port, uint32_t i_slaveAddress, + ecmdI2cBusSpeed_t i_busSpeed, const ecmdDataBuffer& i_data, + uint32_t i_flags); + +uint32_t dllI2cWriteOffset( + const ecmdChipTarget& i_target, uint32_t i_engineId, uint32_t i_port, + uint32_t i_slaveAddress, ecmdI2cBusSpeed_t i_busSpeed, uint64_t i_offset, + uint32_t i_offsetFieldSize, const ecmdDataBuffer& i_data, uint32_t i_flags); + +uint32_t dllI2CMultipleCmds(const ecmdChipTarget& i_target, + std::list& io_cmdsEntries); + +#endif /* ifndef ECMD_REMOVE_I2C_FUNCTIONS (this comment has to be here for \ + makedll.pl to work */ +#ifndef ECMD_REMOVE_GPIO_FUNCTIONS +uint32_t dllGpioConfigPin(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_pin, ecmdDioMode_t i_mode); + +uint32_t dllGpioReadPin(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_pin, uint32_t& o_state); + +uint32_t dllGpioReadLatch(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_pin, ecmdDioMode_t i_mode, + uint32_t& o_state); + +uint32_t dllGpioWriteLatch(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_pin, ecmdDioMode_t i_mode, + uint32_t i_state); + +uint32_t dllGpioReadPins(const ecmdChipTarget& i_target, uint32_t i_engineId, + uint32_t i_mask, uint32_t& o_value); + +uint32_t dllGpioWriteLatches(const ecmdChipTarget& i_target, + uint32_t i_engineId, ecmdDioMode_t i_mode, + uint32_t i_mask, uint32_t i_value); + +uint32_t dllGpioReadConfigRegister(const ecmdChipTarget& i_target, + uint32_t i_engineId, uint32_t i_configReg, + uint32_t& o_value); + +uint32_t dllGpioWriteConfigRegister( + const ecmdChipTarget& i_target, uint32_t i_engineId, + ecmdGpioWriteMode_t i_mode, uint32_t i_configReg, uint32_t i_value); + +#endif // ECMD_REMOVE_GPIO_FUNCTIONS +#ifndef ECMD_REMOVE_POWER_FUNCTIONS +uint32_t dllSystemPowerOn(); + +uint32_t dllSystemPowerOff(); + +uint32_t dllQuerySystemPower(ecmdPowerState_t& o_state); + +uint32_t dllFruPowerOn(const ecmdChipTarget& i_target, bool i_smart); + +uint32_t dllFruPowerOff(const ecmdChipTarget& i_target, bool i_smart); + +uint32_t dllQueryFruPower(const ecmdChipTarget& i_target, + ecmdPowerState_t& o_state); + +uint32_t dllSetPowerMode(const ecmdChipTarget& i_target, + ecmdPowerMode_t i_powerMode); + +uint32_t dllGetPowerMode(const ecmdChipTarget& i_target, + ecmdPowerMode_t& o_powerMode); + +uint32_t dllBiasVoltage(const ecmdChipTarget& i_target, uint32_t i_voltageLevel, + ecmdVoltageType_t i_direction, uint32_t i_biasValue, + bool i_wait); + +uint32_t dllQueryBiasState(const ecmdChipTarget& i_target, + uint32_t i_voltageLevel, uint32_t& o_currentVoltage, + uint32_t& o_targetVoltage, uint32_t& o_timeValue); + +#endif // ECMD_REMOVE_POWER_FUNCTIONS +#ifndef ECMD_REMOVE_ADAL_FUNCTIONS +uint32_t dllAdalPsiInit(const ecmdChipTarget& i_target, uint32_t i_psiPort); + +uint32_t dllAdalPsiLinkEnable(const ecmdChipTarget& i_target, + uint32_t i_psiPort, uint32_t i_enableState); + +uint32_t dllAdalPsiLinkVerify(const ecmdChipTarget& i_target, + uint32_t i_psiPort, uint32_t& o_enableState); + +uint32_t dllAdalPsiSetSpeed(const ecmdChipTarget& i_target, uint32_t i_psiPort, + uint32_t i_speed, uint32_t i_mode); + +#endif // ECMD_REMOVE_ADAL_FUNCTIONS +#ifndef ECMD_REMOVE_SENSOR_FUNCTIONS +uint32_t dllGetThermalSensor( + const ecmdChipTarget& i_target, const char* i_ecmdThermalSensorId, + uint32_t& o_temperature, ecmdThermalUnit_t i_thermalUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetClockSpeedSensor( + const ecmdChipTarget& i_target, const char* i_ecmdClockSpeedSensorId, + uint32_t& o_clockSpeed, ecmdClockSpeedType_t i_clockspeedUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetVoltageSensor( + const ecmdChipTarget& i_target, const char* i_ecmdVoltageSensorId, + uint32_t& o_voltage, ecmdVoltageUnit_t i_voltageUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetCurrentSensor( + const ecmdChipTarget& i_target, const char* i_ecmdCurrentSensorId, + uint32_t& o_current, ecmdCurrentUnit_t i_currentUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetAirDensitySensor( + const ecmdChipTarget& i_target, const char* i_ecmdAirDensitySensorId, + uint32_t& o_airDensity, ecmdAirDensityUnit_t i_airDensityUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetHumiditySensor( + const ecmdChipTarget& i_target, const char* i_ecmdHumiditySensorId, + uint32_t& o_humidity, ecmdHumidityUnit_t i_humidityUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetPowerSensor(const ecmdChipTarget& i_target, + const char* i_ecmdPowerSensorId, uint32_t& o_power, + ecmdPowerUnit_t i_powerUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetUtilizationSensor( + const ecmdChipTarget& i_target, const char* i_ecmdUtilizationSensorId, + uint32_t& o_utilization, ecmdUtilizationUnit_t i_utilizationUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllGetBandwidthSensor( + const ecmdChipTarget& i_target, const char* i_ecmdBandwidthSensorId, + uint32_t& o_bandwidth, ecmdBandwidthUnit_t i_BandwidthUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +uint32_t dllReadDigitalThermalSensor( + const ecmdChipTarget& i_target, const char* i_ecmdDTSSensorId, + ecmdDTSData& o_dtsReadings, ecmdThermalUnit_t i_thermalUnit, + ecmdSensorReadMode_t i_sensorReadMode); + +#endif // ECMD_REMOVE_SENSOR_FUNCTIONS +void dllPushCommandArgs(); + +void dllPopCommandArgs(); + +#ifndef ECMD_REMOVE_LATCH_FUNCTIONS +uint32_t dllGetScandefOrder(const ecmdChipTarget& i_target, uint32_t& o_mode); + +#endif // ECMD_REMOVE_LATCH_FUNCTIONS +std::string dllGetCurrentCmdline(); + +void dllSetCurrentCmdline(int argc, char* argv[]); + +#ifndef ECMD_REMOVE_LATCH_FUNCTIONS +uint32_t dllGetLatch(const ecmdChipTarget& i_target, const char* i_ringName, + const char* i_latchName, std::list& o_data, + ecmdLatchMode_t i_mode, uint32_t i_ring_mode); + +uint32_t dllPutLatch(const ecmdChipTarget& i_target, const char* i_ringName, + const char* i_latchName, const ecmdDataBuffer& i_data, + uint32_t i_startBit, uint32_t i_numBits, + uint32_t& o_matches, ecmdLatchMode_t i_mode, + uint32_t i_ring_mode); + +uint32_t dllGetLatchImage( + const ecmdChipTarget& i_target, const char* i_ringName, + const char* i_latchName, std::list& o_data, + ecmdLatchMode_t i_mode, const ecmdDataBuffer& i_ringImage); + +uint32_t dllPutLatchImage(const ecmdChipTarget& i_target, + const char* i_ringName, const char* i_latchName, + const ecmdDataBuffer& i_data, uint32_t i_startBit, + uint32_t i_numBits, uint32_t& o_matches, + ecmdLatchMode_t i_mode, ecmdDataBuffer& io_ringImage); + +uint32_t dllCreateSparseMaskFromLatch( + const ecmdChipTarget& i_target, const char* i_ringName, + const char* i_latchName, ecmdDataBuffer& o_mask, ecmdLatchMode_t i_mode, + uint32_t i_startBit, uint32_t i_numBits); + +uint32_t dllGetLatchOpt(const ecmdChipTarget& i_target, + const std::list& i_scandefLatchInfo, + std::list& o_data, + uint32_t i_ring_mode); + +uint32_t dllPutLatchOpt( + const ecmdChipTarget& i_target, const ecmdDataBuffer& i_data, + uint32_t i_startBit, uint32_t i_numBits, uint32_t& o_matches, + const std::list& i_scandefLatchInfo, uint32_t i_ring_mode); + +uint32_t dllGetLatchImageOpt( + const ecmdChipTarget& i_target, std::list& o_data, + const std::list& i_scandefLatchInfo, + const ecmdDataBuffer& i_ringImage); + +uint32_t dllPutLatchImageOpt( + const ecmdChipTarget& i_target, const ecmdDataBuffer& i_data, + uint32_t i_startBit, uint32_t i_numBits, uint32_t& o_matches, + const std::list& i_scandefLatchInfo, + ecmdDataBuffer& io_ringImage); + +uint32_t dllCreateSparseMaskFromLatchOpt( + const ecmdChipTarget& i_target, + const std::list& i_scandefLatchInfo, + ecmdDataBuffer& io_mask, uint32_t i_startBit, uint32_t i_numBits); + +#endif // ECMD_REMOVE_LATCH_FUNCTIONS +#ifndef ECMD_REMOVE_PNOR_FUNCTIONS +uint32_t dllGetPnor(const ecmdChipTarget& i_target, std::string i_partitionName, + uint32_t i_partitionOffset, uint32_t i_blockSize, + ecmdDataBuffer& o_data); + +uint32_t dllGetPnorList(const ecmdChipTarget& i_target, + std::string i_partitionName, uint32_t i_partitionOffset, + ecmdPnorListData& o_outData); + +uint32_t dllPutPnor(const ecmdChipTarget& i_target, std::string i_partitionName, + uint32_t i_partitionOffset, uint32_t i_blockSize, + const ecmdDataBuffer& i_data, uint32_t i_flags); + +#endif // ECMD_REMOVE_PNOR_FUNCTIONS +#ifndef ECMD_REMOVE_SPI_FUNCTIONS +uint32_t dllSpiRead(const ecmdChipTarget& i_target, uint32_t i_engine, + uint32_t i_select, uint64_t i_address, uint32_t i_bytes, + uint32_t i_mode, ecmdDataBuffer& o_data); + +uint32_t dllSpiWrite(const ecmdChipTarget& i_target, uint32_t i_engine, + uint32_t i_select, uint64_t i_address, uint32_t i_mode, + const ecmdDataBuffer& i_data); + +#endif /* ifndef ECMD_REMOVE_SPI_FUNCTIONS (this comment has to be here for \ + makedll.pl to work */ +uint32_t dllSetConfigurationComplexHidden( + const ecmdChipTarget& i_target, std::string i_name, + ecmdConfigData i_configData, uint32_t i_mode); + +} // extern C + +#endif +/* The previous has been auto-generated by makedll.pl */ diff --git a/ecmd_plugin/ecmd_dll_cfam.cpp b/ecmd_plugin/ecmd_dll_cfam.cpp new file mode 100644 index 0000000..4ac57ca --- /dev/null +++ b/ecmd_plugin/ecmd_dll_cfam.cpp @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +uint32_t dllGetCfamRegister(const ecmdChipTarget& target, uint32_t address, + ecmdDataBuffer& ecmdData) +{ + std::cout << "ecmd_dll_cfam: dllGetCfamRegister address 0x" << std::hex + << address << std::endl; + int rc = ECMD_FAILURE; + try + { + auto procTarget = ecmd_util::getProcTargetByPos(target.pos); + uint32_t data = 0; + if (!procTarget) + { + std::cerr << "Failed to find processor target for position " + << target.pos << "\n"; + return ECMD_FAILURE; + } + int rc = + hwaccess::HwAccessIntf::getCfamRegister(procTarget, address, data); + if (rc) + { + std::cout << "Failed in getCfamRegister \n"; + return rc; + } + ecmdData.setBitLength(32); + ecmdData.setWord(0, data); + return ECMD_SUCCESS; + } + catch (std::exception& ex) + { + std::cerr << "Exception: " << ex.what() << "\n"; + } + return rc; +} + +uint32_t dllPutCfamRegister(const ecmdChipTarget& target, uint32_t address, + const ecmdDataBuffer& data) +{ + std::cout << "ecmd_dll_cfam: dllPutCfamRegister address 0x" << std::hex + << address << std::endl; + int rc = ECMD_FAILURE; + try + { + auto procTarget = ecmd_util::getProcTargetByPos(target.pos); + if (!procTarget) + { + std::cerr << "Failed to find processor target for position " + << target.pos << "\n"; + return ECMD_FAILURE; + } + int rc = hwaccess::HwAccessIntf::putCfamRegister(procTarget, address, + data.getWord(0)); + if (rc) + { + std::cout << "Failed in getCfamRegister \n"; + return rc; + } + return ECMD_SUCCESS; + } + catch (std::exception& ex) + { + std::cerr << "Exception: " << ex.what() << "\n"; + } + return rc; +} diff --git a/ecmd_plugin/ecmd_dll_init.cpp b/ecmd_plugin/ecmd_dll_init.cpp new file mode 100644 index 0000000..14919f5 --- /dev/null +++ b/ecmd_plugin/ecmd_dll_init.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +constexpr std::string_view envVar = "ECMD_DLL_FILE"; +constexpr std::string_view defaultPath = "/usr/lib/libecmd_plugin.so"; + +// Load the device tree and initialise the targets +static int initTargets(void) +{ + uint32_t rc = ECMD_SUCCESS; + + try + { + /*TODO p12-refactor: fix device tree path*/ + TARGETING::TargetService::instance().init("/tmp/targeting_test.dtb"); + } + catch (std::exception& ex) + { + rc = ECMD_TARGET_NOT_CONFIGURED; + std::cout << "exception raised " << ex.what() << std::endl; + } + return rc; +} + +uint32_t dllInitDll() +{ + uint32_t rc = ECMD_SUCCESS; + rc = initTargets(); + if (rc) + { + std::cerr << "Failed to dllInitDll \n"; + return rc; + } + + if (std::getenv(envVar.data()) == nullptr) + { + if (setenv(envVar.data(), defaultPath.data(), 1) != 0) + { + std::string err = + std::format("Failed to set environment variable {} to {}", + envVar, defaultPath); + std::cout << err << std::endl; + return ECMD_INVALID_DLL_FILENAME; + } + std::cout << std::format("Set {}={}\n", envVar, defaultPath); + } + else + { + std::cout << std::format("{} already set to {}\n", envVar, + std::getenv(envVar.data())); + } + return rc; +} + +uint32_t dllFreeDll() +{ + return ECMD_SUCCESS; +} diff --git a/ecmd_plugin/ecmd_dll_istep.cpp b/ecmd_plugin/ecmd_dll_istep.cpp new file mode 100644 index 0000000..d6b158a --- /dev/null +++ b/ecmd_plugin/ecmd_dll_istep.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +uint32_t executeIstep(uint16_t major, uint16_t minorStart, uint16_t minorEnd) +{ + using namespace istep_table; + uint32_t rc = ECMD_SUCCESS; + + // If istep is 0 then, run chassis on and other workaround steps before + // kick off ipl_run_major_minor() in loop + if (major == 0) + { + /* istep power on */ + rc = ecmd_util::istepPowerOn(); + if (!rc) + { + // Set IPL mode to interactive + rc = ipl_init(IPL_HOSTBOOT); + if (rc) + { + std::cerr << "Unable to set IPL in interactive mode\n"; + return rc; + } + } + else + { + std::cerr << "FAIL: istepPowerOn\n"; + return rc; + } + } // major ==0 + /* loop through each isteps */ + for (uint16_t minor = minorStart; minor <= minorEnd; minor++) + { + auto istepNameOpt = istep_table::getStepName(major, minor); + if (!istepNameOpt) + { + std::cerr << "Invalid istep " << major << "." << minor << std::endl; + continue; + } + IStepDestination destination = getDestination(major, minor); + + // This istep is NOOP + if (destination == IStepDestination::EDBG_ISTEP_NOOP) + { + std::cout << "Requested istep %s is NOOP " << *istepNameOpt + << std::endl; + } + else + { + /* kick off isteps */ + rc = ipl_run_major_minor(major, minor); + if (!rc) + { + if (major == 6 && minor == 4) + { + // if the istep reaches 6.4 then, set the Host state to + // running! + rc = ecmd_util::setHostStateToRunning(); + if (rc != ECMD_SUCCESS) + { + std::cerr << "FAIL: failed to set host state\n"; + return rc; + } + } + std::cout << " PASS: istep " << *istepNameOpt << std::endl; + } + else + { + std::cerr << " FAIL: istep check Error " << *istepNameOpt + << std::endl; + return rc; + } + } + } // end for + return rc; +} +uint32_t dllIStepsByNumber(const ecmdDataBuffer& isteps) +{ + using namespace istep_table; + + uint32_t rc = ECMD_SUCCESS; + uint16_t indexBegin, minorStart = EDBG_INVALID_POSITION; + uint16_t indexEnd, minorEnd = EDBG_INVALID_POSITION; + uint16_t activeStep = EDBG_INVALID_ISTEP_NUM; + + do // Start of single exit point loop. + { + /****************************************************************************************/ + /* First, check to make sure at least 1 bit is active in i_steps + * databuffer, then.... */ + /* For each valid bit in the i_steps databuffer: */ + /* 1) find the index entry #s that start that step and end that + * step */ + /* 2) Call iStepsHelper() multiple times, starting with starting + * index entry # */ + /* and ending with the ending entry #. */ + /****************************************************************************************/ + + // check to see if at least 1 bit in the range is active + if (isteps.getNumBitsSet( + EDBG_FIRST_ISTEP_NUM, + EDBG_LAST_ISTEP_NUM - EDBG_FIRST_ISTEP_NUM + 1)) + { + rc = ECMD_INVALID_ARGS; + std::cerr + << "dllIStepsByNumber: No Steps in active range selected. " + << "Range start: " << EDBG_FIRST_ISTEP_NUM + << " end: " << EDBG_LAST_ISTEP_NUM; + break; // exit do-loop + } + + /* Large 'for' loop that goes through i_steps looking for active + * steps start at begining of range */ + for (activeStep = EDBG_FIRST_ISTEP_NUM; + activeStep <= EDBG_LAST_ISTEP_NUM && rc == ECMD_SUCCESS; + ++activeStep) + { + if (isteps.isBitSet(activeStep)) // this is an active step + { + /* look IPLTable for the existence of this istep number */ + if (false == isValid(activeStep)) + { + /* this is only warning, as the value is in the range, + * but isn't being used */ + printf( + "dllIStepsByNumber: Requested iStep Number %d is invalid.\n", + activeStep); + continue; + } + /* 1a) Lookup first index entry of this active step */ + indexBegin = getPosFirstMinorNumber(activeStep); + minorStart = getIStepMinorNumber(indexBegin); + + /* 1b) Starting with indexBegin, + * lookup last index entry of this active step */ + indexEnd = getPosLastMinorNumber(activeStep); + minorEnd = getIStepMinorNumber(indexEnd); + + /* 2) Call iStepsHelper() multiple times, + * starting with starting index entry # + * and ending with the ending entry #. */ + /* kick off isteps */ + rc = executeIstep(activeStep, minorStart, minorEnd); + + } /* end of 'if' active step check */ + + } /* end of for loop going through active i_steps */ + + } while (0); + + return rc; +} + +uint32_t dllIStepsByName(std::string /*stepName*/) +{ + return ECMD_SUCCESS; +} diff --git a/ecmd_plugin/ecmd_dll_scom.cpp b/ecmd_plugin/ecmd_dll_scom.cpp new file mode 100644 index 0000000..0c7475a --- /dev/null +++ b/ecmd_plugin/ecmd_dll_scom.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#include +#include + +uint32_t dllGetScom(ecmdChipTarget& /*target*/, uint64_t address, + ecmdDataBuffer& /*data*/) +{ + std::cout << "ecmd_dll_scom: dllGetScom address 0x" << std::hex << address + << std::endl; + return ECMD_SUCCESS; +} + +uint32_t dllPutScom(const ecmdChipTarget& /*target*/, uint64_t address, + const ecmdDataBuffer& /*data*/) +{ + std::cout << "ecmd_dll_scom: dllPutScom address 0x" << std::hex << address + << std::endl; + return ECMD_SUCCESS; +} diff --git a/ecmd_plugin/ecmd_util.cpp b/ecmd_plugin/ecmd_util.cpp new file mode 100644 index 0000000..41fe552 --- /dev/null +++ b/ecmd_plugin/ecmd_util.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace ecmd_util +{ +constexpr auto GENESIS_BOOT_FILE = "/var/lib/phal/genesisboot"; + +TARGETING::TargetPtr getProcTargetByPos(uint32_t posValue) +{ + using namespace TARGETING; + auto& ts = TargetService::instance(); + auto top = ts.getTopLevelTarget(); + + // Build predicate to match processor type and position + auto typeProc = std::make_shared>(TYPE_PROC); + auto pos = std::make_shared>(posValue); + + PredicatePostfixExpr procPred; + procPred.push(typeProc).push(pos).And(); + + // Find all matching processor targets + auto&& targets = ts.getAssociated(top, AssociationType::childByPhysical, + RecursionLevel::all, &procPred); + + // Return the matching target (or nullptr) + if (targets.size() == 1) + { + return targets.front(); + } + else + { + std::cerr << "processor target not found for FAPI_POS: " << posValue + << "\n"; + return nullptr; + } +} + +// Check if chassis is on/off +bool isChassisOn() +{ + constexpr std::string_view cmd = "obmcutil chassisstate 2>&1"; + std::array buffer{}; + std::string output; + + // Define unique_ptr with custom deleter for FILE* + using FileCloser = int (*)(FILE*); + + auto pipePtr = + std::unique_ptr(popen(cmd.data(), "r"), pclose); + if (!pipePtr) + { + std::cerr << "Failed to execute command: " << cmd << std::endl; + return false; + } + + // Read command output + while (fgets(buffer.data(), static_cast(buffer.size()), pipePtr.get())) + { + output += buffer.data(); + } + + // Return true if the chassis is ON, false otherwise + return output.contains("State.Chassis.PowerState.On"); +} + +// Start attention handler sevice +int startAttentionHandlerService() +{ + constexpr const char* cmd = "systemctl start attn_handler.service"; + int rc = std::system(cmd); + if (rc != 0) + { + std::cerr << "system() call failed" << rc << std::endl; + rc = -errno; + return rc; + } + return rc; +} + +int startAttnHandler() +{ + int rc = ECMD_SUCCESS; + std::string start_attn_handler_service_cmd = + "systemctl start attn_handler.service"; + + // User the system handler service + rc = system(start_attn_handler_service_cmd.c_str()); + if (rc != 0) + { + rc = -errno; + return rc; + } + + return rc; +} + +int istepPowerOn() +{ + int rc = ECMD_SUCCESS; + const std::string host_reboot_off_cmd = "obmcutil hostrebootoff"; + const std::string chassis_on_cmd = "obmcutil --wait chassison"; + const std::string mbox_reset_cmd = "/usr/sbin/mboxctl --reset"; + + bool chassisOn = isChassisOn(); + uint16_t count = 0; + + if (!chassisOn) + { + // Disable host recovery (istep mode) + rc = std::system(host_reboot_off_cmd.c_str()); + if (rc != 0) + { + rc = -errno; + return rc; + } + + // Trigger chassis on + rc = std::system(chassis_on_cmd.c_str()); + if (rc != 0) + { + rc = -errno; + return rc; + } + + // Wait up to 3 minutes for chassis to turn ON + do + { + chassisOn = isChassisOn(); + if (chassisOn) + break; + + std::this_thread::sleep_for(std::chrono::seconds(1)); + } while (++count < 180); + } + + // Check final state + if (!chassisOn) + { + return -1; // chassis did not power on + } + + // Trigger mbox reset + rc = std::system(mbox_reset_cmd.c_str()); + if (rc != 0) + { + rc = -errno; + return rc; + } + + // Remove genesis boot file if it exists + fs::path genesis_boot_file = GENESIS_BOOT_FILE; + if (fs::exists(genesis_boot_file)) + { + fs::remove(genesis_boot_file); + } + + // Start attention handler service + rc = startAttnHandler(); + if (rc != 0) + { + return rc; + } + + return ECMD_SUCCESS; +} + +// Set host state to running +int setHostStateToRunning() +{ + // TODO:use D-Bus method + const std::string set_host_state_cmd = + "busctl set-property " + "xyz.openbmc_project.State.Host " + "/xyz/openbmc_project/state/host0 " + "xyz.openbmc_project.State.Host " + "CurrentHostState s " + "xyz.openbmc_project.State.Host.HostState.Running"; + + // Try to set host state to Running + int rc = std::system(set_host_state_cmd.c_str()); + if (rc != 0) + { + std::cout << "Failed to set host state to Running " << rc << std::endl; + return rc; + } + + // Best-effort: stop systemd targets; ignore errors + rc = std::system("obmcutil stopofftargets"); + if (rc != 0) + { + std::cerr << "Failed to execute obmcutil stopofftargets, rc=" << rc + << std::endl; + return rc; + } + return ECMD_SUCCESS; +} +} // namespace ecmd_util diff --git a/ecmd_plugin/ecmd_util.hpp b/ecmd_plugin/ecmd_util.hpp new file mode 100644 index 0000000..9e92e24 --- /dev/null +++ b/ecmd_plugin/ecmd_util.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace ecmd_util +{ +TARGETING::TargetPtr getProcTargetByPos(uint32_t posValue); + +bool isChassisOn(); + +int startAttnHandler(); + +// Trigger obmcutil hostrebootoff->chassison->wait for chassison() +int istepPowerOn(); + +// Set host state to running +int setHostStateToRunning(); +} // namespace ecmd_util diff --git a/ecmd_plugin/istep_table.hpp b/ecmd_plugin/istep_table.hpp new file mode 100644 index 0000000..f4cf433 --- /dev/null +++ b/ecmd_plugin/istep_table.hpp @@ -0,0 +1,387 @@ +#pragma once + +//-------------------------------------------------------------------- +// Includes +//-------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +namespace istep_table +{ +// --------------------------------------------------------------------- +// Strongly-typed destination enum +// --------------------------------------------------------------------- +enum class IStepDestination : std::uint8_t +{ + EDBG_ISTEP_HOST = 0x0, // IStep is executed by host + EDBG_ISTEP_SBE, // IStep is executed by Self Boot Engine + EDBG_ISTEP_BMC, // IStep is executed by BMC + EDBG_ISTEP_NOOP, // This istep is NOOP + EDBG_ISTEP_INVALID_DESTINATION +}; + +// --------------------------------------------------------------------- +// IPL Step structure +// --------------------------------------------------------------------- +struct IStep +{ + std::uint16_t major{}; + std::uint16_t minor{}; + std::string_view name{}; + IStepDestination dest{}; +}; + +/****************************************************************************/ +/* !!! --- THIS LIST MUST BE IN ORDER THAT THEY'RE CALLED IN AN IPL --- !!! */ +/****************************************************************************/ + +/****************************************************************************/ +/* NOTE: The istep is executed by the self boot engine/the host code/ */ +/* the attached bmc depending upon the destination type. */ +/* Options: */ +/* EDBG_ISTEP_HOST - The istep is performed by the host */ +/* EDBG_ISTEP_SBE - The istep is performed by the self boot engine */ +/* EDBG_ISTEP_BMC - The istep is performed by the BMC */ +/* EDBG_ISTEP_NOOP - The istep is No OP */ +/* */ +/****************************************************************************/ + +/****************************************************************************/ +/* Warning : The following constants are defined based on the values of this*/ +/* table. Any changes to this table requires examination of the */ +/* values assigned to these constants. */ +/* */ +/* EDBG_FIRST_ISTEP_NUM = 0 */ +/* EDBG_LAST_ISTEP_NUM = 21 */ +/* EDBG_INVALID_ISTEP_NUM = 0xFFFF */ +/* EDBG_INVALID_POSITION = 0xFFFF */ +/****************************************************************************/ +// major | minor | istep name | destination | +// number| number| | | +inline constexpr auto ISteps = std::to_array({ + {0, 1, "poweron", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 2, "startipl", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 3, "disableattns", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 4, "updatehwmodel", IStepDestination::EDBG_ISTEP_BMC}, + {0, 5, "alignment_check", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 6, "set_ref_clock", IStepDestination::EDBG_ISTEP_BMC}, + {0, 7, "proc_clock_test", IStepDestination::EDBG_ISTEP_BMC}, + {0, 8, "proc_prep_ipl", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 9, "edramrepair", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 10, "asset_protection", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 11, "proc_select_boot_prom", IStepDestination::EDBG_ISTEP_BMC}, + {0, 12, "hb_config_update", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 13, "sbe_config_update", IStepDestination::EDBG_ISTEP_BMC}, + {0, 14, "sbe_start", IStepDestination::EDBG_ISTEP_BMC}, + {0, 15, "startprd", IStepDestination::EDBG_ISTEP_NOOP}, + {0, 16, "proc_attn_listen", IStepDestination::EDBG_ISTEP_BMC}, + {1, 1, "proc_sbe_enable_seeprom", IStepDestination::EDBG_ISTEP_NOOP}, + {1, 2, "proc_sbe_pib_init", IStepDestination::EDBG_ISTEP_NOOP}, + {1, 3, "proc_sbe_measure", IStepDestination::EDBG_ISTEP_NOOP}, + {2, 1, "proc_sbe_ld_image", IStepDestination::EDBG_ISTEP_NOOP}, + {2, 2, "proc_sbe_attr_setup", IStepDestination::EDBG_ISTEP_SBE}, + {2, 3, "proc_sbe_tp_dpll_bypass", IStepDestination::EDBG_ISTEP_SBE}, + {2, 4, "proc_sbe_tp_chiplet_reset", IStepDestination::EDBG_ISTEP_SBE}, + {2, 5, "proc_sbe_tp_gptr_time_initf", IStepDestination::EDBG_ISTEP_SBE}, + {2, 6, "proc_sbe_dft_probe_setup_1", IStepDestination::EDBG_ISTEP_SBE}, + {2, 7, "proc_sbe_npll_initf", IStepDestination::EDBG_ISTEP_SBE}, + {2, 8, "proc_sbe_rcs_setup", IStepDestination::EDBG_ISTEP_SBE}, + {2, 9, "proc_sbe_tp_switch_gears", IStepDestination::EDBG_ISTEP_SBE}, + {2, 10, "proc_sbe_npll_setup", IStepDestination::EDBG_ISTEP_SBE}, + {2, 11, "proc_sbe_tp_repr_intf", IStepDestination::EDBG_ISTEP_SBE}, + {2, 12, "proc_sbe_setup_tp_abist", IStepDestination::EDBG_ISTEP_SBE}, + {2, 13, "proc_sbe_tp_arrayinit", IStepDestination::EDBG_ISTEP_SBE}, + {2, 14, "proc_sbe_tp_intf", IStepDestination::EDBG_ISTEP_SBE}, + {2, 15, "proc_sbe_dft_probesetup_2", IStepDestination::EDBG_ISTEP_SBE}, + {2, 16, "proc_sbe_tp_chiplet_init", IStepDestination::EDBG_ISTEP_SBE}, + {3, 1, "proc_sbe_chiplet_setup", IStepDestination::EDBG_ISTEP_SBE}, + {3, 2, "proc_sbe_chiplet_clk_config", IStepDestination::EDBG_ISTEP_SBE}, + {3, 3, "proc_sbe_chiplet_reset", IStepDestination::EDBG_ISTEP_SBE}, + {3, 4, "proc_sbe_gptr_time_initf", IStepDestination::EDBG_ISTEP_SBE}, + {3, 5, "proc_sbe_chiplet_pll_initf", IStepDestination::EDBG_ISTEP_SBE}, + {3, 6, "proc_sbe_chiplet_pll_setup", IStepDestination::EDBG_ISTEP_SBE}, + {3, 7, "proc_sbe_repr_intf", IStepDestination::EDBG_ISTEP_SBE}, + {3, 8, "proc_sbe_abist_setup", IStepDestination::EDBG_ISTEP_SBE}, + {3, 9, "proc_sbe_arrayinit", IStepDestination::EDBG_ISTEP_SBE}, + {3, 10, "proc_sbe_lbist", IStepDestination::EDBG_ISTEP_SBE}, + {3, 11, "proc_sbe_initf", IStepDestination::EDBG_ISTEP_SBE}, + {3, 12, "proc_sbe_startclocks", IStepDestination::EDBG_ISTEP_SBE}, + {3, 13, "proc_sbe_chiplet_init", IStepDestination::EDBG_ISTEP_SBE}, + {3, 14, "proc_sbe_chiplet_fir_init", IStepDestination::EDBG_ISTEP_SBE}, + {3, 15, "proc_sbe_dts_init", IStepDestination::EDBG_ISTEP_SBE}, + {3, 16, "proc_sbe_skew_adjust_setup", IStepDestination::EDBG_ISTEP_SBE}, + {3, 17, "proc_sbe_nest_enable_ridi", IStepDestination::EDBG_ISTEP_SBE}, + {3, 18, "proc_sbe_scominit", IStepDestination::EDBG_ISTEP_SBE}, + {3, 19, "proc_sbe_lpc", IStepDestination::EDBG_ISTEP_SBE}, + {3, 20, "proc_sbe_fabricinit", IStepDestination::EDBG_ISTEP_SBE}, + {3, 21, "proc_sbe_check_boot_proc", IStepDestination::EDBG_ISTEP_SBE}, + {3, 22, "proc_sbe_mcs_setup", IStepDestination::EDBG_ISTEP_SBE}, + {3, 23, "proc_sbe_select_ex", IStepDestination::EDBG_ISTEP_SBE}, + {4, 1, "proc_hcd_cache_poweron", IStepDestination::EDBG_ISTEP_SBE}, + {4, 2, "proc_hcd_cache_reset", IStepDestination::EDBG_ISTEP_SBE}, + {4, 3, "proc_hcd_cache_gptr_time_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 4, "proc_hcd_cache_repair_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 5, "proc_hcd_cache_arrayinit", IStepDestination::EDBG_ISTEP_SBE}, + {4, 6, "proc_hcd_cache_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 7, "proc_hcd_cache_startclocks", IStepDestination::EDBG_ISTEP_SBE}, + {4, 8, "proc_hcd_cache_scominit", IStepDestination::EDBG_ISTEP_SBE}, + {4, 9, "proc_hcd_cache_scom_customize", IStepDestination::EDBG_ISTEP_SBE}, + {4, 10, "proc_hcd_cache_ras_runtime_scom", + IStepDestination::EDBG_ISTEP_SBE}, + {4, 11, "proc_hcd_core_poweron", IStepDestination::EDBG_ISTEP_SBE}, + {4, 12, "proc_hcd_core_reset", IStepDestination::EDBG_ISTEP_SBE}, + {4, 13, "proc_hcd_core_gptr_time_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 14, "proc_hcd_core_repair_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 15, "proc_hcd_core_arrayinit", IStepDestination::EDBG_ISTEP_SBE}, + {4, 16, "proc_hcd_core_initf", IStepDestination::EDBG_ISTEP_SBE}, + {4, 17, "proc_hcd_core_startclocks", IStepDestination::EDBG_ISTEP_SBE}, + {4, 18, "proc_hcd_core_scominit", IStepDestination::EDBG_ISTEP_SBE}, + {4, 19, "proc_hcd_core_scom_customize", IStepDestination::EDBG_ISTEP_SBE}, + {4, 20, "proc_hcd_core_ras_runtime_scom", IStepDestination::EDBG_ISTEP_SBE}, + {5, 1, "proc_sbe_load_bootloader", IStepDestination::EDBG_ISTEP_SBE}, + {5, 2, "proc_sbe_core_spr_setup", IStepDestination::EDBG_ISTEP_SBE}, + {5, 3, "proc_sbe_instruct_start", IStepDestination::EDBG_ISTEP_SBE}, + {6, 1, "host_bootloader", IStepDestination::EDBG_ISTEP_NOOP}, + {6, 2, "host_setup", IStepDestination::EDBG_ISTEP_NOOP}, + {6, 3, "host_istep_enable", IStepDestination::EDBG_ISTEP_NOOP}, + {6, 4, "host_init_fsi", IStepDestination::EDBG_ISTEP_HOST}, + {6, 5, "host_set_ipl_parms", IStepDestination::EDBG_ISTEP_HOST}, + {6, 6, "host_discover_targets", IStepDestination::EDBG_ISTEP_HOST}, + {6, 7, "host_update_primary_tpm", IStepDestination::EDBG_ISTEP_HOST}, + {6, 8, "host_gard", IStepDestination::EDBG_ISTEP_HOST}, + {6, 9, "host_voltage_config", IStepDestination::EDBG_ISTEP_HOST}, + {7, 1, "host_mss_attr_cleanup", IStepDestination::EDBG_ISTEP_HOST}, + {7, 2, "mss_volt", IStepDestination::EDBG_ISTEP_HOST}, + {7, 3, "mss_freq", IStepDestination::EDBG_ISTEP_HOST}, + {7, 4, "mss_eff_config", IStepDestination::EDBG_ISTEP_HOST}, + {7, 5, "mss_attr_update", IStepDestination::EDBG_ISTEP_HOST}, + {8, 1, "host_setup_sbe", IStepDestination::EDBG_ISTEP_HOST}, + {8, 2, "host_secondary_sbe_config", IStepDestination::EDBG_ISTEP_HOST}, + {8, 3, "host_cbs_start", IStepDestination::EDBG_ISTEP_HOST}, + {8, 4, "proc_check_secondary_sbe_seeprom_complete", + IStepDestination::EDBG_ISTEP_HOST}, + {8, 5, "host_attnlisten_proc", IStepDestination::EDBG_ISTEP_HOST}, + {8, 6, "host_fbc_eff_config", IStepDestination::EDBG_ISTEP_HOST}, + {8, 7, "hosteff_config_links", IStepDestination::EDBG_ISTEP_HOST}, + {8, 8, "proc_attr_update", IStepDestination::EDBG_ISTEP_HOST}, + {8, 9, "proc_chiplet_fabric_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {8, 10, "host_set_voltages", IStepDestination::EDBG_ISTEP_HOST}, + {8, 11, "proc_io_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {8, 12, "proc_load_ioppe", IStepDestination::EDBG_ISTEP_HOST}, + {8, 13, "proc_init_ioppe", IStepDestination::EDBG_ISTEP_HOST}, + {8, 14, "proc_iohs_enable_ridi", IStepDestination::EDBG_ISTEP_HOST}, + {9, 1, "proc_io_dccal_done", IStepDestination::EDBG_ISTEP_HOST}, + {9, 2, "fabric_dl_pre_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {9, 3, "fabric_dl_setup_training", IStepDestination::EDBG_ISTEP_HOST}, + {9, 4, "proc_fabric_link_layer", IStepDestination::EDBG_ISTEP_HOST}, + {9, 5, "fabric_dl_post_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {9, 6, "proc_fabric_iovalid", IStepDestination::EDBG_ISTEP_HOST}, + {9, 7, "proc_fbc_eff_config_aggregate", IStepDestination::EDBG_ISTEP_HOST}, + {10, 1, "proc_build_smp", IStepDestination::EDBG_ISTEP_HOST}, + {10, 2, "host_sbe_update", IStepDestination::EDBG_ISTEP_HOST}, + {10, 3, "host_secureboot_lockdown", IStepDestination::EDBG_ISTEP_HOST}, + {10, 4, "proc_chiplet_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {10, 5, "proc_pau_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {10, 6, "proc_pcie_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {10, 7, "proc_scomoverride_chiplets", IStepDestination::EDBG_ISTEP_HOST}, + {10, 8, "proc_chiplet_enable_ridi", IStepDestination::EDBG_ISTEP_HOST}, + {10, 9, "host_rng_bist", IStepDestination::EDBG_ISTEP_HOST}, + {11, 1, "host_prd_hwreconfig", IStepDestination::EDBG_ISTEP_HOST}, + {11, 2, "host_set_mem_volt", IStepDestination::EDBG_ISTEP_HOST}, + {11, 3, "proc_ocmb_enable", IStepDestination::EDBG_ISTEP_HOST}, + {11, 4, "ocmb_check_for_ready", IStepDestination::EDBG_ISTEP_HOST}, + {12, 1, "mss_getecid", IStepDestination::EDBG_ISTEP_HOST}, + {12, 2, "omi_attr_update", IStepDestination::EDBG_ISTEP_HOST}, + {12, 3, "proc_omi_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {12, 4, "ocmb_omi_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {12, 5, "omi_pre_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {12, 6, "omi_setup", IStepDestination::EDBG_ISTEP_HOST}, + {12, 7, "omi_io_run_training", IStepDestination::EDBG_ISTEP_HOST}, + {12, 8, "omi_train_check", IStepDestination::EDBG_ISTEP_HOST}, + {12, 9, "omi_post_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {12, 10, "host_attnlisten_memb", IStepDestination::EDBG_ISTEP_HOST}, + {12, 11, "host_omi_init", IStepDestination::EDBG_ISTEP_HOST}, + {12, 12, "update_omi_firmaware", IStepDestination::EDBG_ISTEP_HOST}, + {13, 1, "mss_scominit", IStepDestination::EDBG_ISTEP_HOST}, + {13, 2, "mss_draminit", IStepDestination::EDBG_ISTEP_HOST}, + {13, 3, "mss_draminit_mc", IStepDestination::EDBG_ISTEP_HOST}, + {14, 1, "mss_memdiag", IStepDestination::EDBG_ISTEP_HOST}, + {14, 2, "mss_thermal_init", IStepDestination::EDBG_ISTEP_HOST}, + {14, 3, "proc_load_iop_xram", IStepDestination::EDBG_ISTEP_HOST}, + {14, 4, "proc_pcie_config", IStepDestination::EDBG_ISTEP_HOST}, + {14, 5, "proc_setup_mmio_bars", IStepDestination::EDBG_ISTEP_HOST}, + {14, 6, "host_secure_rng", IStepDestination::EDBG_ISTEP_HOST}, + {14, 7, "host_enable_memory_encryption", IStepDestination::EDBG_ISTEP_HOST}, + {14, 8, "proc_exit_cache_contained", IStepDestination::EDBG_ISTEP_HOST}, + {14, 9, "proc_htm_setup", IStepDestination::EDBG_ISTEP_HOST}, + {14, 10, "host_mpipl_service", IStepDestination::EDBG_ISTEP_HOST}, + {14, 11, "proc_psiinit", IStepDestination::EDBG_ISTEP_NOOP}, // cronus only + {14, 12, "proc_bmc_pciinit", + IStepDestination::EDBG_ISTEP_NOOP}, // cronus only + {15, 1, "host_build_stop_image", IStepDestination::EDBG_ISTEP_HOST}, + {15, 2, "proc_set_homer_bar", IStepDestination::EDBG_ISTEP_HOST}, + {15, 3, "host_establish_ec_chiplet", IStepDestination::EDBG_ISTEP_HOST}, + {15, 4, "host_start_stop_engine", IStepDestination::EDBG_ISTEP_HOST}, + {16, 1, "host_activate_boot_core", IStepDestination::EDBG_ISTEP_HOST}, + {16, 2, "host_activate_secondary_cores", IStepDestination::EDBG_ISTEP_HOST}, + {16, 3, "host_secure_rng_noop", IStepDestination::EDBG_ISTEP_HOST}, + {16, 4, "mss_scrub", IStepDestination::EDBG_ISTEP_HOST}, + {16, 5, "host_ipl_complete", IStepDestination::EDBG_ISTEP_HOST}, + {17, 1, "collect_drawers", IStepDestination::EDBG_ISTEP_NOOP}, + {17, 2, "proc_psiinit", IStepDestination::EDBG_ISTEP_NOOP}, + {17, 3, "psi_diag", IStepDestination::EDBG_ISTEP_NOOP}, + {18, 1, "sys_proc_eff_config_links", IStepDestination::EDBG_ISTEP_HOST}, + {18, 2, "sys_proc_chiplet_fabric_scominit", + IStepDestination::EDBG_ISTEP_HOST}, + {18, 3, "sys_fabric_dl_pre_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {18, 4, "sys_fabric_dl_setup_training", IStepDestination::EDBG_ISTEP_HOST}, + {18, 5, "sys_proc_fabric_link_layer", IStepDestination::EDBG_ISTEP_HOST}, + {18, 6, "sys_fabric_dl_post_trainadv", IStepDestination::EDBG_ISTEP_HOST}, + {18, 7, "sys_proc_fabric_iovalid", IStepDestination::EDBG_ISTEP_HOST}, + {18, 8, "sys_proc_fbc_eff_config_aggregate", + IStepDestination::EDBG_ISTEP_HOST}, + {18, 9, "proc_tod_setup", IStepDestination::EDBG_ISTEP_HOST}, + {18, 10, "proc_tod_init", IStepDestination::EDBG_ISTEP_HOST}, + {18, 11, "cec_ipl_complete", IStepDestination::EDBG_ISTEP_NOOP}, + {18, 12, "startprd_system", IStepDestination::EDBG_ISTEP_NOOP}, + {18, 13, "attn_listenall", IStepDestination::EDBG_ISTEP_NOOP}, + {19, 1, "prep_host", IStepDestination::EDBG_ISTEP_NOOP}, + {20, 1, "host_load_payload", IStepDestination::EDBG_ISTEP_HOST}, + {20, 2, "host_load_complete", IStepDestination::EDBG_ISTEP_HOST}, + {21, 1, "host_micro_update", IStepDestination::EDBG_ISTEP_HOST}, + {21, 2, "host_runtime_setup", IStepDestination::EDBG_ISTEP_HOST}, + {21, 3, "host_verify_hdat", IStepDestination::EDBG_ISTEP_HOST}, + {21, 4, "host_start_payload", IStepDestination::EDBG_ISTEP_HOST}, + {21, 5, "host_post_start_payload", IStepDestination::EDBG_ISTEP_NOOP}, + {21, 6, "switchbcu", IStepDestination::EDBG_ISTEP_NOOP}, + {21, 7, "completeipl", IStepDestination::EDBG_ISTEP_NOOP}, +}); // end - array initialization + +constexpr std::uint16_t EDBG_FIRST_ISTEP_NUM = 0; +constexpr std::uint16_t EDBG_LAST_ISTEP_NUM = 21; +constexpr std::uint16_t EDBG_INVALID_POSITION = 0xFFFF; +constexpr std::uint16_t EDBG_NUMBER_OF_ISTEPS = ISteps.size(); +constexpr std::uint16_t EDBG_INVALID_ISTEP_NUM = 0xFFFF; + +constexpr std::optional getStepName(uint16_t major, + uint16_t minor) +{ + auto it = std::ranges::find_if(ISteps, [=](auto& s) { + return s.major == major && s.minor == minor; + }); + if (it != ISteps.end()) + { + return it->name; + } + return std::nullopt; +} + +constexpr bool isValid(uint8_t majorNum) +{ + return std::ranges::any_of(ISteps, [=](auto& s) { + return s.major == majorNum; + }); +} + +constexpr bool isValid(std::string_view name) +{ + return std::ranges::any_of(ISteps, [=](auto& s) { return s.name == name; }); +} + +constexpr IStepDestination getDestination(uint16_t majorNum, uint16_t minorNum) +{ + if (auto it = std::ranges::find_if(ISteps, + [=](const IStep& step) { + return step.major == majorNum && + step.minor == minorNum; + }); + it != ISteps.end()) + { + return it->dest; + } + + return IStepDestination::EDBG_ISTEP_INVALID_DESTINATION; +} +// --------------------------------------------------------------------- +// Get the position (index) of the last minor number for a given major +// --------------------------------------------------------------------- +constexpr std::uint16_t getPosLastMinorNumber(std::uint16_t majorNum) +{ + if (majorNum > EDBG_LAST_ISTEP_NUM) + { + return EDBG_INVALID_POSITION; + } + + std::uint16_t position = EDBG_INVALID_POSITION; + + for (std::uint16_t row = 0; row < EDBG_NUMBER_OF_ISTEPS; ++row) + { + if (ISteps[row].major == majorNum) + { + // If this is the last row or next row has a greater major number, + // current row marks the last minor number for this major. + if ((row + 1 == EDBG_NUMBER_OF_ISTEPS) || + (ISteps[row + 1].major > majorNum)) + { + position = row; + break; + } + } + } + + return position; +} + +// --------------------------------------------------------------------- +// Get the position (index) of the first minor number for a given major +// --------------------------------------------------------------------- +constexpr std::uint16_t getPosFirstMinorNumber(std::uint16_t majorNum) +{ + if (majorNum > EDBG_LAST_ISTEP_NUM) + { + return EDBG_INVALID_POSITION; + } + + for (std::uint16_t row = 0; row < EDBG_NUMBER_OF_ISTEPS; ++row) + { + if (ISteps[row].major == majorNum) + { + return row; + } + } + + return EDBG_INVALID_POSITION; +} + +// --------------------------------------------------------------------- +// Get the position (index) of the istep name +// --------------------------------------------------------------------- +constexpr std::uint16_t getPosition(std::string_view istepName) +{ + for (std::uint16_t row = 0; row < EDBG_NUMBER_OF_ISTEPS; ++row) + { + if (ISteps[row].name == istepName) + { + return row; + } + } + return EDBG_INVALID_POSITION; +} + +// --------------------------------------------------------------------- +// Get the minor number for a given istep table position +// --------------------------------------------------------------------- +constexpr std::uint16_t getIStepMinorNumber(std::uint16_t position) +{ + if (position < EDBG_NUMBER_OF_ISTEPS) + { + return ISteps[position].minor; + } + + return EDBG_INVALID_ISTEP_NUM; +} +} // namespace istep_table diff --git a/ecmd_plugin/meson.build b/ecmd_plugin/meson.build new file mode 100644 index 0000000..47a971e --- /dev/null +++ b/ecmd_plugin/meson.build @@ -0,0 +1,71 @@ +# meson.build for ecmd-plugin +# Collect all source files +ecmd_plugin_src = files( + 'ecmd_dll_cfam.cpp', + 'ecmd_dll_init.cpp', + 'ecmd_dll_istep.cpp', + 'ecmd_dll_scom.cpp', + 'ecmd_util.cpp', +) + +# Include directories +ecmd_plugin_inc = include_directories('.') + +# Find dependent libraries +ipl_lib = cxx.find_library('ipl', required: true) +ecmd_lib = cxx.find_library('ecmd', required: true) + +dep_targeting = dependency('libtargeting', required: true) +dep_hwaccess = dependency('libhwaccess', required: true) +dep_targetsvc = dependency('libtargetsvc', required: true) +dep_transport = dependency('libtransport', required: true) + + +# Combine them in a list for linking +ecmd_plugin_deps = [ + ipl_lib, + ecmd_lib, + dep_targeting, + dep_hwaccess, + dep_targetsvc, + dep_transport +] + +# --------------------------------------------------------------------- +# Build the shared library +# --------------------------------------------------------------------- +ecmd_plugin_lib = shared_library( + 'ecmd-plugin', # will produce libecmd-plugin.so + ecmd_plugin_src, + include_directories: ecmd_plugin_inc, + dependencies: ecmd_plugin_deps, + install: true, + install_dir: get_option('libdir'), +) + +ecmd_plugin_dep = declare_dependency( + link_with: ecmd_plugin_lib, + include_directories: ecmd_plugin_inc, + dependencies: ecmd_plugin_deps +) + +# --------------------------------------------------------------------- +# pkg-config file generation +# --------------------------------------------------------------------- +pkgconfig = import('pkgconfig') + +pkgconfig.generate( + libraries: ecmd_plugin_lib, # <— use the variable returned above + version: meson.project_version(), + filebase: 'ecmd-plugin', + name: 'ecmd-plugin', + description: 'eCMD platform plugin shared library', + subdirs: 'ecmd', + requires: [ + 'ipl', + 'targeting', + 'targetsvc', + 'ecmd', + ], +) + diff --git a/meson.build b/meson.build index 9e563a3..30c392c 100644 --- a/meson.build +++ b/meson.build @@ -286,6 +286,8 @@ if build_phal ) endif +subdir('ecmd_plugin') + unit_files = [ 'service_files/pcie-poweroff@.service', 'service_files/xyz.openbmc_project.Control.Host.NMI.service',