battery_logger.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * battery_logger.c
  3. * Samsung Mobile Battery Driver
  4. *
  5. * Copyright (C) 2021 Samsung Electronics
  6. *
  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/types.h>
  14. #include <linux/errno.h>
  15. #include <linux/sched/clock.h>
  16. #include <linux/kernel.h>
  17. #include <linux/security.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/proc_fs.h>
  20. #include <linux/seq_file.h>
  21. #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
  22. #include <stdarg.h>
  23. #else
  24. #include <linux/stdarg.h>
  25. #endif
  26. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
  27. #include <linux/time64.h>
  28. #define SEC_TIMESPEC timespec64
  29. #define SEC_GETTIMEOFDAY ktime_get_real_ts64
  30. #define SEC_RTC_TIME_TO_TM rtc_time64_to_tm
  31. #else
  32. #include <linux/time.h>
  33. #define SEC_TIMESPEC timeval
  34. #define SEC_GETTIMEOFDAY do_gettimeofday
  35. #define SEC_RTC_TIME_TO_TM rtc_time_to_tm
  36. #endif
  37. #include <linux/rtc.h>
  38. #include "sec_battery.h"
  39. #include "battery_logger.h"
  40. #define BATTERYLOG_MAX_STRING_SIZE (1 << 7) /* 128 */
  41. #define BATTERYLOG_MAX_BUF_SIZE 200 /* 200 */
  42. struct batterylog_buf {
  43. unsigned long log_index;
  44. char batstr_buffer[BATTERYLOG_MAX_BUF_SIZE*BATTERYLOG_MAX_STRING_SIZE];
  45. };
  46. struct batterylog_root_str {
  47. struct batterylog_buf *batterylog_buffer;
  48. struct mutex battery_log_lock;
  49. int init;
  50. };
  51. static struct batterylog_root_str batterylog_root;
  52. #if !defined(CONFIG_UML)
  53. static void logger_get_time_of_the_day_in_hr_min_sec(char *tbuf, int len)
  54. {
  55. struct SEC_TIMESPEC tv;
  56. struct rtc_time tm;
  57. unsigned long local_time;
  58. /* Format the Log time R#: [hr:min:sec.microsec] */
  59. SEC_GETTIMEOFDAY(&tv);
  60. /* Convert rtc to local time */
  61. local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
  62. SEC_RTC_TIME_TO_TM(local_time, &tm);
  63. scnprintf(tbuf, len,
  64. "[%d-%02d-%02d %02d:%02d:%02d]",
  65. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  66. tm.tm_hour, tm.tm_min, tm.tm_sec);
  67. }
  68. #endif
  69. static int batterylog_proc_show(struct seq_file *m, void *v)
  70. {
  71. struct batterylog_buf *temp_buffer;
  72. temp_buffer = batterylog_root.batterylog_buffer;
  73. if (!temp_buffer)
  74. goto err;
  75. pr_info("%s\n", __func__);
  76. if (sec_bat_get_lpmode()) {
  77. seq_printf(m,
  78. "*****Battery LPM Logs*****\n");
  79. } else {
  80. seq_printf(m,
  81. "*****Battery Power On Logs*****\n");
  82. }
  83. seq_printf(m, "%s", temp_buffer->batstr_buffer);
  84. err:
  85. return 0;
  86. }
  87. #if defined(CONFIG_UML)
  88. void store_battery_log(const char *fmt, ...) {}
  89. #else
  90. void store_battery_log(const char *fmt, ...)
  91. {
  92. unsigned long long tnsec;
  93. unsigned long rem_nsec;
  94. unsigned long target_index;
  95. char *bat_buf;
  96. int string_len, rem_buf;
  97. char temp[BATTERYLOG_MAX_STRING_SIZE];
  98. va_list ap;
  99. if (!batterylog_root.init)
  100. return;
  101. mutex_lock(&batterylog_root.battery_log_lock);
  102. tnsec = local_clock();
  103. rem_nsec = do_div(tnsec, 1000000000);
  104. logger_get_time_of_the_day_in_hr_min_sec(temp, BATTERYLOG_MAX_STRING_SIZE);
  105. string_len = strlen(temp);
  106. /* To give rem buf size to vsnprint so that it can add '\0' at the end of string. */
  107. rem_buf = BATTERYLOG_MAX_STRING_SIZE - string_len;
  108. pr_debug("%s string len after storing time = %d, time = %llu , rem temp buf = %d\n",
  109. __func__, string_len, tnsec, rem_buf);
  110. va_start(ap, fmt);
  111. /* store upto buff size, data after buff is ignored, hence can't have illegal buff overflow access */
  112. vsnprintf(temp+string_len, sizeof(char)*rem_buf, fmt, ap);
  113. va_end(ap);
  114. target_index = batterylog_root.batterylog_buffer->log_index;
  115. /* Remaining size of actual storage buffer. -2 is used as last 2 indexs are fixed for '\n' and '\0' */
  116. rem_buf = BATTERYLOG_MAX_BUF_SIZE*BATTERYLOG_MAX_STRING_SIZE - target_index-2;
  117. string_len = strlen(temp);
  118. /* If remaining buff size is less than the string then overwrite from start */
  119. if (rem_buf < string_len)
  120. target_index = 0;
  121. bat_buf = &batterylog_root.batterylog_buffer->batstr_buffer[target_index];
  122. if (bat_buf == NULL) {
  123. pr_err("%s target_buffer error\n", __func__);
  124. goto err;
  125. }
  126. strncpy(bat_buf, temp, string_len);
  127. /* '\n' Diffrentiator between two stored strings */
  128. bat_buf[string_len] = '\n';
  129. target_index = target_index+string_len+1;
  130. batterylog_root.batterylog_buffer->log_index = target_index;
  131. err:
  132. mutex_unlock(&batterylog_root.battery_log_lock);
  133. }
  134. #endif
  135. EXPORT_SYMBOL(store_battery_log);
  136. static int batterylog_proc_open(struct inode *inode, struct file *file)
  137. {
  138. return single_open(file, batterylog_proc_show, NULL);
  139. }
  140. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
  141. static const struct proc_ops batterylog_proc_fops = {
  142. .proc_open = batterylog_proc_open,
  143. .proc_read = seq_read,
  144. .proc_lseek = seq_lseek,
  145. .proc_release = single_release,
  146. };
  147. #else
  148. static const struct file_operations batterylog_proc_fops = {
  149. .open = batterylog_proc_open,
  150. .read = seq_read,
  151. .llseek = seq_lseek,
  152. .release = single_release,
  153. };
  154. #endif
  155. int register_batterylog_proc(void)
  156. {
  157. int ret = 0;
  158. if (batterylog_root.init) {
  159. pr_err("%s already registered\n", __func__);
  160. goto err;
  161. }
  162. pr_info("%s\n", __func__);
  163. mutex_init(&batterylog_root.battery_log_lock);
  164. batterylog_root.batterylog_buffer
  165. = kzalloc(sizeof(struct batterylog_buf), GFP_KERNEL);
  166. if (!batterylog_root.batterylog_buffer) {
  167. ret = -ENOMEM;
  168. goto err;
  169. }
  170. pr_info("%s size=%zu\n", __func__, sizeof(struct batterylog_buf));
  171. proc_create("batterylog", 0, NULL, &batterylog_proc_fops);
  172. batterylog_root.init = 1;
  173. err:
  174. return ret;
  175. }
  176. EXPORT_SYMBOL(register_batterylog_proc);
  177. void unregister_batterylog_proc(void)
  178. {
  179. pr_info("%s\n", __func__);
  180. mutex_destroy(&batterylog_root.battery_log_lock);
  181. kfree(batterylog_root.batterylog_buffer);
  182. batterylog_root.batterylog_buffer = NULL;
  183. remove_proc_entry("batterylog", NULL);
  184. batterylog_root.init = 0;
  185. }
  186. EXPORT_SYMBOL(unregister_batterylog_proc);