kernel_samsung_a34x-permissive/drivers/misc/mediatek/aee/aed/reboot-reason.c
2024-04-28 15:49:01 +02:00

159 lines
3.5 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 MediaTek Inc.
*/
#include <asm/memory.h>
#include <asm/setup.h>
#include <linux/init.h>
#include <linux/kobject.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/uaccess.h>
#if IS_ENABLED(CONFIG_MTK_WATCHDOG)
#include <mtk_wd_api.h>
#endif
#include <mt-plat/aee.h>
#include <mt-plat/mboot_params.h>
#include <mt-plat/mrdump.h>
#include "aed.h"
#define RR_PROC_NAME "reboot-reason"
static struct proc_dir_entry *aee_rr_file;
static char aee_cmdline[COMMAND_LINE_SIZE];
static const char *mrdump_get_cmd(void)
{
struct file *fd;
mm_segment_t fs;
loff_t pos = 0;
if (aee_cmdline[0] != 0)
return aee_cmdline;
fs = get_fs();
set_fs(KERNEL_DS);
fd = filp_open("/proc/cmdline", O_RDONLY, 0);
if (IS_ERR(fd)) {
pr_info("kedump: Unable to open /proc/cmdline (%ld)",
PTR_ERR(fd));
set_fs(fs);
return aee_cmdline;
}
vfs_read(fd, (void *)aee_cmdline, COMMAND_LINE_SIZE, &pos);
filp_close(fd, NULL);
fd = NULL;
set_fs(fs);
return aee_cmdline;
}
static int aee_rr_reboot_reason_proc_open(struct inode *inode,
struct file *file)
{
return single_open(file, aee_rr_reboot_reason_show, NULL);
}
static const struct file_operations aee_rr_reboot_reason_proc_fops = {
.open = aee_rr_reboot_reason_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void aee_rr_proc_init(struct proc_dir_entry *aed_proc_dir)
{
aee_rr_file = proc_create(RR_PROC_NAME, 0440, aed_proc_dir,
&aee_rr_reboot_reason_proc_fops);
if (!aee_rr_file)
pr_notice("%s: Can't create rr proc entry\n", __func__);
}
EXPORT_SYMBOL(aee_rr_proc_init);
void aee_rr_proc_done(struct proc_dir_entry *aed_proc_dir)
{
remove_proc_entry(RR_PROC_NAME, aed_proc_dir);
}
EXPORT_SYMBOL(aee_rr_proc_done);
/* define /sys/bootinfo/powerup_reason */
static ssize_t powerup_reason_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char boot_reason[64];
char *br_ptr;
char *br_ptr_e;
memset(boot_reason, 0x0, 64);
br_ptr = strstr(mrdump_get_cmd(), "androidboot.bootreason=");
if (br_ptr) {
br_ptr_e = strstr(br_ptr, " ");
/* get boot reason */
if (br_ptr_e) {
strncpy(boot_reason, br_ptr + 23,
br_ptr_e - br_ptr - 23);
boot_reason[br_ptr_e - br_ptr - 23] = '\0';
}
#if IS_ENABLED(CONFIG_MTK_AEE_IPANIC)
if (aee_rr_last_fiq_step())
strncpy(boot_reason, "kpanic", 7);
#endif
if (!strncmp(boot_reason, "2sec_reboot",
strlen("2sec_reboot"))) {
br_ptr = strstr(mrdump_get_cmd(),
"has_battery_removed=1");
if (!br_ptr)
return snprintf(buf, sizeof(boot_reason),
"%s_abnormal\n", boot_reason);
}
return snprintf(buf, sizeof(boot_reason), "%s\n", boot_reason);
} else {
return 0;
}
}
static struct kobj_attribute powerup_reason_attr = __ATTR_RO(powerup_reason);
struct kobject *bootinfo_kobj;
EXPORT_SYMBOL(bootinfo_kobj);
static struct attribute *bootinfo_attrs[] = {
&powerup_reason_attr.attr,
NULL
};
static struct attribute_group bootinfo_attr_group = {
.attrs = bootinfo_attrs,
};
int ksysfs_bootinfo_init(void)
{
int error;
bootinfo_kobj = kobject_create_and_add("bootinfo", NULL);
if (!bootinfo_kobj)
return -ENOMEM;
error = sysfs_create_group(bootinfo_kobj, &bootinfo_attr_group);
if (error)
kobject_put(bootinfo_kobj);
return error;
}
void ksysfs_bootinfo_exit(void)
{
kobject_put(bootinfo_kobj);
}
/* end sysfs bootinfo */