developer | e303c2e | 2022-02-09 11:35:09 +0800 | [diff] [blame] | 1 | --- 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(); |