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
18static 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
43static __initdata char *message;
44static 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
55static __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
62static 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
69static 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
101static 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
113static 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
124static __initdata LIST_HEAD(dir_list);
125struct dir_entry {
126    struct list_head list;
127    char *name;
128    time64_t mtime;
129};
130
131static 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
143static 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
155static __initdata time64_t mtime;
156
157/* cpio header parsing */
158
159static __initdata unsigned long ino, major, minor, nlink;
160static __initdata umode_t mode;
161static __initdata unsigned long body_len, name_len;
162static __initdata uid_t uid;
163static __initdata gid_t gid;
164static __initdata unsigned rdev;
165
166static 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
192static __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
204static __initdata char *victim;
205static unsigned long byte_count __initdata;
206static __initdata loff_t this_header, next_header;
207
208static inline void __init eat(unsigned n)
209{
210    victim += n;
211    this_header += n;
212    byte_count -= n;
213}
214
215static __initdata char *collected;
216static long remains __initdata;
217static __initdata char *collect;
218
219static 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
233static __initdata char *header_buf, *symlink_buf, *name_buf;
234
235static int __init do_start(void)
236{
237    read_into(header_buf, 0x6e, GotHeader);
238    return 0;
239}
240
241static 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
257static 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
290static 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
302static 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
313static 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
326static 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
338static __initdata struct file *wfile;
339static __initdata loff_t wfile_pos;
340
341static 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
386static 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
412static 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
424static __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
429static 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
440static 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
465static unsigned long my_inptr; /* index of next byte to be processed in inbuf */
466
467#include <linux/decompress/generic.h>
468
469static 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
535static int __initdata do_retain_initrd;
536
537static 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
548static 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
559void __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
572static 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
598static inline bool kexec_free_initrd(void)
599{
600    return false;
601}
602#endif /* CONFIG_KEXEC_CORE */
603
604#ifdef CONFIG_BLK_DEV_RAM
605static 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
627static 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
654done:
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
673static void __init unpack_rootfs_async(void *unused, async_cookie_t cookie)
674{
675    populate_rootfs();
676}
677
678static int __init populate_rootfs_async(void)
679{
680    async_schedule(unpack_rootfs_async, NULL);
681    return 0;
682}
683
684pure_initcall(populate_rootfs_async);
685#else
686rootfs_initcall(populate_rootfs);
687#endif
688