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