1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "recovery-refresh" 18 19 // 20 // Strictly to deal with reboot into system after OTA, then 21 // reboot while in system before boot complete landing us back 22 // into recovery to continue with any mitigations with retained 23 // log history. This simply refreshes the pmsg files from 24 // the last pmsg file contents. 25 // 26 // Usage: 27 // recovery-refresh [--force-rotate|--rotate] 28 // 29 // All file content representing in the recovery/ directory stored in 30 // /sys/fs/pstore/pmsg-ramoops-0 in logger format that reside in the 31 // LOG_ID_SYSTEM buffer at ANDROID_LOG_INFO priority or higher is 32 // refreshed into /dev/pmsg0. This ensures that an unexpected reboot 33 // before recovery-persist is run will still contain the associated 34 // pmsg Android Logger content. 35 // 36 // --force-rotate recovery/last_kmsg and recovery.last_log files are 37 // rotated with .<number> suffixes upwards. 38 // --rotate rotated only if rocovery/last_msg or recovery/last_log 39 // exist, otherwise perform 1:1 refresh. 40 // 41 42 #include <string.h> 43 44 #include <string> 45 46 #include <android/log.h> /* Android Log Priority Tags */ 47 #include <log/logger.h> /* Android Log packet format */ 48 #include <private/android_logger.h> /* private pmsg functions */ 49 50 static const char LAST_KMSG_FILE[] = "recovery/last_kmsg"; 51 static const char LAST_LOG_FILE[] = "recovery/last_log"; 52 53 static ssize_t logbasename( 54 log_id_t /* logId */, 55 char /* prio */, 56 const char *filename, 57 const char * /* buf */, size_t len, 58 void *arg) { 59 if (strstr(LAST_KMSG_FILE, filename) || 60 strstr(LAST_LOG_FILE, filename)) { 61 bool *doRotate = reinterpret_cast<bool *>(arg); 62 *doRotate = true; 63 } 64 return len; 65 } 66 67 static ssize_t logrotate( 68 log_id_t logId, 69 char prio, 70 const char *filename, 71 const char *buf, size_t len, 72 void *arg) { 73 bool *doRotate = reinterpret_cast<bool *>(arg); 74 if (!*doRotate) { 75 return __android_log_pmsg_file_write(logId, prio, filename, buf, len); 76 } 77 78 std::string name(filename); 79 size_t dot = name.find_last_of("."); 80 std::string sub = name.substr(0, dot); 81 82 if (!strstr(LAST_KMSG_FILE, sub.c_str()) && 83 !strstr(LAST_LOG_FILE, sub.c_str())) { 84 return __android_log_pmsg_file_write(logId, prio, filename, buf, len); 85 } 86 87 // filename rotation 88 if (dot == std::string::npos) { 89 name += ".1"; 90 } else { 91 std::string number = name.substr(dot + 1); 92 if (!isdigit(number.data()[0])) { 93 name += ".1"; 94 } else { 95 unsigned long long i = std::stoull(number); 96 name = sub + "." + std::to_string(i + 1); 97 } 98 } 99 100 return __android_log_pmsg_file_write(logId, prio, name.c_str(), buf, len); 101 } 102 103 int main(int argc, char **argv) { 104 static const char filter[] = "recovery/"; 105 static const char force_rotate_flag[] = "--force-rotate"; 106 static const char rotate_flag[] = "--rotate"; 107 ssize_t ret; 108 bool doRotate = false; 109 110 // Take last pmsg contents and rewrite it to the current pmsg session. 111 if ((argc <= 1) || !argv[1] || 112 (((doRotate = strcmp(argv[1], rotate_flag))) && 113 strcmp(argv[1], force_rotate_flag))) { 114 doRotate = false; 115 } else if (!doRotate) { 116 // Do we need to rotate? 117 __android_log_pmsg_file_read( 118 LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, 119 logbasename, &doRotate); 120 } 121 122 // Take action to refresh pmsg contents 123 ret = __android_log_pmsg_file_read( 124 LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, 125 logrotate, &doRotate); 126 127 return (ret < 0) ? ret : 0; 128 } 129