MTK平台 main log导入到uart口

文摘 Android Kernel MediaTek 2020-02-1 阅读:5625

man_uart_log.jpg


[DESCRIPTION]
不开机问题调试起来比较麻烦,可能是底层出错,比如KE、preloader崩溃,lk崩溃,也可能是上层崩溃。
如果是上层崩溃,需要抓main log,抓log步骤如下:

  1. 先检查adb shell是否可用,如果可用可以用adb shell "logcat -v time -b main -b system > logcat.txt"
  2. 如果不能用,则要开uart console,具体请参考:FAQ03891
  3. 如果uart console也不能用,那么只能在上层代码里让main log直接导入到uart口了。下面提供方法。

[SOLUTION]

方案一:

  1. 在system/core/liblog/logd_write.c或system/core/liblog/logger_write.c添加代码到__write_to_log_daemon(),将main log导入到kernel buffer:
static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
{
    ......
    if (!nr) {
        return -EINVAL;
    }
#if 1 /* add this block */
    if (log_id == LOG_ID_MAIN || log_id == LOG_ID_SYSTEM) {
        static const char* name = "/dev/__kmsg__";
        static int klog_fd = -1;

        if (klog_fd < 0) {
            klog_fd = open("/dev/kmsg", O_WRONLY|O_CLOEXEC);
            if (klog_fd < 0 && mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
                klog_fd = open(name, O_WRONLY|O_CLOEXEC);
                unlink(name);
            }
        }
        if (klog_fd >= 0 && *(unsigned char *)vec[0].iov_base >= ANDROID_LOG_WARN) {
            char c = '?', str[5 + vec[1].iov_len + vec[2].iov_len];
            long rt;
 
            switch (*(unsigned char *)vec[0].iov_base) {
            case ANDROID_LOG_WARN: c = 'W'; break;
            case ANDROID_LOG_ERROR: c = 'E'; break;
            case ANDROID_LOG_FATAL: c = 'F'; break;
            case ANDROID_LOG_SILENT: c = 'S'; break;
            default: break;
            }
            rt = snprintf(str, sizeof(str) - 1, "%c %s %s\n", c, (char *)vec[1].iov_base, (char *)vec[2].iov_base);
            if (rt > 0)
                TEMP_FAILURE_RETRY(write(klog_fd, str, rt));
        }
    }
#endif
    ......
}
  1. 修改kernel/drivers/char/mem.c里的
[11] = { "kmsg", 0644, &kmsg_fops, NULL },

修改为:

[11] = { "kmsg", 0666, &kmsg_fops, NULL },
  1. 在external/sepolicy/domain.te添加:
allow domain kmsg_device:chr_file rw_file_perms;
  1. 在external/sepolicy/device.te修改:
type kmsg_device, dev_type;

修改为:

type kmsg_device, dev_type, mlstrustedobject;
  1. 全编译:
  2. -j24
  3. 抓到的uart log大致如下:
[14:46:02.401] [ 22.618857] .(1)[388:mediaserver][name:ccci&][ccci1/chr]MD state 2, 3
[14:46:02.401] [ 22.619350] .(2)[787:CCCIReadThread]W SpeechMessengerECCCI ..[MD Reset Notify(MSG_M2A_EM_DATA_REQUEST: 0xaf700000)]..
[14:46:02.401] [ 22.622637] E SpeechMessengerECCCI SendMsgFailErrorHandling(), message: 0x2f760000
[14:46:02.429] [ 22.624168] W SpeechMessengerECCCI SendMsgFailErrorHandling(), message: 0x2f760000, ack don't care
  1. 注意:O版本后还需下面的修改
    为所有进程添加mknodat的权限

/external/minijail/util.c

45#elif defined(__arm__)
46#if defined(__ANDROID__)
47const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket",
48 "writev"};
49#else
50const char *log_syscalls[] = {"connect", "gettimeofday", "send"};
51#endif
52#elif defined(__aarch64__)
53#if defined(__ANDROID__)
54const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev"};
55#else
56const char *log_syscalls[] = {"connect", "send"};

修改为

45#elif defined(__arm__)
46#if defined(__ANDROID__)
47const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket",
48 "writev","mknodat"};
49#else
50const char *log_syscalls[] = {"connect", "gettimeofday", "send"};
51#endif
52#elif defined(__aarch64__)
53#if defined(__ANDROID__)
54const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev","mknodat"};
55#else
56const char *log_syscalls[] = {"connect", "send"};

方案二:

1.  #include <cutils/klog.h>

2.  #define ERROR(x...)   KLOG_ERROR("module_name", x)
     #define NOTICE(x...)  KLOG_NOTICE("module_name", x)
     #define INFO(x...)    KLOG_INFO("module_name", x)

3.  NOTICE("%s: val=%d \n", __FUNCTION__, value);

0条评论

© 2024 芯缘异码. Powered by Typecho