1 /*
2  * \file       ocsd_c_api_custom_obj.cpp
3  * \brief      OpenCSD :
4  *
5  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6  */
7 
8 /*
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /* pull in the C++ decode library */
36 #include "opencsd.h"
37 
38 #include "opencsd/c_api/opencsd_c_api.h"
39 #include "ocsd_c_api_custom_obj.h"
40 #include "common/ocsd_lib_dcd_register.h"
41 
42 /***************** C-API functions ********************************/
43 
44 /** register a custom decoder with the library */
45 OCSD_C_API ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t  *p_dcd_fact)
46 {
47     ocsd_err_t err = OCSD_OK;
48     OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister();
49 
50     // check not already registered
51     if(pRegister->isRegisteredDecoder(name))
52         return OCSD_ERR_DCDREG_NAME_REPEAT;
53 
54     // validate the factory interface structure
55     if((p_dcd_fact->createDecoder == 0) ||
56        (p_dcd_fact->destroyDecoder == 0) ||
57        (p_dcd_fact->csidFromConfig == 0)
58        )
59         return OCSD_ERR_INVALID_PARAM_VAL;
60 
61     // create a wrapper.
62     CustomDcdMngrWrapper *pWrapper = new (std::nothrow) CustomDcdMngrWrapper();
63     if(pRegister == 0)
64         return OCSD_ERR_MEM;
65 
66     p_dcd_fact->protocol_id = OcsdLibDcdRegister::getNextCustomProtocolID();
67     if(p_dcd_fact->protocol_id < OCSD_PROTOCOL_END)
68     {
69         // fill out the wrapper and register it
70         pWrapper->setAPIDcdFact(p_dcd_fact);
71         err = pRegister->registerDecoderTypeByName(name,pWrapper);
72         if(err != OCSD_OK)
73             OcsdLibDcdRegister::releaseLastCustomProtocolID();
74     }
75     else
76         err =  OCSD_ERR_DCDREG_TOOMANY; // too many decoders
77 
78     if(err != OCSD_OK)
79         delete pWrapper;
80 
81     return err;
82 }
83 
84 OCSD_C_API ocsd_err_t ocsd_deregister_decoders()
85 {
86     // destroys all builtin and custom decoders & library registration object.
87     OcsdLibDcdRegister::deregisterAllDecoders();
88     return OCSD_OK;
89 }
90 
91 OCSD_C_API ocsd_err_t ocsd_cust_protocol_to_str(const ocsd_trace_protocol_t pkt_protocol, const void *trc_pkt, char *buffer, const int buflen)
92 {
93     OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister();
94     IDecoderMngr *p_mngr = 0;
95     if (OCSD_PROTOCOL_IS_CUSTOM(pkt_protocol) && (pRegister->getDecoderMngrByType(pkt_protocol, &p_mngr) == OCSD_OK))
96     {
97         CustomDcdMngrWrapper *pWrapper = static_cast<CustomDcdMngrWrapper *>(p_mngr);
98         pWrapper->pktToString(trc_pkt, buffer, buflen);
99         return OCSD_OK;
100     }
101     return OCSD_ERR_NO_PROTOCOL;
102 }
103 
104 /***************** Decode Manager Wrapper *****************************/
105 
106 CustomDcdMngrWrapper::CustomDcdMngrWrapper()
107 {
108     m_dcd_fact.protocol_id = OCSD_PROTOCOL_END;
109 }
110 
111 
112     // set the C-API decoder factory interface
113 void CustomDcdMngrWrapper::setAPIDcdFact(ocsd_extern_dcd_fact_t *p_dcd_fact)
114 {
115     m_dcd_fact = *p_dcd_fact;
116 }
117 
118 // create and destroy decoders
119 ocsd_err_t CustomDcdMngrWrapper::createDecoder(const int create_flags, const int instID, const CSConfig *p_config,  TraceComponent **ppComponent)
120 {
121     ocsd_err_t err = OCSD_OK;
122     if(m_dcd_fact.protocol_id == OCSD_PROTOCOL_END)
123         return OCSD_ERR_NOT_INIT;
124 
125     CustomDecoderWrapper *pComp = new (std::nothrow) CustomDecoderWrapper();
126     *ppComponent = pComp;
127     if (pComp == 0)
128         return OCSD_ERR_MEM;
129 
130     ocsd_extern_dcd_cb_fns lib_callbacks;
131     CustomDecoderWrapper::SetCallbacks(lib_callbacks);
132     lib_callbacks.lib_context = pComp;
133     lib_callbacks.packetCBFlags = 0;
134 
135     ocsd_extern_dcd_inst_t *pDecodeInst = pComp->getDecoderInstInfo();
136 
137     err = m_dcd_fact.createDecoder( create_flags,
138         ((CustomConfigWrapper *)p_config)->getConfig(),
139         &lib_callbacks,
140         pDecodeInst);
141 
142     if (err == OCSD_OK)
143     {
144         // validate the decoder
145         if ((pDecodeInst->fn_data_in == 0) ||
146             (pDecodeInst->fn_update_pkt_mon == 0) ||
147             (pDecodeInst->cs_id == 0) ||
148             (pDecodeInst->decoder_handle == 0) ||
149             (pDecodeInst->p_decoder_name == 0)
150             )
151         {
152             err = OCSD_ERR_INVALID_PARAM_VAL;
153         }
154     }
155 
156     if (err != OCSD_OK)
157         delete pComp;
158     else
159         pComp->updateNameFromDcdInst();
160     return err;
161 }
162 
163 ocsd_err_t CustomDcdMngrWrapper::destroyDecoder(TraceComponent *pComponent)
164 {
165     CustomDecoderWrapper *pCustWrap = dynamic_cast<CustomDecoderWrapper *>(pComponent);
166     if(m_dcd_fact.protocol_id != OCSD_PROTOCOL_END)
167         m_dcd_fact.destroyDecoder(pCustWrap->getDecoderInstInfo()->decoder_handle);
168     delete pCustWrap;
169     return OCSD_OK;
170 }
171 
172 const ocsd_trace_protocol_t CustomDcdMngrWrapper::getProtocolType() const
173 {
174     return m_dcd_fact.protocol_id;
175 }
176 
177 ocsd_err_t CustomDcdMngrWrapper::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct)
178 {
179     ocsd_err_t err = OCSD_OK;
180     CustomConfigWrapper *pConfig = new (std::nothrow) CustomConfigWrapper(pDataStruct);
181     if(!pConfig)
182         return OCSD_ERR_MEM;
183 
184     if(m_dcd_fact.csidFromConfig == 0)
185         return OCSD_ERR_NOT_INIT;
186 
187     unsigned char csid;
188     err = m_dcd_fact.csidFromConfig(pDataStruct,&csid);
189     if(err == OCSD_OK)
190     {
191         pConfig->setCSID(csid);
192         *pConfigBase = pConfig;
193     }
194     return err;
195 }
196 
197 ocsd_err_t CustomDcdMngrWrapper::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn)
198 {
199     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
200     if(pDecoder == 0)
201         return OCSD_ERR_INVALID_PARAM_TYPE;
202 
203     *ppDataIn = pDecoder;
204     return OCSD_OK;
205 }
206 
207 // component connections
208 // all
209 ocsd_err_t CustomDcdMngrWrapper::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog)
210 {
211     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
212     if (pDecoder == 0)
213         return OCSD_ERR_INVALID_PARAM_TYPE;
214     pDecoder->getErrorLogAttachPt()->replace_first(pIErrorLog);
215     return OCSD_OK;
216 }
217 
218 // full decoder
219 ocsd_err_t CustomDcdMngrWrapper::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec)
220 {
221     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
222     if(pDecoder == 0)
223         return OCSD_ERR_INVALID_PARAM_TYPE;
224     pDecoder->attachInstrDecI(pIInstrDec);
225     return OCSD_OK;
226 }
227 
228 ocsd_err_t CustomDcdMngrWrapper::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor)
229 {
230     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
231     if(pDecoder == 0)
232         return OCSD_ERR_INVALID_PARAM_TYPE;
233     pDecoder->attachMemAccI(pMemAccessor);
234     return OCSD_OK;
235 }
236 
237 ocsd_err_t CustomDcdMngrWrapper::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink)
238 {
239     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
240     if(pDecoder == 0)
241         return OCSD_ERR_INVALID_PARAM_TYPE;
242     pDecoder->attachGenElemI(pOutSink);
243     return OCSD_OK;
244 }
245 
246 // pkt processor only
247 ocsd_err_t CustomDcdMngrWrapper::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon)
248 {
249     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
250     if(pDecoder == 0)
251         return OCSD_ERR_INVALID_PARAM_TYPE;
252     IPktRawDataMon<void> *pIF = 0;
253     if (pPktRawDataMon)
254     {
255         pIF = dynamic_cast<IPktRawDataMon<void> *>(pPktRawDataMon);
256         if (!pIF)
257             return OCSD_ERR_INVALID_PARAM_TYPE;
258     }
259     pDecoder->attachPtkMonI(pIF);
260     return OCSD_OK;
261 }
262 
263 ocsd_err_t CustomDcdMngrWrapper::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer)
264 {
265     // indexers for external custom will also be external and custom.
266     return OCSD_ERR_DCD_INTERFACE_UNUSED;
267 }
268 
269 ocsd_err_t CustomDcdMngrWrapper::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink)
270 {
271     CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
272     if(pDecoder == 0)
273         return OCSD_ERR_INVALID_PARAM_TYPE;
274     IPktDataIn<void> *pIF = 0;
275     if (pPktDataInSink)
276     {
277         pIF = dynamic_cast<IPktDataIn<void> *>(pPktDataInSink);
278         if(!pIF)
279             return OCSD_ERR_INVALID_PARAM_TYPE;
280     }
281     pDecoder->attachPtkSinkI(pIF);
282     return OCSD_OK;
283 }
284 
285 void CustomDcdMngrWrapper::pktToString(const void *pkt, char *pStrBuffer, int bufSize)
286 {
287     if (m_dcd_fact.pktToString)
288         m_dcd_fact.pktToString(pkt, pStrBuffer, bufSize);
289     else
290         snprintf(pStrBuffer, bufSize, "CUSTOM_PKT[]: print unsupported; protocol(%d).",m_dcd_fact.protocol_id);
291 }
292 
293 /************************** Decoder instance wrapper **************************************/
294 
295 /* callback functions */
296 ocsd_datapath_resp_t GenElemOpCB( const void *lib_context,
297                                                 const ocsd_trc_index_t index_sop,
298                                                 const uint8_t trc_chan_id,
299                                                 const ocsd_generic_trace_elem *elem)
300 {
301     if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn)
302         return ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn->TraceElemIn(index_sop,trc_chan_id,*(OcsdTraceElement *)elem);
303     return OCSD_RESP_FATAL_NOT_INIT;
304 }
305 
306 void LogErrorCB(const void *lib_context, const ocsd_err_severity_t filter_level, const ocsd_err_t code, const ocsd_trc_index_t idx, const uint8_t chan_id, const char *pMsg)
307 {
308     if (lib_context)
309     {
310         if(pMsg)
311             ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id, std::string(pMsg)));
312         else
313             ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id));
314     }
315 }
316 
317 void LogMsgCB(const void *lib_context, const ocsd_err_severity_t filter_level, const char *msg)
318 {
319     if (lib_context && msg)
320         ((CustomDecoderWrapper *)lib_context)->LogMessage(filter_level, std::string(msg));
321 }
322 
323 ocsd_err_t DecodeArmInstCB(const void *lib_context, ocsd_instr_info *instr_info)
324 {
325     if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec)
326         return ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec->DecodeInstruction(instr_info);
327     return OCSD_ERR_ATTACH_INVALID_PARAM;
328 }
329 
330 ocsd_err_t MemAccessCB(const void *lib_context,
331     const ocsd_vaddr_t address,
332     const uint8_t cs_trace_id,
333     const ocsd_mem_space_acc_t mem_space,
334     uint32_t *num_bytes,
335     uint8_t *p_buffer)
336 {
337     if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor)
338         return ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor->ReadTargetMemory(address, cs_trace_id, mem_space, num_bytes, p_buffer);
339     return OCSD_ERR_INVALID_PARAM_VAL;
340 }
341 
342 void PktMonCB(const void *lib_context,
343     const ocsd_datapath_op_t op,
344     const ocsd_trc_index_t index_sop,
345     const void *pkt,
346     const uint32_t size,
347     const uint8_t *p_data)
348 {
349     if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktMon)
350         ((CustomDecoderWrapper *)lib_context)->m_pPktMon->RawPacketDataMon(op, index_sop, pkt, size, p_data);
351 }
352 
353 ocsd_datapath_resp_t PktDataSinkCB(const void *lib_context,
354     const ocsd_datapath_op_t op,
355     const ocsd_trc_index_t index_sop,
356     const void *pkt)
357 {
358     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
359     if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktIn)
360         resp = ((CustomDecoderWrapper *)lib_context)->m_pPktIn->PacketDataIn(op, index_sop, pkt);
361     return resp;
362 }
363 
364 
365 
366 /** decoder instance object */
367 CustomDecoderWrapper::CustomDecoderWrapper() : TraceComponent("extern_wrapper"),
368     m_pGenElemIn(0),
369     m_pIInstrDec(0),
370     m_pMemAccessor(0),
371     m_pPktMon(0),
372     m_pPktIn(0)
373 {
374 }
375 
376 CustomDecoderWrapper::~CustomDecoderWrapper()
377 {
378 }
379 
380 ocsd_datapath_resp_t CustomDecoderWrapper::TraceDataIn( const ocsd_datapath_op_t op,
381                                               const ocsd_trc_index_t index,
382                                               const uint32_t dataBlockSize,
383                                               const uint8_t *pDataBlock,
384                                               uint32_t *numBytesProcessed)
385 {
386     if(m_decoder_inst.fn_data_in)
387         return m_decoder_inst.fn_data_in( m_decoder_inst.decoder_handle,
388                                           op,
389                                           index,
390                                           dataBlockSize,
391                                           pDataBlock,
392                                           numBytesProcessed);
393     return OCSD_RESP_FATAL_NOT_INIT;
394 }
395 
396 void CustomDecoderWrapper::attachPtkMonI(IPktRawDataMon<void>* pIF)
397 {
398     m_pPktMon = pIF;
399     int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
400     m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
401 }
402 
403 void CustomDecoderWrapper::attachPtkSinkI(IPktDataIn<void>* pIF)
404 {
405     m_pPktIn = pIF;
406     int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
407     m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
408 }
409 
410 void CustomDecoderWrapper::updateNameFromDcdInst()
411 {
412     // create a unique component name from the decoder name + cs-id.
413     std::string name_combined = m_decoder_inst.p_decoder_name;
414     char num_buffer[32];
415     sprintf(num_buffer, "_%04d", m_decoder_inst.cs_id);
416     name_combined += (std::string)num_buffer;
417     setComponentName(name_combined);
418 }
419 
420 void CustomDecoderWrapper::SetCallbacks(ocsd_extern_dcd_cb_fns & callbacks)
421 {
422     callbacks.fn_arm_instruction_decode = DecodeArmInstCB;
423     callbacks.fn_gen_elem_out = GenElemOpCB;
424     callbacks.fn_log_error = LogErrorCB;
425     callbacks.fn_log_msg = LogMsgCB;
426     callbacks.fn_memory_access = MemAccessCB;
427     callbacks.fn_packet_data_sink = PktDataSinkCB;
428     callbacks.fn_packet_mon = PktMonCB;
429 }
430 
431 /* End of File ocsd_c_api_custom_obj.cpp */
432