abc_spec_manager.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /* abc_spec_manager.c
  2. *
  3. * Abnormal Behavior Catcher's spec manager.
  4. *
  5. * Copyright 2021 Samsung Electronics
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. */
  18. #include <linux/sti/abc_spec_manager.h>
  19. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  20. #include <linux/sti/abc_kunit.h>
  21. #endif
  22. struct list_head abc_spec_list;
  23. EXPORT_SYMBOL_KUNIT(abc_spec_list);
  24. struct abc_event_group_struct abc_event_group_list[] = {
  25. {ABC_GROUP_CAMERA_MIPI_ERROR_ALL, "camera", "mipi_error_all"},
  26. };
  27. #if IS_ENABLED(CONFIG_OF)
  28. int abc_parse_dt(struct device *dev)
  29. {
  30. struct abc_platform_data *pdata = dev->platform_data;
  31. struct spec_data_type1 *spec_type1;
  32. struct device_node *np;
  33. struct device_node *type1_np;
  34. int idx, rc;
  35. np = dev->of_node;
  36. pdata->nItem = of_get_child_count(np);
  37. if (!pdata->nItem) {
  38. dev_err(dev, "There are no items");
  39. return -ENODEV;
  40. }
  41. /* spec_type_1 */
  42. type1_np = of_find_node_by_name(np, "abc_spec_type1");
  43. rc = of_property_count_strings(type1_np, ERROR_KEY);
  44. INIT_LIST_HEAD(&abc_spec_list);
  45. for (idx = 0; idx < rc; idx++) {
  46. spec_type1 = devm_kzalloc(dev, sizeof(struct spec_data_type1), GFP_KERNEL);
  47. if (!spec_type1)
  48. return -ENOMEM;
  49. if (abc_parse_dt_type1(dev, type1_np, idx, spec_type1)) {
  50. ABC_PRINT("failed parse dt spec_type1 idx : %d", idx);
  51. continue;
  52. }
  53. list_add_tail(&spec_type1->node, &abc_spec_list);
  54. }
  55. return 0;
  56. }
  57. #endif
  58. int sec_abc_get_normal_token_value(char *dst, char *src, char *token)
  59. {
  60. int token_len = strlen(token);
  61. if (strncmp(src, token, token_len) || !*(src + token_len)) {
  62. ABC_DEBUG("Invalid input : src-%s, token-%s", src, token);
  63. return -EINVAL;
  64. }
  65. strlcpy(dst, src + token_len, ABC_EVENT_STR_MAX);
  66. return 0;
  67. }
  68. EXPORT_SYMBOL_KUNIT(sec_abc_get_normal_token_value);
  69. int sec_abc_get_event_module(char *dst, char *src)
  70. {
  71. return sec_abc_get_normal_token_value(dst, src, "MODULE=");
  72. }
  73. EXPORT_SYMBOL_KUNIT(sec_abc_get_event_module);
  74. int sec_abc_get_ext_log(char *dst, char *src)
  75. {
  76. return sec_abc_get_normal_token_value(dst, src, "EXT_LOG=");
  77. }
  78. EXPORT_SYMBOL_KUNIT(sec_abc_get_ext_log);
  79. int sec_abc_get_event_name(char *dst, char *src)
  80. {
  81. int ret_info = 0, ret_warn = 0;
  82. ret_info = sec_abc_get_normal_token_value(dst, src, "INFO=");
  83. ret_warn = sec_abc_get_normal_token_value(dst, src, "WARN=");
  84. return (ret_info & ret_warn) ? -EINVAL : 0;
  85. }
  86. EXPORT_SYMBOL_KUNIT(sec_abc_get_event_name);
  87. int sec_abc_get_event_type(char *dst, char *src)
  88. {
  89. if (strncmp(src, "WARN", 4) && strncmp(src, "INFO", 4)) {
  90. ABC_PRINT("Invalid input : %s", src);
  91. return -EINVAL;
  92. }
  93. strlcpy(dst, src, 5);
  94. return 0;
  95. }
  96. EXPORT_SYMBOL_KUNIT(sec_abc_get_event_type);
  97. int sec_abc_get_count(int *dst, char *src)
  98. {
  99. if (strncmp(src, "COUNT=", 6) || !*(src + 6)) {
  100. ABC_PRINT("Invalid input : %s", src);
  101. return -EINVAL;
  102. }
  103. if (!strncmp(src + 6, "DEFAULT", 7)) {
  104. *dst = ABC_DEFAULT_COUNT;
  105. return 0;
  106. }
  107. if (kstrtoint(src + 6, 0, dst) || *dst <= 0 || *dst > ABC_EVENT_BUFFER_MAX) {
  108. ABC_PRINT("Invalid input : %s", src);
  109. return -EINVAL;
  110. }
  111. return 0;
  112. }
  113. EXPORT_SYMBOL_KUNIT(sec_abc_get_count);
  114. unsigned int sec_abc_get_ktime_ms(void)
  115. {
  116. u64 ktime;
  117. /* Calculate current kernel time */
  118. ktime = local_clock();
  119. do_div(ktime, NSEC_PER_MSEC);
  120. return (unsigned int)ktime;
  121. }
  122. EXPORT_SYMBOL_KUNIT(sec_abc_get_ktime_ms);
  123. int sec_abc_make_key_data(struct abc_key_data *key_data, char *str)
  124. {
  125. char *event_strings[ABC_UEVENT_MAX] = {0,};
  126. char temp[ABC_BUFFER_MAX];
  127. char *c, *p;
  128. int idx = 0, i;
  129. ABC_DEBUG("start : %s", str);
  130. strlcpy(temp, str, ABC_BUFFER_MAX);
  131. p = temp;
  132. while ((c = strsep(&p, "@")) != NULL && idx < ABC_UEVENT_MAX) {
  133. event_strings[idx] = c;
  134. idx++;
  135. }
  136. if (idx >= ABC_UEVENT_MAX)
  137. return -EINVAL;
  138. if (sec_abc_get_event_module(key_data->event_module, event_strings[0]))
  139. return -EINVAL;
  140. if (sec_abc_get_event_name(key_data->event_name, event_strings[1]))
  141. return -EINVAL;
  142. if (sec_abc_get_event_type(key_data->event_type, event_strings[1]))
  143. return -EINVAL;
  144. for (i = 2; i < idx; i++) {
  145. if (!strncmp(event_strings[i], "EXT_LOG=", 8)) {
  146. if (sec_abc_get_ext_log(key_data->ext_log, event_strings[i]))
  147. return -EINVAL;
  148. } else
  149. return -EINVAL;
  150. }
  151. key_data->cur_time = sec_abc_get_ktime_ms();
  152. ABC_DEBUG("Module(%s) Level(%s) Event(%s) EXT_LOG(%s) cur_time(%d)",
  153. key_data->event_module,
  154. key_data->event_type,
  155. key_data->event_name,
  156. key_data->ext_log,
  157. key_data->cur_time);
  158. return 0;
  159. }
  160. EXPORT_SYMBOL_KUNIT(sec_abc_make_key_data);
  161. struct abc_common_spec_data *sec_abc_get_matched_common_spec(char *module_name, char *error_name)
  162. {
  163. return sec_abc_get_matched_common_spec_type1(module_name, error_name);
  164. }
  165. EXPORT_SYMBOL_KUNIT(sec_abc_get_matched_common_spec);
  166. int sec_abc_get_buffer_size_from_threshold_cnt(int threshold_cnt)
  167. {
  168. int i, min_buffer_size = 16;
  169. for (i = 1; i < threshold_cnt; i *= 2)
  170. ;
  171. return min_buffer_size > i ? min_buffer_size : i;
  172. }
  173. EXPORT_SYMBOL_KUNIT(sec_abc_get_buffer_size_from_threshold_cnt);
  174. void sec_abc_enqueue_event_data(struct abc_key_data *key_data)
  175. {
  176. struct abc_common_spec_data *common_spec = NULL;
  177. common_spec = sec_abc_get_matched_common_spec(key_data->event_module, key_data->event_name);
  178. if (!common_spec || !strcmp(key_data->event_type, "INFO")) {
  179. ABC_PRINT_KUNIT("There is no matched buffer");
  180. } else {
  181. ABC_DEBUG_KUNIT("There is a matched buffer. Enqueue data");
  182. sec_abc_enqueue_event_data_type1(common_spec, key_data->cur_time);
  183. }
  184. }
  185. EXPORT_SYMBOL_KUNIT(sec_abc_enqueue_event_data);
  186. void sec_abc_reset_event_buffer(struct abc_key_data *key_data)
  187. {
  188. struct abc_common_spec_data *common_spec;
  189. struct spec_data_type1 *spec_type1;
  190. common_spec = sec_abc_get_matched_common_spec(key_data->event_module, key_data->event_name);
  191. if (!common_spec || !strcmp(key_data->event_type, "INFO")) {
  192. ABC_PRINT_KUNIT("There is no matched buffer");
  193. } else {
  194. ABC_PRINT_KUNIT("There is a matched buffer. Reset buffer");
  195. spec_type1 = container_of(common_spec, struct spec_data_type1, common_spec);
  196. sec_abc_reset_buffer_type1(spec_type1);
  197. }
  198. }
  199. EXPORT_SYMBOL_KUNIT(sec_abc_reset_event_buffer);
  200. bool sec_abc_reached_spec(struct abc_key_data *key_data)
  201. {
  202. struct abc_common_spec_data *common_spec;
  203. if (!strcmp(key_data->event_type, "INFO")) {
  204. ABC_PRINT("INFO doesn't have spec");
  205. return false;
  206. }
  207. common_spec = sec_abc_get_matched_common_spec(key_data->event_module, key_data->event_name);
  208. if (!common_spec)
  209. return true;
  210. return sec_abc_reached_spec_type1(common_spec, key_data->cur_time);
  211. }
  212. EXPORT_SYMBOL_KUNIT(sec_abc_reached_spec);
  213. int sec_abc_parse_spec_cmd(char *str, struct abc_spec_cmd *abc_spec)
  214. {
  215. int idx = 0;
  216. char temp[ABC_BUFFER_MAX];
  217. char *c, *p;
  218. char *sys_input_strings[3] = { 0, };
  219. strlcpy(temp, str, ABC_BUFFER_MAX);
  220. p = temp;
  221. while ((c = strsep(&p, "@")) != NULL && idx < ABC_SPEC_CMD_STR_MAX) {
  222. sys_input_strings[idx] = c;
  223. idx++;
  224. }
  225. if (idx != ABC_SPEC_CMD_STR_MAX)
  226. return -EINVAL;
  227. if (sec_abc_get_event_module(abc_spec->module, sys_input_strings[0]))
  228. return -EINVAL;
  229. if (sec_abc_get_event_name(abc_spec->name, sys_input_strings[1]))
  230. return -EINVAL;
  231. strlcpy(abc_spec->spec, sys_input_strings[2], ABC_EVENT_STR_MAX);
  232. return 0;
  233. }
  234. EXPORT_SYMBOL_KUNIT(sec_abc_parse_spec_cmd);
  235. int sec_abc_apply_changed_spec(char *module_name, char *error_name, char *spec)
  236. {
  237. struct abc_common_spec_data *common_spec;
  238. struct spec_data_type1 *spec_type1;
  239. int idx = 0, count = 0;
  240. ABC_PRINT("start : %s %s %s", module_name, error_name, spec);
  241. idx = sec_abc_get_idx_of_registered_event(module_name, error_name);
  242. if (idx < 0)
  243. return -EINVAL;
  244. if (!strcmp(spec, "OFF")) {
  245. abc_event_list[idx].enabled = false;
  246. return 0;
  247. }
  248. if (sec_abc_get_count(&count, spec))
  249. return -EINVAL;
  250. if (abc_event_list[idx].singular_spec) {
  251. if (count == ABC_DEFAULT_COUNT) {
  252. abc_event_list[idx].enabled = true;
  253. return 0;
  254. } else
  255. return -EINVAL;
  256. }
  257. common_spec = sec_abc_get_matched_common_spec(module_name, error_name);
  258. if (!common_spec)
  259. return -EINVAL;
  260. abc_event_list[idx].enabled = false;
  261. spec_type1 = container_of(common_spec, struct spec_data_type1, common_spec);
  262. if (count == ABC_DEFAULT_COUNT)
  263. count = spec_type1->default_count;
  264. spec_type1->threshold_cnt = count;
  265. spec_type1->buffer.size = count + 1;
  266. if (abc_alloc_memory_to_buffer_type1(spec_type1, spec_type1->buffer.size))
  267. return -ENOMEM;
  268. sec_abc_reset_buffer_type1(spec_type1);
  269. abc_event_list[idx].enabled = true;
  270. ABC_PRINT("MODULE(%s) ERROR(%s) COUNT(%d) TIME(%d) Enabled(%d)",
  271. common_spec->module_name,
  272. common_spec->error_name,
  273. spec_type1->threshold_cnt,
  274. spec_type1->threshold_time,
  275. abc_event_list[idx].enabled);
  276. return 0;
  277. }
  278. EXPORT_SYMBOL_KUNIT(sec_abc_apply_changed_spec);
  279. enum abc_event_group sec_abc_get_group(char *module, char *name)
  280. {
  281. int idx = 0;
  282. for (idx = 0; idx < ARRAY_SIZE(abc_event_group_list); idx++) {
  283. if (strcmp(module, abc_event_group_list[idx].module) == 0 &&
  284. strcmp(name, abc_event_group_list[idx].name) == 0) {
  285. return abc_event_group_list[idx].group;
  286. }
  287. }
  288. return ABC_GROUP_NONE;
  289. }
  290. EXPORT_SYMBOL_KUNIT(sec_abc_get_group);
  291. int sec_abc_apply_changed_group_spec(enum abc_event_group group, char *spec)
  292. {
  293. int idx = 0;
  294. ABC_PRINT("start : %d %s", group, spec);
  295. for (idx = 0; idx < REGISTERED_ABC_EVENT_TOTAL; idx++) {
  296. if (group == abc_event_list[idx].group) {
  297. if (sec_abc_apply_changed_spec(abc_event_list[idx].module_name,
  298. abc_event_list[idx].error_name, spec)) {
  299. return -EINVAL;
  300. }
  301. }
  302. }
  303. return 0;
  304. }
  305. EXPORT_SYMBOL_KUNIT(sec_abc_apply_changed_group_spec);
  306. void sec_abc_change_spec(const char *str)
  307. {
  308. char *cmd_string, *p;
  309. char temp[ABC_BUFFER_MAX * 5];
  310. int cnt = 0;
  311. enum abc_event_group group;
  312. struct abc_spec_cmd abc_spec;
  313. ABC_PRINT("start : %s", str);
  314. if (!strncmp(str, "reset", 5)) {
  315. sec_abc_reset_all_spec();
  316. ABC_PRINT("end : %s", str);
  317. return;
  318. }
  319. strlcpy(temp, str, ABC_BUFFER_MAX * 5);
  320. p = temp;
  321. while ((cmd_string = strsep(&p, ",\n")) != NULL && cnt < REGISTERED_ABC_EVENT_TOTAL) {
  322. cnt++;
  323. if (!cmd_string[0])
  324. continue;
  325. if (sec_abc_parse_spec_cmd(cmd_string, &abc_spec)) {
  326. ABC_PRINT_KUNIT("Invalid change cmd. Check the Input");
  327. break;
  328. }
  329. group = sec_abc_get_group(abc_spec.module, abc_spec.name);
  330. if (group == ABC_GROUP_NONE) {
  331. if (sec_abc_apply_changed_spec(abc_spec.module, abc_spec.name, abc_spec.spec)) {
  332. ABC_PRINT_KUNIT("Invalid change cmd. Check the Input");
  333. break;
  334. }
  335. } else {
  336. if (sec_abc_apply_changed_group_spec(group, abc_spec.spec)) {
  337. ABC_PRINT_KUNIT("Invalid change cmd. Check the Input");
  338. break;
  339. }
  340. }
  341. }
  342. }
  343. void sec_abc_reset_all_buffer(void)
  344. {
  345. struct spec_data_type1 *spec_type1;
  346. list_for_each_entry(spec_type1, &abc_spec_list, node) {
  347. sec_abc_reset_buffer_type1(spec_type1);
  348. }
  349. }
  350. EXPORT_SYMBOL_KUNIT(sec_abc_reset_all_buffer);
  351. void sec_abc_reset_all_spec(void)
  352. {
  353. struct spec_data_type1 *spec_type1;
  354. list_for_each_entry(spec_type1, &abc_spec_list, node) {
  355. spec_type1->threshold_cnt = spec_type1->default_count;
  356. spec_type1->buffer.size = spec_type1->threshold_cnt + 1;
  357. abc_event_list[spec_type1->common_spec.idx].enabled = spec_type1->default_enabled;
  358. sec_abc_reset_buffer_type1(spec_type1);
  359. }
  360. }
  361. EXPORT_SYMBOL_KUNIT(sec_abc_reset_all_spec);
  362. int sec_abc_read_spec(char *buf)
  363. {
  364. struct spec_data_type1 *spec_type1;
  365. int len = 0, idx;
  366. len += scnprintf(buf + len, PAGE_SIZE - len, "spec type1\n");
  367. list_for_each_entry(spec_type1, &abc_spec_list, node) {
  368. len += scnprintf(buf + len, PAGE_SIZE - len, "MODULE=%s ",
  369. spec_type1->common_spec.module_name);
  370. len += scnprintf(buf + len, PAGE_SIZE - len, "WARN=%s ",
  371. spec_type1->common_spec.error_name);
  372. len += scnprintf(buf + len, PAGE_SIZE - len, "THRESHOLD_CNT=%d ",
  373. spec_type1->threshold_cnt);
  374. len += scnprintf(buf + len, PAGE_SIZE - len, "THRESHOLD_TIME=%d ",
  375. spec_type1->threshold_time);
  376. idx = spec_type1->common_spec.idx;
  377. len += scnprintf(buf + len, PAGE_SIZE - len, "ENABLE=%s",
  378. ((abc_event_list[idx].enabled) ? "ON" : "OFF"));
  379. len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
  380. }
  381. for (idx = 0; idx < ARRAY_SIZE(abc_event_group_list); idx++) {
  382. len += scnprintf(buf + len, PAGE_SIZE - len, "MODULE=%s ",
  383. abc_event_group_list[idx].module);
  384. len += scnprintf(buf + len, PAGE_SIZE - len, "WARN=%s ",
  385. abc_event_group_list[idx].name);
  386. len += scnprintf(buf + len, PAGE_SIZE - len, "THRESHOLD_CNT=group ");
  387. len += scnprintf(buf + len, PAGE_SIZE - len, "THRESHOLD_TIME=group ");
  388. len += scnprintf(buf + len, PAGE_SIZE - len, "ENABLE=group");
  389. len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
  390. }
  391. ABC_PRINT("%d", len);
  392. return len;
  393. }
  394. void sec_abc_free_spec_buffer(void)
  395. {
  396. struct spec_data_type1 *spec_buf;
  397. list_for_each_entry(spec_buf, &abc_spec_list, node) {
  398. kfree(spec_buf->buffer.abc_element);
  399. spec_buf->buffer.abc_element = NULL;
  400. spec_buf->buffer.buffer_max = 0;
  401. }
  402. }
  403. EXPORT_SYMBOL_KUNIT(sec_abc_free_spec_buffer);
  404. MODULE_DESCRIPTION("Samsung ABC Driver's spec manager");
  405. MODULE_AUTHOR("Samsung Electronics");
  406. MODULE_LICENSE("GPL");