1.sp9820e安卓4.4开启长按power开启sysdump
1.1uboot开启arm reset
u-boot15/include/configs/sp9820e_2h10.h
#if DEBUG
#define CONFIG_7S_RST_SW_MODE 1 //0:hw reset,1:arm reset,power keep on //soft for debug version
#else
#define CONFIG_7S_RST_SW_MODE 0 //0:hw reset,1:arm reset,power keep on //hard for user version
#endif
uboot sysdump源文件目录
./u-boot15/common/loader/sysdump.c
1.2 配置文件修改为on
vendor/sprd/proprietories-source/sprd_debug/systemDebugger/user/.sprd_debugger.conf
---off
+++on
2.kernel处源码分析:
./kernel/drivers/soc/sprd/debug/sysdump/sysdump.c
2.1初始化时创建了一个//proc/sprd_sysdump控制节点
int sysdump_sysctl_init(void)
{
/*get_sprd_sysdump_info_paddr(); */
unsigned long sprd_sysdump_info_paddr;
struct proc_dir_entry *sysdump_proc;
sprd_sysdump_info_paddr = get_sprd_sysdump_info_paddr();
if (!sprd_sysdump_info_paddr)
pr_emerg("get sprd_sysdump_info_paddr failed.\n");
sprd_sysdump_info = (struct sysdump_info *)
phys_to_virt(sprd_sysdump_info_paddr);
pr_emerg("vaddr is %p,paddr is %p\n",
sprd_sysdump_info, (void *)sprd_sysdump_info_paddr);
sysdump_sysctl_hdr =
register_sysctl_table((struct ctl_table *)sysdump_sysctl_root);
if (!sysdump_sysctl_hdr)
return -ENOMEM;
crash_notes = alloc_percpu(note_buf_t);
if (crash_notes == NULL)
return -ENOMEM;
if (input_register_handler(&sysdump_handler))
pr_emerg("regist sysdump_handler failed.\n");
sysdump_proc = proc_create("sprd_sysdump", S_IWUSR | S_IRUSR, NULL, &sysdump_proc_fops);
if (!sysdump_proc)
return -ENOMEM;
sprd_sysdump_init = 1;
memset(g_ktxt_hash_data, 0x55, SHA1_DIGEST_SIZE);
sg_init_one(&sg, _stext, _etext-_stext);
desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
crypto_hash_init(&desc);
return 0;
}
2.2从代码中可以看出,往/proc/sprd_sysdump中写on就会打开sysdump,写off则关掉。
static ssize_t sprd_sysdump_write(struct file *file, const char __user *buf,
size_t count, loff_t *data)
{
char sysdump_buf[5] = {0};
pr_emerg("sprd_sysdump_write: start!!!\n");
if (count) {
if (copy_from_user(sysdump_buf, buf, count)) {
pr_emerg("sprd_sysdump_write: copy_from_user failed!!!\n");
return -1;
}
sysdump_buf[count] = '\0';
if (!strncmp(sysdump_buf, "on", 2)) {
pr_emerg("sprd_sysdump_write: enable user version sysdump!!!\n");
sysdump_status = 1;
sprd_set_reboot_mode("dumpenable");
set_sysdump_enable(1);
#ifndef CONFIG_SPRD_DEBUG
sysdump_enable_watchdog(0);
#endif
} else if (!strncmp(sysdump_buf, "off", 3)) {
pr_emerg("sprd_sysdump_write: disable user version sysdump!!!\n");
sysdump_status = 0;
sprd_set_reboot_mode("dumpdisable");
set_sysdump_enable(0);
#ifndef CONFIG_SPRD_DEBUG
sysdump_enable_watchdog(1);
#endif
}
}
pr_emerg("sprd_sysdump_write: end!!!\n");
return count;
}
2.3 cat /proc/sprd_sysdump读取sysdump开启状态
static int sprd_sysdump_read(struct seq_file *s, void *v)
{
seq_printf(s, "sysdump_status = %d\n", sysdump_status);
return 0;
}
static int sprd_sysdump_open(struct inode *inode, struct file *file)
{
return single_open(file, sprd_sysdump_read, NULL);
}
3.用户层开启sysdump
vendor/sprd/proprietories-source/sprd_debug/systemDebugger/
3.1 Android.mk中对userdebug和user版作了区分
LOCAL_MODULE := .sprd_debugger.conf
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
ifneq ($(TARGET_BUILD_VARIANT),user)
LOCAL_SRC_FILES := userdebug/$(LOCAL_MODULE)
else
LOCAL_SRC_FILES := user/$(LOCAL_MODULE)
endif
3.2查看user/user版的配置文件、
user/.sprd_debugger.conf
root@root:systemDebugger$ cat user/.sprd_debugger.conf
off
userdebug/.sprd_debugger.conf
root@root:systemDebugger$ cat user/.sprd_debugger.conf
on
3.3 用户层代码,读取配置文件中的值,将on/off 写入SPRD_SYSDUMP_CONFIG
#define SPRD_CONFIG_PATH "data/sprd_debug/.sprd_debugger.conf"
#define SPRD_CONFIG_ORIG "/system/etc/.sprd_debugger.conf"
#define SPRD_SYSDUMP_CONFIG "/proc/sprd_sysdump"
#define SOCKET_NAME "SystemDebugger"
static int do_server(){
FILE* fp;
int result;
if ((fp = fopen(SPRD_CONFIG_PATH, "r"))== NULL) {
result = copyConfFile();
if(result==-1) {
ALOGE(" Unable to open %s : %s\n", SPRD_CONFIG_PATH, strerror(errno));
return -1;
}
ALOGD("Initial config %s ", sysdumpconfig);
} else {
sysdumpconfig = fgets(configBuffer, sizeof(configBuffer), fp);
fclose(fp);
}
ALOGD("sysdumpconfig = %s",sysdumpconfig);
if(sysdumpconfig == NULL){
if ((fp = fopen(SPRD_SYSDUMP_CONFIG, "r"))){
sysdumpconfig = fgets(configBuffer, sizeof(configBuffer), fp);
ALOGD("gets config from %s = %s", SPRD_SYSDUMP_CONFIG,sysdumpconfig);
if(strstr(sysdumpconfig,"1")) {
writeConfig("on");
strcpy(sysdumpconfig, "on");
} else {
writeConfig("off");
strcpy(sysdumpconfig, "off");
}
ALOGD("set sysdumpconfig = %s",sysdumpconfig);
} else {
ALOGE(" Unable to open %s : %s\n", SPRD_SYSDUMP_CONFIG, strerror(errno));
return -1;
}
}
if(strstr(sysdumpconfig,"on")) {
if(writeFile(SPRD_SYSDUMP_CONFIG, "on") == -1) {
property_set("persist.sys.sysdump", "-1");
} else {
property_set("persist.sys.sysdump", "on");
ALOGD("Initial sysdump on");
}
} else if(strstr(sysdumpconfig,"off")){
if(writeFile(SPRD_SYSDUMP_CONFIG, "off") == -1) {
property_set("persist.sys.sysdump", "-1");
} else {
property_set("persist.sys.sysdump", "off");
ALOGD("Initial sysdump off");
}
}