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