sec_param.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * drivers/misc/sec_param.c
  3. *
  4. * Copyright (c) 2011 Samsung Electronics
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/device.h>
  12. #include <linux/slab.h>
  13. #include <linux/fs.h>
  14. #include <linux/uaccess.h>
  15. #include <linux/sec_param.h>
  16. #include <linux/file.h>
  17. #include <linux/syscalls.h>
  18. #define PARAM_RD 0
  19. #define PARAM_WR 1
  20. #define SEC_PARAM_FILE_NAME "/dev/block/platform/msm_sdcc.1/by-name/param" /* parameter block */
  21. #if defined(CONFIG_PARAM_SIZE_983000)
  22. #define SEC_PARAM_FILE_SIZE 0x983000 /* 9.5MB */
  23. #else
  24. #define SEC_PARAM_FILE_SIZE 0xA00000 /* 10MB */
  25. #endif
  26. #define SEC_PARAM_FILE_OFFSET (SEC_PARAM_FILE_SIZE - 0x100000)
  27. /* single global instance */
  28. struct sec_param_data *param_data;
  29. static bool param_sec_operation(void *value, int offset,
  30. int size, int direction)
  31. {
  32. /* Read from PARAM(parameter) partition */
  33. struct file *filp;
  34. mm_segment_t fs;
  35. int ret = true;
  36. int flag = (direction == PARAM_WR) ? (O_RDWR | O_SYNC) : O_RDONLY;
  37. pr_debug("%s %p %x %d %d\n", __func__, value, offset, size, direction);
  38. filp = filp_open(SEC_PARAM_FILE_NAME, flag, 0);
  39. if (IS_ERR(filp)) {
  40. pr_err("%s: filp_open failed. (%ld)\n",
  41. __func__, PTR_ERR(filp));
  42. return false;
  43. }
  44. fs = get_fs();
  45. set_fs(get_ds());
  46. ret = filp->f_op->llseek(filp, offset, SEEK_SET);
  47. if (ret < 0) {
  48. pr_err("%s FAIL LLSEEK\n", __func__);
  49. ret = false;
  50. goto param_sec_debug_out;
  51. }
  52. if (direction == PARAM_RD)
  53. ret = filp->f_op->read(filp, (char __user *)value,
  54. size, &filp->f_pos);
  55. else if (direction == PARAM_WR)
  56. ret = filp->f_op->write(filp, (char __user *)value,
  57. size, &filp->f_pos);
  58. param_sec_debug_out:
  59. set_fs(fs);
  60. filp_close(filp, NULL);
  61. return ret;
  62. }
  63. bool sec_open_param(void)
  64. {
  65. int ret = true;
  66. int offset = SEC_PARAM_FILE_OFFSET;
  67. if (param_data != NULL)
  68. return true;
  69. param_data = kmalloc(sizeof(struct sec_param_data), GFP_KERNEL);
  70. ret = param_sec_operation(param_data, offset,
  71. sizeof(struct sec_param_data), PARAM_RD);
  72. if (!ret) {
  73. kfree(param_data);
  74. param_data = NULL;
  75. pr_err("%s PARAM OPEN FAIL\n", __func__);
  76. return false;
  77. }
  78. return ret;
  79. }
  80. EXPORT_SYMBOL(sec_open_param);
  81. bool sec_get_param(enum sec_param_index index, void *value)
  82. {
  83. int ret = true;
  84. ret = sec_open_param();
  85. if (!ret)
  86. return ret;
  87. switch (index) {
  88. case param_index_debuglevel:
  89. memcpy(value, &(param_data->debuglevel), sizeof(unsigned int));
  90. break;
  91. case param_index_uartsel:
  92. memcpy(value, &(param_data->uartsel), sizeof(unsigned int));
  93. break;
  94. case param_rory_control:
  95. memcpy(value, &(param_data->rory_control),
  96. sizeof(unsigned int));
  97. break;
  98. case param_index_movinand_checksum_done:
  99. memcpy(value, &(param_data->movinand_checksum_done),
  100. sizeof(unsigned int));
  101. break;
  102. case param_index_movinand_checksum_pass:
  103. memcpy(value, &(param_data->movinand_checksum_pass),
  104. sizeof(unsigned int));
  105. break;
  106. #if defined(CONFIG_MACH_APEXQ) || defined(CONFIG_MACH_AEGIS2)
  107. case param_slideCount:
  108. memcpy(value, &(param_data->slideCount),
  109. sizeof(unsigned int));
  110. break;
  111. #endif
  112. #if defined(CONFIG_GSM_MODEM_SPRD6500) || defined(CONFIG_SGLTE_QSC_MODEM)
  113. case param_update_cp_bin:
  114. memcpy(value, &(param_data->update_cp_bin),
  115. sizeof(unsigned int));
  116. printk(KERN_INFO "param_data.update_cp_bin :[%d]!!", param_data->update_cp_bin);
  117. break;
  118. #endif
  119. #ifdef CONFIG_RTC_AUTO_PWRON_PARAM
  120. case param_index_boot_alarm_set:
  121. memcpy(value, &(param_data->boot_alarm_set), sizeof(unsigned int));
  122. break;
  123. case param_index_boot_alarm_value_l:
  124. memcpy(value, &(param_data->boot_alarm_value_l), sizeof(unsigned int));
  125. break;
  126. case param_index_boot_alarm_value_h:
  127. memcpy(value, &(param_data->boot_alarm_value_h), sizeof(unsigned int));
  128. break;
  129. #endif
  130. #ifdef CONFIG_SEC_MONITOR_BATTERY_REMOVAL
  131. case param_index_normal_poweroff:
  132. memcpy(&(param_data->normal_poweroff), value, sizeof(unsigned int));
  133. break;
  134. #endif
  135. #ifdef CONFIG_RESTART_REASON_SEC_PARAM
  136. case param_index_restart_reason:
  137. memcpy(value, &(param_data->param_restart_reason), sizeof(unsigned int));
  138. break;
  139. #endif
  140. default:
  141. return false;
  142. }
  143. return true;
  144. }
  145. EXPORT_SYMBOL(sec_get_param);
  146. bool sec_set_param(enum sec_param_index index, void *value)
  147. {
  148. int ret = true;
  149. int offset = SEC_PARAM_FILE_OFFSET;
  150. ret = sec_open_param();
  151. if (!ret)
  152. return ret;
  153. switch (index) {
  154. case param_index_debuglevel:
  155. memcpy(&(param_data->debuglevel),
  156. value, sizeof(unsigned int));
  157. break;
  158. case param_index_uartsel:
  159. memcpy(&(param_data->uartsel),
  160. value, sizeof(unsigned int));
  161. break;
  162. case param_rory_control:
  163. memcpy(&(param_data->rory_control),
  164. value, sizeof(unsigned int));
  165. break;
  166. case param_index_movinand_checksum_done:
  167. memcpy(&(param_data->movinand_checksum_done),
  168. value, sizeof(unsigned int));
  169. break;
  170. case param_index_movinand_checksum_pass:
  171. memcpy(&(param_data->movinand_checksum_pass),
  172. value, sizeof(unsigned int));
  173. break;
  174. #if defined(CONFIG_MACH_APEXQ) || defined(CONFIG_MACH_AEGIS2)
  175. case param_slideCount:
  176. memcpy(&(param_data->slideCount),
  177. value, sizeof(unsigned int));
  178. break;
  179. #endif
  180. #if defined(CONFIG_GSM_MODEM_SPRD6500) || defined(CONFIG_SGLTE_QSC_MODEM)
  181. case param_update_cp_bin:
  182. memcpy(&(param_data->update_cp_bin),
  183. value, sizeof(unsigned int));
  184. break;
  185. #endif
  186. #ifdef CONFIG_RTC_AUTO_PWRON_PARAM
  187. case param_index_boot_alarm_set:
  188. memcpy(&(param_data->boot_alarm_set), value, sizeof(unsigned int));
  189. break;
  190. case param_index_boot_alarm_value_l:
  191. memcpy(&(param_data->boot_alarm_value_l), value, sizeof(unsigned int));
  192. break;
  193. case param_index_boot_alarm_value_h:
  194. memcpy(&(param_data->boot_alarm_value_h), value, sizeof(unsigned int));
  195. break;
  196. #endif
  197. #ifdef CONFIG_SEC_MONITOR_BATTERY_REMOVAL
  198. case param_index_normal_poweroff:
  199. memcpy(&(param_data->normal_poweroff), value, sizeof(unsigned int));
  200. break;
  201. #endif
  202. #ifdef CONFIG_RESTART_REASON_SEC_PARAM
  203. case param_index_restart_reason:
  204. memcpy(&(param_data->param_restart_reason),
  205. value, sizeof(unsigned int));
  206. break;
  207. #endif
  208. default:
  209. return false;
  210. }
  211. return param_sec_operation(param_data, offset,
  212. sizeof(struct sec_param_data), PARAM_WR);
  213. }
  214. EXPORT_SYMBOL(sec_set_param);
  215. /* ##########################################################
  216. * #
  217. * # SEC PARAM Driver sysfs file
  218. * # 1. movinand_checksum_done_show
  219. * # 2. movinand_checksum_pass_show
  220. * ##########################################################
  221. * */
  222. static struct class *sec_param_class;
  223. struct device *sec_param_dev;
  224. static ssize_t movinand_checksum_done_show
  225. (struct device *dev, struct device_attribute *attr, char *buf)
  226. {
  227. int ret = 0;
  228. sec_get_param(param_index_movinand_checksum_done, &ret);
  229. if (ret == 1 || ret == 0) {
  230. pr_err("checksum is not in valuable range.\n");
  231. ret = 1;
  232. }
  233. return snprintf(buf, PAGE_SIZE, "%u\n", ret);
  234. }
  235. static DEVICE_ATTR(movinand_checksum_done,
  236. 0664, movinand_checksum_done_show, NULL);
  237. static ssize_t movinand_checksum_pass_show
  238. (struct device *dev, struct device_attribute *attr, char *buf)
  239. {
  240. int ret = 0;
  241. sec_get_param(param_index_movinand_checksum_pass, &ret);
  242. if (ret == 1 || ret == 0) {
  243. pr_err("checksum is not in valuable range.\n");
  244. ret = 1;
  245. }
  246. return snprintf(buf, PAGE_SIZE, "%u\n", ret);
  247. }
  248. static DEVICE_ATTR(movinand_checksum_pass,
  249. 0664, movinand_checksum_pass_show, NULL);
  250. int sec_param_sysfs_init(void)
  251. {
  252. int ret = 0;
  253. sec_param_class = class_create(THIS_MODULE, "sec_param");
  254. if (IS_ERR(sec_param_class)) {
  255. pr_err("Failed to create class(mdnie_class)!!\n");
  256. ret = -1;
  257. goto failed_create_class;
  258. }
  259. sec_param_dev = device_create(sec_param_class,
  260. NULL, 0, NULL, "sec_param");
  261. if (IS_ERR(sec_param_dev)) {
  262. printk(KERN_ERR "Failed to create device(sec_param_dev)!!");
  263. ret = -1;
  264. goto failed_create_dev;
  265. }
  266. if (device_create_file(sec_param_dev,
  267. &dev_attr_movinand_checksum_done) < 0) {
  268. pr_err("Failed to create device file!(%s)!\n",
  269. dev_attr_movinand_checksum_done.attr.name);
  270. ret = -1;
  271. }
  272. if (device_create_file(sec_param_dev,
  273. &dev_attr_movinand_checksum_pass) < 0) {
  274. pr_err("Failed to create device file!(%s)!\n",
  275. dev_attr_movinand_checksum_pass.attr.name);
  276. ret = -1;
  277. }
  278. failed_create_class:
  279. return ret;
  280. failed_create_dev:
  281. class_destroy(sec_param_class);
  282. return ret;
  283. }
  284. module_init(sec_param_sysfs_init);