示例#1
0
/* verify the file is ELF and ppc, and open it up */
static int
open_file(const char *ftype, char *file, Elf32_External_Ehdr *hdr,
	struct stat *f_stat)
{
	int fd;

	if ((fd = open(file, 0)) < 0)
		errx(2, "Can't open %s '%s': %s", ftype, file, strerror(errno));
	fstat(fd, f_stat);

	if (read(fd, hdr, sizeof(Elf32_External_Ehdr)) !=
	    sizeof(Elf32_External_Ehdr))
		errx(3, "Can't read input '%s': %s", file, strerror(errno));

	if (hdr->e_ident[EI_MAG0] != ELFMAG0 ||
	    hdr->e_ident[EI_MAG1] != ELFMAG1 ||
	    hdr->e_ident[EI_MAG2] != ELFMAG2 ||
	    hdr->e_ident[EI_MAG3] != ELFMAG3 ||
	    hdr->e_ident[EI_CLASS] != ELFCLASS32)
		errx(3, "input '%s' is not ELF32 format", file);

	if (hdr->e_ident[EI_DATA] != ELFDATA2MSB)
		errx(3, "input '%s' is not big-endian", file);

	if (ELFGET16(hdr->e_machine) != EM_PPC)
		errx(3, "input '%s' is not PowerPC exec binary", file);

	return(fd);
}
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;
}
示例#3
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;
}
示例#4
0
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;
}
示例#5
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;
}