diff options
author | Mark Salyzyn <salyzyn@google.com> | 2016-03-09 23:58:16 +0100 |
---|---|---|
committer | Mark Salyzyn <salyzyn@google.com> | 2016-03-31 22:52:54 +0200 |
commit | 13aca598f8e93548fef36d87136e85ce8c9d18de (patch) | |
tree | b166f4a950fefb3e8427ddc51cb1264da7a48aec /recovery-refresh.cpp | |
parent | Import translations. DO NOT MERGE (diff) | |
download | android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar.gz android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar.bz2 android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar.lz android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar.xz android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.tar.zst android_bootable_recovery-13aca598f8e93548fef36d87136e85ce8c9d18de.zip |
Diffstat (limited to 'recovery-refresh.cpp')
-rw-r--r-- | recovery-refresh.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/recovery-refresh.cpp b/recovery-refresh.cpp new file mode 100644 index 000000000..70adc70ee --- /dev/null +++ b/recovery-refresh.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "recovery-refresh" + +// +// Strictly to deal with reboot into system after OTA, then +// reboot while in system before boot complete landing us back +// into recovery to continue with any mitigations with retained +// log history. This simply refreshes the pmsg files from +// the last pmsg file contents. +// +// Usage: +// recovery-refresh [--force-rotate|--rotate] +// +// All file content representing in the recovery/ directory stored in +// /sys/fs/pstore/pmsg-ramoops-0 in logger format that reside in the +// LOG_ID_SYSTEM buffer at ANDROID_LOG_INFO priority or higher is +// refreshed into /dev/pmsg0. This ensures that an unexpected reboot +// before recovery-persist is run will still contain the associated +// pmsg Android Logger content. +// +// --force-rotate recovery/last_kmsg and recovery.last_log files are +// rotated with .<number> suffixes upwards. +// --rotate rotated only if rocovery/last_msg or recovery/last_log +// exist, otherwise perform 1:1 refresh. +// + +#include <string.h> + +#include <string> + +#include <android/log.h> /* Android Log Priority Tags */ +#include <log/logger.h> /* Android Log packet format */ +#include <private/android_logger.h> /* private pmsg functions */ + +static const char LAST_KMSG_FILE[] = "recovery/last_kmsg"; +static const char LAST_LOG_FILE[] = "recovery/last_log"; + +static ssize_t logbasename( + log_id_t /* logId */, + char /* prio */, + const char *filename, + const char * /* buf */, size_t len, + void *arg) { + if (strstr(LAST_KMSG_FILE, filename) || + strstr(LAST_LOG_FILE, filename)) { + bool *doRotate = reinterpret_cast<bool *>(arg); + *doRotate = true; + } + return len; +} + +static ssize_t logrotate( + log_id_t logId, + char prio, + const char *filename, + const char *buf, size_t len, + void *arg) { + bool *doRotate = reinterpret_cast<bool *>(arg); + if (!*doRotate) { + return __android_log_pmsg_file_write(logId, prio, filename, buf, len); + } + + std::string name(filename); + size_t dot = name.find_last_of("."); + std::string sub = name.substr(0, dot); + + if (!strstr(LAST_KMSG_FILE, sub.c_str()) && + !strstr(LAST_LOG_FILE, sub.c_str())) { + return __android_log_pmsg_file_write(logId, prio, filename, buf, len); + } + + // filename rotation + if (dot == std::string::npos) { + name += ".1"; + } else { + std::string number = name.substr(dot + 1); + if (!isdigit(number.data()[0])) { + name += ".1"; + } else { + unsigned long long i = std::stoull(number); + name = sub + "." + std::to_string(i + 1); + } + } + + return __android_log_pmsg_file_write(logId, prio, name.c_str(), buf, len); +} + +int main(int argc, char **argv) { + static const char filter[] = "recovery/"; + static const char force_rotate_flag[] = "--force-rotate"; + static const char rotate_flag[] = "--rotate"; + ssize_t ret; + bool doRotate = false; + + // Take last pmsg contents and rewrite it to the current pmsg session. + if ((argc <= 1) || !argv[1] || + (((doRotate = strcmp(argv[1], rotate_flag))) && + strcmp(argv[1], force_rotate_flag))) { + doRotate = false; + } else if (!doRotate) { + // Do we need to rotate? + __android_log_pmsg_file_read( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, + logbasename, &doRotate); + } + + // Take action to refresh pmsg contents + ret = __android_log_pmsg_file_read( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, + logrotate, &doRotate); + + return (ret < 0) ? ret : 0; +} |