env.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /*
  2. * Copyright (C) 2015 MediaTek Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/slab.h>
  14. #include <linux/fs.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/statfs.h>
  17. #include <asm/uaccess.h> /*set_fs get_fs mm_segment_t */
  18. #if defined(CONFIG_MTK_TLC_NAND_SUPPORT)
  19. #include "partition_define_tlc.h"
  20. #else
  21. #include "partition_define_mlc.h"
  22. #endif
  23. #include <env.h>
  24. #ifndef CONFIG_MTK_EMMC_SUPPORT
  25. #include <linux/syscalls.h>
  26. #include <mtd/mtd-abi.h>
  27. #include <linux/mtd/mtd.h>
  28. #include <linux/mutex.h>
  29. static DEFINE_MUTEX(env_first_read_mutex);
  30. static int is_first_read_write;
  31. static int misc_mtd_number = -1;
  32. #endif
  33. #define MODULE_NAME "LK_ENV"
  34. #define DATA_FREE_SIZE_TH_NAME "data_free_size_th"
  35. env_t g_env;
  36. static int env_valid;
  37. static char *env_buffer;
  38. #ifdef CONFIG_MTK_EMMC_SUPPORT
  39. static loff_t env_addr;
  40. #endif
  41. static char env_get_char(int index);
  42. static char *env_get_addr(int index);
  43. static int envmatch(char *s1, int i2);
  44. static int write_env_area(char *env_buf);
  45. static int read_env_area(char *env_buf);
  46. static void load_default_env(void);
  47. static int get_env_valid_length(void);
  48. static int ENV_Nand_Write(char *env_buf);
  49. static int ENV_Nand_Read(char *env_buf);
  50. #ifdef LIMIT_SDCARD_SIZE
  51. long long data_free_size_th = DATA_FREE_SIZE_TH_DEFAULT;
  52. #else
  53. long long data_free_size_th = 0;
  54. #endif
  55. #ifndef CONFIG_MTK_EMMC_SUPPORT
  56. /* /dev/misc is not exist until Android is started, postpone read Nand to first read/write function */
  57. static int ENV_Self_Init(char *env_buf)
  58. {
  59. int checksum = 0;
  60. int i;
  61. int ret = 0;
  62. mutex_lock(&env_first_read_mutex);
  63. if (is_first_read_write < 2) /* limit variable count to avoid overflow */
  64. is_first_read_write++;
  65. if (is_first_read_write == 1) {
  66. ret = read_env_area(env_buf);
  67. if (ret < 0) {
  68. is_first_read_write = 0;
  69. mutex_unlock(&env_first_read_mutex);
  70. return 0;
  71. }
  72. memcpy(g_env.sig, env_buffer, sizeof(g_env.sig));
  73. memcpy(g_env.sig_1, env_buffer + CFG_ENV_SIG_1_OFFSET, sizeof(g_env.sig_1));
  74. if (!strcmp(g_env.sig, ENV_SIG) && !strcmp(g_env.sig_1, ENV_SIG)) {
  75. g_env.checksum = *((int *)env_buffer + CFG_ENV_CHECKSUM_OFFSET / 4);
  76. for (i = 0; i < CFG_ENV_DATA_SIZE; i++)
  77. checksum += g_env.env_data[i];
  78. if (checksum != g_env.checksum) {
  79. pr_err("[%s]checksum mismatch s %d d %d!\n", MODULE_NAME,
  80. g_env.checksum, checksum);
  81. env_valid = 0;
  82. goto end;
  83. } else {
  84. pr_err("[%s]ENV initialize success\n", MODULE_NAME);
  85. env_valid = 1;
  86. }
  87. } else {
  88. pr_err("[%s]ENV SIG Wrong\n", MODULE_NAME);
  89. env_valid = 0;
  90. goto end;
  91. }
  92. end:
  93. if (!env_valid)
  94. memset(env_buffer, 0x00, CFG_ENV_SIZE);
  95. mutex_unlock(&env_first_read_mutex);
  96. load_default_env();
  97. } else {
  98. mutex_unlock(&env_first_read_mutex);
  99. }
  100. return 0;
  101. }
  102. #endif
  103. static ssize_t env_proc_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
  104. {
  105. int err = 0;
  106. int env_valid_length = get_env_valid_length();
  107. #ifndef CONFIG_MTK_EMMC_SUPPORT
  108. ENV_Self_Init(env_buffer);
  109. #endif
  110. if (!env_valid) {
  111. char p[32];
  112. char *page = (char *)p;
  113. int err = 0;
  114. ssize_t len = 0;
  115. pr_err("no env valid\n");
  116. page += sprintf(page, "\nno env valid\n");
  117. len = page - &p[0];
  118. if (*ppos >= len)
  119. return 0;
  120. err = copy_to_user(buf, (char *)p, len);
  121. *ppos += len;
  122. if (err)
  123. return err;
  124. return len;
  125. }
  126. if (*ppos >= env_valid_length)
  127. return 0;
  128. if ((size + *ppos) > env_valid_length)
  129. size = env_valid_length - *ppos;
  130. err = copy_to_user(buf, g_env.env_data + *ppos, size);
  131. if (err)
  132. return err;
  133. *ppos += size;
  134. return size;
  135. }
  136. static ssize_t env_proc_write(struct file *file, const char __user *buf, size_t size,
  137. loff_t *ppos)
  138. {
  139. char *buffer = NULL;
  140. int ret, i, v_index = 0;
  141. #ifndef CONFIG_MTK_EMMC_SUPPORT
  142. ENV_Self_Init(env_buffer);
  143. #endif
  144. buffer = kmalloc(size, GFP_KERNEL);
  145. if (buffer == NULL) {
  146. ret = -ENOMEM;
  147. pr_err("[env_proc_write]alloc buffer fail\n");
  148. goto fail_malloc;
  149. }
  150. memset(buffer, 0x00, size);
  151. if (copy_from_user(buffer, buf, size)) {
  152. ret = -EFAULT;
  153. goto end;
  154. }
  155. /*parse buffer into name and value */
  156. for (i = 0; i < size; i++) {
  157. if (buffer[i] == '=') {
  158. v_index = i + 1;
  159. buffer[i] = '\0';
  160. buffer[size - 1] = '\0';
  161. break;
  162. }
  163. }
  164. if (i == size) {
  165. pr_err("write fail, buffer:%s\n", buffer);
  166. ret = -EFAULT;
  167. goto end;
  168. } else {
  169. pr_err("[env_proc_write]name :%s,value:%s\n", buffer, buffer + v_index);
  170. }
  171. if (!strcmp(buffer, DATA_FREE_SIZE_TH_NAME)) {
  172. #ifdef LIMIT_SDCARD_SIZE
  173. struct kstatfs stat;
  174. long long data_free_size = 0;
  175. char *value = buffer + v_index;
  176. long long value_new = 0;
  177. int mum = 1;
  178. char value_buf[20] = { 0 };
  179. struct file *fp = NULL;
  180. char tmp_buff[20];
  181. for (i = 0; i < strlen(value); i++) {
  182. if (value[i] == 'M' || value[i] == 'm') {
  183. mum = 1024 * 1024;
  184. break;
  185. } else if (value[i] == 'K' || value[i] == 'k') {
  186. mum = 1024;
  187. break;
  188. }
  189. value_buf[i] = value[i];
  190. }
  191. kstrtoll(value_buf, &value_new);
  192. value_new *= num;
  193. fp = filp_open("/data", O_RDONLY, 0777);
  194. if (IS_ERR(fp)) {
  195. pr_err("open data fail\n");
  196. ret = -EFAULT;
  197. goto end;
  198. }
  199. vfs_statfs(&fp->f_path, &stat);
  200. data_free_size = stat.f_bfree * stat.f_bsize;
  201. filp_close(fp, NULL);
  202. if (value_new >= data_free_size) {
  203. pr_err("new value %llx more than data free size %llx, setting fail\n",
  204. value_new, data_free_size);
  205. ret = -EFAULT;
  206. goto end;
  207. }
  208. sprintf(tmp_buff, "%lld", value_new);
  209. ret = set_env(buffer, tmp_buff);
  210. #else
  211. pr_err("[env_proc_write]it don't support limit sdcard size\n");
  212. ret = -EFAULT;
  213. goto end;
  214. #endif
  215. } else {
  216. ret = set_env(buffer, buffer + v_index);
  217. }
  218. /**/ end:
  219. kfree(buffer);
  220. fail_malloc:
  221. if (ret)
  222. return ret;
  223. else
  224. return size;
  225. }
  226. static long env_proc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  227. {
  228. struct env_ioctl en_ctl;
  229. int ret = 0;
  230. char *name_buf = NULL;
  231. char *value_buf = NULL;
  232. char *value_r = NULL;
  233. #ifndef CONFIG_MTK_EMMC_SUPPORT
  234. ENV_Self_Init(env_buffer);
  235. #endif
  236. memset(&en_ctl, 0x00, sizeof(struct env_ioctl));
  237. if (copy_from_user((void *)&en_ctl, (void *)arg, sizeof(struct env_ioctl))) {
  238. ret = -EFAULT;
  239. goto fail;
  240. }
  241. if (en_ctl.name_len <= 0 || en_ctl.value_len <= 0) {
  242. ret = 0;
  243. goto end;
  244. }
  245. name_buf = kmalloc(en_ctl.name_len, GFP_KERNEL);
  246. if (!name_buf) {
  247. ret = -ENOMEM;
  248. goto fail;
  249. }
  250. value_buf = kmalloc(en_ctl.value_len, GFP_KERNEL);
  251. if (!value_buf) {
  252. ret = -ENOMEM;
  253. goto fail_malloc;
  254. }
  255. if (copy_from_user((void *)name_buf, (void *)en_ctl.name, en_ctl.name_len)) {
  256. ret = -EFAULT;
  257. goto end;
  258. }
  259. if (*name_buf == '\0') {
  260. ret = 0;
  261. goto end;
  262. }
  263. switch (cmd) {
  264. case ENV_READ:
  265. value_r = get_env(name_buf);
  266. if (value_r == NULL) {
  267. ret = 0;
  268. pr_err("[lk_env]cann't find %s\n", name_buf);
  269. goto end;
  270. }
  271. if ((strlen(value_r) + 1) > en_ctl.value_len) {
  272. ret = -EFAULT;
  273. goto end;
  274. }
  275. if (copy_to_user((void *)en_ctl.value, (void *)value_r, strlen(value_r) + 1)) {
  276. ret = -EFAULT;
  277. goto end;
  278. }
  279. break;
  280. case ENV_WRITE:
  281. if (copy_from_user((void *)value_buf, (void *)en_ctl.value, en_ctl.value_len)) {
  282. ret = -EFAULT;
  283. goto end;
  284. }
  285. ret = set_env(name_buf, value_buf);
  286. break;
  287. default:
  288. pr_err("[lk_env]wrong cmd\n");
  289. ret = -EINVAL;
  290. goto end;
  291. }
  292. end:
  293. kfree(value_buf);
  294. fail_malloc:
  295. kfree(name_buf);
  296. fail:
  297. return ret;
  298. }
  299. static const struct file_operations env_proc_fops = {
  300. .read = env_proc_read,
  301. .write = env_proc_write,
  302. .unlocked_ioctl = env_proc_ioctl,
  303. };
  304. static int get_env_valid_length(void)
  305. {
  306. int len = 0;
  307. if (env_valid) {
  308. for (len = 0; len < CFG_ENV_DATA_SIZE; len++) {
  309. if (g_env.env_data[len] == '\0' && g_env.env_data[len + 1] == '\0')
  310. break;
  311. }
  312. return len;
  313. } else {
  314. return 0;
  315. }
  316. }
  317. #ifdef CONFIG_MTK_EMMC_SUPPORT
  318. void env_init(loff_t env_part_addr)
  319. #else
  320. void env_init(loff_t env_part_addr, int mtd_number)
  321. #endif
  322. {
  323. #ifdef CONFIG_MTK_EMMC_SUPPORT
  324. int ret, i;
  325. int checksum = 0;
  326. #endif
  327. struct proc_dir_entry *env_proc;
  328. pr_err("[%s]ENV initialize env_part_addr %llx\n", MODULE_NAME, env_part_addr);
  329. #ifdef CONFIG_MTK_EMMC_SUPPORT
  330. if (!env_part_addr) {
  331. pr_err("env_part_addr is 0, env_init fail\n");
  332. return;
  333. }
  334. env_addr = env_part_addr + CFG_ENV_OFFSET;
  335. #endif
  336. env_buffer = kmalloc(CFG_ENV_SIZE, GFP_KERNEL);
  337. if (!env_buffer)
  338. return;
  339. memset(env_buffer, 0x00, CFG_ENV_SIZE);
  340. g_env.env_data = env_buffer + CFG_ENV_DATA_OFFSET;
  341. env_proc = proc_create("lk_env", 0600, NULL, &env_proc_fops);
  342. if (env_proc == NULL) {
  343. pr_err("create /proc/lk_env fail\n");
  344. return;
  345. }
  346. #ifdef CONFIG_MTK_EMMC_SUPPORT /* postpone Nand init to first read/write operation */
  347. ret = read_env_area(env_buffer);
  348. if (ret < 0) {
  349. pr_err("[%s]read_env_area fail, ret = %x\n", MODULE_NAME, ret);
  350. env_valid = 0;
  351. goto end;
  352. }
  353. memcpy(g_env.sig, env_buffer, sizeof(g_env.sig));
  354. memcpy(g_env.sig_1, env_buffer + CFG_ENV_SIG_1_OFFSET, sizeof(g_env.sig_1));
  355. if (!strcmp(g_env.sig, ENV_SIG) && !strcmp(g_env.sig_1, ENV_SIG)) {
  356. g_env.checksum = *((int *)env_buffer + CFG_ENV_CHECKSUM_OFFSET / 4);
  357. for (i = 0; i < CFG_ENV_DATA_SIZE; i++)
  358. checksum += g_env.env_data[i];
  359. if (checksum != g_env.checksum) {
  360. pr_err("[%s]checksum mismatch s %d d %d!\n", MODULE_NAME, g_env.checksum,
  361. checksum);
  362. env_valid = 0;
  363. goto end;
  364. } else {
  365. pr_err("[%s]ENV initialize success\n", MODULE_NAME);
  366. env_valid = 1;
  367. }
  368. } else {
  369. pr_err("[%s]ENV SIG Wrong\n", MODULE_NAME);
  370. env_valid = 0;
  371. goto end;
  372. }
  373. end:
  374. if (!env_valid)
  375. memset(env_buffer, 0x00, CFG_ENV_SIZE);
  376. load_default_env();
  377. #else /* not def MTK_EMMC_SUPPORT */
  378. /* spin_lock_init(&env_lock); */
  379. misc_mtd_number = mtd_number;
  380. #endif /* #ifdef MTK_EMMC_SUPPORT */
  381. }
  382. EXPORT_SYMBOL(env_init);
  383. static void load_default_env(void)
  384. {
  385. int i, ret;
  386. char *tmp;
  387. int mum = 1;
  388. char load_buf[20] = { 0 };
  389. pr_err("[%s]load default env\n", MODULE_NAME);
  390. tmp = get_env(DATA_FREE_SIZE_TH_NAME);
  391. if (tmp == NULL) {
  392. pr_err("[%s]can not find %s,set the default value\n", MODULE_NAME,
  393. DATA_FREE_SIZE_TH_NAME);
  394. sprintf(load_buf, "%d", DATA_FREE_SIZE_TH_DEFAULT);
  395. set_env(DATA_FREE_SIZE_TH_NAME, load_buf);
  396. return;
  397. }
  398. for (i = 0; i < strlen(tmp); i++) {
  399. if (tmp[i] == 'M' || tmp[i] == 'm') {
  400. mum = 1024 * 1024;
  401. break;
  402. } else if (tmp[i] == 'K' || tmp[i] == 'k') {
  403. mum = 1024;
  404. break;
  405. }
  406. load_buf[i] = tmp[i];
  407. }
  408. ret = kstrtoll(load_buf, 10, &data_free_size_th);
  409. data_free_size_th *= mum;
  410. pr_err("[%s]find %s = %llx\n", MODULE_NAME, DATA_FREE_SIZE_TH_NAME, data_free_size_th);
  411. }
  412. char *get_env(char *name)
  413. {
  414. int i, nxt;
  415. #ifndef CONFIG_MTK_EMMC_SUPPORT
  416. ENV_Self_Init(env_buffer);
  417. #endif
  418. pr_err("[%s]get_env %s\n", MODULE_NAME, name);
  419. if (!env_valid)
  420. return NULL;
  421. for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
  422. int val;
  423. for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
  424. if (nxt >= CFG_ENV_SIZE)
  425. return NULL;
  426. }
  427. val = envmatch((char *)name, i);
  428. if (val < 0)
  429. continue;
  430. return ((char *)env_get_addr(val));
  431. }
  432. return NULL;
  433. }
  434. EXPORT_SYMBOL(get_env);
  435. static char env_get_char(int index)
  436. {
  437. return *(g_env.env_data + index);
  438. }
  439. static char *env_get_addr(int index)
  440. {
  441. return (g_env.env_data + index);
  442. }
  443. static int envmatch(char *s1, int i2)
  444. {
  445. while (*s1 == env_get_char(i2++))
  446. if (*s1++ == '=')
  447. return i2;
  448. if (*s1 == '\0' && env_get_char(i2 - 1) == '=')
  449. return i2;
  450. return (-1);
  451. }
  452. int set_env(char *name, char *value)
  453. {
  454. int len, oldval;
  455. char *env, *nxt = NULL;
  456. int ret;
  457. char *env_data = g_env.env_data;
  458. #ifndef CONFIG_MTK_EMMC_SUPPORT
  459. ENV_Self_Init(env_buffer);
  460. #endif
  461. pr_err("[%s]set_env %s %s\n", MODULE_NAME, name, value);
  462. oldval = -1;
  463. if (!env_buffer)
  464. return -1;
  465. if (!env_valid) {
  466. env = env_data;
  467. goto add;
  468. }
  469. for (env = env_data; *env; env = nxt + 1) {
  470. for (nxt = env; *nxt; ++nxt)
  471. ;
  472. oldval = envmatch((char *)name, env - env_data);
  473. if (oldval >= 0)
  474. break;
  475. }
  476. if (oldval > 0) {
  477. if (*++nxt == '\0') {
  478. if (env > env_data)
  479. env--;
  480. else
  481. *env = '\0';
  482. } else {
  483. for (;;) {
  484. *env = *nxt++;
  485. if ((*env == '\0') && (*nxt == '\0'))
  486. break;
  487. ++env;
  488. }
  489. }
  490. *++env = '\0';
  491. }
  492. for (env = env_data; *env || *(env + 1); ++env)
  493. ;
  494. if (env > env_data)
  495. ++env;
  496. add:
  497. if (*value == '\0') {
  498. pr_err("[LK_ENV]clear %s\n", name);
  499. goto write_env;
  500. }
  501. /*
  502. * Overflow when:
  503. * "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data)
  504. */
  505. len = strlen(name) + 2;
  506. /* add '=' for first arg, ' ' for all others */
  507. len += strlen(value) + 1;
  508. if (len > (&env_data[CFG_ENV_DATA_SIZE] - env)) {
  509. pr_err("## Error: environment overflow, \"%s\" deleted\n", name);
  510. return -1;
  511. }
  512. while ((*env = *name++) != '\0')
  513. env++;
  514. *env = '=';
  515. while ((*++env = *value++) != '\0')
  516. ;
  517. write_env:
  518. /* end is marked with double '\0' */
  519. *++env = '\0';
  520. memset(env, 0x00, CFG_ENV_DATA_SIZE - (env - env_data));
  521. ret = write_env_area(env_buffer);
  522. if (ret < 0) {
  523. pr_err("[%s]write env fail\n", MODULE_NAME);
  524. memset(env_buffer, 0x00, CFG_ENV_SIZE);
  525. return -1;
  526. }
  527. env_valid = 1;
  528. return 0;
  529. }
  530. EXPORT_SYMBOL(set_env);
  531. static int write_env_area(char *env_buf)
  532. {
  533. int reval;
  534. int i, checksum = 0;
  535. memcpy(env_buf, ENV_SIG, sizeof(g_env.sig));
  536. memcpy(env_buf + CFG_ENV_SIG_1_OFFSET, ENV_SIG, sizeof(g_env.sig));
  537. for (i = 0; i < (CFG_ENV_DATA_SIZE); i++)
  538. checksum += *(env_buf + CFG_ENV_DATA_OFFSET + i);
  539. *((int *)env_buf + CFG_ENV_CHECKSUM_OFFSET / 4) = checksum;
  540. #ifdef CONFIG_MTK_EMMC_SUPPORT
  541. #ifdef CONFIG_MTK_NEW_COMBO_EMMC_SUPPORT
  542. reval =
  543. eMMC_rw_x((loff_t) env_addr, (u32 *) env_buf, 0, 1, CFG_ENV_SIZE, 1, EMMC_PART_USER);
  544. #else
  545. reval = eMMC_rw_x((loff_t) env_addr, (u32 *) env_buf, 0, 1, CFG_ENV_SIZE, 1, USER);
  546. #endif
  547. if (reval)
  548. return -EIO;
  549. #else
  550. reval = ENV_Nand_Write(env_buf);
  551. if (reval < 0)
  552. return -EIO;
  553. #endif
  554. return 0;
  555. }
  556. static int read_env_area(char *env_buf)
  557. {
  558. #ifdef CONFIG_MTK_EMMC_SUPPORT
  559. int reval;
  560. #ifdef CONFIG_MTK_NEW_COMBO_EMMC_SUPPORT
  561. reval =
  562. eMMC_rw_x((loff_t) env_addr, (u32 *) env_buf, 0, 0, CFG_ENV_SIZE, 1, EMMC_PART_USER);
  563. #else
  564. reval = eMMC_rw_x((loff_t) env_addr, (u32 *) env_buf, 0, 0, CFG_ENV_SIZE, 1, USER);
  565. #endif
  566. if (reval)
  567. return -EIO;
  568. #else
  569. int reval;
  570. reval = ENV_Nand_Read(env_buf);
  571. if (reval < 0)
  572. return -EIO;
  573. #endif
  574. return 0;
  575. }
  576. #ifndef CONFIG_MTK_EMMC_SUPPORT
  577. #define LOG_DEVICE "/dev/misc"
  578. int ENV_Nand_Read(char *env_buf)
  579. {
  580. int result;
  581. loff_t offset = 0;
  582. char *buffer = env_buf;
  583. size_t read;
  584. struct mtd_info *mtd;
  585. if (misc_mtd_number < 0) {
  586. pr_err("ENV_Nand_Read: wrong misc mtd number: %d!!!\n", misc_mtd_number);
  587. return -1;
  588. }
  589. mtd = get_mtd_device(NULL, misc_mtd_number);
  590. if (!mtd) {
  591. pr_err("ENV_Nand_Read: get device info fail!!!\n");
  592. put_mtd_device(mtd);
  593. return -1;
  594. }
  595. offset = mtd->erasesize;
  596. result = mtd_read(mtd, offset, CFG_ENV_SIZE, &read, buffer);
  597. if (result) {
  598. pr_err("ENV_Nand_Read: read env data fail, result = %d !!!\n", result);
  599. put_mtd_device(mtd);
  600. return -1;
  601. }
  602. put_mtd_device(mtd);
  603. return 0;
  604. }
  605. static void env_erase_callback(struct erase_info *instr)
  606. {
  607. wake_up((wait_queue_head_t *) instr->priv);
  608. }
  609. int ENV_Nand_Write(char *env_buf)
  610. {
  611. int result = 0;
  612. loff_t offset = 0;
  613. char *buffer = env_buf;
  614. wait_queue_head_t waitq;
  615. DECLARE_WAITQUEUE(wait, current);
  616. size_t write;
  617. struct mtd_info *mtd;
  618. struct erase_info erase;
  619. if (misc_mtd_number < 0) {
  620. pr_err("ENV_Nand_Read: wrong misc mtd number: %d!!!\n", misc_mtd_number);
  621. return -1;
  622. }
  623. mtd = get_mtd_device(NULL, misc_mtd_number);
  624. if (!mtd) {
  625. pr_err("ENV_Nand_Read: get device info fail!!!\n");
  626. put_mtd_device(mtd);
  627. return -1;
  628. }
  629. offset = mtd->erasesize;
  630. init_waitqueue_head(&waitq);
  631. erase.mtd = mtd;
  632. erase.addr = offset;
  633. erase.len = mtd->erasesize;
  634. erase.callback = env_erase_callback;
  635. erase.priv = (unsigned long)&waitq;
  636. result = mtd_erase(mtd, &erase);
  637. if (!result) {
  638. set_current_state(TASK_UNINTERRUPTIBLE);
  639. add_wait_queue(&waitq, &wait);
  640. if (erase.state != MTD_ERASE_DONE && erase.state != MTD_ERASE_FAILED)
  641. schedule();
  642. remove_wait_queue(&waitq, &wait);
  643. set_current_state(TASK_RUNNING);
  644. result = (erase.state == MTD_ERASE_FAILED) ? -EIO : 0;
  645. }
  646. if (result) {
  647. pr_err("ENV_Nand_Write: erase device failed");
  648. put_mtd_device(mtd);
  649. return -1;
  650. }
  651. result = mtd_write(mtd, offset, CFG_ENV_SIZE, &write, buffer);
  652. if (result) {
  653. pr_err("ENV_Nand_Write: Write env data fail, result = %d !!!\n", result);
  654. put_mtd_device(mtd);
  655. return -1;
  656. }
  657. put_mtd_device(mtd);
  658. return 0;
  659. }
  660. #endif