1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun * You may obtain a copy of the License at
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun * limitations under the License.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define _GNU_SOURCE
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <dirent.h>
20*4882a593Smuzhiyun #include <libgen.h>
21*4882a593Smuzhiyun #include <stdio.h>
22*4882a593Smuzhiyun #include <stdlib.h>
23*4882a593Smuzhiyun #include <string.h>
24*4882a593Smuzhiyun #include <unistd.h>
25*4882a593Smuzhiyun #include <sys/stat.h>
26*4882a593Smuzhiyun #include <sys/types.h>
27*4882a593Smuzhiyun #include <sys/wait.h>
28*4882a593Smuzhiyun #include <sys/mount.h>
29*4882a593Smuzhiyun #include <errno.h>
30*4882a593Smuzhiyun #include "mtdutils.h"
31*4882a593Smuzhiyun #include "rk29.h"
32*4882a593Smuzhiyun #include "common.h"
33*4882a593Smuzhiyun
run(const char * filename,char * const argv[])34*4882a593Smuzhiyun int run(const char *filename, char *const argv[])
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun struct stat s;
37*4882a593Smuzhiyun int status;
38*4882a593Smuzhiyun pid_t pid;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun if (stat(filename, &s) != 0) {
41*4882a593Smuzhiyun LOGE("cannot find '%s'", filename);
42*4882a593Smuzhiyun return -1;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun LOGI("executing '%s'\n", filename);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun pid = fork();
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (pid == 0) {
50*4882a593Smuzhiyun setpgid(0, getpid());
51*4882a593Smuzhiyun /* execute */
52*4882a593Smuzhiyun execv(filename, argv);
53*4882a593Smuzhiyun LOGE("can't run %s (%s)\n", filename, strerror(errno));
54*4882a593Smuzhiyun /* exit */
55*4882a593Smuzhiyun _exit(0);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun if (pid < 0) {
59*4882a593Smuzhiyun LOGE("failed to fork and start '%s'\n", filename);
60*4882a593Smuzhiyun return -1;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (-1 == waitpid(pid, &status, WCONTINUED | WUNTRACED)) {
64*4882a593Smuzhiyun LOGE("wait for child error\n");
65*4882a593Smuzhiyun return -1;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun if (WIFEXITED(status)) {
69*4882a593Smuzhiyun LOGI("executed '%s' done\n", filename);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun LOGI("executed '%s' return %d\n", filename, WEXITSTATUS(status));
73*4882a593Smuzhiyun return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
rk_check_and_resizefs(const char * filename)76*4882a593Smuzhiyun int rk_check_and_resizefs(const char *filename)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun int result;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun const char *const e2fsck_argv[] = { "/sbin/e2fsck", "-fy", filename, NULL };
81*4882a593Smuzhiyun const char *const resizefs_argv[] = { "/sbin/resize2fs", filename, NULL };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun result = run(e2fsck_argv[0], (char **) e2fsck_argv);
84*4882a593Smuzhiyun if (result) {
85*4882a593Smuzhiyun LOGI("e2fsck check '%s' failed!\n", filename);
86*4882a593Smuzhiyun return result;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun result = run(resizefs_argv[0], (char **) resizefs_argv);
90*4882a593Smuzhiyun if (result) {
91*4882a593Smuzhiyun LOGI("resizefs '%s' failed!\n", filename);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return result;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
rk_check_and_resizefs_f2fs(const char * filename)97*4882a593Smuzhiyun int rk_check_and_resizefs_f2fs(const char *filename)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun int result;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun const char *const e2fsck_argv[] = { "fsck_f2fs", filename, NULL };
102*4882a593Smuzhiyun const char *const resizefs_argv[] = { "resize.f2fs", filename, NULL };
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun result = run(e2fsck_argv[0], (char **) e2fsck_argv);
105*4882a593Smuzhiyun if (result) {
106*4882a593Smuzhiyun LOGI("fsck_f2fs check '%s' failed!\n", filename);
107*4882a593Smuzhiyun return result;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun result = run(resizefs_argv[0], (char **) resizefs_argv);
111*4882a593Smuzhiyun if (result) {
112*4882a593Smuzhiyun LOGI("resize.f2fs '%s' failed!\n", filename);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun return result;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
make_extfs(const char * path,const char * label,const char * type)118*4882a593Smuzhiyun static int make_extfs(const char *path, const char *label, const char *type)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun const char *const mke2fs[] = {
121*4882a593Smuzhiyun "/sbin/mke2fs", "-t", type, "-q", path, NULL,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun // max-mount-counts(0) + time-dependent checking(0) + fslabel
125*4882a593Smuzhiyun const char *const tune2fs[] = {
126*4882a593Smuzhiyun "/sbin/tune2fs", "-c", "0", "-i", "0", "-L", label, path, NULL,
127*4882a593Smuzhiyun };
128*4882a593Smuzhiyun int result;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun LOGI("format '%s' to %s filesystem\n", path, type);
131*4882a593Smuzhiyun result = run(mke2fs[0], (char **) mke2fs);
132*4882a593Smuzhiyun if (result) {
133*4882a593Smuzhiyun LOGI("failed!\n");
134*4882a593Smuzhiyun return result;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun result = run(tune2fs[0], (char **) tune2fs);
138*4882a593Smuzhiyun if (result) {
139*4882a593Smuzhiyun LOGI("failed!\n");
140*4882a593Smuzhiyun return result;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return result;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
make_ext2(const char * path,const char * label)146*4882a593Smuzhiyun int make_ext2(const char *path, const char *label)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun return make_extfs(path, label, "ext2");
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
make_ext4(const char * path,const char * label)151*4882a593Smuzhiyun int make_ext4(const char *path, const char *label)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun return make_extfs(path, label, "ext4");
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
make_vfat(const char * path,const char * label)156*4882a593Smuzhiyun int make_vfat(const char *path, const char *label)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun // fat32
159*4882a593Smuzhiyun const char *const mkdosfs[] = {
160*4882a593Smuzhiyun "/sbin/mkdosfs", "-F", "32", "-n", label, path, NULL,
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun LOGI("format '%s' to vfat filesystem\n", path);
164*4882a593Smuzhiyun return run(mkdosfs[0], (char **) mkdosfs);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
make_ntfs(const char * path,const char * label)167*4882a593Smuzhiyun int make_ntfs(const char *path, const char *label)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun // compression
170*4882a593Smuzhiyun const char *const mkntfs[] = {
171*4882a593Smuzhiyun "mkntfs", "-F", "C", "Q", "-L", label, path, NULL,
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun LOGI("format '%s' to ntfs filesystem\n", path);
175*4882a593Smuzhiyun return run(mkntfs[0], (char **) mkntfs);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun #ifndef min
179*4882a593Smuzhiyun #define min(a,b) ((a)<(b)?(a):(b))
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun
rk29_fread(void * ptr,size_t size,size_t nmemb,FILE * stream)182*4882a593Smuzhiyun size_t rk29_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun char buf[READ_SIZE];
185*4882a593Smuzhiyun int fd;
186*4882a593Smuzhiyun long begin, end;
187*4882a593Smuzhiyun off_t offset;
188*4882a593Smuzhiyun ssize_t sz;
189*4882a593Smuzhiyun size_t count = 0, total;
190*4882a593Smuzhiyun char *p = ptr;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (!ptr)
193*4882a593Smuzhiyun return 0;
194*4882a593Smuzhiyun if (!size || !nmemb)
195*4882a593Smuzhiyun return 0;
196*4882a593Smuzhiyun if (!stream)
197*4882a593Smuzhiyun return 0;
198*4882a593Smuzhiyun fd = fileno(stream);
199*4882a593Smuzhiyun if (fd < 0)
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun begin = ftell(stream);
203*4882a593Smuzhiyun if (begin < 0)
204*4882a593Smuzhiyun begin = 0;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun total = size * nmemb;
207*4882a593Smuzhiyun if (!total)
208*4882a593Smuzhiyun return 0;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun end = begin + total;
211*4882a593Smuzhiyun offset = begin & ~READ_MASK;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (begin & READ_MASK) {
214*4882a593Smuzhiyun sz = pread(fd, buf, READ_SIZE, offset);
215*4882a593Smuzhiyun if (sz < READ_SIZE)
216*4882a593Smuzhiyun goto out;
217*4882a593Smuzhiyun count = min(end, offset + READ_SIZE) - begin;
218*4882a593Smuzhiyun memcpy(p, buf + (begin & READ_MASK), count);
219*4882a593Smuzhiyun p += count;
220*4882a593Smuzhiyun offset += READ_SIZE;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun for (; offset < (end & ~READ_MASK); offset += READ_SIZE) {
224*4882a593Smuzhiyun sz = pread(fd, buf, READ_SIZE, offset);
225*4882a593Smuzhiyun if (sz < READ_SIZE)
226*4882a593Smuzhiyun goto out;
227*4882a593Smuzhiyun count += READ_SIZE;
228*4882a593Smuzhiyun memcpy(p, buf, READ_SIZE);
229*4882a593Smuzhiyun p += READ_SIZE;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (count < total && (end & READ_MASK)) {
233*4882a593Smuzhiyun offset = end & ~READ_MASK;
234*4882a593Smuzhiyun sz = pread(fd, buf, READ_SIZE, offset);
235*4882a593Smuzhiyun if (sz < READ_SIZE)
236*4882a593Smuzhiyun goto out;
237*4882a593Smuzhiyun memcpy(p, buf, end - offset);
238*4882a593Smuzhiyun count += end - offset;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun out:
241*4882a593Smuzhiyun count /= size;
242*4882a593Smuzhiyun fseek(stream, begin + count * size, SEEK_SET);
243*4882a593Smuzhiyun return count;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
rk29_fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)246*4882a593Smuzhiyun size_t rk29_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun char buf[WRITE_SIZE];
249*4882a593Smuzhiyun int fd;
250*4882a593Smuzhiyun long begin, end;
251*4882a593Smuzhiyun off_t offset;
252*4882a593Smuzhiyun ssize_t sz;
253*4882a593Smuzhiyun size_t count = 0, total;
254*4882a593Smuzhiyun char *p = (char *)ptr;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (!ptr)
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun if (!size || !nmemb)
259*4882a593Smuzhiyun return 0;
260*4882a593Smuzhiyun if (!stream)
261*4882a593Smuzhiyun return 0;
262*4882a593Smuzhiyun fd = fileno(stream);
263*4882a593Smuzhiyun if (fd < 0)
264*4882a593Smuzhiyun return 0;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun begin = ftell(stream);
267*4882a593Smuzhiyun if (begin < 0)
268*4882a593Smuzhiyun begin = 0;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun total = size * nmemb;
271*4882a593Smuzhiyun if (!total)
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun end = begin + total;
275*4882a593Smuzhiyun offset = begin & ~WRITE_MASK;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if (begin & WRITE_MASK) {
278*4882a593Smuzhiyun sz = pread(fd, buf, WRITE_SIZE, offset);
279*4882a593Smuzhiyun if (sz < WRITE_SIZE)
280*4882a593Smuzhiyun goto out;
281*4882a593Smuzhiyun count = min(end, offset + WRITE_SIZE) - begin;
282*4882a593Smuzhiyun memcpy(buf + (begin & WRITE_MASK), p, count);
283*4882a593Smuzhiyun sz = pwrite(fd, buf, WRITE_SIZE, offset);
284*4882a593Smuzhiyun if (sz < WRITE_SIZE)
285*4882a593Smuzhiyun goto out;
286*4882a593Smuzhiyun p += count;
287*4882a593Smuzhiyun offset += WRITE_SIZE;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun for (; offset < (end & ~WRITE_MASK); offset += WRITE_SIZE) {
291*4882a593Smuzhiyun sz = pwrite(fd, p, WRITE_SIZE, offset);
292*4882a593Smuzhiyun if (sz < WRITE_SIZE)
293*4882a593Smuzhiyun goto out;
294*4882a593Smuzhiyun count += WRITE_SIZE;
295*4882a593Smuzhiyun p += WRITE_SIZE;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (count < total && (end & WRITE_MASK)) {
299*4882a593Smuzhiyun offset = end & ~WRITE_MASK;
300*4882a593Smuzhiyun sz = pread(fd, buf, WRITE_SIZE, offset);
301*4882a593Smuzhiyun if (sz < WRITE_SIZE)
302*4882a593Smuzhiyun goto out;
303*4882a593Smuzhiyun memcpy(buf, p, end - offset);
304*4882a593Smuzhiyun sz = pwrite(fd, buf, WRITE_SIZE, offset);
305*4882a593Smuzhiyun if (sz < WRITE_SIZE)
306*4882a593Smuzhiyun goto out;
307*4882a593Smuzhiyun count += end - offset;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun out:
310*4882a593Smuzhiyun count /= size;
311*4882a593Smuzhiyun fseek(stream, begin + count * size, SEEK_SET);
312*4882a593Smuzhiyun return count;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315