secdp_logger.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd.
  4. * http://www.samsung.com
  5. *
  6. * SECDP logger
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/version.h>
  13. #include <linux/kernel.h>
  14. #include <linux/errno.h>
  15. #include <linux/string.h>
  16. #include <linux/types.h>
  17. #include <linux/stat.h>
  18. #include <linux/module.h>
  19. #include <linux/proc_fs.h>
  20. #include <linux/time.h>
  21. #include <linux/uaccess.h>
  22. #include <linux/ktime.h>
  23. #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 0)
  24. #include <linux/sched/clock.h>
  25. #else
  26. #include <linux/sched.h>
  27. #endif
  28. #include <linux/secdp_logger.h>
  29. #include "secdp_unit_test.h"
  30. #define BUF_SIZE SZ_64K
  31. #define MAX_STR_LEN 160
  32. #define PROC_FILE_NAME "dplog"
  33. #define LOG_PREFIX "secdp"
  34. static char log_buf[BUF_SIZE];
  35. static unsigned int g_curpos;
  36. static int is_secdp_logger_init;
  37. static int is_buf_full;
  38. static int log_max_count = -1;
  39. static unsigned int max_mode_count;
  40. static struct mutex dplog_lock;
  41. static struct proc_dir_entry *g_entry;
  42. static void dp_logger_print_date_time(void)
  43. {
  44. char tmp[64] = {0x0, };
  45. struct tm tm;
  46. struct timespec64 ts;
  47. unsigned long sec;
  48. ktime_get_real_ts64(&ts);
  49. sec = ts.tv_sec - (sys_tz.tz_minuteswest * 60);
  50. time64_to_tm(sec, 0, &tm);
  51. snprintf(tmp, sizeof(tmp), "!@[%02d-%02d %02d:%02d:%02d.%03lu]",
  52. tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
  53. ts.tv_nsec / 1000000);
  54. secdp_logger_print("%s\n", tmp);
  55. }
  56. /* set max log count, if count is -1, no limit */
  57. void secdp_logger_set_max_count(int count)
  58. {
  59. log_max_count = count;
  60. dp_logger_print_date_time();
  61. }
  62. static void _secdp_logger_print(const char *fmt, va_list args)
  63. {
  64. int len;
  65. char buf[MAX_STR_LEN] = {0, };
  66. u64 time;
  67. unsigned long nsec;
  68. volatile unsigned int curpos;
  69. mutex_lock(&dplog_lock);
  70. time = local_clock();
  71. nsec = do_div(time, 1000000000);
  72. len = snprintf(buf, sizeof(buf), "[%5lu.%06ld] ",
  73. (unsigned long)time, nsec / 1000);
  74. len += vsnprintf(buf + len, MAX_STR_LEN - len, fmt, args);
  75. if (len > MAX_STR_LEN)
  76. len = MAX_STR_LEN;
  77. curpos = g_curpos;
  78. if (curpos + len >= BUF_SIZE) {
  79. g_curpos = curpos = 0;
  80. is_buf_full = 1;
  81. }
  82. memcpy(log_buf + curpos, buf, len);
  83. g_curpos += len;
  84. mutex_unlock(&dplog_lock);
  85. }
  86. void secdp_logger_print(const char *fmt, ...)
  87. {
  88. va_list args;
  89. if (!is_secdp_logger_init)
  90. return;
  91. if (!log_max_count)
  92. return;
  93. if (log_max_count > 0)
  94. log_max_count--;
  95. va_start(args, fmt);
  96. _secdp_logger_print(fmt, args);
  97. va_end(args);
  98. }
  99. /* set max num of modes print */
  100. void secdp_logger_set_mode_max_count(unsigned int num)
  101. {
  102. max_mode_count = num + 1;
  103. }
  104. void secdp_logger_dec_mode_count(void)
  105. {
  106. if (!is_secdp_logger_init)
  107. return;
  108. if (max_mode_count > 0)
  109. max_mode_count--;
  110. }
  111. void secdp_logger_print_mode(const char *fmt, ...)
  112. {
  113. va_list args;
  114. if (!is_secdp_logger_init)
  115. return;
  116. if (!max_mode_count)
  117. return;
  118. va_start(args, fmt);
  119. _secdp_logger_print(fmt, args);
  120. va_end(args);
  121. }
  122. void secdp_logger_hex_dump(void *buf, void *pref, size_t size)
  123. {
  124. uint8_t *ptr = buf;
  125. size_t i;
  126. char tmp[128] = {0x0, };
  127. char *ptmp = tmp;
  128. int len;
  129. if (!is_secdp_logger_init)
  130. return;
  131. if (!log_max_count)
  132. return;
  133. if (log_max_count > 0)
  134. log_max_count--;
  135. for (i = 0; i < size; i++) {
  136. len = snprintf(ptmp, 4, "%02x ", *ptr++);
  137. ptmp = ptmp + len;
  138. if (((i+1)%16) == 0) {
  139. secdp_logger_print("%s%s\n", (char *)pref, tmp);
  140. ptmp = tmp;
  141. }
  142. }
  143. if (i % 16) {
  144. len = ptmp - tmp;
  145. tmp[len] = 0x0;
  146. secdp_logger_print("%s%s\n", (char *)pref, tmp);
  147. }
  148. }
  149. static ssize_t secdp_logger_read(struct file *file, char __user *buf,
  150. size_t len, loff_t *offset)
  151. {
  152. loff_t pos = *offset;
  153. ssize_t count;
  154. size_t size;
  155. volatile unsigned int curpos = g_curpos;
  156. if (is_buf_full || BUF_SIZE <= curpos)
  157. size = BUF_SIZE;
  158. else
  159. size = (size_t)curpos;
  160. if (pos >= size)
  161. return 0;
  162. count = min(len, size);
  163. if ((pos + count) > size)
  164. count = size - pos;
  165. if (copy_to_user(buf, log_buf + pos, count))
  166. return -EFAULT;
  167. *offset += count;
  168. return count;
  169. }
  170. #if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
  171. static const struct proc_ops secdp_logger_ops = {
  172. .proc_read = secdp_logger_read,
  173. .proc_lseek = default_llseek,
  174. };
  175. #else
  176. static const struct file_operations secdp_logger_ops = {
  177. .owner = THIS_MODULE,
  178. .read = secdp_logger_read,
  179. .llseek = default_llseek,
  180. };
  181. #endif
  182. int secdp_logger_init(void)
  183. {
  184. struct proc_dir_entry *entry;
  185. if (is_secdp_logger_init)
  186. return 0;
  187. entry = proc_create(PROC_FILE_NAME, 0444, NULL, &secdp_logger_ops);
  188. if (!entry) {
  189. pr_err("%s: failed to create proc entry\n", __func__);
  190. return 0;
  191. }
  192. proc_set_size(entry, BUF_SIZE);
  193. is_secdp_logger_init = 1;
  194. g_entry = entry;
  195. mutex_init(&dplog_lock);
  196. secdp_logger_print("dp logger init ok\n");
  197. return 0;
  198. }
  199. void secdp_logger_deinit(void)
  200. {
  201. if (!g_entry)
  202. return;
  203. proc_remove(g_entry);
  204. is_secdp_logger_init = 0;
  205. g_entry = NULL;
  206. mutex_destroy(&dplog_lock);
  207. secdp_logger_print("dp logger deinit ok\n");
  208. }