cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

initramfs.c (17579B)


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