log_store_lk.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. #define MOD "LK_LOG_STORE"
  47. #define DEBUG_LOG
  48. #define EMMC_LOG_BUF_SIZE (0x200000)
  49. #ifdef DEBUG_LOG
  50. #define LOG_DEBUG(fmt, ...) \
  51. log_store_enable = false; \
  52. _dprintf(fmt, ##__VA_ARGS__); \
  53. log_store_enable = true
  54. #else
  55. #define LOG_DEBUG(fmt, ...)
  56. #endif
  57. /* !!!!!!! Because log store be called by print, so these function don't use print log to debug.*/
  58. enum {
  59. LOG_WRITE = 0x1, /* Log is write to buff */
  60. LOG_READ_KERNEL = 0x2, /* Log have readed by kernel */
  61. LOG_WRITE_EMMC = 0x4, /* log need save to emmc */
  62. LOG_EMPTY = 0x8, /* log is empty */
  63. LOG_FULL = 0x10, /* log is full */
  64. LOG_PL_FINISH = 0X20, /* pl boot up finish */
  65. LOG_LK_FINISH = 0X40, /* lk boot up finish */
  66. LOG_DEFAULT = LOG_WRITE_EMMC|LOG_EMPTY,
  67. } BLOG_FLAG;
  68. static int log_store_status = BUFF_NOT_READY;
  69. static struct pl_lk_log *dram_curlog_header;
  70. static char *pbuff;
  71. static struct dram_buf_header *sram_dram_buff;
  72. bool log_store_enable = true;
  73. static bool lk_is_full = false;
  74. static u32 lk_renew;
  75. u64 part_end;
  76. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
  77. int part_id;
  78. #endif
  79. void log_store_init(void)
  80. {
  81. struct sram_log_header *sram_header = NULL;
  82. unsigned int addr, size;
  83. LOG_DEBUG("%s:lk log_store_init start.\n", MOD);
  84. if (log_store_status != BUFF_NOT_READY) {
  85. LOG_DEBUG("%s:log_sotore_status is ready!\n", MOD);
  86. return;
  87. }
  88. /* SRAM buff header init */
  89. sram_log_store_addr_size(&addr, &size);
  90. sram_header = (struct sram_log_header *)addr;
  91. if (sram_header->sig != SRAM_HEADER_SIG) {
  92. LOG_DEBUG("%s:sram header 0x%x is not match: %d!\n", MOD, (unsigned int)sram_header, sram_header->sig);
  93. memset(sram_header, 0, sizeof(struct sram_log_header));
  94. sram_header->sig = SRAM_HEADER_SIG;
  95. log_store_status = BUFF_ALLOC_ERROR;
  96. return;
  97. }
  98. sram_dram_buff = &(sram_header->dram_buf);
  99. if (sram_dram_buff->sig != DRAM_HEADER_SIG || sram_dram_buff->flag == BUFF_ALLOC_ERROR) {
  100. log_store_status = BUFF_ALLOC_ERROR;
  101. LOG_DEBUG("%s:sram_dram_buff 0x%x, sig 0x%x, flag 0x%x.\n", MOD,
  102. (unsigned int)sram_dram_buff, (unsigned int)sram_dram_buff->sig, (unsigned int)sram_dram_buff->flag);
  103. return;
  104. }
  105. pbuff = (char *)sram_dram_buff->buf_addr;
  106. dram_curlog_header = (struct pl_lk_log*)&(sram_header->dram_curlog_header);
  107. #ifdef MTK_3LEVEL_PAGETABLE
  108. uint32_t start = ROUNDDOWN((uint32_t)pbuff, PAGE_SIZE);
  109. uint32_t logsize = ROUNDUP(((uint32_t)pbuff - start + LOG_STORE_SIZE), PAGE_SIZE);
  110. LOG_DEBUG("%s:dram pl/lk log buff mapping start addr = 0x%x, size = 0x%x\n", MOD, start, logsize);
  111. if (start >= DRAM_PHY_ADDR) {
  112. /*need to use header in DRAZM, we must allocate it first */
  113. log_store_enable = false;
  114. arch_mmu_map((uint64_t) start, start,
  115. MMU_MEMORY_TYPE_DEVICE | MMU_MEMORY_AP_P_RW_U_NA, logsize);
  116. log_store_enable = true;
  117. }
  118. #endif
  119. 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",
  120. MOD, (unsigned int)sram_header, (unsigned int)dram_curlog_header, (unsigned int)dram_curlog_header->sig, (unsigned int)dram_curlog_header->buff_size,
  121. (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);
  122. if (dram_curlog_header->sig != LOG_STORE_SIG || dram_curlog_header->buff_size != LOG_STORE_SIZE
  123. || dram_curlog_header->off_pl != sizeof(struct pl_lk_log)) {
  124. log_store_status = BUFF_ERROR;
  125. LOG_DEBUG("%s: BUFF_ERROR, sig 0x%x, buff_size 0x%x, off_pl 0x%x.\n", MOD,
  126. dram_curlog_header->sig, dram_curlog_header->buff_size, dram_curlog_header->off_pl);
  127. return;
  128. }
  129. if (dram_curlog_header->sz_pl + sizeof(struct pl_lk_log) >= LOG_STORE_SIZE) {
  130. LOG_DEBUG("%s: buff full pl size 0x%x.\n", MOD, dram_curlog_header->sz_pl);
  131. log_store_status = BUFF_FULL;
  132. return;
  133. }
  134. dram_curlog_header->off_lk = sizeof(struct pl_lk_log) + dram_curlog_header->sz_pl;
  135. dram_curlog_header->sz_lk = 0;
  136. dram_curlog_header->lk_flag = LOG_DEFAULT;
  137. log_store_status = BUFF_READY;
  138. LOG_DEBUG("%s: buff ready.\n", MOD);
  139. }
  140. void lk_log_store(char c)
  141. {
  142. if (log_store_enable == false)
  143. return;
  144. if (log_store_status == BUFF_NOT_READY)
  145. log_store_init();
  146. if ((log_store_status != BUFF_READY) || (log_store_status == BUFF_FULL))
  147. return;
  148. if (lk_is_full) {
  149. if (lk_renew >= dram_curlog_header->sz_lk) lk_renew = 0;
  150. *(pbuff + dram_curlog_header->off_lk + lk_renew) = c;
  151. lk_renew++;
  152. } else {
  153. *(pbuff + dram_curlog_header->off_lk + dram_curlog_header->sz_lk) = c;
  154. dram_curlog_header->sz_lk++;
  155. if ((dram_curlog_header->off_lk + dram_curlog_header->sz_lk) >= LOG_STORE_SIZE) {
  156. lk_is_full = true;
  157. lk_renew = 0;
  158. LOG_DEBUG("%s: dram lk buff full", MOD);
  159. }
  160. }
  161. sram_dram_buff->buf_point = dram_curlog_header->sz_lk + dram_curlog_header->sz_pl;
  162. }
  163. u32 current_buf_addr_get(void)
  164. {
  165. return (u32)(sram_dram_buff->buf_addr);
  166. }
  167. u32 current_lk_buf_addr_get(void)
  168. {
  169. return (u32)(sram_dram_buff->buf_addr + dram_curlog_header->off_lk);
  170. }
  171. u32 current_buf_pl_lk_log_size_get(void)
  172. {
  173. return (dram_curlog_header->sz_pl + dram_curlog_header->sz_lk);
  174. }
  175. inline void expdb_write(part_dev_t *dev, u64 offset, uchar *buf, u64 size)
  176. {
  177. log_store_enable = false;
  178. #if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  179. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  180. dev->write(dev, buf, offset, size, part_id);
  181. #else
  182. dev->write(dev, buf, offset, size);
  183. #endif
  184. #else
  185. dev->write(dev, buf, offset, size, part_id);
  186. #endif
  187. log_store_enable = true;
  188. }
  189. inline void expdb_read(part_dev_t *dev, u64 offset, uchar *buf, u64 size)
  190. {
  191. log_store_enable = false;
  192. #if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  193. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
  194. dev->read(dev, offset, buf, size, part_id);
  195. #else
  196. dev->read(dev, offset, buf, size);
  197. #endif
  198. #else
  199. dev->read(dev, offset, buf, size, part_id);
  200. #endif
  201. log_store_enable = true;
  202. }
  203. /* check emmc log_store config valid, or re-write it */
  204. bool emmc_config_valid(struct log_emmc_header *log_header, u64 block_size)
  205. {
  206. bool ret = true;
  207. if (log_header->sig != LOG_EMMC_SIG) {
  208. memset(log_header, 0, sizeof(struct log_emmc_header));
  209. log_header->sig = LOG_EMMC_SIG;
  210. return false;
  211. }
  212. if(log_header->offset >= EMMC_LOG_BUF_SIZE - block_size) {
  213. log_header->offset = 0;
  214. ret = false;
  215. }
  216. return ret;
  217. }
  218. /* read expdb partition and log config header info*/
  219. part_dev_t* read_emmc_config(struct log_emmc_header *log_header)
  220. {
  221. int index = 0;
  222. part_dev_t *dev = NULL;
  223. log_store_enable = false;
  224. index = partition_get_index("expdb");
  225. dev = mt_part_get_device();
  226. if (index == -1 || dev == NULL) {
  227. LOG_DEBUG("%s: no %s partition[%d]\n", MOD, "expdb", index);
  228. return NULL;
  229. }
  230. #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
  231. part_id = partition_get_region(index);
  232. #endif
  233. part_end = partition_get_offset(index) + partition_get_size(index);
  234. log_store_enable = true;
  235. expdb_read(dev, part_end - dev->blkdev->blksz,
  236. (uchar *)log_header, sizeof(struct log_emmc_header));
  237. if (emmc_config_valid(log_header, dev->blkdev->blksz) == false)
  238. expdb_write(dev, part_end - dev->blkdev->blksz,
  239. (uchar *)log_header, sizeof(struct log_emmc_header));
  240. return dev;
  241. }
  242. void set_emmc_config(int type, int value)
  243. {
  244. part_dev_t *dev = NULL;
  245. struct log_emmc_header log_header;
  246. memset(&log_header, 0, sizeof(log_header));
  247. if ((dev = read_emmc_config(&log_header)) == NULL)
  248. return;
  249. if (type == UART_LOG) { // uart log
  250. if (value)
  251. log_header.uart_flag = 1;
  252. else
  253. log_header.uart_flag = 2;
  254. }
  255. #ifdef LK_LOG_LEVEL_SUPPORT
  256. else if (type == LOG_LEVEL) { // lk log level
  257. log_header.reserve[LOG_LEVEL - 1] = LOG_LEVEL_MASK | value;
  258. }
  259. #endif
  260. else if (type == PRINTK_RATELIMIT) { // printk ratelimit
  261. if (value) {
  262. log_header.reserve[PRINTK_RATELIMIT - 1] = RATELIMIT_DISABLE;
  263. } else {
  264. log_header.reserve[PRINTK_RATELIMIT - 1] = RATELIMIT_ENABLE;
  265. }
  266. }
  267. expdb_write(dev, part_end - dev->blkdev->blksz,
  268. (uchar *)&log_header, sizeof(struct log_emmc_header));
  269. }
  270. #ifdef LK_LOG_LEVEL_SUPPORT
  271. void set_lk_log_level(int level)
  272. {
  273. set_emmc_config(LOG_LEVEL, level);
  274. lk_log_level = level;
  275. }
  276. #endif
  277. void set_uart_log_flag(bool enable)
  278. {
  279. #ifdef UART_SWITCH_SUPPORT
  280. set_emmc_config(UART_LOG, enable);
  281. #endif
  282. }
  283. void set_printk_ratelimit(bool enable)
  284. {
  285. set_emmc_config(PRINTK_RATELIMIT, enable);
  286. }
  287. void read_ratelimit_config()
  288. {
  289. struct log_emmc_header log_header;
  290. memset(&log_header, 0, sizeof(log_header));
  291. if (read_emmc_config(&log_header) == NULL) {
  292. dprintf(INFO, "READ PRINTK RATELIMIT CONFIG FAIL!\n");
  293. return;
  294. }
  295. if (log_header.reserve[PRINTK_RATELIMIT - 1] == RATELIMIT_DISABLE) {
  296. dprintf(INFO, "APPEND KERNEL CMDLINE printk.devkmsg=on\n");
  297. if (cmdline_append("printk.devkmsg=on") != true) {
  298. dprintf(CRITICAL, "set printk.devkmsg=on fail!");
  299. return;
  300. }
  301. dprintf(INFO, "set printk.devkmsg=on success\n");
  302. } else if (log_header.reserve[PRINTK_RATELIMIT - 1] == RATELIMIT_ENABLE) {
  303. dprintf(INFO, "APPEND KERNEL CMDLINE printk.devkmsg=ratelimit\n");
  304. if (cmdline_append("printk.devkmsg=ratelimit") != true) {
  305. dprintf(CRITICAL, "set printk.devkmsg=ratelimit fail!");
  306. return;
  307. }
  308. dprintf(INFO, "set printk.devkmsg=ratelimit success\n");
  309. }
  310. }
  311. int read_kedump_config()
  312. {
  313. struct log_emmc_header log_header;
  314. memset(&log_header, 0, sizeof(log_header));
  315. if (read_emmc_config(&log_header) == NULL) {
  316. dprintf(INFO, "READ KEDUMP CONFIG FAIL!\n");
  317. return 0;
  318. }
  319. if (log_header.reserve[KEDUMP_CTL - 1] == KEDUMP_DISABLE) {
  320. dprintf(INFO, "kedump is disabled!\n");
  321. return 0;
  322. }
  323. return 1;
  324. }
  325. /* exception power off in lk phase, sava log to emmc to analyze*/
  326. #ifndef DRAM_PHY_ADDR
  327. #define DRAM_PHY_ADDR (0x40000000)
  328. #endif
  329. void save_pllk_log(void)
  330. {
  331. u32 add, size;
  332. part_dev_t *dev = NULL;
  333. u32 emmc_remain_buf_size = 0;
  334. struct log_emmc_header log_header;
  335. LOG_DEBUG("%s: save pllk log.\n", MOD);
  336. memset(&log_header, 0, sizeof(log_header));
  337. if ((dev = read_emmc_config(&log_header)) == NULL)
  338. return;
  339. add = sram_dram_buff->buf_addr;
  340. size = dram_curlog_header->sz_pl + dram_curlog_header->sz_lk;
  341. if (add < DRAM_PHY_ADDR)
  342. return;
  343. if (size > EMMC_LOG_BUF_SIZE/4) {
  344. /* store size max 0.25 emm log, now is 512K */
  345. add = add + (size - EMMC_LOG_BUF_SIZE/4);
  346. size = EMMC_LOG_BUF_SIZE/4;
  347. }
  348. emmc_remain_buf_size = EMMC_LOG_BUF_SIZE - dev->blkdev->blksz - log_header.offset;
  349. if (size > emmc_remain_buf_size) {
  350. expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE + log_header.offset, (uchar *)add, emmc_remain_buf_size);
  351. expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE, (uchar *)(add + emmc_remain_buf_size), size - emmc_remain_buf_size);
  352. log_header.offset = size - emmc_remain_buf_size;
  353. } else {
  354. expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE + log_header.offset, (uchar *)add, size);
  355. log_header.offset = log_header.offset + size;
  356. }
  357. /*to-do: atf log*/
  358. /* re-write offset to config*/
  359. expdb_write(dev, part_end - dev->blkdev->blksz,
  360. (uchar *)&log_header, sizeof(struct log_emmc_header));
  361. }