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