log_store_lk.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /* This software/firmware and related documentation ("MediaTek Software") are
  2. * protected under relevant copyright laws. The information contained herein is
  3. * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
  4. * the prior written permission of MediaTek inc. and/or its licensors, any
  5. * reproduction, modification, use or disclosure of MediaTek Software, and
  6. * information contained herein, in whole or in part, shall be strictly
  7. * prohibited.
  8. *
  9. * MediaTek Inc. (C) 2010. All rights reserved.
  10. *
  11. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  12. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  13. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
  14. * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
  15. * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  17. * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
  18. * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
  19. * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
  20. * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
  21. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
  22. * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
  23. * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
  24. * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
  26. * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
  27. * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
  28. * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
  29. * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek
  32. * Software") have been modified by MediaTek Inc. All revisions are subject to
  33. * any receiver's applicable license agreements with MediaTek Inc.
  34. */
  35. #include <stdlib.h>
  36. #include <arch/arm/mmu.h>
  37. #include "log_store_lk.h"
  38. #ifdef MTK_GPT_SCHEME_SUPPORT
  39. #include <platform/partition.h>
  40. #else
  41. #include <mt_partition.h>
  42. #endif
  43. #include "part_interface.h"
  44. #include "block_generic_interface.h"
  45. #include <bootargs.h>
  46. #include "mt_pmic.h"
  47. #define MOD "LK_LOG_STORE"
  48. #define DEBUG_LOG
  49. #define EMMC_LOG_BUF_SIZE (0x200000)
  50. #ifdef DEBUG_LOG
  51. #define LOG_DEBUG(fmt, ...) \
  52. log_store_enable = false; \
  53. _dprintf(fmt, ##__VA_ARGS__); \
  54. log_store_enable = true
  55. #else
  56. #define LOG_DEBUG(fmt, ...)
  57. #endif
  58. /* !!!!!!! Because log store be called by print, so these function don't use print log to debug.*/
  59. enum {
  60. LOG_WRITE = 0x1, /* Log is write to buff */
  61. LOG_READ_KERNEL = 0x2, /* Log have readed by kernel */
  62. LOG_WRITE_EMMC = 0x4, /* log need save to emmc */
  63. LOG_EMPTY = 0x8, /* log is empty */
  64. LOG_FULL = 0x10, /* log is full */
  65. LOG_PL_FINISH = 0X20, /* pl boot up finish */
  66. LOG_LK_FINISH = 0X40, /* lk boot up finish */
  67. LOG_DEFAULT = LOG_WRITE_EMMC|LOG_EMPTY,
  68. } BLOG_FLAG;
  69. static int log_store_status = BUFF_NOT_READY;
  70. static struct pl_lk_log *dram_curlog_header;
  71. static struct sram_log_header *sram_header;
  72. static char *pbuff;
  73. static struct dram_buf_header *sram_dram_buff;
  74. bool log_store_enable = true;
  75. static bool lk_is_full = false;
  76. static u32 lk_renew;
  77. u64 part_end;
  78. off_t part_size;
  79. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
  80. int part_id;
  81. #endif
  82. static u32 last_boot_phase;
  83. u32 set_pmic_boot_phase(u32 boot_phase)
  84. {
  85. u32 ret;
  86. boot_phase = boot_phase & BOOT_PHASE_MASK;
  87. log_store_enable = false;
  88. ret = pmic_config_interface(0xA0E, boot_phase, BOOT_PHASE_MASK, PMIC_BOOT_PHASE_SHIFT);
  89. log_store_enable = true;
  90. return ret;
  91. }
  92. u32 get_pmic_boot_phase()
  93. {
  94. u32 value = 0, ret;
  95. ret = pmic_read_interface(0xA0E, &value, BOOT_PHASE_MASK, PMIC_LAST_BOOT_PHASE_SHIFT);
  96. if (ret == 0)
  97. last_boot_phase = value;
  98. return value;
  99. }
  100. void log_store_init(void)
  101. {
  102. unsigned int addr, size;
  103. LOG_DEBUG("%s:lk log_store_init start.\n", MOD);
  104. if (log_store_status != BUFF_NOT_READY) {
  105. LOG_DEBUG("%s:log_sotore_status is ready!\n", MOD);
  106. return;
  107. }
  108. /* SRAM buff header init */
  109. sram_log_store_addr_size(&addr, &size);
  110. sram_header = (struct sram_log_header *)addr;
  111. if (sram_header->sig != SRAM_HEADER_SIG) {
  112. LOG_DEBUG("%s:sram header 0x%x is not match: %d!\n", MOD, (unsigned int)sram_header, sram_header->sig);
  113. memset(sram_header, 0, sizeof(struct sram_log_header));
  114. sram_header->sig = SRAM_HEADER_SIG;
  115. log_store_status = BUFF_ALLOC_ERROR;
  116. return;
  117. }
  118. sram_dram_buff = &(sram_header->dram_buf);
  119. if (sram_dram_buff->sig != DRAM_HEADER_SIG || sram_dram_buff->flag == BUFF_ALLOC_ERROR) {
  120. log_store_status = BUFF_ALLOC_ERROR;
  121. LOG_DEBUG("%s:sram_dram_buff 0x%x, sig 0x%x, flag 0x%x.\n", MOD,
  122. (unsigned int)sram_dram_buff, (unsigned int)sram_dram_buff->sig, (unsigned int)sram_dram_buff->flag);
  123. return;
  124. }
  125. pbuff = (char *)sram_dram_buff->buf_addr;
  126. dram_curlog_header = (struct pl_lk_log*)&(sram_header->dram_curlog_header);
  127. #ifdef MTK_3LEVEL_PAGETABLE
  128. uint32_t start = ROUNDDOWN((uint32_t)pbuff, PAGE_SIZE);
  129. uint32_t logsize = ROUNDUP(((uint32_t)pbuff - start + LOG_STORE_SIZE), PAGE_SIZE);
  130. LOG_DEBUG("%s:dram pl/lk log buff mapping start addr = 0x%x, size = 0x%x\n", MOD, start, logsize);
  131. if (start >= DRAM_PHY_ADDR) {
  132. /*need to use header in DRAZM, we must allocate it first */
  133. log_store_enable = false;
  134. arch_mmu_map((uint64_t) start, start,
  135. MMU_MEMORY_TYPE_DEVICE | MMU_MEMORY_AP_P_RW_U_NA, logsize);
  136. log_store_enable = true;
  137. }
  138. #endif
  139. LOG_DEBUG("%s:sram buff header 0x%x,current log header 0x%x, sig 0x%x, buff_size 0x%x, pl log size 0x%x@0x%x, lk log size 0x%x@0x%x!\n",
  140. MOD, (unsigned int)sram_header, (unsigned int)dram_curlog_header, (unsigned int)dram_curlog_header->sig, (unsigned int)dram_curlog_header->buff_size,
  141. (unsigned int)dram_curlog_header->sz_pl, (unsigned int)dram_curlog_header->off_pl, (unsigned int)dram_curlog_header->sz_lk, (unsigned int)dram_curlog_header->off_lk);
  142. if (dram_curlog_header->sig != LOG_STORE_SIG || dram_curlog_header->buff_size != LOG_STORE_SIZE
  143. || dram_curlog_header->off_pl != sizeof(struct pl_lk_log)) {
  144. log_store_status = BUFF_ERROR;
  145. LOG_DEBUG("%s: BUFF_ERROR, sig 0x%x, buff_size 0x%x, off_pl 0x%x.\n", MOD,
  146. dram_curlog_header->sig, dram_curlog_header->buff_size, dram_curlog_header->off_pl);
  147. return;
  148. }
  149. if (dram_curlog_header->sz_pl + sizeof(struct pl_lk_log) >= LOG_STORE_SIZE) {
  150. LOG_DEBUG("%s: buff full pl size 0x%x.\n", MOD, dram_curlog_header->sz_pl);
  151. log_store_status = BUFF_FULL;
  152. return;
  153. }
  154. dram_curlog_header->off_lk = sizeof(struct pl_lk_log) + dram_curlog_header->sz_pl;
  155. dram_curlog_header->sz_lk = 0;
  156. dram_curlog_header->lk_flag = LOG_DEFAULT;
  157. log_store_status = BUFF_READY;
  158. LOG_DEBUG("%s: buff ready.\n", MOD);
  159. }
  160. void lk_log_store(char c)
  161. {
  162. if (log_store_enable == false)
  163. return;
  164. if (log_store_status == BUFF_NOT_READY)
  165. log_store_init();
  166. if ((log_store_status != BUFF_READY) || (log_store_status == BUFF_FULL))
  167. return;
  168. if (lk_is_full) {
  169. if (lk_renew >= dram_curlog_header->sz_lk) lk_renew = 0;
  170. *(pbuff + dram_curlog_header->off_lk + lk_renew) = c;
  171. lk_renew++;
  172. } else {
  173. *(pbuff + dram_curlog_header->off_lk + dram_curlog_header->sz_lk) = c;
  174. dram_curlog_header->sz_lk++;
  175. if ((dram_curlog_header->off_lk + dram_curlog_header->sz_lk) >= LOG_STORE_SIZE) {
  176. lk_is_full = true;
  177. lk_renew = 0;
  178. LOG_DEBUG("%s: dram lk buff full", MOD);
  179. }
  180. }
  181. sram_dram_buff->buf_point = dram_curlog_header->sz_lk + dram_curlog_header->sz_pl;
  182. }
  183. u32 current_buf_addr_get(void)
  184. {
  185. return sram_dram_buff->buf_addr;
  186. }
  187. u32 current_lk_buf_addr_get(void)
  188. {
  189. return (sram_dram_buff->buf_addr + dram_curlog_header->off_lk);
  190. }
  191. u32 current_buf_pl_lk_log_size_get(void)
  192. {
  193. return (dram_curlog_header->sz_pl + dram_curlog_header->sz_lk);
  194. }
  195. inline void expdb_write(off_t offset, u8 *buf, size_t size)
  196. {
  197. log_store_enable = false;
  198. int ret = partition_write("expdb", offset, buf, size);
  199. LOG_DEBUG("%s: %s offset %lld size %zu ret value = %zu\n", MOD, __func__, offset, size, ret);
  200. log_store_enable = true;
  201. }
  202. inline void expdb_read(part_dev_t *dev, u64 offset, uchar *buf, u64 size)
  203. {
  204. log_store_enable = false;
  205. #if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  206. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  207. dev->read(dev, offset, buf, size, part_id);
  208. #else
  209. dev->read(dev, offset, buf, size);
  210. #endif
  211. #else
  212. dev->read(dev, offset, buf, size, part_id);
  213. #endif
  214. log_store_enable = true;
  215. }
  216. /* check emmc log_store config valid, or re-write it */
  217. bool emmc_config_valid(struct log_emmc_header *log_header, u64 block_size)
  218. {
  219. bool ret = true;
  220. if (log_header->sig != LOG_EMMC_SIG) {
  221. memset(log_header, 0, sizeof(struct log_emmc_header));
  222. log_header->sig = LOG_EMMC_SIG;
  223. return false;
  224. }
  225. if(log_header->offset >= EMMC_LOG_BUF_SIZE - block_size) {
  226. log_header->offset = 0;
  227. ret = false;
  228. }
  229. return ret;
  230. }
  231. /* read expdb partition and log config header info*/
  232. part_dev_t* read_emmc_config(struct log_emmc_header *log_header)
  233. {
  234. int index = 0;
  235. part_dev_t *dev = NULL;
  236. log_store_enable = false;
  237. index = partition_get_index("expdb");
  238. dev = mt_part_get_device();
  239. if (index == -1 || dev == NULL) {
  240. LOG_DEBUG("%s: no %s partition[%d]\n", MOD, "expdb", index);
  241. return NULL;
  242. }
  243. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
  244. part_id = partition_get_region(index);
  245. #endif
  246. part_end = partition_get_offset(index) + partition_get_size(index);
  247. part_size = partition_get_size(index);
  248. log_store_enable = true;
  249. expdb_read(dev, part_end - dev->blkdev->blksz,
  250. (uchar *)log_header, sizeof(struct log_emmc_header));
  251. if (emmc_config_valid(log_header, dev->blkdev->blksz) == false) {
  252. LOG_DEBUG("%s: %s write emmc\n", MOD, __func__);
  253. expdb_write(part_size - (off_t)dev->blkdev->blksz,
  254. (u8 *)log_header, sizeof(struct log_emmc_header));
  255. }
  256. return dev;
  257. }
  258. void set_emmc_config(int type, int value)
  259. {
  260. part_dev_t *dev = NULL;
  261. struct log_emmc_header log_header;
  262. if (type > EMMC_STORE_FLAG_TYPE_NR) {
  263. LOG_DEBUG("%s: config type %d is invalid.\n", MOD, type);
  264. return;
  265. }
  266. memset(&log_header, 0, sizeof(log_header));
  267. if ((dev = read_emmc_config(&log_header)) == NULL)
  268. return;
  269. if (type == UART_LOG || type == PRINTK_RATELIMIT || type == KEDUMP_CTL) {
  270. if (value)
  271. log_header.reserve_flag[type] = FLAG_ENABLE;
  272. else
  273. log_header.reserve_flag[type] = FLAG_DISABLE;
  274. } else {
  275. log_header.reserve_flag[type] = value;
  276. }
  277. LOG_DEBUG("%s:%s config type %d value %d.\n", MOD, __func__, type, value);
  278. expdb_write(part_size - (off_t)dev->blkdev->blksz,
  279. (u8 *)&log_header, sizeof(struct log_emmc_header));
  280. }
  281. void set_boot_phase(u32 boot_step)
  282. {
  283. struct log_emmc_header log_header;
  284. part_dev_t *dev = NULL;
  285. memset(&log_header, 0, sizeof(struct log_emmc_header));
  286. if (sram_header->reserve[SRAM_PMIC_BOOT_PHASE] == FLAG_ENABLE){
  287. set_pmic_boot_phase(boot_step);
  288. if (last_boot_phase == 0)
  289. get_pmic_boot_phase();
  290. }
  291. if ((dev = read_emmc_config(&log_header)) == NULL)
  292. return;
  293. boot_step = boot_step & BOOT_PHASE_MASK;
  294. // get last boot phase
  295. if (last_boot_phase == 0)
  296. last_boot_phase = (log_header.reserve_flag[BOOT_STEP] >> LAST_BOOT_PHASE_SHIFT) & BOOT_PHASE_MASK;
  297. // clear now boot phase
  298. log_header.reserve_flag[BOOT_STEP] = log_header.reserve_flag[BOOT_STEP] & (BOOT_PHASE_MASK << LAST_BOOT_PHASE_SHIFT);
  299. // set now boot phase
  300. log_header.reserve_flag[BOOT_STEP] = log_header.reserve_flag[BOOT_STEP] | (boot_step << NOW_BOOT_PHASE_SHIFT);
  301. expdb_write(part_size - dev->blkdev->blksz, (uchar *)&log_header, sizeof(struct log_emmc_header));
  302. LOG_DEBUG("%s:get last boot flag= 0x%x\n", MOD, last_boot_phase);
  303. }
  304. u32 get_last_boot_phase(void)
  305. {
  306. return last_boot_phase;
  307. }
  308. void set_uart_log_flag(bool enable)
  309. {
  310. #ifdef UART_SWITCH_SUPPORT
  311. set_emmc_config(UART_LOG, enable);
  312. #endif
  313. }
  314. void set_printk_ratelimit(bool enable)
  315. {
  316. set_emmc_config(PRINTK_RATELIMIT, !enable);
  317. }
  318. void read_ratelimit_config()
  319. {
  320. struct log_emmc_header log_header;
  321. memset(&log_header, 0, sizeof(log_header));
  322. if (read_emmc_config(&log_header) == NULL) {
  323. dprintf(INFO, "READ PRINTK RATELIMIT CONFIG FAIL!\n");
  324. return;
  325. }
  326. if (log_header.reserve_flag[PRINTK_RATELIMIT] == FLAG_DISABLE) {
  327. dprintf(INFO, "APPEND KERNEL CMDLINE printk.devkmsg=on\n");
  328. if (cmdline_append("printk.devkmsg=on") != true) {
  329. dprintf(CRITICAL, "set printk.devkmsg=on fail!");
  330. return;
  331. }
  332. dprintf(INFO, "set printk.devkmsg=on success\n");
  333. }
  334. }
  335. int read_kedump_config()
  336. {
  337. struct log_emmc_header log_header;
  338. memset(&log_header, 0, sizeof(log_header));
  339. if (read_emmc_config(&log_header) == NULL) {
  340. dprintf(INFO, "READ KEDUMP CONFIG FAIL!\n");
  341. return 0;
  342. }
  343. if (log_header.reserve_flag[KEDUMP_CTL] == FLAG_DISABLE) {
  344. dprintf(INFO, "kedump is disabled!\n");
  345. return 0;
  346. }
  347. return 1;
  348. }
  349. /* exception power off in lk phase, sava log to emmc to analyze*/
  350. #ifndef DRAM_PHY_ADDR
  351. #define DRAM_PHY_ADDR (0x40000000)
  352. #endif
  353. void save_pllk_log(void)
  354. {
  355. u32 add;
  356. size_t size = 0, emmc_remain_buf_size = 0;
  357. part_dev_t *dev = NULL;
  358. struct log_emmc_header log_header;
  359. struct emmc_log emmc_log;
  360. LOG_DEBUG("%s: start save pllk log.\n", MOD);
  361. memset(&log_header, 0, sizeof(log_header));
  362. if ((dev = read_emmc_config(&log_header)) == NULL) {
  363. LOG_DEBUG("%s: read_emmc_config not correct.\n", MOD);
  364. return;
  365. }
  366. add = sram_dram_buff->buf_addr;
  367. size = dram_curlog_header->sz_pl + dram_curlog_header->sz_lk;
  368. if (add < DRAM_PHY_ADDR) {
  369. LOG_DEBUG("%s: sram_dram_buff->buf_addr not correct.\n", MOD);
  370. return;
  371. }
  372. if (size > EMMC_LOG_BUF_SIZE/4) {
  373. /* store size max 0.25 emm log, now is 512K */
  374. add = add + (size - EMMC_LOG_BUF_SIZE/4);
  375. size = EMMC_LOG_BUF_SIZE/4;
  376. }
  377. if (size % 4 != 0)
  378. size = size + 4 - size % 4;
  379. emmc_remain_buf_size = EMMC_LOG_BUF_SIZE - dev->blkdev->blksz - log_header.offset;
  380. emmc_log.start = log_header.offset;
  381. LOG_DEBUG("%s: part_size %lld.\n", MOD, part_size);
  382. if (size > emmc_remain_buf_size) {
  383. LOG_DEBUG("%s: size > emmc_remain_buf_size write emmc.\n", MOD);
  384. expdb_write(part_size - (off_t)EMMC_LOG_BUF_SIZE + (off_t)log_header.offset, (u8 *)add, emmc_remain_buf_size);
  385. expdb_write(part_size - (off_t)EMMC_LOG_BUF_SIZE, (u8 *)(add + emmc_remain_buf_size), size - emmc_remain_buf_size);
  386. log_header.offset = size - emmc_remain_buf_size;
  387. } else {
  388. LOG_DEBUG("%s: size <= emmc_remain_buf_size write emmc.\n", MOD);
  389. expdb_write(part_size - (off_t)EMMC_LOG_BUF_SIZE + (off_t)log_header.offset, (u8 *)add, size);
  390. log_header.offset = log_header.offset + size;
  391. }
  392. emmc_log.type = LOG_PLLK;
  393. emmc_log.end = log_header.offset;
  394. add = part_size - (off_t)dev->blkdev->blksz + (off_t)sizeof(log_header) + (off_t)log_header.reserve_flag[LOG_INDEX] * (off_t)sizeof(struct emmc_log);
  395. LOG_DEBUG("%s: config write emmc.\n", MOD);
  396. expdb_write(add, (u8 *)&emmc_log, sizeof(struct emmc_log));
  397. log_header.reserve_flag[LOG_INDEX] += 1;
  398. log_header.reserve_flag[LOG_INDEX] = log_header.reserve_flag[LOG_INDEX] % HEADER_INDEX_MAX;
  399. /* re-write offset to config*/
  400. LOG_DEBUG("%s: config re-write emmc.\n", MOD);
  401. expdb_write(part_size - (off_t)dev->blkdev->blksz,
  402. (u8 *)&log_header, sizeof(struct log_emmc_header));
  403. LOG_DEBUG("%s: save pllk log size 0x%x, offset 0x%x.\n", MOD, size, emmc_log.start);
  404. }