0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <stdio.h>
0018 #include <string.h>
0019 #include <stdlib.h>
0020 #include <unistd.h>
0021
0022 #include <sys/fcntl.h>
0023 #include <sys/stat.h>
0024 #include <sys/types.h>
0025
0026 #include <linux/a.out.h>
0027 #include <linux/coff.h>
0028 #include <linux/param.h>
0029 #ifdef __ELF__
0030 # include <linux/elf.h>
0031 # define elfhdr elf64_hdr
0032 # define elf_phdr elf64_phdr
0033 # define elf_check_arch(x) ((x)->e_machine == EM_ALPHA)
0034 #endif
0035
0036
0037 #define BLOCK_SIZE 512
0038
0039 const char * prog_name;
0040
0041
0042 static void
0043 usage (void)
0044 {
0045 fprintf(stderr,
0046 "usage: %s [-v] -p file primary\n"
0047 " %s [-vb] file [secondary]\n", prog_name, prog_name);
0048 exit(1);
0049 }
0050
0051
0052 int
0053 main (int argc, char *argv[])
0054 {
0055 size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
0056 int fd, ofd, i, j, verbose = 0, primary = 0;
0057 char buf[8192], *inname;
0058 struct exec * aout;
0059 long offset;
0060 #ifdef __ELF__
0061 struct elfhdr *elf;
0062 struct elf_phdr *elf_phdr;
0063 unsigned long long e_entry;
0064 #endif
0065
0066 prog_name = argv[0];
0067
0068 for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
0069 for (j = 1; argv[i][j]; ++j) {
0070 switch (argv[i][j]) {
0071 case 'v':
0072 verbose = ~verbose;
0073 break;
0074
0075 case 'b':
0076 pad = BLOCK_SIZE;
0077 break;
0078
0079 case 'p':
0080 primary = 1;
0081 break;
0082 }
0083 }
0084 }
0085
0086 if (i >= argc) {
0087 usage();
0088 }
0089 inname = argv[i++];
0090
0091 fd = open(inname, O_RDONLY);
0092 if (fd == -1) {
0093 perror("open");
0094 exit(1);
0095 }
0096
0097 ofd = 1;
0098 if (i < argc) {
0099 ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
0100 if (ofd == -1) {
0101 perror("open");
0102 exit(1);
0103 }
0104 }
0105
0106 if (primary) {
0107
0108
0109 unsigned long bb[64], sum = 0;
0110 struct stat st;
0111 off_t size;
0112 int i;
0113
0114 if (ofd == 1) {
0115 usage();
0116 }
0117
0118 if (fstat(fd, &st) == -1) {
0119 perror("fstat");
0120 exit(1);
0121 }
0122
0123 size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
0124 memset(bb, 0, sizeof(bb));
0125 strcpy((char *) bb, "Linux SRM bootblock");
0126 bb[60] = size / BLOCK_SIZE;
0127 bb[61] = 1;
0128 bb[62] = 0;
0129 for (i = 0; i < 63; ++i) {
0130 sum += bb[i];
0131 }
0132 bb[63] = sum;
0133 if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
0134 perror("boot-block write");
0135 exit(1);
0136 }
0137 printf("%lu\n", size);
0138 return 0;
0139 }
0140
0141
0142
0143 if (read(fd, buf, sizeof(buf)) < 0) {
0144 perror("read");
0145 exit(1);
0146 }
0147
0148 #ifdef __ELF__
0149 elf = (struct elfhdr *) buf;
0150
0151 if (elf->e_ident[0] == 0x7f && str_has_prefix((char *)elf->e_ident + 1, "ELF")) {
0152 if (elf->e_type != ET_EXEC) {
0153 fprintf(stderr, "%s: %s is not an ELF executable\n",
0154 prog_name, inname);
0155 exit(1);
0156 }
0157 if (!elf_check_arch(elf)) {
0158 fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
0159 prog_name, elf->e_machine);
0160 exit(1);
0161 }
0162 if (elf->e_phnum != 1) {
0163 fprintf(stderr,
0164 "%s: %d program headers (forgot to link with -N?)\n",
0165 prog_name, elf->e_phnum);
0166 }
0167
0168 e_entry = elf->e_entry;
0169
0170 lseek(fd, elf->e_phoff, SEEK_SET);
0171 if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
0172 perror("read");
0173 exit(1);
0174 }
0175
0176 elf_phdr = (struct elf_phdr *) buf;
0177 offset = elf_phdr->p_offset;
0178 mem_size = elf_phdr->p_memsz;
0179 fil_size = elf_phdr->p_filesz;
0180
0181
0182 if (elf_phdr->p_vaddr < e_entry) {
0183 unsigned long delta = e_entry - elf_phdr->p_vaddr;
0184 offset += delta;
0185 mem_size -= delta;
0186 fil_size -= delta;
0187 elf_phdr->p_vaddr += delta;
0188 }
0189
0190 if (verbose) {
0191 fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
0192 prog_name, (long) elf_phdr->p_vaddr,
0193 elf_phdr->p_vaddr + fil_size, offset);
0194 }
0195 } else
0196 #endif
0197 {
0198 aout = (struct exec *) buf;
0199
0200 if (!(aout->fh.f_flags & COFF_F_EXEC)) {
0201 fprintf(stderr, "%s: %s is not in executable format\n",
0202 prog_name, inname);
0203 exit(1);
0204 }
0205
0206 if (aout->fh.f_opthdr != sizeof(aout->ah)) {
0207 fprintf(stderr, "%s: %s has unexpected optional header size\n",
0208 prog_name, inname);
0209 exit(1);
0210 }
0211
0212 if (N_MAGIC(*aout) != OMAGIC) {
0213 fprintf(stderr, "%s: %s is not an OMAGIC file\n",
0214 prog_name, inname);
0215 exit(1);
0216 }
0217 offset = N_TXTOFF(*aout);
0218 fil_size = aout->ah.tsize + aout->ah.dsize;
0219 mem_size = fil_size + aout->ah.bsize;
0220
0221 if (verbose) {
0222 fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
0223 prog_name, aout->ah.text_start,
0224 aout->ah.text_start + fil_size, offset);
0225 }
0226 }
0227
0228 if (lseek(fd, offset, SEEK_SET) != offset) {
0229 perror("lseek");
0230 exit(1);
0231 }
0232
0233 if (verbose) {
0234 fprintf(stderr, "%s: copying %lu byte from %s\n",
0235 prog_name, (unsigned long) fil_size, inname);
0236 }
0237
0238 tocopy = fil_size;
0239 while (tocopy > 0) {
0240 n = tocopy;
0241 if (n > sizeof(buf)) {
0242 n = sizeof(buf);
0243 }
0244 tocopy -= n;
0245 if ((size_t) read(fd, buf, n) != n) {
0246 perror("read");
0247 exit(1);
0248 }
0249 do {
0250 nwritten = write(ofd, buf, n);
0251 if ((ssize_t) nwritten == -1) {
0252 perror("write");
0253 exit(1);
0254 }
0255 n -= nwritten;
0256 } while (n > 0);
0257 }
0258
0259 if (pad) {
0260 mem_size = ((mem_size + pad - 1) / pad) * pad;
0261 }
0262
0263 tocopy = mem_size - fil_size;
0264 if (tocopy > 0) {
0265 fprintf(stderr,
0266 "%s: zero-filling bss and aligning to %lu with %lu bytes\n",
0267 prog_name, pad, (unsigned long) tocopy);
0268
0269 memset(buf, 0x00, sizeof(buf));
0270 do {
0271 n = tocopy;
0272 if (n > sizeof(buf)) {
0273 n = sizeof(buf);
0274 }
0275 nwritten = write(ofd, buf, n);
0276 if ((ssize_t) nwritten == -1) {
0277 perror("write");
0278 exit(1);
0279 }
0280 tocopy -= nwritten;
0281 } while (tocopy > 0);
0282 }
0283 return 0;
0284 }