Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * addinitrd - program to add a initrd image to an ecoff kernel | |
3 | * | |
4 | * (C) 1999 Thomas Bogendoerfer | |
5 | * minor modifications, cleanup: Guido Guenther <agx@sigxcpu.org> | |
6 | * further cleanup: Maciej W. Rozycki | |
7 | */ | |
8 | ||
9 | #include <sys/types.h> | |
10 | #include <sys/stat.h> | |
11 | #include <fcntl.h> | |
12 | #include <unistd.h> | |
13 | #include <stdio.h> | |
14 | #include <netinet/in.h> | |
15 | ||
16 | #include "ecoff.h" | |
17 | ||
18 | #define MIPS_PAGE_SIZE 4096 | |
19 | #define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1) | |
20 | ||
21 | #define swab16(x) \ | |
22 | ((unsigned short)( \ | |
23 | (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ | |
24 | (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) | |
25 | ||
26 | #define swab32(x) \ | |
27 | ((unsigned int)( \ | |
28 | (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ | |
29 | (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ | |
30 | (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ | |
31 | (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) | |
32 | ||
33 | #define SWAB(a) (swab ? swab32(a) : (a)) | |
34 | ||
49a89efb | 35 | void die(char *s) |
1da177e4 | 36 | { |
49a89efb RB |
37 | perror(s); |
38 | exit(1); | |
1da177e4 LT |
39 | } |
40 | ||
49a89efb | 41 | int main(int argc, char *argv[]) |
1da177e4 LT |
42 | { |
43 | int fd_vmlinux,fd_initrd,fd_outfile; | |
44 | FILHDR efile; | |
45 | AOUTHDR eaout; | |
46 | SCNHDR esecs[3]; | |
47 | struct stat st; | |
48 | char buf[1024]; | |
49 | unsigned long loadaddr; | |
50 | unsigned long initrd_header[2]; | |
51 | int i,cnt; | |
52 | int swab = 0; | |
53 | ||
54 | if (argc != 4) { | |
49a89efb RB |
55 | printf("Usage: %s <vmlinux> <initrd> <outfile>\n",argv[0]); |
56 | exit(1); | |
1da177e4 LT |
57 | } |
58 | ||
59 | if ((fd_vmlinux = open (argv[1],O_RDONLY)) < 0) | |
49a89efb | 60 | die("open vmlinux"); |
1da177e4 | 61 | if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile) |
49a89efb | 62 | die("read file header"); |
1da177e4 | 63 | if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout) |
49a89efb | 64 | die("read aout header"); |
1da177e4 | 65 | if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs) |
49a89efb | 66 | die("read section headers"); |
1da177e4 LT |
67 | /* |
68 | * check whether the file is good for us | |
69 | */ | |
70 | /* TBD */ | |
71 | ||
72 | /* | |
73 | * check, if we have to swab words | |
74 | */ | |
75 | if (ntohs(0xaa55) == 0xaa55) { | |
76 | if (efile.f_magic == swab16(MIPSELMAGIC)) | |
77 | swab = 1; | |
78 | } else { | |
79 | if (efile.f_magic == swab16(MIPSEBMAGIC)) | |
80 | swab = 1; | |
81 | } | |
82 | ||
83 | /* make sure we have an empty data segment for the initrd */ | |
84 | if (eaout.dsize || esecs[1].s_size) { | |
49a89efb RB |
85 | fprintf(stderr, "Data segment not empty. Giving up!\n"); |
86 | exit(1); | |
1da177e4 LT |
87 | } |
88 | if ((fd_initrd = open (argv[2], O_RDONLY)) < 0) | |
49a89efb | 89 | die("open initrd"); |
1da177e4 | 90 | if (fstat (fd_initrd, &st) < 0) |
49a89efb | 91 | die("fstat initrd"); |
1da177e4 LT |
92 | loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) |
93 | + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8; | |
94 | if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size))) | |
95 | loadaddr += MIPS_PAGE_SIZE; | |
96 | initrd_header[0] = SWAB(0x494E5244); | |
97 | initrd_header[1] = SWAB(st.st_size); | |
98 | eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8); | |
99 | eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr); | |
100 | ||
101 | if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC,0666)) < 0) | |
49a89efb | 102 | die("open outfile"); |
1da177e4 | 103 | if (write (fd_outfile, &efile, sizeof efile) != sizeof efile) |
49a89efb | 104 | die("write file header"); |
1da177e4 | 105 | if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout) |
49a89efb | 106 | die("write aout header"); |
1da177e4 | 107 | if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs) |
49a89efb | 108 | die("write section headers"); |
1da177e4 LT |
109 | /* skip padding */ |
110 | if(lseek(fd_vmlinux, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1) | |
49a89efb | 111 | die("lseek vmlinux"); |
1da177e4 | 112 | if(lseek(fd_outfile, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1) |
49a89efb | 113 | die("lseek outfile"); |
1da177e4 LT |
114 | /* copy text segment */ |
115 | cnt = SWAB(eaout.tsize); | |
116 | while (cnt) { | |
117 | if ((i = read (fd_vmlinux, buf, sizeof buf)) <= 0) | |
49a89efb | 118 | die("read vmlinux"); |
1da177e4 | 119 | if (write (fd_outfile, buf, i) != i) |
49a89efb | 120 | die("write vmlinux"); |
1da177e4 LT |
121 | cnt -= i; |
122 | } | |
123 | if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header) | |
49a89efb | 124 | die("write initrd header"); |
1da177e4 LT |
125 | while ((i = read (fd_initrd, buf, sizeof buf)) > 0) |
126 | if (write (fd_outfile, buf, i) != i) | |
49a89efb RB |
127 | die("write initrd"); |
128 | close(fd_vmlinux); | |
129 | close(fd_initrd); | |
1da177e4 LT |
130 | return 0; |
131 | } |