blob: edc4a2e29900165fdaa106a6421a6d48f870b228 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* printf */
2#include <stdio.h>
3
4/* open */
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8
9/* read */
10#include <unistd.h>
11
12/* free */
13#include <stdlib.h>
14
15/* ioctl */
16#include <sys/ioctl.h>
17
18/* lseek64 */
19#ifndef _LARGEFILE64_SOURCE
20#define _LARGEFILE64_SOURCE
21#endif
22#include <sys/types.h>
23#include <unistd.h>
24
25/* bzero */
26#include <strings.h>
27
28/* strlen, memset, strncpy, strtok... */
29#include <string.h>
30
31/* errno */
32#include <errno.h>
33
34/* BLKGETSIZE64 */
35#include <linux/fs.h>
36
37/* mrdump related */
38#include "mrdump_log.h"
39#include "mrdump_common.h"
40#include "mrdump_status.h"
41#include "mrdump_status_private.h"
42
43#ifdef __YOCTO_OS__
44#define strlcpy strncpy
45#endif
46
47static int file_read_string(const char* path, char *content, int len)
48{
49 if (len <= 0) {
50 return -2;
51 }
52
53 int fd = open(path, O_RDONLY);
54 if (fd < 0) {
55 return -1;
56 }
57
58 /* Preserved NULL byte */
59 len--;
60 int size = 0;
61 do {
62 int ret = read(fd, content + size, len - size);
63 if (ret <= 0)
64 break;
65 size = size + ret;
66 } while (size < len);
67 content[size] = 0;
68
69 close(fd);
70 return size;
71}
72
73static int expdb_open(struct partinfo *partinfo)
74{
75 uint64_t part_size;
76 uint32_t part_blksize;
77
78 memset(partinfo, 0, sizeof(struct partinfo));
79
80 char *pp = mrdump_get_device_node(MRDUMP_EXPDB_NAME);
81 if (pp == NULL) {
82 MD_LOGE("%s: No expdb partition found", __func__);
83 return -1;
84 }
85
86 int fd = open(pp, O_RDWR);
87 if (fd < 0) {
88 MD_LOGE("%s: open expdb failed(%d)", __func__, errno);
89 free(pp);
90 return -1;
91 }
92 free(pp);
93
94 if (ioctl(fd, BLKGETSIZE64, &part_size) < 0) {
95 MD_LOGE("%s, get expdb partition size fail(%d)", __func__, errno);
96 close(fd);
97 return -1;
98 }
99
100 if (ioctl(fd, BLKSSZGET, &part_blksize) < 0) {
101 MD_LOGE("%s, get sector size fail(%d)", __func__, errno);
102 close(fd);
103 return -1;
104 }
105
106 partinfo->fd = fd;
107 partinfo->size = part_size;
108 partinfo->blksize = part_blksize;
109
110 return 0;
111}
112
113int mrdump_is_supported(void)
114{
115 char kversion[16], lversion[16];
116 int klen, llen;
117
118 bzero(kversion, sizeof(kversion));
119 bzero(lversion, sizeof(lversion));
120
121 if (file_read_string(MRDUMP_KVER, kversion, sizeof(kversion)) < 0) {
122 MD_LOGE("%s: cannot get kernel version\n", __func__);
123 return 0;
124 }
125
126 klen = strlen(kversion);
127 if (klen == 0) {
128 MD_LOGE("%s: null kernel version\n", __func__);
129 return 0;
130 }
131
132 if (file_read_string(MRDUMP_LVER, lversion, sizeof(lversion)) < 0) {
133 MD_LOGE("%s: cannot get lk version\n", __func__);
134 return 0;
135 }
136
137 llen = strlen(lversion);
138 if (llen == 0) {
139 MD_LOGE("%s: null lk version\n", __func__);
140 return 0;
141 }
142
143 if ((klen != llen) || (strncmp(kversion, lversion, klen) != 0)) {
144 MD_LOGE("%s: kernel and lk version mismatched.\n", __func__);
145 return 0;
146 }
147
148 MD_LOGI("%s: true\n", __func__);
149 return 1;
150}
151
152bool mrdump_status_clear(void)
153{
154 struct partinfo partinfo;
155
156 if (expdb_open(&partinfo) >= 0) {
157 if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
158 MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
159 close(partinfo.fd);
160 return false;
161 }
162
163 struct mrdump_cblock_result cblock_result;
164 if (read(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
165 MD_LOGE("%s: Can't read part fd %d\n", __func__, partinfo.fd);
166 close(partinfo.fd);
167 return false;
168 }
169 memset(cblock_result.status, 0, sizeof(cblock_result.status));
170 strncpy(cblock_result.status, "CLEAR", 5);
171
172 if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
173 MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
174 close(partinfo.fd);
175 return false;
176 }
177 if (write(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
178 MD_LOGE("%s: Can't write part fd %d\n", __func__, partinfo.fd);
179 close(partinfo.fd);
180 return false;
181 }
182 close(partinfo.fd);
183 return true;
184 }
185 return false;
186}
187
188bool mrdump_status_get(struct mrdump_status_result *result)
189{
190 memset(result, 0, sizeof(struct mrdump_status_result));
191 result->struct_size = sizeof(struct mrdump_status_result);
192
193 struct partinfo partinfo;
194 if (expdb_open(&partinfo) >= 0) {
195 if (lseek64(partinfo.fd, partinfo.size - MRDUMP_OFFSET, SEEK_SET) < 0) {
196 MD_LOGE("%s: Can't seek part fd %d\n", __func__, partinfo.fd);
197 close(partinfo.fd);
198 return false;
199 }
200
201 struct mrdump_cblock_result cblock_result;
202 if (read(partinfo.fd, &cblock_result, sizeof(struct mrdump_cblock_result)) != sizeof(struct mrdump_cblock_result)) {
203 MD_LOGE("%s: Can't read part fd %d\n", __func__, partinfo.fd);
204 close(partinfo.fd);
205 return false;
206 }
207 close(partinfo.fd);
208
209 if (strcmp(cblock_result.sig, MRDUMP_SIG) != 0) {
210 MD_LOGE("%s: Signature mismatched (result: %s)\n", __func__, cblock_result.sig);
211 return false;
212 }
213 /* Copy/parsing status line */
214 strncpy(result->status_line, cblock_result.status, sizeof(cblock_result.status));
215 result->status_line[sizeof(result->status_line) - 1] = 0;
216
217 char *saveptr;
218 cblock_result.status[sizeof(cblock_result.status) - 1] = 0;
219 char *strval = strtok_r(cblock_result.status, "\n", &saveptr);
220 if (strval != NULL) {
221 if (strcmp(strval, "OK") == 0) {
222 result->status = MRDUMP_STATUS_OK;
223 result->output = MRDUMP_OUTPUT_NULL;
224
225 do {
226 strval = strtok_r(NULL, "\n", &saveptr);
227 if (strval != NULL) {
228 if (strncmp(strval, "OUTPUT:", 7) == 0) {
229 if (strcmp(strval + 7, "EXT4_DATA") == 0) {
230 result->output = MRDUMP_OUTPUT_DATA_FS;
231 }
232 else if (strcmp(strval + 7, "PARTITION_DATA") == 0) {
233 result->output = MRDUMP_OUTPUT_PARTITION;
234 }
235 else {
236 return false;
237 }
238 }
239 else if (strncmp(strval, "MODE:", 5) == 0) {
240 strlcpy(result->mode, strval + 5, sizeof(result->mode));
241 }
242 }
243 } while (strval != NULL);
244 }
245 else if (strcmp(strval, "NONE") == 0) {
246 result->status = MRDUMP_STATUS_NONE;
247 }
248 else if (strcmp(strval, "CLEAR") == 0) {
249 result->status = MRDUMP_STATUS_NONE;
250 }
251 else {
252 result->status = MRDUMP_STATUS_FAILED;
253 }
254 }
255 else {
256 MD_LOGE("%s: status parsing error \"%s\"\n", __func__, cblock_result.status);
257 return false;
258 }
259
260 strncpy(result->log_buf, cblock_result.log_buf, sizeof(cblock_result.log_buf));
261 result->log_buf[sizeof(result->log_buf) - 1] = 0;
262 return true;
263 }
264 return false;
265}