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