1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "panic_error_info_handle.h"
17 #include <sys/stat.h>
18 #include "securec.h"
19 #include "hiview_logger.h"
20 #include "parameters.h"
21 #include "string_util.h"
22 #include "time_util.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace PanicErrorInfoHandle {
27 DEFINE_LOG_LABEL(0xD002D11, "PanicErrorInfoHandle");
28
29 using namespace std;
30
31 namespace {
32 constexpr int EVENT_MAX_LEN = 32;
33 constexpr int CATEGORY_MAX_LEN = 32;
34 constexpr int MODULE_MAX_LEN = 32;
35 constexpr int TIMESTAMP_MAX_LEN = 24;
36 constexpr int ERROR_DESC_MAX_LEN = 512;
37
38 constexpr const char* const HISTORY_LOG_PATH = "/data/log/bbox/history.log";
39 constexpr const char* const SYS_FS_PSTORE_PATH = "/sys/fs/pstore/blackbox-ramoops-0";
40
41 /* fault category type */
42 constexpr const char* const CATEGORY_SYSTEM_REBOOT = "SYSREBOOT";
43 constexpr const char* const CATEGORY_SYSTEM_POWEROFF = "POWEROFF";
44 constexpr const char* const CATEGORY_SYSTEM_PANIC = "PANIC";
45 constexpr const char* const CATEGORY_SYSTEM_OOPS = "OOPS";
46 constexpr const char* const CATEGORY_SYSTEM_CUSTOM = "CUSTOM";
47 constexpr const char* const CATEGORY_SYSTEM_WATCHDOG = "HWWATCHDOG";
48 constexpr const char* const CATEGORY_SYSTEM_HUNGTASK = "HUNGTASK";
49 constexpr const char* const CATEGORY_SUBSYSTEM_CUSTOM = "CUSTOM";
50
51 /* top category type */
52 constexpr const char* const TOP_CATEGORY_SYSTEM_RESET = "System Reset";
53 constexpr const char* const TOP_CATEGORY_FREEZE = "System Freeze";
54 constexpr const char* const TOP_CATEGORY_SYSTEM_POWEROFF = "POWEROFF";
55 constexpr const char* const TOP_CATEGORY_SUBSYSTEM_CRASH = "Subsystem Crash";
56
57 /* module type */
58 constexpr const char* const MODULE_SYSTEM = "SYSTEM";
59
60 /* fault event type */
61 constexpr const char* const EVENT_SYSREBOOT = "SYSREBOOT";
62 constexpr const char* const EVENT_LONGPRESS = "LONGPRESS";
63 constexpr const char* const EVENT_COMBINATIONKEY = "COMBINATIONKEY";
64 constexpr const char* const EVENT_SUBSYSREBOOT = "SUBSYSREBOOT";
65 constexpr const char* const EVENT_POWEROFF = "POWEROFF";
66 constexpr const char* const EVENT_PANIC = "PANIC";
67 constexpr const char* const EVENT_OOPS = "OOPS";
68 constexpr const char* const EVENT_SYS_WATCHDOG = "SYSWATCHDOG";
69 constexpr const char* const EVENT_HUNGTASK = "HUNGTASK";
70 }
71
72 struct ErrorInfo {
73 char event[EVENT_MAX_LEN];
74 char category[CATEGORY_MAX_LEN];
75 char module[MODULE_MAX_LEN];
76 char errorTime[TIMESTAMP_MAX_LEN];
77 char errorDesc[ERROR_DESC_MAX_LEN];
78 };
79
80
81 struct ErrorInfoToCategory {
82 const char *module;
83 struct {
84 const char *event;
85 const char *category;
86 const char *topCategory;
87 } map;
88 };
89
90 struct ErrorInfoToCategory g_errorInfoCategories[] = {
91 {
92 MODULE_SYSTEM,
93 {EVENT_SYSREBOOT, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
94 },
95 {
96 MODULE_SYSTEM,
97 {EVENT_LONGPRESS, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
98 },
99 {
100 MODULE_SYSTEM,
101 {EVENT_COMBINATIONKEY, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
102 },
103 {
104 MODULE_SYSTEM,
105 {EVENT_SUBSYSREBOOT, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
106 },
107 {
108 MODULE_SYSTEM,
109 {EVENT_POWEROFF, CATEGORY_SYSTEM_POWEROFF, TOP_CATEGORY_SYSTEM_POWEROFF}
110 },
111 {
112 MODULE_SYSTEM,
113 {EVENT_PANIC, CATEGORY_SYSTEM_PANIC, TOP_CATEGORY_SYSTEM_RESET}
114 },
115 {
116 MODULE_SYSTEM,
117 {EVENT_OOPS, CATEGORY_SYSTEM_OOPS, TOP_CATEGORY_SYSTEM_RESET}
118 },
119 {
120 MODULE_SYSTEM,
121 {EVENT_SYS_WATCHDOG, CATEGORY_SYSTEM_WATCHDOG, TOP_CATEGORY_FREEZE}
122 },
123 {
124 MODULE_SYSTEM,
125 {EVENT_HUNGTASK, CATEGORY_SYSTEM_HUNGTASK, TOP_CATEGORY_FREEZE}
126 },
127 };
128
GetTopCategory(const char * module,const char * event)129 static const char *GetTopCategory(const char *module, const char *event)
130 {
131 int i;
132 int count = sizeof(g_errorInfoCategories) / sizeof(ErrorInfoToCategory);
133 if ((!module || !event)) {
134 HIVIEW_LOGE("module: %{public}p, event: %{public}p\n", module, event);
135 return TOP_CATEGORY_SUBSYSTEM_CRASH;
136 }
137 for (i = 0; i < count; i++) {
138 if (!strcmp(g_errorInfoCategories[i].module, module) &&
139 !strcmp(g_errorInfoCategories[i].map.event, event)) {
140 return g_errorInfoCategories[i].map.topCategory;
141 }
142 }
143 if (!strcmp(module, MODULE_SYSTEM)) {
144 return TOP_CATEGORY_SYSTEM_RESET;
145 }
146 return TOP_CATEGORY_SUBSYSTEM_CRASH;
147 }
148
GetCategory(const char * module,const char * event)149 static const char *GetCategory(const char *module, const char *event)
150 {
151 int i;
152 int count = sizeof(g_errorInfoCategories) / sizeof(ErrorInfoToCategory);
153
154 if ((!module || !event)) {
155 HIVIEW_LOGE("module: %{public}p, event: %{public}p\n", module, event);
156 return CATEGORY_SUBSYSTEM_CUSTOM;
157 }
158 for (i = 0; i < count; i++) {
159 if (!strcmp(g_errorInfoCategories[i].module, module) &&
160 !strcmp(g_errorInfoCategories[i].map.event, event)) {
161 return g_errorInfoCategories[i].map.category;
162 }
163 }
164 if (!strcmp(module, MODULE_SYSTEM)) {
165 return CATEGORY_SYSTEM_CUSTOM;
166 }
167 return CATEGORY_SUBSYSTEM_CUSTOM;
168 }
169
SaveHistoryLog(string bboxTime,string bboxSysreset,ErrorInfo * info)170 static void SaveHistoryLog(string bboxTime, string bboxSysreset, ErrorInfo* info)
171 {
172 ofstream fout;
173 fout.open(HISTORY_LOG_PATH, ios::out | ios::app);
174 if (!fout.is_open()) {
175 HIVIEW_LOGE("Failed to open file: %{public}s, error=%{public}d", HISTORY_LOG_PATH, errno);
176 return;
177 }
178 fout << "[" << GetTopCategory(info->module, info->event) << "],";
179 fout << "module[" << info->module << "],";
180 fout << "category[" << GetCategory(info->module, info->event) << "],";
181 fout << "event[" << info->event << "],";
182 fout << "time[" << bboxTime << "],";
183 fout << "sysreboot[" << bboxSysreset << "],";
184 fout << "errdesc[" << info->errorDesc << "],";
185 fout << "logpath[/data/log/bbox]";
186 fout << endl;
187 HIVIEW_LOGE("GetTopCategory: %{public}s, module: %{public}s",
188 GetTopCategory(info->module, info->event), info->module);
189 HIVIEW_LOGE("category: %{public}s, event: %{public}s",
190 GetCategory(info->module, info->event), info->event);
191 HIVIEW_LOGE("time: %{public}s, sysreboot: %{public}s, errorDesc: %{public}s",
192 bboxTime.c_str(), bboxSysreset.c_str(), info->errorDesc);
193 }
194
TryCreateDir(const string & dir)195 static bool TryCreateDir(const string &dir)
196 {
197 struct stat info;
198
199 if (stat(dir.c_str(), &info) != 0) {
200 constexpr mode_t defaultLogDirMode = 0770;
201 if (mkdir(dir.c_str(), defaultLogDirMode) != 0) {
202 HIVIEW_LOGE("dir: %{public}s create failed", dir.c_str());
203 return false;
204 }
205 HIVIEW_LOGI("dir: %{public}s create success", dir.c_str());
206 return true;
207 }
208
209 if (info.st_mode & S_IFDIR) {
210 HIVIEW_LOGI("dir:%{public}s already existed", dir.c_str());
211 return true;
212 }
213 HIVIEW_LOGE("path: %{public}s is file not dir", dir.c_str());
214 return false;
215 }
216
CopyPstoreFileToHistoryLog(ifstream & fin)217 static void CopyPstoreFileToHistoryLog(ifstream &fin)
218 {
219 uint64_t startTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC;
220 string dirPath = "/data/log/bbox/" +
221 TimeUtil::TimestampFormatToDate(startTime, "%Y%m%d-%H%M%S") + "/";
222 if (!TryCreateDir(dirPath)) {
223 HIVIEW_LOGE("TryCreateDir failed. path: %{public}s", dirPath.c_str());
224 return;
225 }
226 string targetPath = dirPath + "last_kmsg";
227 ofstream fout;
228 fout.open(targetPath, ios::in | ios::out | ios::trunc);
229 if (!fout.is_open()) {
230 HIVIEW_LOGE("Failed to open file: %{public}s error=%{public}d", targetPath.c_str(), errno);
231 return;
232 }
233 fout << fin.rdbuf();
234 fout << endl;
235 }
236
RKTransData(std::string bboxTime,std::string bboxSysreset)237 void RKTransData(std::string bboxTime, std::string bboxSysreset)
238 {
239 string deviceInfo = system::GetParameter("const.product.devicetype", "");
240 if (deviceInfo != "default") {
241 return;
242 }
243 ifstream fin(SYS_FS_PSTORE_PATH);
244 if (!fin.is_open()) {
245 HIVIEW_LOGE("Failed to open file: %{public}s, error=%{public}d", SYS_FS_PSTORE_PATH, errno);
246 return;
247 }
248 ErrorInfo info = {};
249 fin.read(reinterpret_cast<char* >(&info), sizeof(ErrorInfo));
250 if (!fin) {
251 HIVIEW_LOGE("Read error_info failed");
252 return;
253 }
254 SaveHistoryLog(bboxTime, bboxSysreset, &info);
255 CopyPstoreFileToHistoryLog(fin);
256 }
257 }
258 }
259 }
260