| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- /* This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein is
- * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
- * the prior written permission of MediaTek inc. and/or its licensors, any
- * reproduction, modification, use or disclosure of MediaTek Software, and
- * information contained herein, in whole or in part, shall be strictly
- * prohibited.
- *
- * MediaTek Inc. (C) 2010. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
- * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
- * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
- * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
- * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
- * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
- * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
- * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
- * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
- * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
- * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
- * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
- * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
- * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek
- * Software") have been modified by MediaTek Inc. All revisions are subject to
- * any receiver's applicable license agreements with MediaTek Inc.
- */
- #include <stdlib.h>
- #include <arch/arm/mmu.h>
- #include "log_store_lk.h"
- #ifdef MTK_GPT_SCHEME_SUPPORT
- #include <platform/partition.h>
- #else
- #include <mt_partition.h>
- #endif
- #include "part_interface.h"
- #include "block_generic_interface.h"
- #include <bootargs.h>
- #define MOD "LK_LOG_STORE"
- #define DEBUG_LOG
- #define EMMC_LOG_BUF_SIZE (0x200000)
- #ifdef DEBUG_LOG
- #define LOG_DEBUG(fmt, ...) \
- log_store_enable = false; \
- _dprintf(fmt, ##__VA_ARGS__); \
- log_store_enable = true
- #else
- #define LOG_DEBUG(fmt, ...)
- #endif
- /* !!!!!!! Because log store be called by print, so these function don't use print log to debug.*/
- enum {
- LOG_WRITE = 0x1, /* Log is write to buff */
- LOG_READ_KERNEL = 0x2, /* Log have readed by kernel */
- LOG_WRITE_EMMC = 0x4, /* log need save to emmc */
- LOG_EMPTY = 0x8, /* log is empty */
- LOG_FULL = 0x10, /* log is full */
- LOG_PL_FINISH = 0X20, /* pl boot up finish */
- LOG_LK_FINISH = 0X40, /* lk boot up finish */
- LOG_DEFAULT = LOG_WRITE_EMMC|LOG_EMPTY,
- } BLOG_FLAG;
- static int log_store_status = BUFF_NOT_READY;
- static struct pl_lk_log *dram_curlog_header;
- static char *pbuff;
- static struct dram_buf_header *sram_dram_buff;
- bool log_store_enable = true;
- static bool lk_is_full = false;
- static u32 lk_renew;
- u64 part_end;
- #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
- int part_id;
- #endif
- void log_store_init(void)
- {
- struct sram_log_header *sram_header = NULL;
- unsigned int addr, size;
- LOG_DEBUG("%s:lk log_store_init start.\n", MOD);
- if (log_store_status != BUFF_NOT_READY) {
- LOG_DEBUG("%s:log_sotore_status is ready!\n", MOD);
- return;
- }
- /* SRAM buff header init */
- sram_log_store_addr_size(&addr, &size);
- sram_header = (struct sram_log_header *)addr;
- if (sram_header->sig != SRAM_HEADER_SIG) {
- LOG_DEBUG("%s:sram header 0x%x is not match: %d!\n", MOD, (unsigned int)sram_header, sram_header->sig);
- memset(sram_header, 0, sizeof(struct sram_log_header));
- sram_header->sig = SRAM_HEADER_SIG;
- log_store_status = BUFF_ALLOC_ERROR;
- return;
- }
- sram_dram_buff = &(sram_header->dram_buf);
- if (sram_dram_buff->sig != DRAM_HEADER_SIG || sram_dram_buff->flag == BUFF_ALLOC_ERROR) {
- log_store_status = BUFF_ALLOC_ERROR;
- LOG_DEBUG("%s:sram_dram_buff 0x%x, sig 0x%x, flag 0x%x.\n", MOD,
- (unsigned int)sram_dram_buff, (unsigned int)sram_dram_buff->sig, (unsigned int)sram_dram_buff->flag);
- return;
- }
- pbuff = (char *)sram_dram_buff->buf_addr;
- dram_curlog_header = (struct pl_lk_log*)&(sram_header->dram_curlog_header);
- #ifdef MTK_3LEVEL_PAGETABLE
- uint32_t start = ROUNDDOWN((uint32_t)pbuff, PAGE_SIZE);
- uint32_t logsize = ROUNDUP(((uint32_t)pbuff - start + LOG_STORE_SIZE), PAGE_SIZE);
- LOG_DEBUG("%s:dram pl/lk log buff mapping start addr = 0x%x, size = 0x%x\n", MOD, start, logsize);
- if (start >= DRAM_PHY_ADDR) {
- /*need to use header in DRAZM, we must allocate it first */
- log_store_enable = false;
- arch_mmu_map((uint64_t) start, start,
- MMU_MEMORY_TYPE_DEVICE | MMU_MEMORY_AP_P_RW_U_NA, logsize);
- log_store_enable = true;
- }
- #endif
- 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",
- MOD, (unsigned int)sram_header, (unsigned int)dram_curlog_header, (unsigned int)dram_curlog_header->sig, (unsigned int)dram_curlog_header->buff_size,
- (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);
- if (dram_curlog_header->sig != LOG_STORE_SIG || dram_curlog_header->buff_size != LOG_STORE_SIZE
- || dram_curlog_header->off_pl != sizeof(struct pl_lk_log)) {
- log_store_status = BUFF_ERROR;
- LOG_DEBUG("%s: BUFF_ERROR, sig 0x%x, buff_size 0x%x, off_pl 0x%x.\n", MOD,
- dram_curlog_header->sig, dram_curlog_header->buff_size, dram_curlog_header->off_pl);
- return;
- }
- if (dram_curlog_header->sz_pl + sizeof(struct pl_lk_log) >= LOG_STORE_SIZE) {
- LOG_DEBUG("%s: buff full pl size 0x%x.\n", MOD, dram_curlog_header->sz_pl);
- log_store_status = BUFF_FULL;
- return;
- }
- dram_curlog_header->off_lk = sizeof(struct pl_lk_log) + dram_curlog_header->sz_pl;
- dram_curlog_header->sz_lk = 0;
- dram_curlog_header->lk_flag = LOG_DEFAULT;
- log_store_status = BUFF_READY;
- LOG_DEBUG("%s: buff ready.\n", MOD);
- }
- void lk_log_store(char c)
- {
- if (log_store_enable == false)
- return;
- if (log_store_status == BUFF_NOT_READY)
- log_store_init();
- if ((log_store_status != BUFF_READY) || (log_store_status == BUFF_FULL))
- return;
- if (lk_is_full) {
- if (lk_renew >= dram_curlog_header->sz_lk) lk_renew = 0;
- *(pbuff + dram_curlog_header->off_lk + lk_renew) = c;
- lk_renew++;
- } else {
- *(pbuff + dram_curlog_header->off_lk + dram_curlog_header->sz_lk) = c;
- dram_curlog_header->sz_lk++;
- if ((dram_curlog_header->off_lk + dram_curlog_header->sz_lk) >= LOG_STORE_SIZE) {
- lk_is_full = true;
- lk_renew = 0;
- LOG_DEBUG("%s: dram lk buff full", MOD);
- }
- }
- sram_dram_buff->buf_point = dram_curlog_header->sz_lk + dram_curlog_header->sz_pl;
- }
- u32 current_buf_addr_get(void)
- {
- return (u32)(sram_dram_buff->buf_addr);
- }
- u32 current_lk_buf_addr_get(void)
- {
- return (u32)(sram_dram_buff->buf_addr + dram_curlog_header->off_lk);
- }
- u32 current_buf_pl_lk_log_size_get(void)
- {
- return (dram_curlog_header->sz_pl + dram_curlog_header->sz_lk);
- }
- inline void expdb_write(part_dev_t *dev, u64 offset, uchar *buf, u64 size)
- {
- log_store_enable = false;
- #if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
- #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
- dev->write(dev, buf, offset, size, part_id);
- #else
- dev->write(dev, buf, offset, size);
- #endif
- #else
- dev->write(dev, buf, offset, size, part_id);
- #endif
- log_store_enable = true;
- }
- inline void expdb_read(part_dev_t *dev, u64 offset, uchar *buf, u64 size)
- {
- log_store_enable = false;
- #if defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
- #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)
- dev->read(dev, offset, buf, size, part_id);
- #else
- dev->read(dev, offset, buf, size);
- #endif
- #else
- dev->read(dev, offset, buf, size, part_id);
- #endif
- log_store_enable = true;
- }
- /* check emmc log_store config valid, or re-write it */
- bool emmc_config_valid(struct log_emmc_header *log_header, u64 block_size)
- {
- bool ret = true;
- if (log_header->sig != LOG_EMMC_SIG) {
- memset(log_header, 0, sizeof(struct log_emmc_header));
- log_header->sig = LOG_EMMC_SIG;
- return false;
- }
- if(log_header->offset >= EMMC_LOG_BUF_SIZE - block_size) {
- log_header->offset = 0;
- ret = false;
- }
- return ret;
- }
- /* read expdb partition and log config header info*/
- part_dev_t* read_emmc_config(struct log_emmc_header *log_header)
- {
- int index = 0;
- part_dev_t *dev = NULL;
- log_store_enable = false;
- index = partition_get_index("expdb");
- dev = mt_part_get_device();
- if (index == -1 || dev == NULL) {
- LOG_DEBUG("%s: no %s partition[%d]\n", MOD, "expdb", index);
- return NULL;
- }
- #if defined(MTK_NEW_COMBO_EMMC_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT) || defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_UFS_SUPPORT)
- part_id = partition_get_region(index);
- #endif
- part_end = partition_get_offset(index) + partition_get_size(index);
- log_store_enable = true;
- expdb_read(dev, part_end - dev->blkdev->blksz,
- (uchar *)log_header, sizeof(struct log_emmc_header));
- if (emmc_config_valid(log_header, dev->blkdev->blksz) == false)
- expdb_write(dev, part_end - dev->blkdev->blksz,
- (uchar *)log_header, sizeof(struct log_emmc_header));
- return dev;
- }
- void set_emmc_config(int type, int value)
- {
- part_dev_t *dev = NULL;
- struct log_emmc_header log_header;
- memset(&log_header, 0, sizeof(log_header));
- if ((dev = read_emmc_config(&log_header)) == NULL)
- return;
- if (type == UART_LOG) { // uart log
- if (value)
- log_header.uart_flag = 1;
- else
- log_header.uart_flag = 2;
- }
- #ifdef LK_LOG_LEVEL_SUPPORT
- else if (type == LOG_LEVEL) { // lk log level
- log_header.reserve[LOG_LEVEL - 1] = LOG_LEVEL_MASK | value;
- }
- #endif
- else if (type == PRINTK_RATELIMIT) { // printk ratelimit
- if (value) {
- log_header.reserve[PRINTK_RATELIMIT - 1] = RATELIMIT_DISABLE;
- } else {
- log_header.reserve[PRINTK_RATELIMIT - 1] = RATELIMIT_ENABLE;
- }
- }
- expdb_write(dev, part_end - dev->blkdev->blksz,
- (uchar *)&log_header, sizeof(struct log_emmc_header));
- }
- #ifdef LK_LOG_LEVEL_SUPPORT
- void set_lk_log_level(int level)
- {
- set_emmc_config(LOG_LEVEL, level);
- lk_log_level = level;
- }
- #endif
- void set_uart_log_flag(bool enable)
- {
- #ifdef UART_SWITCH_SUPPORT
- set_emmc_config(UART_LOG, enable);
- #endif
- }
- void set_printk_ratelimit(bool enable)
- {
- set_emmc_config(PRINTK_RATELIMIT, enable);
- }
- void read_ratelimit_config()
- {
- struct log_emmc_header log_header;
- memset(&log_header, 0, sizeof(log_header));
- if (read_emmc_config(&log_header) == NULL) {
- dprintf(INFO, "READ PRINTK RATELIMIT CONFIG FAIL!\n");
- return;
- }
- if (log_header.reserve[PRINTK_RATELIMIT - 1] == RATELIMIT_DISABLE) {
- dprintf(INFO, "APPEND KERNEL CMDLINE printk.devkmsg=on\n");
- if (cmdline_append("printk.devkmsg=on") != true) {
- dprintf(CRITICAL, "set printk.devkmsg=on fail!");
- return;
- }
- dprintf(INFO, "set printk.devkmsg=on success\n");
- } else if (log_header.reserve[PRINTK_RATELIMIT - 1] == RATELIMIT_ENABLE) {
- dprintf(INFO, "APPEND KERNEL CMDLINE printk.devkmsg=ratelimit\n");
- if (cmdline_append("printk.devkmsg=ratelimit") != true) {
- dprintf(CRITICAL, "set printk.devkmsg=ratelimit fail!");
- return;
- }
- dprintf(INFO, "set printk.devkmsg=ratelimit success\n");
- }
- }
- int read_kedump_config()
- {
- struct log_emmc_header log_header;
- memset(&log_header, 0, sizeof(log_header));
- if (read_emmc_config(&log_header) == NULL) {
- dprintf(INFO, "READ KEDUMP CONFIG FAIL!\n");
- return 0;
- }
- if (log_header.reserve[KEDUMP_CTL - 1] == KEDUMP_DISABLE) {
- dprintf(INFO, "kedump is disabled!\n");
- return 0;
- }
- return 1;
- }
- /* exception power off in lk phase, sava log to emmc to analyze*/
- #ifndef DRAM_PHY_ADDR
- #define DRAM_PHY_ADDR (0x40000000)
- #endif
- void save_pllk_log(void)
- {
- u32 add, size;
- part_dev_t *dev = NULL;
- u32 emmc_remain_buf_size = 0;
- struct log_emmc_header log_header;
- LOG_DEBUG("%s: save pllk log.\n", MOD);
- memset(&log_header, 0, sizeof(log_header));
- if ((dev = read_emmc_config(&log_header)) == NULL)
- return;
- add = sram_dram_buff->buf_addr;
- size = dram_curlog_header->sz_pl + dram_curlog_header->sz_lk;
- if (add < DRAM_PHY_ADDR)
- return;
- if (size > EMMC_LOG_BUF_SIZE/4) {
- /* store size max 0.25 emm log, now is 512K */
- add = add + (size - EMMC_LOG_BUF_SIZE/4);
- size = EMMC_LOG_BUF_SIZE/4;
- }
- emmc_remain_buf_size = EMMC_LOG_BUF_SIZE - dev->blkdev->blksz - log_header.offset;
- if (size > emmc_remain_buf_size) {
- expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE + log_header.offset, (uchar *)add, emmc_remain_buf_size);
- expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE, (uchar *)(add + emmc_remain_buf_size), size - emmc_remain_buf_size);
- log_header.offset = size - emmc_remain_buf_size;
- } else {
- expdb_write(dev, part_end - EMMC_LOG_BUF_SIZE + log_header.offset, (uchar *)add, size);
- log_header.offset = log_header.offset + size;
- }
- /*to-do: atf log*/
- /* re-write offset to config*/
- expdb_write(dev, part_end - dev->blkdev->blksz,
- (uchar *)&log_header, sizeof(struct log_emmc_header));
- }
|