int putfile(char *from_file, int to) { struct exec ex; char buf[2048]; int n, total; int from, check_sum = 0; struct hppa_lifload load; Elf32_External_Ehdr elf_header; Elf32_External_Phdr *elf_segments; int i, header_count, memory_needed, elf_load_image_segment; if ((from = open(from_file, O_RDONLY)) < 0) err(1, "%s", from_file); n = read(from, &ex, sizeof(ex)); if (n != sizeof(ex)) err(1, "%s: reading file header", from_file); entry = ex.a_entry; if (N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC) entry += sizeof(ex); else if (IS_ELF(*(Elf32_External_Ehdr *)&ex)) { if (lseek(from, 0, SEEK_SET) < 0) err(1, "lseek"); n = read(from, &elf_header, sizeof (elf_header)); if (n != sizeof (elf_header)) err(1, "%s: reading ELF header", from_file); header_count = ELFGET16(elf_header.e_phnum); memory_needed = header_count * sizeof (Elf32_External_Phdr); elf_segments = malloc(memory_needed); if (elf_segments == NULL) err(1, "malloc"); if (lseek(from, ELFGET32(elf_header.e_phoff), SEEK_SET) < 0) err(1, "lseek"); n = read(from, elf_segments, memory_needed); if (n != memory_needed) err(1, "%s: reading ELF segments", from_file); elf_load_image_segment = -1; for (i = 0; i < header_count; i++) { if (ELFGET32(elf_segments[i].p_filesz) && ELFGET32(elf_segments[i].p_flags) & PF_X) { if (elf_load_image_segment != -1) errx(1, "%s: more than one ELF program " "segment", from_file); elf_load_image_segment = i; } } if (elf_load_image_segment == -1) errx(1, "%s: no suitable ELF program segment", from_file); entry = ELFGET32(elf_header.e_entry) + ELFGET32(elf_segments[elf_load_image_segment].p_offset) - ELFGET32(elf_segments[elf_load_image_segment].p_vaddr); } else if (*(uint8_t *)&ex == 0x1f && ((uint8_t *)&ex)[1] == 0x8b) { entry = 0; } else errx(1, "%s: bad magic number", from_file); entry += sizeof(load); lseek(to, sizeof(load), SEEK_CUR); total = 0; n = sizeof(buf) - sizeof(load); /* copy the whole file */ for (lseek(from, 0, SEEK_SET); ; n = sizeof(buf)) { memset(buf, 0, sizeof(buf)); if ((n = read(from, buf, n)) < 0) err(1, "%s", from_file); else if (n == 0) break; if (write(to, buf, n) != n) err(1, "%s", to_file); total += n; check_sum = cksum(check_sum, (int *)buf, n); } /* load header */ load.address = htobe32(loadpoint + sizeof(load)); load.count = htobe32(4 + total); check_sum = cksum(check_sum, (int *)&load, sizeof(load)); if (verbose) warnx("wrote %d bytes of file \'%s\'", total, from_file); total += sizeof(load); /* insert the header */ lseek(to, -total, SEEK_CUR); if (write(to, &load, sizeof(load)) != sizeof(load)) err(1, "%s", to_file); lseek(to, total - sizeof(load), SEEK_CUR); memset(buf, 0, sizeof(buf)); /* pad to int */ n = sizeof(int) - total % sizeof(int); if (total % sizeof(int)) { if (write(to, buf, n) != n) err(1, "%s", to_file); else total += n; } /* pad to the blocksize */ n = sizeof(buf) - total % sizeof(buf); if (n < sizeof(int)) { n += sizeof(buf); total += sizeof(buf); } else total += n; /* TODO should pad here to the 65k boundary for tape boot */ if (verbose) warnx("checksum is 0x%08x", -check_sum); check_sum = htobe32(-check_sum); if (write(to, &check_sum, sizeof(int)) != sizeof(int)) err(1, "%s", to_file); n -= sizeof(int); if (write(to, buf, n) != n) err(1, "%s", to_file); if (close(from) < 0) err(1, "%s", from_file); return total; }
static int rs6000_build_image(char *kernel, char *boot, char *rawdev, char *outname) { unsigned char *elf_img = NULL, *kern_img = NULL; int i, ch, tmp, kgzlen, err; int elf_fd, rs6000_fd, kern_fd, elf_img_len = 0, elf_pad; uint32_t swapped[128]; off_t lenpos, kstart, kend; unsigned long length; long flength; gzFile gzf; struct stat kern_stat; Elf32_External_Phdr phdr; elf_fd = open_file("bootloader", boot, &hdr, &elf_stat); kern_fd = open_file("kernel", kernel, &khdr, &kern_stat); kern_len = kern_stat.st_size + RS6000_MAGICSIZE + KERNLENSIZE; for (i = 0; i < ELFGET16(hdr.e_phnum); i++) { lseek(elf_fd, ELFGET32(hdr.e_phoff) + sizeof(phdr) * i, SEEK_SET); if (read(elf_fd, &phdr, sizeof(phdr)) != sizeof(phdr)) errx(3, "Can't read input '%s' phdr : %s", boot, strerror(errno)); if ((ELFGET32(phdr.p_type) != PT_LOAD) || !(ELFGET32(phdr.p_flags) & PF_X)) continue; fstat(elf_fd, &elf_stat); elf_img_len = elf_stat.st_size - ELFGET32(phdr.p_offset); elf_pad = ELFGET32(phdr.p_memsz) - ELFGET32(phdr.p_filesz); if (verboseflag) printf("Padding %d\n", elf_pad); lseek(elf_fd, ELFGET32(phdr.p_offset), SEEK_SET); break; } if ((rs6000_fd = open(outname, O_RDWR|O_TRUNC, 0)) < 0) { /* we couldn't open it, it must be new */ rs6000_fd = creat(outname, 0644); if (rs6000_fd < 0) errx(2, "Can't open output '%s': %s", outname, strerror(errno)); } /* Set file pos. to 2nd sector where image will be written */ lseek(rs6000_fd, 0x400, SEEK_SET); /* Copy boot image */ elf_img = malloc(elf_img_len); if (!elf_img) errx(3, "Can't malloc: %s", strerror(errno)); if (read(elf_fd, elf_img, elf_img_len) != elf_img_len) errx(3, "Can't read file '%s' : %s", boot, strerror(errno)); write(rs6000_fd, elf_img, elf_img_len); free(elf_img); /* now dump in the padding space for the BSS */ elf_pad += 100; /* just a little extra for good luck */ lseek(rs6000_fd, elf_pad, SEEK_CUR); /* Copy kernel */ kern_img = malloc(kern_stat.st_size); if (kern_img == NULL) errx(3, "Can't malloc: %s", strerror(errno)); /* we need to jump back after having read the headers */ lseek(kern_fd, 0, SEEK_SET); if (read(kern_fd, (void *)kern_img, kern_stat.st_size) != kern_stat.st_size) errx(3, "Can't read kernel '%s' : %s", kernel, strerror(errno)); gzf = gzdopen(dup(rs6000_fd), "a"); if (gzf == NULL) errx(3, "Can't init compression: %s", strerror(errno)); if (gzsetparams(gzf, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) errx(3, "%s", gzerror(gzf, &err)); /* write a magic number and size before the kernel */ write(rs6000_fd, (void *)rs6000_magic, RS6000_MAGICSIZE); lenpos = lseek(rs6000_fd, 0, SEEK_CUR); if (verboseflag) printf("wrote magic at pos 0x%lx\n", (unsigned long)lenpos); tmp = sa_htobe32(0); write(rs6000_fd, (void *)&tmp, KERNLENSIZE); /* write in the compressed kernel */ kstart = lseek(rs6000_fd, 0, SEEK_CUR); if (verboseflag) printf("kernel start at pos 0x%lx\n", (unsigned long)kstart); kgzlen = gzwrite(gzf, kern_img, kern_stat.st_size); gzclose(gzf); kend = lseek(rs6000_fd, 0, SEEK_CUR); if (verboseflag) printf("kernel end at pos 0x%lx\n", (unsigned long)kend); /* jump back to the length position now that we know the length */ lseek(rs6000_fd, lenpos, SEEK_SET); kgzlen = kend - kstart; tmp = sa_htobe32(kgzlen); if (verboseflag) printf("kernel len = 0x%x tmp = 0x%x\n", kgzlen, tmp); write(rs6000_fd, (void *)&tmp, KERNLENSIZE); #if 0 lseek(rs6000_fd, sizeof(boot_record_t) + sizeof(config_record_t), SEEK_SET); /* set entry and length */ length = sa_htole32(0x400); write(rs6000_fd, &length, sizeof(length)); length = sa_htole32(0x400 + elf_img_len + 8 + kgzlen); write(rs6000_fd, &length, sizeof(length)); #endif /* generate the header now that we know the kernel length */ if (verboseflag) printf("building records\n"); rs6000_build_records(elf_img_len + 8 + kgzlen); lseek(rs6000_fd, 0, SEEK_SET); /* ROM wants it byteswapped in 32bit chunks */ if (verboseflag) printf("writing records\n"); memcpy(swapped, &bootrec, sizeof(rs6000_boot_record_t)); for (i=0; i < 128; i++) swapped[i] = htonl(swapped[i]); write(rs6000_fd, swapped, sizeof(rs6000_boot_record_t)); memcpy(swapped, &confrec, sizeof(rs6000_config_record_t)); for (i=0; i < 128; i++) swapped[i] = htonl(swapped[i]); write(rs6000_fd, swapped, sizeof(rs6000_config_record_t)); free(kern_img); close(kern_fd); close(rs6000_fd); close(elf_fd); return 0; }
static int bebox_build_image(char *kernel, char *boot, char *rawdev, char *outname) { unsigned char *elf_img = NULL, *kern_img = NULL, *header_img = NULL; int i, ch, tmp, kgzlen, err, hsize = BEBOX_HEADER_SIZE; int elf_fd, bebox_fd, kern_fd, elf_img_len = 0; off_t lenpos, kstart, kend, toff, endoff, flength; uint32_t swapped[128]; int32_t *offset; gzFile gzf; struct stat kern_stat; struct bebox_image_block *p; struct timeval tp; Elf32_External_Phdr phdr; elf_fd = open_file("bootloader", boot, &hdr, &elf_stat); if (inkernflag) { kern_fd = open_file("kernel", kernel, &khdr, &kern_stat); kern_len = kern_stat.st_size + BEBOX_MAGICSIZE + KERNLENSIZE; } else kern_len = BEBOX_MAGICSIZE + KERNLENSIZE; for (i = 0; i < ELFGET16(hdr.e_phnum); i++) { lseek(elf_fd, ELFGET32(hdr.e_phoff) + sizeof(phdr) * i, SEEK_SET); if (read(elf_fd, &phdr, sizeof(phdr)) != sizeof(phdr)) errx(3, "Can't read input '%s' phdr : %s", boot, strerror(errno)); if ((ELFGET32(phdr.p_type) != PT_LOAD) || !(ELFGET32(phdr.p_flags) & PF_X)) continue; fstat(elf_fd, &elf_stat); elf_img_len = ELFGET32(phdr.p_filesz); lseek(elf_fd, ELFGET32(phdr.p_offset), SEEK_SET); break; } if ((bebox_fd = open(outname, O_RDWR|O_TRUNC, 0)) < 0) { /* we couldn't open it, it must be new */ bebox_fd = creat(outname, 0644); if (bebox_fd < 0) errx(2, "Can't open output '%s': %s", outname, strerror(errno)); } lseek(bebox_fd, hsize, SEEK_SET); if (inkernflag) { /* * write the header with the wrong values to get the offset * right */ bebox_write_header(bebox_fd, elf_img_len, kern_stat.st_size); /* Copy kernel */ kern_img = malloc(kern_stat.st_size); if (kern_img == NULL) errx(3, "Can't malloc: %s", strerror(errno)); /* we need to jump back after having read the headers */ lseek(kern_fd, 0, SEEK_SET); if (read(kern_fd, (void *)kern_img, kern_stat.st_size) != kern_stat.st_size) errx(3, "Can't read kernel '%s' : %s", kernel, strerror(errno)); gzf = gzdopen(dup(bebox_fd), "a"); if (gzf == NULL) errx(3, "Can't init compression: %s", strerror(errno)); if (gzsetparams(gzf, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) errx(3, "%s", gzerror(gzf, &err)); } else bebox_write_header(bebox_fd, elf_img_len, 0); /* write a magic number and size before the kernel */ write(bebox_fd, (void *)bebox_magic, BEBOX_MAGICSIZE); lenpos = lseek(bebox_fd, 0, SEEK_CUR); tmp = sa_htobe32(0); write(bebox_fd, (void *)&tmp, KERNLENSIZE); if (inkernflag) { /* write in the compressed kernel */ kstart = lseek(bebox_fd, 0, SEEK_CUR); kgzlen = gzwrite(gzf, kern_img, kern_stat.st_size); gzclose(gzf); kend = lseek(bebox_fd, 0, SEEK_CUR); free(kern_img); } else { kstart = kend = lseek(bebox_fd, 0, SEEK_CUR); kgzlen = 0; } /* jump back to the length position now that we know the length */ lseek(bebox_fd, lenpos, SEEK_SET); kgzlen = kend - kstart; tmp = sa_htobe32(kgzlen); write(bebox_fd, (void *)&tmp, KERNLENSIZE); /* now rewrite the header correctly */ lseek(bebox_fd, hsize, SEEK_SET); tmp = kgzlen + BEBOX_MAGICSIZE + KERNLENSIZE; toff = bebox_write_header(bebox_fd, elf_img_len, tmp); /* Copy boot image */ elf_img = malloc(elf_img_len); if (!elf_img) errx(3, "Can't malloc: %s", strerror(errno)); if (read(elf_fd, elf_img, elf_img_len) != elf_img_len) errx(3, "Can't read file '%s' : %s", boot, strerror(errno)); lseek(bebox_fd, toff + hsize, SEEK_SET); write(bebox_fd, elf_img, elf_img_len); free(elf_img); if (inkernflag) close(kern_fd); close(elf_fd); /* Now go back and write in the block header */ endoff = lseek(bebox_fd, 0, SEEK_END); lseek(bebox_fd, 0, SEEK_SET); header_img = malloc(BEBOX_HEADER_SIZE); if (!header_img) errx(3, "Can't malloc: %s", strerror(errno)); memset(header_img, 0, BEBOX_HEADER_SIZE); /* copy the boot image into the buffer */ for (p = bebox_image_block; p->offset != -1; p++) memcpy(header_img + p->offset, p->data, p->size); /* fill used block bitmap */ memset(header_img + BEBOX_FILE_BLOCK_MAP_START, 0xff, BEBOX_FILE_BLOCK_MAP_END - BEBOX_FILE_BLOCK_MAP_START); /* fix the file size in the header */ tmp = endoff - BEBOX_HEADER_SIZE; *(int32_t *)(header_img + BEBOX_FILE_SIZE_OFFSET) = (int32_t)sa_htobe32(tmp); *(int32_t *)(header_img + BEBOX_FILE_SIZE_ALIGN_OFFSET) = (int32_t)sa_htobe32(roundup(tmp, BEBOX_FILE_BLOCK_SIZE)); gettimeofday(&tp, 0); for (offset = bebox_mtime_offset; *offset != -1; offset++) *(int32_t *)(header_img + *offset) = (int32_t)sa_htobe32(tp.tv_sec); write(bebox_fd, header_img, BEBOX_HEADER_SIZE); /* now pad the end */ flength = roundup(endoff, BEBOX_BLOCK_SIZE); /* refill the header_img with zeros */ memset(header_img, 0, BEBOX_BLOCK_SIZE * 2); lseek(bebox_fd, 0, SEEK_END); write(bebox_fd, header_img, flength - endoff); close(bebox_fd); free(header_img); return 0; }
static int prep_build_image(char *kernel, char *boot, char *rawdev, char *outname) { unsigned char *elf_img = NULL, *kern_img = NULL; int i, ch, tmp, kgzlen, err; int elf_fd, prep_fd, kern_fd, elf_img_len = 0; off_t lenpos, kstart, kend; unsigned long length; long flength; gzFile gzf; struct stat kern_stat; Elf32_External_Phdr phdr; elf_fd = open_file("bootloader", boot, &hdr, &elf_stat); if (inkernflag) { kern_fd = open_file("kernel", kernel, &khdr, &kern_stat); kern_len = kern_stat.st_size + PREP_MAGICSIZE + KERNLENSIZE; } else kern_len = PREP_MAGICSIZE + KERNLENSIZE; for (i = 0; i < ELFGET16(hdr.e_phnum); i++) { lseek(elf_fd, ELFGET32(hdr.e_phoff) + sizeof(phdr) * i, SEEK_SET); if (read(elf_fd, &phdr, sizeof(phdr)) != sizeof(phdr)) errx(3, "Can't read input '%s' phdr : %s", boot, strerror(errno)); if ((ELFGET32(phdr.p_type) != PT_LOAD) || !(ELFGET32(phdr.p_flags) & PF_X)) continue; fstat(elf_fd, &elf_stat); elf_img_len = elf_stat.st_size - ELFGET32(phdr.p_offset); lseek(elf_fd, ELFGET32(phdr.p_offset), SEEK_SET); break; } if ((prep_fd = open(outname, O_RDWR|O_TRUNC, 0)) < 0) { /* we couldn't open it, it must be new */ prep_fd = creat(outname, 0644); if (prep_fd < 0) errx(2, "Can't open output '%s': %s", outname, strerror(errno)); } prep_check_mbr(prep_fd, rawdev); /* Set file pos. to 2nd sector where image will be written */ lseek(prep_fd, 0x400, SEEK_SET); /* Copy boot image */ elf_img = malloc(elf_img_len); if (!elf_img) errx(3, "Can't malloc: %s", strerror(errno)); if (read(elf_fd, elf_img, elf_img_len) != elf_img_len) errx(3, "Can't read file '%s' : %s", boot, strerror(errno)); write(prep_fd, elf_img, elf_img_len); free(elf_img); if (inkernflag) { /* Copy kernel */ kern_img = malloc(kern_stat.st_size); if (kern_img == NULL) errx(3, "Can't malloc: %s", strerror(errno)); /* we need to jump back after having read the headers */ lseek(kern_fd, 0, SEEK_SET); if (read(kern_fd, (void *)kern_img, kern_stat.st_size) != kern_stat.st_size) errx(3, "Can't read kernel '%s' : %s", kernel, strerror(errno)); } gzf = gzdopen(dup(prep_fd), "a"); if (gzf == NULL) errx(3, "Can't init compression: %s", strerror(errno)); if (gzsetparams(gzf, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) errx(3, "%s", gzerror(gzf, &err)); /* write a magic number and size before the kernel */ write(prep_fd, (void *)prep_magic, PREP_MAGICSIZE); lenpos = lseek(prep_fd, 0, SEEK_CUR); tmp = sa_htobe32(0); write(prep_fd, (void *)&tmp, KERNLENSIZE); /* write in the compressed kernel */ kstart = lseek(prep_fd, 0, SEEK_CUR); if (inkernflag) { kgzlen = gzwrite(gzf, kern_img, kern_stat.st_size); gzclose(gzf); } kend = lseek(prep_fd, 0, SEEK_CUR); /* jump back to the length position now that we know the length */ lseek(prep_fd, lenpos, SEEK_SET); kgzlen = kend - kstart; tmp = sa_htobe32(kgzlen); write(prep_fd, (void *)&tmp, KERNLENSIZE); length = sa_htole32(0x400 + elf_img_len + 8 + kgzlen); lseek(prep_fd, sizeof(mbr) + 4, SEEK_SET); write(prep_fd, &length, sizeof(length)); flength = 0x400 + elf_img_len + 8 + kgzlen; if (lfloppyflag) flength -= (5760 * 512); else flength -= (2880 * 512); if (flength > 0 && !saloneflag) fprintf(stderr, "%s: Image %s is %ld bytes larger than single" " floppy. Can only be used for netboot.\n", getprogname(), outname, flength); if (inkernflag) { free(kern_img); close(kern_fd); } close(prep_fd); close(elf_fd); return 0; }