/**
 * \file swd_log.h
 * \brief keymaster log abstraction for keymaster service
 * \author i.matushchak@samsung.com
 * \version 0.1
 * \date Created 2015/08/13
 * \par In Samsung R&D Institute Ukraine (SRK) under a contract between
 * \par LLC Samsung Electronics Ukraine Company (Kiev, Ukraine) and
 * \par Samsung Electronics Co, Ltd (Seoul, Republic of Korea)
 * \par Copyright: (c) Samsung Electronics Co, Ltd 2015. All rights reserved.
 **/

#ifndef SWD_LOG_H
#define SWD_LOG_H

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#ifdef EMU_X86
#define DEBUG_FNAME // add file name to LOGx
#endif // ifdef EMU_X86
#define IMPORT_DEBUG_LEVEL 0 // added to pass cts performance test

#ifdef EMU_X86
#include <stdio.h>
#define tz_printf(fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)

#elif USE_MOBICORE
#include <tlStd.h>
#define tz_printf(fmt, ...) tlApiLogPrintf(fmt "\n", ## __VA_ARGS__)

#elif USE_QUALCOMM
#include <qsee_log.h>
#define tz_printf(fmt, ...) qsee_log(QSEE_LOG_MSG_ERROR, fmt, ## __VA_ARGS__)

#elif USE_TEEGRIS
#define tz_printf(fmt, ...) printf(fmt "\n", ## __VA_ARGS__)
#endif /* USE_TEEGRIS */

#ifdef DEBUG_FNAME
#define FNAME (1 + strrchr(__FILE__, '/'))
#else // ifdef DEBUG_FNAME
#define FNAME NULL
#endif // ifdef DEBUG_FNAME

#define TZ_LOG(lvl, fmt, ...)                                                     \
    do {                                                                          \
        extern char _swd_str[256];                                                \
        snprintf(_swd_str, sizeof(_swd_str), "%s" fmt,                            \
                 km_get_log_fmt(lvl, FNAME, __func__, __LINE__), ## __VA_ARGS__); \
        _swd_str[sizeof(_swd_str) - 1] = '\0';                                    \
        tz_printf("%s", _swd_str);                                                \
        swd_push_log(_swd_str);                                                   \
    } while (0)

#if defined(EMU_X86) && !defined(TL_DEBUG)
#define LOGW(fmt, ...) no_printf(NULL, ## __VA_ARGS__)
#define LOGE(fmt, ...) no_printf(NULL, ## __VA_ARGS__)
#else /* EMU_X86 */
#define LOGW(fmt, ...) TZ_LOG(2, fmt, ## __VA_ARGS__)
#define LOGE(fmt, ...) TZ_LOG(3, fmt, ## __VA_ARGS__)
#endif /* EMU_X86 */

#ifdef TL_DEBUG
#define LOGD(fmt, ...) TZ_LOG(1, fmt, ## __VA_ARGS__)
#define LOGI(fmt, ...) TZ_LOG(0, fmt, ## __VA_ARGS__)
#define DUMP(b, l) km_dump(b, l)
#else /* TL_DEBUG */
#define LOGD(fmt, ...) no_printf(NULL, ## __VA_ARGS__)
#define LOGI(fmt, ...) TZ_LOG(0, fmt, ## __VA_ARGS__)
#define DUMP(b, l) no_printf(NULL, b, l)
#endif /* TL_DEBUG */

#define KM_PRIx64_FMT "0x%08x%08x"
#define PRI_MASK (~0ull >> (sizeof(unsigned) * 8))
#define KM_PRIx64_PRN(a) (unsigned)((a& ~PRI_MASK) >> sizeof(unsigned) * 8), (unsigned)(a& PRI_MASK)

#define KM_DUMP_BLOB(b) DUMP((b)->data, (b)->len)
#define KM_DUMP_ASN1STR(s) DUMP((s)->data, (s)->length)

#ifdef DEBUG
#define GET_POINTER(p) (p)
#else
#define GET_POINTER(p) ((p == NULL)?((void *)0):((void *)0x10000001))
#endif

char *km_get_log_fmt(const int lvl, const char *file, const char *func, const int l);

void no_printf(const char *fmt, ...);
void swd_push_log(const char *str);
void swd_logs_free(void);
void *swd_get_logs(void);
void km_dump_hex(const char *title, const void *_data, int length);

#ifdef TL_DEBUG
void km_dump(const void *b, int len);
#endif /* TL_DEBUG */

#endif // TZ_LOG_H
