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