1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/async.h> 3 #include <linux/delay.h> 4 #include <linux/dirent.h> 5 #include <linux/export.h> 6 #include <linux/fcntl.h> 7 #include <linux/file.h> 8 #include <linux/fs.h> 9 #include <linux/fs_struct.h> 10 #include <linux/hex.h> 11 #include <linux/init.h> 12 #include <linux/init_syscalls.h> 13 #include <linux/kstrtox.h> 14 #include <linux/memblock.h> 15 #include <linux/mm.h> 16 #include <linux/namei.h> 17 #include <linux/overflow.h> 18 #include <linux/security.h> 19 #include <linux/slab.h> 20 #include <linux/string.h> 21 #include <linux/syscalls.h> 22 #include <linux/types.h> 23 #include <linux/umh.h> 24 #include <linux/utime.h> 25 26 #include <asm/byteorder.h> 27 28 #include "do_mounts.h" 29 #include "initramfs_internal.h" 30 31 static __initdata bool csum_present; 32 static __initdata u32 io_csum; 33 34 static ssize_t __init xwrite(struct file *file, const unsigned char *p, 35 size_t count, loff_t *pos) 36 { 37 ssize_t out = 0; 38 39 /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */ 40 while (count) { 41 ssize_t rv = kernel_write(file, p, count, pos); 42 43 if (rv < 0) { 44 if (rv == -EINTR || rv == -EAGAIN) 45 continue; 46 return out ? out : rv; 47 } else if (rv == 0) 48 break; 49 50 if (csum_present) { 51 ssize_t i; 52 53 for (i = 0; i < rv; i++) 54 io_csum += p[i]; 55 } 56 57 p += rv; 58 out += rv; 59 count -= rv; 60 } 61 62 return out; 63 } 64 65 static __initdata char *message; 66 static void __init error(char *x) 67 { 68 if (!message) 69 message = x; 70 } 71 72 #define panic_show_mem(fmt, ...) \ 73 ({ show_mem(); panic(fmt, ##__VA_ARGS__); }) 74 75 /* link hash */ 76 77 #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) 78 79 static __initdata struct hash { 80 int ino, minor, major; 81 umode_t mode; 82 struct hash *next; 83 char name[N_ALIGN(PATH_MAX)]; 84 } *head[32]; 85 static __initdata bool hardlink_seen; 86 87 static inline int hash(int major, int minor, int ino) 88 { 89 unsigned long tmp = ino + minor + (major << 3); 90 tmp += tmp >> 5; 91 return tmp & 31; 92 } 93 94 static char __init *find_link(int major, int minor, int ino, 95 umode_t mode, char *name) 96 { 97 struct hash **p, *q; 98 for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) { 99 if ((*p)->ino != ino) 100 continue; 101 if ((*p)->minor != minor) 102 continue; 103 if ((*p)->major != major) 104 continue; 105 if (((*p)->mode ^ mode) & S_IFMT) 106 continue; 107 return (*p)->name; 108 } 109 q = kmalloc_obj(struct hash); 110 if (!q) 111 panic_show_mem("can't allocate link hash entry"); 112 q->major = major; 113 q->minor = minor; 114 q->ino = ino; 115 q->mode = mode; 116 strscpy(q->name, name); 117 q->next = NULL; 118 *p = q; 119 hardlink_seen = true; 120 return NULL; 121 } 122 123 static void __init free_hash(void) 124 { 125 struct hash **p, *q; 126 for (p = head; hardlink_seen && p < head + 32; p++) { 127 while (*p) { 128 q = *p; 129 *p = q->next; 130 kfree(q); 131 } 132 } 133 hardlink_seen = false; 134 } 135 136 #ifdef CONFIG_INITRAMFS_PRESERVE_MTIME 137 static void __init do_utime(char *filename, time64_t mtime) 138 { 139 struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } }; 140 init_utimes(filename, t); 141 } 142 143 static void __init do_utime_path(const struct path *path, time64_t mtime) 144 { 145 struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } }; 146 vfs_utimes(path, t); 147 } 148 149 static __initdata LIST_HEAD(dir_list); 150 struct dir_entry { 151 struct list_head list; 152 time64_t mtime; 153 char name[]; 154 }; 155 156 static void __init dir_add(const char *name, size_t nlen, time64_t mtime) 157 { 158 struct dir_entry *de; 159 160 de = kmalloc_flex(*de, name, nlen); 161 if (!de) 162 panic_show_mem("can't allocate dir_entry buffer"); 163 INIT_LIST_HEAD(&de->list); 164 strscpy(de->name, name, nlen); 165 de->mtime = mtime; 166 list_add(&de->list, &dir_list); 167 } 168 169 static void __init dir_utime(void) 170 { 171 struct dir_entry *de, *tmp; 172 list_for_each_entry_safe(de, tmp, &dir_list, list) { 173 list_del(&de->list); 174 do_utime(de->name, de->mtime); 175 kfree(de); 176 } 177 } 178 #else 179 static void __init do_utime(char *filename, time64_t mtime) {} 180 static void __init do_utime_path(const struct path *path, time64_t mtime) {} 181 static void __init dir_add(const char *name, size_t nlen, time64_t mtime) {} 182 static void __init dir_utime(void) {} 183 #endif 184 185 static __initdata time64_t mtime; 186 187 /* cpio header parsing */ 188 189 static __initdata unsigned long ino, major, minor, nlink; 190 static __initdata umode_t mode; 191 static __initdata unsigned long body_len, name_len; 192 static __initdata uid_t uid; 193 static __initdata gid_t gid; 194 static __initdata unsigned rdev; 195 static __initdata u32 hdr_csum; 196 197 static int __init parse_header(char *s) 198 { 199 __be32 header[13]; 200 int ret; 201 202 ret = hex2bin((u8 *)header, s + 6, sizeof(header)); 203 if (ret) { 204 error("damaged header"); 205 return ret; 206 } 207 208 ino = be32_to_cpu(header[0]); 209 mode = be32_to_cpu(header[1]); 210 uid = be32_to_cpu(header[2]); 211 gid = be32_to_cpu(header[3]); 212 nlink = be32_to_cpu(header[4]); 213 mtime = be32_to_cpu(header[5]); /* breaks in y2106 */ 214 body_len = be32_to_cpu(header[6]); 215 major = be32_to_cpu(header[7]); 216 minor = be32_to_cpu(header[8]); 217 rdev = new_encode_dev(MKDEV(be32_to_cpu(header[9]), be32_to_cpu(header[10]))); 218 name_len = be32_to_cpu(header[11]); 219 hdr_csum = be32_to_cpu(header[12]); 220 return 0; 221 } 222 223 /* Finite-state machine */ 224 225 static __initdata enum state { 226 Start, 227 Collect, 228 GotHeader, 229 SkipIt, 230 GotName, 231 CopyFile, 232 GotSymlink, 233 Reset 234 } state, next_state; 235 236 static __initdata char *victim; 237 static unsigned long byte_count __initdata; 238 static __initdata loff_t this_header, next_header; 239 240 static inline void __init eat(unsigned n) 241 { 242 victim += n; 243 this_header += n; 244 byte_count -= n; 245 } 246 247 static __initdata char *collected; 248 static long remains __initdata; 249 static __initdata char *collect; 250 251 static void __init read_into(char *buf, unsigned size, enum state next) 252 { 253 if (byte_count >= size) { 254 collected = victim; 255 eat(size); 256 state = next; 257 } else { 258 collect = collected = buf; 259 remains = size; 260 next_state = next; 261 state = Collect; 262 } 263 } 264 265 static __initdata char *header_buf, *symlink_buf, *name_buf; 266 267 static int __init do_start(void) 268 { 269 read_into(header_buf, CPIO_HDRLEN, GotHeader); 270 return 0; 271 } 272 273 static int __init do_collect(void) 274 { 275 unsigned long n = remains; 276 if (byte_count < n) 277 n = byte_count; 278 memcpy(collect, victim, n); 279 eat(n); 280 collect += n; 281 if ((remains -= n) != 0) 282 return 1; 283 state = next_state; 284 return 0; 285 } 286 287 static int __init do_header(void) 288 { 289 if (!memcmp(collected, "070701", 6)) { 290 csum_present = false; 291 } else if (!memcmp(collected, "070702", 6)) { 292 csum_present = true; 293 } else { 294 if (memcmp(collected, "070707", 6) == 0) 295 error("incorrect cpio method used: use -H newc option"); 296 else 297 error("no cpio magic"); 298 return 1; 299 } 300 if (parse_header(collected)) 301 return 1; 302 next_header = this_header + N_ALIGN(name_len) + body_len; 303 next_header = (next_header + 3) & ~3; 304 state = SkipIt; 305 if (name_len <= 0 || name_len > PATH_MAX) 306 return 0; 307 if (S_ISLNK(mode)) { 308 if (body_len > PATH_MAX) 309 return 0; 310 collect = collected = symlink_buf; 311 remains = N_ALIGN(name_len) + body_len; 312 next_state = GotSymlink; 313 state = Collect; 314 return 0; 315 } 316 if (S_ISREG(mode) || !body_len) 317 read_into(name_buf, N_ALIGN(name_len), GotName); 318 return 0; 319 } 320 321 static int __init do_skip(void) 322 { 323 if (this_header + byte_count < next_header) { 324 eat(byte_count); 325 return 1; 326 } else { 327 eat(next_header - this_header); 328 state = next_state; 329 return 0; 330 } 331 } 332 333 static int __init do_reset(void) 334 { 335 while (byte_count && *victim == '\0') 336 eat(1); 337 if (byte_count && (this_header & 3)) 338 error("broken padding"); 339 return 1; 340 } 341 342 static void __init clean_path(char *path, umode_t fmode) 343 { 344 struct kstat st; 345 346 if (!init_stat(path, &st, AT_SYMLINK_NOFOLLOW) && 347 (st.mode ^ fmode) & S_IFMT) { 348 if (S_ISDIR(st.mode)) 349 init_rmdir(path); 350 else 351 init_unlink(path); 352 } 353 } 354 355 static int __init maybe_link(void) 356 { 357 if (nlink >= 2) { 358 char *old = find_link(major, minor, ino, mode, collected); 359 if (old) { 360 clean_path(collected, 0); 361 return (init_link(old, collected) < 0) ? -1 : 1; 362 } 363 } 364 return 0; 365 } 366 367 static __initdata struct file *wfile; 368 static __initdata loff_t wfile_pos; 369 370 static int __init do_name(void) 371 { 372 state = SkipIt; 373 next_state = Reset; 374 375 /* name_len > 0 && name_len <= PATH_MAX checked in do_header */ 376 if (collected[name_len - 1] != '\0') { 377 pr_err("initramfs name without nulterm: %.*s\n", 378 (int)name_len, collected); 379 error("malformed archive"); 380 return 1; 381 } 382 383 if (strcmp(collected, "TRAILER!!!") == 0) { 384 free_hash(); 385 return 0; 386 } 387 clean_path(collected, mode); 388 if (S_ISREG(mode)) { 389 int ml = maybe_link(); 390 if (ml >= 0) { 391 int openflags = O_WRONLY|O_CREAT|O_LARGEFILE; 392 if (ml != 1) 393 openflags |= O_TRUNC; 394 wfile = filp_open(collected, openflags, mode); 395 if (IS_ERR(wfile)) 396 return 0; 397 wfile_pos = 0; 398 io_csum = 0; 399 400 vfs_fchown(wfile, uid, gid); 401 vfs_fchmod(wfile, mode); 402 if (body_len) 403 vfs_truncate(&wfile->f_path, body_len); 404 state = CopyFile; 405 } 406 } else if (S_ISDIR(mode)) { 407 init_mkdir(collected, mode); 408 init_chown(collected, uid, gid, 0); 409 init_chmod(collected, mode); 410 dir_add(collected, name_len, mtime); 411 } else if (S_ISBLK(mode) || S_ISCHR(mode) || 412 S_ISFIFO(mode) || S_ISSOCK(mode)) { 413 if (maybe_link() == 0) { 414 init_mknod(collected, mode, rdev); 415 init_chown(collected, uid, gid, 0); 416 init_chmod(collected, mode); 417 do_utime(collected, mtime); 418 } 419 } 420 return 0; 421 } 422 423 static int __init do_copy(void) 424 { 425 if (byte_count >= body_len) { 426 if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len) 427 error("write error"); 428 429 do_utime_path(&wfile->f_path, mtime); 430 fput(wfile); 431 if (csum_present && io_csum != hdr_csum) 432 error("bad data checksum"); 433 eat(body_len); 434 state = SkipIt; 435 return 0; 436 } else { 437 if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count) 438 error("write error"); 439 body_len -= byte_count; 440 eat(byte_count); 441 return 1; 442 } 443 } 444 445 static int __init do_symlink(void) 446 { 447 if (collected[name_len - 1] != '\0') { 448 pr_err("initramfs symlink without nulterm: %.*s\n", 449 (int)name_len, collected); 450 error("malformed archive"); 451 return 1; 452 } 453 collected[N_ALIGN(name_len) + body_len] = '\0'; 454 clean_path(collected, 0); 455 init_symlink(collected + N_ALIGN(name_len), collected); 456 init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW); 457 do_utime(collected, mtime); 458 state = SkipIt; 459 next_state = Reset; 460 return 0; 461 } 462 463 static __initdata int (*actions[])(void) = { 464 [Start] = do_start, 465 [Collect] = do_collect, 466 [GotHeader] = do_header, 467 [SkipIt] = do_skip, 468 [GotName] = do_name, 469 [CopyFile] = do_copy, 470 [GotSymlink] = do_symlink, 471 [Reset] = do_reset, 472 }; 473 474 static long __init write_buffer(char *buf, unsigned long len) 475 { 476 byte_count = len; 477 victim = buf; 478 479 while (!actions[state]()) 480 ; 481 return len - byte_count; 482 } 483 484 static long __init flush_buffer(void *bufv, unsigned long len) 485 { 486 char *buf = bufv; 487 long written; 488 long origLen = len; 489 if (message) 490 return -1; 491 while ((written = write_buffer(buf, len)) < len && !message) { 492 char c = buf[written]; 493 if (c == '0') { 494 buf += written; 495 len -= written; 496 state = Start; 497 } else if (c == 0) { 498 buf += written; 499 len -= written; 500 state = Reset; 501 } else 502 error("junk within compressed archive"); 503 } 504 return origLen; 505 } 506 507 static unsigned long my_inptr __initdata; /* index of next byte to be processed in inbuf */ 508 509 #include <linux/decompress/generic.h> 510 511 /** 512 * unpack_to_rootfs - decompress and extract an initramfs archive 513 * @buf: input initramfs archive to extract 514 * @len: length of initramfs data to process 515 * 516 * Returns: NULL for success or an error message string 517 * 518 * This symbol shouldn't be used externally. It's available for unit tests. 519 */ 520 char * __init unpack_to_rootfs(char *buf, unsigned long len) 521 { 522 long written; 523 decompress_fn decompress; 524 const char *compress_name; 525 struct { 526 char header[CPIO_HDRLEN]; 527 char symlink[PATH_MAX + N_ALIGN(PATH_MAX) + 1]; 528 char name[N_ALIGN(PATH_MAX)]; 529 } *bufs = kmalloc_obj(*bufs); 530 531 if (!bufs) 532 panic_show_mem("can't allocate buffers"); 533 534 header_buf = bufs->header; 535 symlink_buf = bufs->symlink; 536 name_buf = bufs->name; 537 538 state = Start; 539 this_header = 0; 540 message = NULL; 541 while (!message && len) { 542 loff_t saved_offset = this_header; 543 if (*buf == '0' && !(this_header & 3)) { 544 state = Start; 545 written = write_buffer(buf, len); 546 buf += written; 547 len -= written; 548 continue; 549 } 550 if (!*buf) { 551 buf++; 552 len--; 553 this_header++; 554 continue; 555 } 556 this_header = 0; 557 decompress = decompress_method(buf, len, &compress_name); 558 pr_debug("Detected %s compressed data\n", compress_name); 559 if (decompress) { 560 int res = decompress(buf, len, NULL, flush_buffer, NULL, 561 &my_inptr, error); 562 if (res) 563 error("decompressor failed"); 564 } else if (compress_name) { 565 pr_err("compression method %s not configured\n", 566 compress_name); 567 error("decompressor failed"); 568 } else 569 error("invalid magic at start of compressed archive"); 570 if (state != Reset) 571 error("junk at the end of compressed archive"); 572 this_header = saved_offset + my_inptr; 573 buf += my_inptr; 574 len -= my_inptr; 575 } 576 dir_utime(); 577 /* free any hardlink state collected without optional TRAILER!!! */ 578 free_hash(); 579 kfree(bufs); 580 return message; 581 } 582 583 static int __initdata do_retain_initrd; 584 585 static int __init retain_initrd_param(char *str) 586 { 587 if (*str) 588 return 0; 589 do_retain_initrd = 1; 590 return 1; 591 } 592 __setup("retain_initrd", retain_initrd_param); 593 594 #ifdef CONFIG_ARCH_HAS_KEEPINITRD 595 static int __init keepinitrd_setup(char *__unused) 596 { 597 do_retain_initrd = 1; 598 return 1; 599 } 600 __setup("keepinitrd", keepinitrd_setup); 601 #endif 602 603 static bool __initdata initramfs_async = true; 604 static int __init initramfs_async_setup(char *str) 605 { 606 return kstrtobool(str, &initramfs_async) == 0; 607 } 608 __setup("initramfs_async=", initramfs_async_setup); 609 610 extern char __initramfs_start[]; 611 extern unsigned long __initramfs_size; 612 #include <linux/initrd.h> 613 #include <linux/kexec.h> 614 615 static BIN_ATTR(initrd, 0440, sysfs_bin_attr_simple_read, NULL, 0); 616 617 void __init reserve_initrd_mem(void) 618 { 619 phys_addr_t start; 620 unsigned long size; 621 622 /* Ignore the virtual address computed during device tree parsing */ 623 initrd_start = initrd_end = 0; 624 625 if (!phys_initrd_size) 626 return; 627 /* 628 * Round the memory region to page boundaries as per free_initrd_mem() 629 * This allows us to detect whether the pages overlapping the initrd 630 * are in use, but more importantly, reserves the entire set of pages 631 * as we don't want these pages allocated for other purposes. 632 */ 633 start = round_down(phys_initrd_start, PAGE_SIZE); 634 size = phys_initrd_size + (phys_initrd_start - start); 635 size = round_up(size, PAGE_SIZE); 636 637 if (!memblock_is_region_memory(start, size)) { 638 pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region", 639 (u64)start, size); 640 goto disable; 641 } 642 643 if (memblock_is_region_reserved(start, size)) { 644 pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region\n", 645 (u64)start, size); 646 goto disable; 647 } 648 649 memblock_reserve(start, size); 650 /* Now convert initrd to virtual addresses */ 651 initrd_start = (unsigned long)__va(phys_initrd_start); 652 initrd_end = initrd_start + phys_initrd_size; 653 initrd_below_start_ok = 1; 654 655 return; 656 disable: 657 pr_cont(" - disabling initrd\n"); 658 initrd_start = 0; 659 initrd_end = 0; 660 } 661 662 void __weak __init free_initrd_mem(unsigned long start, unsigned long end) 663 { 664 free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM, 665 "initrd"); 666 } 667 668 #ifdef CONFIG_CRASH_RESERVE 669 static bool __init kexec_free_initrd(void) 670 { 671 unsigned long crashk_start = (unsigned long)__va(crashk_res.start); 672 unsigned long crashk_end = (unsigned long)__va(crashk_res.end); 673 674 /* 675 * If the initrd region is overlapped with crashkernel reserved region, 676 * free only memory that is not part of crashkernel region. 677 */ 678 if (initrd_start >= crashk_end || initrd_end <= crashk_start) 679 return false; 680 681 /* 682 * Initialize initrd memory region since the kexec boot does not do. 683 */ 684 memset((void *)initrd_start, 0, initrd_end - initrd_start); 685 if (initrd_start < crashk_start) 686 free_initrd_mem(initrd_start, crashk_start); 687 if (initrd_end > crashk_end) 688 free_initrd_mem(crashk_end, initrd_end); 689 return true; 690 } 691 #else 692 static inline bool kexec_free_initrd(void) 693 { 694 return false; 695 } 696 #endif /* CONFIG_KEXEC_CORE */ 697 698 #ifdef CONFIG_BLK_DEV_RAM 699 static void __init populate_initrd_image(char *err) 700 { 701 ssize_t written; 702 struct file *file; 703 loff_t pos = 0; 704 705 printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n", 706 err); 707 file = filp_open("/initrd.image", O_WRONLY|O_CREAT|O_LARGEFILE, 0700); 708 if (IS_ERR(file)) 709 return; 710 711 written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start, 712 &pos); 713 if (written != initrd_end - initrd_start) 714 pr_err("/initrd.image: incomplete write (%zd != %ld)\n", 715 written, initrd_end - initrd_start); 716 fput(file); 717 } 718 #endif /* CONFIG_BLK_DEV_RAM */ 719 720 static void __init unpack_initramfs(async_cookie_t cookie) 721 { 722 /* Load the built in initramfs */ 723 char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size); 724 if (err) 725 panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */ 726 727 if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE)) 728 return; 729 730 if (IS_ENABLED(CONFIG_BLK_DEV_RAM)) 731 printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n"); 732 else 733 printk(KERN_INFO "Unpacking initramfs...\n"); 734 735 err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start); 736 if (err) { 737 #ifdef CONFIG_BLK_DEV_RAM 738 populate_initrd_image(err); 739 #else 740 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err); 741 #endif 742 } 743 } 744 745 static void __init do_populate_rootfs(void *unused, async_cookie_t cookie) 746 { 747 scoped_with_init_fs() { 748 unpack_initramfs(cookie); 749 security_initramfs_populated(); 750 } 751 752 /* 753 * If the initrd region is overlapped with crashkernel reserved region, 754 * free only memory that is not part of crashkernel region. 755 */ 756 if (!do_retain_initrd && initrd_start && !kexec_free_initrd()) { 757 free_initrd_mem(initrd_start, initrd_end); 758 } else if (do_retain_initrd && initrd_start) { 759 bin_attr_initrd.size = initrd_end - initrd_start; 760 bin_attr_initrd.private = (void *)initrd_start; 761 if (sysfs_create_bin_file(firmware_kobj, &bin_attr_initrd)) 762 pr_err("Failed to create initrd sysfs file"); 763 } 764 initrd_start = 0; 765 initrd_end = 0; 766 767 init_flush_fput(); 768 } 769 770 static ASYNC_DOMAIN_EXCLUSIVE(initramfs_domain); 771 static async_cookie_t initramfs_cookie; 772 773 void wait_for_initramfs(void) 774 { 775 if (!initramfs_cookie) { 776 /* 777 * Something before rootfs_initcall wants to access 778 * the filesystem/initramfs. Probably a bug. Make a 779 * note, avoid deadlocking the machine, and let the 780 * caller's access fail as it used to. 781 */ 782 pr_warn_once("wait_for_initramfs() called before rootfs_initcalls\n"); 783 return; 784 } 785 async_synchronize_cookie_domain(initramfs_cookie + 1, &initramfs_domain); 786 } 787 EXPORT_SYMBOL_GPL(wait_for_initramfs); 788 789 static int __init populate_rootfs(void) 790 { 791 initramfs_cookie = async_schedule_domain(do_populate_rootfs, NULL, 792 &initramfs_domain); 793 usermodehelper_enable(); 794 if (!initramfs_async) 795 wait_for_initramfs(); 796 return 0; 797 } 798 rootfs_initcall(populate_rootfs); 799