/******************************************************************************/
/*---用户空间:subsystem_ramdump
service ss_ramdump /system/bin/subsystem_ramdump 2
class late_start
group system
---*/
/******************************************************************************/
static void ssr_tool_helper(void)
{
ALOGI("Usage:./system/bin/subsystem_ramdump [arg1] [arg2] [arg3]");
ALOGI("[arg1]: (1/2) Ramdump location: 1: eMMC: /data/ramdump or 2: SD card: /sdcard/ramdump");
ALOGI("[arg2]: (1/0) 1: Enable RPM log / 0: Disable RPM log");
ALOGI("[arg3]: (1/0) 1: Enable qdss ramdump / 0: Disable qdss ramdump");
}
static int parse_args(int argc, char **argv)
{
int location, rpmlog, qdss;
ssr_tool_helper();
if (argc == 1) {
// Use default ramdump location; disable rpm log ; disable qdss ramdump;
ALOGI(" Using default ramdump location 1: eMMC: /data/ramdump");
ALOGI(" Using default 0: Disable RPM log");
ALOGI(" Using default 0: Disable qdss ramdump");
location = 1;
rpmlog = 0;
qdss = 0;
}
}
#define DUMP_SETTING "/sys/module/subsystem_restart/parameters/enable_ramdumps"
static int ssr_check_ramdump_setting(void)
{
int ret = 0;
int fd;
char buf[2];
if ((fd = open(DUMP_SETTING, O_RDONLY)) < 0) {
}
if (read(fd, buf, 2) <= 0) {
}
if (buf[0] == '1') {
ret = 0;
} else if (buf[0] == '0') {
ret = -EINVAL;
} else {
ALOGE("Invalid ramdump setting %s", buf);
ret = -EINVAL;
}
return ret:
}
/*遍历/dev: 找到ramdump_xxx的设备:保存到全局变量:ramdump_list[] and pfd_num*/
static int ssr_search_pil_ramdump(void)
{
int ret = 0;
int i = 0;
struct dirent *dir_p;
DIR *dir_s;
dir_s = opendir(PIL_RAMDUMP_DIR);
while ((dir_p = readdir(dir_s)) != NULL) {
if (strncmp(dir_p->d_name, DUMP_HEAD_STR, 8) == 0) {
strlcpy(ramdump_list[i], dir_p->d_name, PIL_NAME_SIZE);
i++;
}
}
/* Store pil ramdump number */
pfd_num = i;
closedir(dir_s);
return ret;
}
static int ssr_ramdump_init(ramdump_s *dump, int androidBuild )
{
int ret = 0;
int i;
/* check if ramdump folder can be created */
if (check_folder(dump->dir) != 0) {
ALOGI("Attemping to create %s", dump->dir);
if ((ret = create_folder(ramdump.dir)) < 0) {
ALOGE("Unable to create %s", dump->dir);
goto open_error;
}
}
if ( androidBuild ) {
/* init ramdump semaphore */
if (sem_init(&ramdump_sem, 0, 0) != 0) {
ret = -EINVAL;
goto ramdump_semaphore_error;
}
/* init qdss semaphore */
if (sem_init(&qdss_sem, 0, 0) != 0) {
ret = -EINVAL;
goto qdss_semaphore_error;
}
}
/* init ramdump parameters */
for (i = 0; i < DUMP_NUM; i++) {
dump->fd[i] = -1;
dump->dev[i] = -1;
}
/* open fd in ramdump list */
if ((ret = open_ramdump_fd(dump)) < 0) {
ALOGE("Failed to open ramdump devices");
goto open_ramdump_error;
}
/* Store fd to polling struct */
for (i = 0; i < pfd_num; i++) {
pfd[i].fd = dump->fd[i];
pfd[i].events = POLLIN;
pfd[i].revents = 0;
}
ssr_flag = 0;
return ret;
}
poll:
RETURN VALUE
On success, a positive number is returned; this is the number of structures which have nonzero revents fields
(in other words, those descriptors with events or errors reported).
A value of 0 indicates that the call timed out and no file descriptors were ready.
On error, -1 is returned, and errno is set appropriately.
int main(int argc, char *argv[])
{
int ret = 0;
int i;
char timestamp[TIMEBUF_SIZE];
int timeout = -1;
char *ssname = NULL;
/* Loop forever and poll */
while (1) {
/* Poll all ramdump files */
ret = poll(pfd, pfd_num, timeout);
if (ret<0) {
ALOGE("Polling ramdump failed: %d", ret);
break;
} else if (0==ret) {
}
if (-1==timeout) {
ssname = NULL;
timeout = 300;
}
/* Get current time */
if (get_current_timestamp(timestamp, TIMEBUF_SIZE) == NULL) {
}
/* Collect ramdumps */
for (i = 0; i < pfd_num; i++) {
ret = generate_ramdump(i, &ramdump, timestamp);
/* If ramdump generation is failed, exit the program */
if ((ret > 0) && (NULL == ssname) && (strncmp(ramdump_list[ramdump.dev[i]], DUMP_SMEM_STR, 12))) {
ssname = ramdump_list[ramdump.dev[i]];
}
}
}
}
int generate_ramdump(int index, ramdump_s *dump, char *tm)
{
int ret = 0;
int numBytes = 0;
int totalBytes = 0;
int fd = -1;
char *rd_buf;
char f_name[FILENAME_SIZE];
int should_skip = 0;
/* Check to see if we have anything to do */
if ((pfd[index].revents & POLLIN) == 0)
goto skip_dump_generation;
/* Read first section of ramdump to determine type */
while ((numBytes = read(pfd[index].fd, rd_buf, CHK_ELF_LEN)) > 0) {
*(rd_buf + numBytes) = '\0';
if (should_skip)
strcpy(f_name, "/dev/null");
else if (strstr(rd_buf, STR_ELF))
ssr_ramdump_filename(index, dump, f_name, tm, 1);
else
ssr_ramdump_filename(index, dump, f_name, tm, 0);
/* Open the output file */
fd = open(f_name, O_WRONLY | O_CREAT, S_IRUSR);
/* Write first section ramdump into file and exit loop */
ret = write(fd, rd_buf, numBytes);
totalBytes += numBytes;
break; /*这里有个break*/
}
/* Read data from the ramdump, and write it into the output file */
while ((numBytes = read(pfd[index].fd, rd_buf, BUFFER_SIZE)) > 0) {
ret = write(fd, rd_buf, numBytes);
if (ret < 0) {
ALOGE("Failed to write to dump file %s",
f_name);
goto dump_write_error;
}
totalBytes += numBytes;
}
/* Make sure things are written */
fsync(fd);
}
/*************产生ramdump 文件后的处理*******************/
ALOGE("Ramdump: Polling ramdump timeout: %d\n", ret);
ALOGE("compress and clear the crash file[%s]\n", dump_name_buf);
snprintf(cmd_buf, CMD_SIZE, "busybox tar czf %s/%s%s.tgz %s", ramdump.dir, ssname, timestamp, dump_name_buf);
cmd_result = system(cmd_buf);
ALOGE("tar ramdump, cmd_result:0x%x",cmd_result);
sprintf(cmd_buf, "logcat -t 3000 -f %s/%s%s_logcat.log" ,ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);
sprintf(cmd_buf, "dmesg > %s/%s%s_dmesg.log", ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);
sprintf(cmd_buf, "getprop > %s/%s%s_props.txt", ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);
/* 这堆想干什么?
char tmpdump[32] = "/sdcard/sysmatlog/tmpmdmdump";
char srcdump[64] = "";
snprintf(srcdump,sizeof(srcdump), "%s%s", ssname, timestamp);
char dstdump[64] = "";
snprintf(dstdump,sizeof(dstdump),"%s.",srcdump);
int mat_fd = -1;
sprintf(cmd_buf, "rm -r %s + mkdir %s", tmpdump, tmpdump);
char matshcmd[1024] = "";
sprintf(matshcmd, "[execmds=%s+busybox cp %s/%s* %s/+busybox split -b 3m -a 1 %s/%s.tgz %s/%stgz. + rm %s/%s.tgz+logorgfilespath=%s]@subsysRD_%s ", cmd_buf, ramdump.dir, srcdump, tmpdump, tmpdump, srcdump, tmpdump, dstdump, tmpdump, srcdump, tmpdump, ssname);
ALOGE("matshcmd: %s", matshcmd);
mat_fd = open("/dev/sysmatdrv", O_WRONLY);
*/