1 #include <linux/init.h> 2 #include <linux/fs.h> 3 #include <linux/slab.h> 4 #include <linux/types.h> 5 #include <linux/fcntl.h> 6 #include <linux/delay.h> 7 #include <linux/string.h> 8 #include <linux/syscalls.h> 9 10 static __initdata char *message; 11 static void __init error(char *x) 12 { 13 if (!message) 14 message = x; 15 } 16 17 /* link hash */ 18 19 #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) 20 21 static __initdata struct hash { 22 int ino, minor, major; 23 mode_t mode; 24 struct hash *next; 25 char name[N_ALIGN(PATH_MAX)]; 26 } *head[32]; 27 28 static inline int hash(int major, int minor, int ino) 29 { 30 unsigned long tmp = ino + minor + (major << 3); 31 tmp += tmp >> 5; 32 return tmp & 31; 33 } 34 35 static char __init *find_link(int major, int minor, int ino, 36 mode_t mode, char *name) 37 { 38 struct hash **p, *q; 39 for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) { 40 if ((*p)->ino != ino) 41 continue; 42 if ((*p)->minor != minor) 43 continue; 44 if ((*p)->major != major) 45 continue; 46 if (((*p)->mode ^ mode) & S_IFMT) 47 continue; 48 return (*p)->name; 49 } 50 q = kmalloc(sizeof(struct hash), GFP_KERNEL); 51 if (!q) 52 panic("can't allocate link hash entry"); 53 q->major = major; 54 q->minor = minor; 55 q->ino = ino; 56 q->mode = mode; 57 strcpy(q->name, name); 58 q->next = NULL; 59 *p = q; 60 return NULL; 61 } 62 63 static void __init free_hash(void) 64 { 65 struct hash **p, *q; 66 for (p = head; p < head + 32; p++) { 67 while (*p) { 68 q = *p; 69 *p = q->next; 70 kfree(q); 71 } 72 } 73 } 74 75 /* cpio header parsing */ 76 77 static __initdata unsigned long ino, major, minor, nlink; 78 static __initdata mode_t mode; 79 static __initdata unsigned long body_len, name_len; 80 static __initdata uid_t uid; 81 static __initdata gid_t gid; 82 static __initdata unsigned rdev; 83 84 static void __init parse_header(char *s) 85 { 86 unsigned long parsed[12]; 87 char buf[9]; 88 int i; 89 90 buf[8] = '\0'; 91 for (i = 0, s += 6; i < 12; i++, s += 8) { 92 memcpy(buf, s, 8); 93 parsed[i] = simple_strtoul(buf, NULL, 16); 94 } 95 ino = parsed[0]; 96 mode = parsed[1]; 97 uid = parsed[2]; 98 gid = parsed[3]; 99 nlink = parsed[4]; 100 body_len = parsed[6]; 101 major = parsed[7]; 102 minor = parsed[8]; 103 rdev = new_encode_dev(MKDEV(parsed[9], parsed[10])); 104 name_len = parsed[11]; 105 } 106 107 /* FSM */ 108 109 static __initdata enum state { 110 Start, 111 Collect, 112 GotHeader, 113 SkipIt, 114 GotName, 115 CopyFile, 116 GotSymlink, 117 Reset 118 } state, next_state; 119 120 static __initdata char *victim; 121 static __initdata unsigned count; 122 static __initdata loff_t this_header, next_header; 123 124 static __initdata int dry_run; 125 126 static inline void __init eat(unsigned n) 127 { 128 victim += n; 129 this_header += n; 130 count -= n; 131 } 132 133 static __initdata char *collected; 134 static __initdata int remains; 135 static __initdata char *collect; 136 137 static void __init read_into(char *buf, unsigned size, enum state next) 138 { 139 if (count >= size) { 140 collected = victim; 141 eat(size); 142 state = next; 143 } else { 144 collect = collected = buf; 145 remains = size; 146 next_state = next; 147 state = Collect; 148 } 149 } 150 151 static __initdata char *header_buf, *symlink_buf, *name_buf; 152 153 static int __init do_start(void) 154 { 155 read_into(header_buf, 110, GotHeader); 156 return 0; 157 } 158 159 static int __init do_collect(void) 160 { 161 unsigned n = remains; 162 if (count < n) 163 n = count; 164 memcpy(collect, victim, n); 165 eat(n); 166 collect += n; 167 if ((remains -= n) != 0) 168 return 1; 169 state = next_state; 170 return 0; 171 } 172 173 static int __init do_header(void) 174 { 175 if (memcmp(collected, "070707", 6)==0) { 176 error("incorrect cpio method used: use -H newc option"); 177 return 1; 178 } 179 if (memcmp(collected, "070701", 6)) { 180 error("no cpio magic"); 181 return 1; 182 } 183 parse_header(collected); 184 next_header = this_header + N_ALIGN(name_len) + body_len; 185 next_header = (next_header + 3) & ~3; 186 if (dry_run) { 187 read_into(name_buf, N_ALIGN(name_len), GotName); 188 return 0; 189 } 190 state = SkipIt; 191 if (name_len <= 0 || name_len > PATH_MAX) 192 return 0; 193 if (S_ISLNK(mode)) { 194 if (body_len > PATH_MAX) 195 return 0; 196 collect = collected = symlink_buf; 197 remains = N_ALIGN(name_len) + body_len; 198 next_state = GotSymlink; 199 state = Collect; 200 return 0; 201 } 202 if (S_ISREG(mode) || !body_len) 203 read_into(name_buf, N_ALIGN(name_len), GotName); 204 return 0; 205 } 206 207 static int __init do_skip(void) 208 { 209 if (this_header + count < next_header) { 210 eat(count); 211 return 1; 212 } else { 213 eat(next_header - this_header); 214 state = next_state; 215 return 0; 216 } 217 } 218 219 static int __init do_reset(void) 220 { 221 while(count && *victim == '\0') 222 eat(1); 223 if (count && (this_header & 3)) 224 error("broken padding"); 225 return 1; 226 } 227 228 static int __init maybe_link(void) 229 { 230 if (nlink >= 2) { 231 char *old = find_link(major, minor, ino, mode, collected); 232 if (old) 233 return (sys_link(old, collected) < 0) ? -1 : 1; 234 } 235 return 0; 236 } 237 238 static void __init clean_path(char *path, mode_t mode) 239 { 240 struct stat st; 241 242 if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) { 243 if (S_ISDIR(st.st_mode)) 244 sys_rmdir(path); 245 else 246 sys_unlink(path); 247 } 248 } 249 250 static __initdata int wfd; 251 252 static int __init do_name(void) 253 { 254 state = SkipIt; 255 next_state = Reset; 256 if (strcmp(collected, "TRAILER!!!") == 0) { 257 free_hash(); 258 return 0; 259 } 260 if (dry_run) 261 return 0; 262 clean_path(collected, mode); 263 if (S_ISREG(mode)) { 264 int ml = maybe_link(); 265 if (ml >= 0) { 266 int openflags = O_WRONLY|O_CREAT; 267 if (ml != 1) 268 openflags |= O_TRUNC; 269 wfd = sys_open(collected, openflags, mode); 270 271 if (wfd >= 0) { 272 sys_fchown(wfd, uid, gid); 273 sys_fchmod(wfd, mode); 274 state = CopyFile; 275 } 276 } 277 } else if (S_ISDIR(mode)) { 278 sys_mkdir(collected, mode); 279 sys_chown(collected, uid, gid); 280 sys_chmod(collected, mode); 281 } else if (S_ISBLK(mode) || S_ISCHR(mode) || 282 S_ISFIFO(mode) || S_ISSOCK(mode)) { 283 if (maybe_link() == 0) { 284 sys_mknod(collected, mode, rdev); 285 sys_chown(collected, uid, gid); 286 sys_chmod(collected, mode); 287 } 288 } 289 return 0; 290 } 291 292 static int __init do_copy(void) 293 { 294 if (count >= body_len) { 295 sys_write(wfd, victim, body_len); 296 sys_close(wfd); 297 eat(body_len); 298 state = SkipIt; 299 return 0; 300 } else { 301 sys_write(wfd, victim, count); 302 body_len -= count; 303 eat(count); 304 return 1; 305 } 306 } 307 308 static int __init do_symlink(void) 309 { 310 collected[N_ALIGN(name_len) + body_len] = '\0'; 311 clean_path(collected, 0); 312 sys_symlink(collected + N_ALIGN(name_len), collected); 313 sys_lchown(collected, uid, gid); 314 state = SkipIt; 315 next_state = Reset; 316 return 0; 317 } 318 319 static __initdata int (*actions[])(void) = { 320 [Start] = do_start, 321 [Collect] = do_collect, 322 [GotHeader] = do_header, 323 [SkipIt] = do_skip, 324 [GotName] = do_name, 325 [CopyFile] = do_copy, 326 [GotSymlink] = do_symlink, 327 [Reset] = do_reset, 328 }; 329 330 static int __init write_buffer(char *buf, unsigned len) 331 { 332 count = len; 333 victim = buf; 334 335 while (!actions[state]()) 336 ; 337 return len - count; 338 } 339 340 static void __init flush_buffer(char *buf, unsigned len) 341 { 342 int written; 343 if (message) 344 return; 345 while ((written = write_buffer(buf, len)) < len && !message) { 346 char c = buf[written]; 347 if (c == '0') { 348 buf += written; 349 len -= written; 350 state = Start; 351 } else if (c == 0) { 352 buf += written; 353 len -= written; 354 state = Reset; 355 } else 356 error("junk in compressed archive"); 357 } 358 } 359 360 /* 361 * gzip declarations 362 */ 363 364 #define OF(args) args 365 366 #ifndef memzero 367 #define memzero(s, n) memset ((s), 0, (n)) 368 #endif 369 370 typedef unsigned char uch; 371 typedef unsigned short ush; 372 typedef unsigned long ulg; 373 374 #define WSIZE 0x8000 /* window size--must be a power of two, and */ 375 /* at least 32K for zip's deflate method */ 376 377 static uch *inbuf; 378 static uch *window; 379 380 static unsigned insize; /* valid bytes in inbuf */ 381 static unsigned inptr; /* index of next byte to be processed in inbuf */ 382 static unsigned outcnt; /* bytes in output buffer */ 383 static long bytes_out; 384 385 #define get_byte() (inptr < insize ? inbuf[inptr++] : -1) 386 387 /* Diagnostic functions (stubbed out) */ 388 #define Assert(cond,msg) 389 #define Trace(x) 390 #define Tracev(x) 391 #define Tracevv(x) 392 #define Tracec(c,x) 393 #define Tracecv(c,x) 394 395 #define STATIC static 396 #define INIT __init 397 398 static void __init flush_window(void); 399 static void __init error(char *m); 400 401 #define NO_INFLATE_MALLOC 402 403 #include "../lib/inflate.c" 404 405 /* =========================================================================== 406 * Write the output window window[0..outcnt-1] and update crc and bytes_out. 407 * (Used for the decompressed data only.) 408 */ 409 static void __init flush_window(void) 410 { 411 ulg c = crc; /* temporary variable */ 412 unsigned n; 413 uch *in, ch; 414 415 flush_buffer(window, outcnt); 416 in = window; 417 for (n = 0; n < outcnt; n++) { 418 ch = *in++; 419 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 420 } 421 crc = c; 422 bytes_out += (ulg)outcnt; 423 outcnt = 0; 424 } 425 426 static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) 427 { 428 int written; 429 dry_run = check_only; 430 header_buf = kmalloc(110, GFP_KERNEL); 431 symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); 432 name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); 433 window = kmalloc(WSIZE, GFP_KERNEL); 434 if (!window || !header_buf || !symlink_buf || !name_buf) 435 panic("can't allocate buffers"); 436 state = Start; 437 this_header = 0; 438 message = NULL; 439 while (!message && len) { 440 loff_t saved_offset = this_header; 441 if (*buf == '0' && !(this_header & 3)) { 442 state = Start; 443 written = write_buffer(buf, len); 444 buf += written; 445 len -= written; 446 continue; 447 } 448 if (!*buf) { 449 buf++; 450 len--; 451 this_header++; 452 continue; 453 } 454 this_header = 0; 455 insize = len; 456 inbuf = buf; 457 inptr = 0; 458 outcnt = 0; /* bytes in output buffer */ 459 bytes_out = 0; 460 crc = (ulg)0xffffffffL; /* shift register contents */ 461 makecrc(); 462 gunzip(); 463 if (state != Reset) 464 error("junk in gzipped archive"); 465 this_header = saved_offset + inptr; 466 buf += inptr; 467 len -= inptr; 468 } 469 kfree(window); 470 kfree(name_buf); 471 kfree(symlink_buf); 472 kfree(header_buf); 473 return message; 474 } 475 476 static int __initdata do_retain_initrd; 477 478 static int __init retain_initrd_param(char *str) 479 { 480 if (*str) 481 return 0; 482 do_retain_initrd = 1; 483 return 1; 484 } 485 __setup("retain_initrd", retain_initrd_param); 486 487 extern char __initramfs_start[], __initramfs_end[]; 488 #include <linux/initrd.h> 489 #include <linux/kexec.h> 490 491 static void __init free_initrd(void) 492 { 493 #ifdef CONFIG_KEXEC 494 unsigned long crashk_start = (unsigned long)__va(crashk_res.start); 495 unsigned long crashk_end = (unsigned long)__va(crashk_res.end); 496 #endif 497 if (do_retain_initrd) 498 goto skip; 499 500 #ifdef CONFIG_KEXEC 501 /* 502 * If the initrd region is overlapped with crashkernel reserved region, 503 * free only memory that is not part of crashkernel region. 504 */ 505 if (initrd_start < crashk_end && initrd_end > crashk_start) { 506 /* 507 * Initialize initrd memory region since the kexec boot does 508 * not do. 509 */ 510 memset((void *)initrd_start, 0, initrd_end - initrd_start); 511 if (initrd_start < crashk_start) 512 free_initrd_mem(initrd_start, crashk_start); 513 if (initrd_end > crashk_end) 514 free_initrd_mem(crashk_end, initrd_end); 515 } else 516 #endif 517 free_initrd_mem(initrd_start, initrd_end); 518 skip: 519 initrd_start = 0; 520 initrd_end = 0; 521 } 522 523 static int __init populate_rootfs(void) 524 { 525 char *err = unpack_to_rootfs(__initramfs_start, 526 __initramfs_end - __initramfs_start, 0); 527 if (err) 528 panic(err); 529 if (initrd_start) { 530 #ifdef CONFIG_BLK_DEV_RAM 531 int fd; 532 printk(KERN_INFO "checking if image is initramfs..."); 533 err = unpack_to_rootfs((char *)initrd_start, 534 initrd_end - initrd_start, 1); 535 if (!err) { 536 printk(" it is\n"); 537 unpack_to_rootfs((char *)initrd_start, 538 initrd_end - initrd_start, 0); 539 free_initrd(); 540 return 0; 541 } 542 printk("it isn't (%s); looks like an initrd\n", err); 543 fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); 544 if (fd >= 0) { 545 sys_write(fd, (char *)initrd_start, 546 initrd_end - initrd_start); 547 sys_close(fd); 548 free_initrd(); 549 } 550 #else 551 printk(KERN_INFO "Unpacking initramfs..."); 552 err = unpack_to_rootfs((char *)initrd_start, 553 initrd_end - initrd_start, 0); 554 if (err) 555 panic(err); 556 printk(" done\n"); 557 free_initrd(); 558 #endif 559 } 560 return 0; 561 } 562 rootfs_initcall(populate_rootfs); 563