blob: a4a9d6c1173d53c91b4ffe638930d9947e9f7e32 [file] [log] [blame]
developere303c2e2022-02-09 11:35:09 +08001--- a/CMakeLists.txt
2+++ b/CMakeLists.txt
3@@ -5,6 +5,10 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror
4
5 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
6
7+ADD_LIBRARY(fstools-bootparam SHARED
8+ boot_param.c)
9+INSTALL(TARGETS fstools-bootparam LIBRARY DESTINATION lib)
10+
11 ADD_LIBRARY(fstools SHARED
12 libfstools/snapshot.c
13 libfstools/extroot.c
14@@ -15,7 +19,7 @@ ADD_LIBRARY(fstools SHARED
15 libfstools/ubi.c
16 libfstools/rootdisk.c
17 libfstools/find.c)
18-TARGET_LINK_LIBRARIES(fstools ubox)
19+TARGET_LINK_LIBRARIES(fstools ubox fstools-bootparam)
20 INSTALL(TARGETS fstools LIBRARY DESTINATION lib)
21
22 ADD_LIBRARY(blkid-tiny SHARED
23@@ -75,9 +79,9 @@ INSTALL(TARGETS blockd RUNTIME DESTINATI
24 ADD_EXECUTABLE(block block.c probe.c probe-libblkid.c)
25 IF(DEFINED CMAKE_UBIFS_EXTROOT)
26 ADD_DEFINITIONS(-DUBIFS_EXTROOT)
27- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ubi-utils ${json})
28+ TARGET_LINK_LIBRARIES(block blkid-tiny fstools-bootparam dl uci ubox ubus blobmsg_json ubi-utils ${json})
29 ELSE(DEFINED CMAKE_UBIFS_EXTROOT)
30- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ${json})
31+ TARGET_LINK_LIBRARIES(block blkid-tiny fstools-bootparam dl uci ubox ubus blobmsg_json ${json})
32 ENDIF(DEFINED CMAKE_UBIFS_EXTROOT)
33 INSTALL(TARGETS block RUNTIME DESTINATION sbin)
34
35--- a/block.c
36+++ b/block.c
37@@ -47,6 +47,7 @@
38 #include <libubus.h>
39
40 #include "probe.h"
41+#include "boot_param.h"
42
43 #define AUTOFS_MOUNT_PATH "/tmp/run/blockd/"
44
45@@ -89,6 +90,9 @@ static LIST_HEAD(devices);
46 static int anon_mount, anon_swap, auto_mount, auto_swap, check_fs;
47 static unsigned int delay_root;
48
49+static char *hide_block_devs[3];
50+static uint32_t num_hide_block_devs;
51+
52 enum {
53 CFG_ANON_MOUNT,
54 CFG_ANON_SWAP,
55@@ -498,9 +502,12 @@ static struct probe_info* _probe_path(ch
56 return probe_path(path);
57 }
58
59+static char* find_mount_point(char *block);
60+
61 static int _cache_load(const char *path)
62 {
63 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
64+ uint32_t i;
65 int j;
66 glob_t gl;
67
68@@ -509,8 +516,30 @@ static int _cache_load(const char *path)
69
70 for (j = 0; j < gl.gl_pathc; j++) {
71 struct probe_info *pr = _probe_path(gl.gl_pathv[j]);
72- if (pr)
73+ bool skip_curr = false;
74+
75+ if (pr) {
76+ char *mp = find_mount_point(pr->dev);
77+ if (mp) {
78+ /* Skip blocks mounted as root or overlay */
79+ if (!strcmp(mp, "/rom") ||
80+ !strcmp(mp, "/overlay"))
81+ continue;
82+ }
83+
84+ for (i = 0; i < num_hide_block_devs; i++) {
85+ /* Skip blocks used for dual boot */
86+ if (!strcmp(hide_block_devs[i], pr->dev)) {
87+ skip_curr = true;
88+ break;
89+ }
90+ }
91+
92+ if (skip_curr)
93+ continue;
94+
95 list_add_tail(&pr->list, &devices);
96+ }
97 }
98
99 globfree(&gl);
100@@ -1801,6 +1830,26 @@ static int main_swapoff(int argc, char *
101 return 0;
102 }
103
104+static bool add_hide_block_dev(char *path)
105+{
106+ if (num_hide_block_devs >= ARRAY_SIZE(hide_block_devs))
107+ return false;
108+
109+ hide_block_devs[num_hide_block_devs++] = path;
110+ return true;
111+}
112+
113+static void hide_boot_param_dev(const char *name)
114+{
115+ char *path;
116+
117+ path = boot_param_get_dev(name);
118+ if (path) {
119+ if (!add_hide_block_dev(path))
120+ free(path);
121+ }
122+}
123+
124 int main(int argc, char **argv)
125 {
126 char *base = basename(*argv);
127@@ -1810,6 +1859,10 @@ int main(int argc, char **argv)
128 ulog_open(-1, -1, "block");
129 ulog_threshold(LOG_NOTICE);
130
131+ hide_boot_param_dev("rootfs_data_part");
132+ hide_boot_param_dev("boot_rootfs_part");
133+ hide_boot_param_dev("upgrade_rootfs_part");
134+
135 if (!strcmp(base, "swapon"))
136 return main_swapon(argc, argv);
137
138--- a/boot_param.c
139+++ b/boot_param.c
140@@ -0,0 +1,270 @@
141+/* SPDX-License-Identifier: BSD-3-Clause */
142+/*
143+ * Copyright (C) 2022 MediaTek Inc. All rights reserved.
144+ *
145+ * Author: Weijie Gao <weijie.gao@mediatek.com>
146+ */
147+
148+#include <sys/types.h>
149+#include <sys/stat.h>
150+#include <stdio.h>
151+#include <string.h>
152+#include <dirent.h>
153+#include <fcntl.h>
154+#include <unistd.h>
155+#include <glob.h>
156+#include <dlfcn.h>
157+
158+#include <blkid/blkid.h>
159+#include <libubox/ulog.h>
160+#include "boot_param.h"
161+
162+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
163+
164+#define BOOT_PARAM_STR_MAX_LEN 256
165+
166+static struct {
167+ bool loaded;
168+ blkid_probe (*new_probe_from_filename)(const char *);
169+ int (*do_safeprobe)(blkid_probe);
170+ int (*probe_lookup_value)(blkid_probe, const char *, const char **, size_t *);
171+ void (*free_probe)(blkid_probe);
172+ int (*probe_enable_partitions)(blkid_probe, int);
173+ int (*probe_set_partitions_flags)(blkid_probe, int);
174+} libblkid = {};
175+
176+bool read_boot_param_bool(const char *name)
177+{
178+ char path[BOOT_PARAM_STR_MAX_LEN], val;
179+ size_t len;
180+ FILE *f;
181+
182+ snprintf(path, sizeof(path), "/sys/module/boot_param/parameters/%s",
183+ name);
184+
185+ f = fopen(path, "rb");
186+ if (!f)
187+ return false;
188+
189+ len = fread(&val, 1, 1, f);
190+ fclose(f);
191+
192+ if (len != 1)
193+ return false;
194+
195+ return val == 'Y';
196+}
197+
198+int read_boot_param_string(const char *name, char *val, size_t maxsize)
199+{
200+ char path[BOOT_PARAM_STR_MAX_LEN];
201+ size_t len;
202+ FILE *f;
203+
204+ snprintf(path, sizeof(path), "/sys/module/boot_param/parameters/%s",
205+ name);
206+
207+ f = fopen(path, "rb");
208+ if (!f) {
209+ val[0] = 0;
210+ return -1;
211+ }
212+
213+ len = fread(val, 1, maxsize, f);
214+ fclose(f);
215+
216+ while (len > 0) {
217+ if (val[len - 1] != '\n' && val[len - 1] != '\r')
218+ break;
219+
220+ len--;
221+ }
222+
223+ if (len < maxsize)
224+ val[len] = 0;
225+
226+ return len;
227+}
228+
229+int write_boot_param_string(const char *name, const char *val)
230+{
231+ size_t wlen, len = strlen(val);
232+ char path[BOOT_PARAM_STR_MAX_LEN];
233+ FILE *f;
234+
235+ if (len >= BOOT_PARAM_STR_MAX_LEN)
236+ return -1;
237+
238+ snprintf(path, sizeof(path), "/sys/module/boot_param/parameters/%s",
239+ name);
240+
241+ f = fopen(path, "wb");
242+ if (!f)
243+ return -1;
244+
245+ wlen = fwrite(val, 1, len, f);
246+ fclose(f);
247+
248+ return wlen;
249+}
250+
251+static bool load_libblkid(void)
252+{
253+ void *lib;
254+
255+ if (libblkid.loaded)
256+ return true;
257+
258+ lib = dlopen("libblkid.so", RTLD_GLOBAL);
259+
260+ if (!lib)
261+ lib = dlopen("libblkid.so.1", RTLD_GLOBAL);
262+
263+ if (!lib)
264+ return false;
265+
266+ libblkid.new_probe_from_filename = dlsym(lib, "blkid_new_probe_from_filename");
267+ if (!libblkid.new_probe_from_filename)
268+ return false;
269+
270+ libblkid.do_safeprobe = dlsym(lib, "blkid_do_safeprobe");
271+ if (!libblkid.do_safeprobe)
272+ return false;
273+
274+ libblkid.probe_lookup_value = dlsym(lib, "blkid_probe_lookup_value");
275+ if (!libblkid.probe_lookup_value)
276+ return false;
277+
278+ libblkid.free_probe = dlsym(lib, "blkid_free_probe");
279+ if (!libblkid.free_probe)
280+ return false;
281+
282+ libblkid.probe_enable_partitions = dlsym(lib, "blkid_probe_enable_partitions");
283+ if (!libblkid.probe_enable_partitions)
284+ return false;
285+
286+ libblkid.probe_set_partitions_flags = dlsym(lib, "blkid_probe_set_partitions_flags");
287+ if (!libblkid.probe_set_partitions_flags)
288+ return false;
289+
290+ libblkid.loaded = true;
291+ return true;
292+}
293+
294+static char *lookup_block_dev(const char *path, const char *key, bool is_uuid)
295+{
296+ int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
297+ const char *type, *value;
298+ char *result = NULL;
299+ size_t len;
300+ glob_t gl;
301+ int i;
302+
303+ if (glob(path, gl_flags, NULL, &gl) < 0)
304+ return NULL;
305+
306+ type = is_uuid ? "PART_ENTRY_UUID" : "PART_ENTRY_NAME";
307+
308+ for (i = 0; i < gl.gl_pathc; i++) {
309+ blkid_probe pr = libblkid.new_probe_from_filename(gl.gl_pathv[i]);
310+ if (!pr)
311+ continue;
312+
313+ libblkid.probe_enable_partitions(pr, 1);
314+ libblkid.probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
315+
316+ if (libblkid.do_safeprobe(pr))
317+ goto free_pr;
318+
319+ if (!libblkid.probe_lookup_value(pr, type, &value, &len)) {
320+ if (!strcmp(value, key))
321+ result = strdup(gl.gl_pathv[i]);
322+ }
323+
324+ free_pr:
325+ libblkid.free_probe(pr);
326+
327+ if (result)
328+ break;
329+ }
330+
331+ globfree(&gl);
332+
333+ return result;
334+}
335+
336+static char *find_block_dev(const char *key, bool is_uuid)
337+{
338+ char *devpath = NULL;
339+ int i;
340+
341+ static const char *block_pats[] = {
342+ "/dev/loop*",
343+ "/dev/mmcblk*",
344+ "/dev/sd*",
345+ "/dev/hd*",
346+ "/dev/md*",
347+ "/dev/nvme*",
348+ "/dev/vd*",
349+ "/dev/xvd*",
350+ "/dev/mapper/*",
351+ };
352+
353+ if (!load_libblkid())
354+ return NULL;
355+
356+ for (i = 0; i < ARRAY_SIZE(block_pats); i++) {
357+ devpath = lookup_block_dev(block_pats[i], key, is_uuid);
358+ if (devpath)
359+ break;
360+ }
361+
362+ return devpath;
363+}
364+
365+char *blockdev_parse(const char *name)
366+{
367+ char *e, *part_dev_path;
368+ struct stat st;
369+
370+ if (!name)
371+ return NULL;
372+
373+ e = strchr(name, '=');
374+ if (e) {
375+ *e = 0;
376+ e++;
377+ }
378+
379+ if (!e) {
380+ if (stat(name, &st))
381+ return NULL;
382+
383+ if (!S_ISBLK(st.st_mode))
384+ return NULL;
385+
386+ part_dev_path = strdup(name);
387+ } else if (!strcmp(name, "PARTLABEL")) {
388+ part_dev_path = find_block_dev(e, false);
389+ } else if (!strcmp(name, "PARTUUID")) {
390+ if (strlen(e) != 36)
391+ return NULL;
392+ part_dev_path = find_block_dev(e, true);
393+ } else {
394+ return NULL;
395+ }
396+
397+ return part_dev_path;
398+}
399+
400+char *boot_param_get_dev(const char *name)
401+{
402+ char partkey[BOOT_PARAM_STR_MAX_LEN];
403+
404+ read_boot_param_string(name, partkey, sizeof(partkey));
405+
406+ if (!partkey[0])
407+ return NULL;
408+
409+ return blockdev_parse(partkey);
410+}
411--- a/boot_param.h
412+++ b/boot_param.h
413@@ -0,0 +1,21 @@
414+// SPDX-License-Identifier: BSD-3-Clause
415+/*
416+ * Copyright (C) 2022 MediaTek Inc. All rights reserved.
417+ *
418+ * Author: Weijie Gao <weijie.gao@mediatek.com>
419+ */
420+
421+#ifndef _BOOT_PARAM_H_
422+#define _BOOT_PARAM_H_
423+
424+#include <stddef.h>
425+#include <stdbool.h>
426+
427+bool read_boot_param_bool(const char *name);
428+int read_boot_param_string(const char *name, char *val, size_t maxsize);
429+int write_boot_param_string(const char *name, const char *val);
430+
431+char *blockdev_parse(const char *name);
432+char *boot_param_get_dev(const char *name);
433+
434+#endif /* _BOOT_PARAM_H_ */
435--- a/libfstools/rootdisk.c
436+++ b/libfstools/rootdisk.c
437@@ -26,6 +26,7 @@
438
439 #include "libfstools.h"
440 #include "volume.h"
441+#include "../boot_param.h"
442
443 #include <linux/loop.h>
444
445@@ -42,6 +43,7 @@ struct rootdev_volume {
446 struct volume v;
447 uint64_t offset;
448 char loop_name[32];
449+ char *dev_path;
450 };
451
452 static const char *rootdev;
453@@ -109,11 +111,15 @@ static int get_squashfs(struct squashfs_
454
455 static bool rootdisk_use_f2fs(struct rootdev_volume *p)
456 {
457+ const char *dev = rootdev;
458 uint64_t size = 0;
459 bool ret = false;
460 int fd;
461
462- fd = open(rootdev, O_RDONLY);
463+ if (p->dev_path)
464+ dev = p->dev_path;
465+
466+ fd = open(dev, O_RDONLY);
467 if (ioctl(fd, BLKGETSIZE64, &size) == 0)
468 ret = size - p->offset > F2FS_MINSIZE;
469 close(fd);
470@@ -121,6 +127,30 @@ static bool rootdisk_use_f2fs(struct roo
471 return ret;
472 }
473
474+static struct volume *find_existed_rootfs_data(void)
475+{
476+ struct rootdev_volume *p;
477+ char *rootfs_data_dev;
478+
479+ rootfs_data_dev = boot_param_get_dev("rootfs_data_part");
480+
481+ if (!rootfs_data_dev)
482+ return NULL;
483+
484+ ULOG_NOTE("Using existed rootfs_data device %s\n", rootfs_data_dev);
485+
486+ write_boot_param_string("rootfs_data_part", rootfs_data_dev);
487+
488+ p = calloc(1, sizeof(*p));
489+ p->v.drv = &rootdisk_driver;
490+ p->v.name = "rootfs_data";
491+
492+ p->offset = 0;
493+ p->dev_path = rootfs_data_dev;
494+
495+ return &p->v;
496+}
497+
498 static struct volume *rootdisk_volume_find(char *name)
499 {
500 struct squashfs_super_block sb;
501@@ -129,6 +159,9 @@ static struct volume *rootdisk_volume_fi
502 if (strcmp(name, "rootfs_data") != 0)
503 return NULL;
504
505+ if (read_boot_param_bool("no_split_rootfs_data"))
506+ return find_existed_rootfs_data();
507+
508 if (!rootdev)
509 rootdev = get_rootdev("/");
510 if (!rootdev)
511@@ -160,12 +193,16 @@ static struct volume *rootdisk_volume_fi
512 static int rootdisk_volume_identify(struct volume *v)
513 {
514 struct rootdev_volume *p = container_of(v, struct rootdev_volume, v);
515+ const char *dev = rootdev;
516 int ret = FS_NONE;
517 uint32_t magic = 0;
518 size_t n;
519 FILE *f;
520
521- f = fopen(rootdev, "r");
522+ if (p->dev_path)
523+ dev = p->dev_path;
524+
525+ f = fopen(dev, "r");
526 if (!f)
527 return ret;
528
529@@ -265,6 +302,13 @@ static int rootdisk_volume_init(struct v
530 char str[128];
531 int ret = 0;
532
533+ if (p->dev_path) {
534+ /* Do not create loop device with no_split_rootfs_data set */
535+ v->type = BLOCKDEV;
536+ v->blk = p->dev_path;
537+ goto do_format;
538+ }
539+
540 if (!p->loop_name[0] && rootdisk_create_loop(p) != 0) {
541 ULOG_ERR("unable to create loop device\n");
542 return -1;
543@@ -273,6 +317,7 @@ static int rootdisk_volume_init(struct v
544 v->type = BLOCKDEV;
545 v->blk = p->loop_name;
546
547+do_format:
548 switch (rootdisk_volume_identify(v)) {
549 case FS_NONE:
550 ULOG_INFO("rootdisk overlay filesystem has not been formatted yet\n");
551--- a/mount_root.c
552+++ b/mount_root.c
553@@ -23,6 +23,8 @@
554 #include "libfstools/libfstools.h"
555 #include "libfstools/volume.h"
556
557+#include "boot_param.h"
558+
559 /*
560 * Called in the early (PREINIT) stage, when we immediately need some writable
561 * filesystem.
562@@ -58,6 +60,12 @@ start(int argc, char *argv[1])
563 /* There isn't extroot, so just try to mount "rootfs_data" */
564 volume_init(data);
565 switch (volume_identify(data)) {
566+ case -1:
567+ /* Use ramoverlay if no "rootfs_data" device found with no_split_rootfs_data set */
568+ if (!read_boot_param_bool("no_split_rootfs_data"))
569+ break;
570+
571+ /* fall through */
572 case FS_NONE:
573 ULOG_WARN("no usable overlay filesystem found, using tmpfs overlay\n");
574 return ramoverlay();