xref: /minix3/usr.sbin/installboot/arch/pmax.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: pmax.c,v 1.15 2013/10/21 15:37:46 christos Exp $	*/
29f8e6353SEvgeniy Ivanov 
39f8e6353SEvgeniy Ivanov /*-
49f8e6353SEvgeniy Ivanov  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
59f8e6353SEvgeniy Ivanov  * All rights reserved.
69f8e6353SEvgeniy Ivanov  *
79f8e6353SEvgeniy Ivanov  * This code is derived from software contributed to The NetBSD Foundation
89f8e6353SEvgeniy Ivanov  * by Simon Burge.
99f8e6353SEvgeniy Ivanov  *
109f8e6353SEvgeniy Ivanov  * This code is derived from software contributed to The NetBSD Foundation
119f8e6353SEvgeniy Ivanov  * by Luke Mewburn of Wasabi Systems.
129f8e6353SEvgeniy Ivanov  *
139f8e6353SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
149f8e6353SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
159f8e6353SEvgeniy Ivanov  * are met:
169f8e6353SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
179f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
189f8e6353SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
199f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
209f8e6353SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
219f8e6353SEvgeniy Ivanov  *
229f8e6353SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
239f8e6353SEvgeniy Ivanov  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
249f8e6353SEvgeniy Ivanov  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
259f8e6353SEvgeniy Ivanov  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
269f8e6353SEvgeniy Ivanov  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
279f8e6353SEvgeniy Ivanov  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
289f8e6353SEvgeniy Ivanov  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
299f8e6353SEvgeniy Ivanov  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
309f8e6353SEvgeniy Ivanov  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319f8e6353SEvgeniy Ivanov  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
329f8e6353SEvgeniy Ivanov  * POSSIBILITY OF SUCH DAMAGE.
339f8e6353SEvgeniy Ivanov  */
349f8e6353SEvgeniy Ivanov 
359f8e6353SEvgeniy Ivanov /*
369f8e6353SEvgeniy Ivanov  * Copyright (c) 1999 Ross Harvey.  All rights reserved.
379f8e6353SEvgeniy Ivanov  *
389f8e6353SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
399f8e6353SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
409f8e6353SEvgeniy Ivanov  * are met:
419f8e6353SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
429f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
439f8e6353SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
449f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
459f8e6353SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
469f8e6353SEvgeniy Ivanov  * 3. All advertising materials mentioning features or use of this software
479f8e6353SEvgeniy Ivanov  *    must display the following acknowledgement:
489f8e6353SEvgeniy Ivanov  *      This product includes software developed by Ross Harvey
499f8e6353SEvgeniy Ivanov  *	for the NetBSD Project.
509f8e6353SEvgeniy Ivanov  * 4. The name of the author may not be used to endorse or promote products
519f8e6353SEvgeniy Ivanov  *    derived from this software without specific prior written permission
529f8e6353SEvgeniy Ivanov  *
539f8e6353SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
549f8e6353SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
559f8e6353SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
569f8e6353SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
579f8e6353SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
589f8e6353SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
599f8e6353SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
609f8e6353SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
619f8e6353SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
629f8e6353SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
639f8e6353SEvgeniy Ivanov  */
649f8e6353SEvgeniy Ivanov 
659f8e6353SEvgeniy Ivanov /*
669f8e6353SEvgeniy Ivanov  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
679f8e6353SEvgeniy Ivanov  *
689f8e6353SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
699f8e6353SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
709f8e6353SEvgeniy Ivanov  * are met:
719f8e6353SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
729f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
739f8e6353SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
749f8e6353SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
759f8e6353SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
769f8e6353SEvgeniy Ivanov  * 3. All advertising materials mentioning features or use of this software
779f8e6353SEvgeniy Ivanov  *    must display the following acknowledgement:
789f8e6353SEvgeniy Ivanov  *      This product includes software developed by Christopher G. Demetriou
799f8e6353SEvgeniy Ivanov  *	for the NetBSD Project.
809f8e6353SEvgeniy Ivanov  * 4. The name of the author may not be used to endorse or promote products
819f8e6353SEvgeniy Ivanov  *    derived from this software without specific prior written permission
829f8e6353SEvgeniy Ivanov  *
839f8e6353SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
849f8e6353SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
859f8e6353SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
869f8e6353SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
879f8e6353SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
889f8e6353SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
899f8e6353SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
909f8e6353SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
919f8e6353SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
929f8e6353SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
939f8e6353SEvgeniy Ivanov  */
949f8e6353SEvgeniy Ivanov 
959f8e6353SEvgeniy Ivanov #if HAVE_NBTOOL_CONFIG_H
969f8e6353SEvgeniy Ivanov #include "nbtool_config.h"
979f8e6353SEvgeniy Ivanov #endif
989f8e6353SEvgeniy Ivanov 
999f8e6353SEvgeniy Ivanov #include <sys/cdefs.h>
1009f8e6353SEvgeniy Ivanov #if !defined(__lint)
101*84d9c625SLionel Sambuc __RCSID("$NetBSD: pmax.c,v 1.15 2013/10/21 15:37:46 christos Exp $");
1029f8e6353SEvgeniy Ivanov #endif	/* !__lint */
1039f8e6353SEvgeniy Ivanov 
1049f8e6353SEvgeniy Ivanov #include <sys/param.h>
1059f8e6353SEvgeniy Ivanov 
1069f8e6353SEvgeniy Ivanov #include <assert.h>
1079f8e6353SEvgeniy Ivanov #include <err.h>
1089f8e6353SEvgeniy Ivanov #include <stddef.h>
1099f8e6353SEvgeniy Ivanov #include <stdio.h>
1109f8e6353SEvgeniy Ivanov #include <stdlib.h>
1119f8e6353SEvgeniy Ivanov #include <string.h>
1129f8e6353SEvgeniy Ivanov #include <unistd.h>
1139f8e6353SEvgeniy Ivanov 
1149f8e6353SEvgeniy Ivanov #include <sys/exec_elf.h>
1159f8e6353SEvgeniy Ivanov 
1169f8e6353SEvgeniy Ivanov #include "installboot.h"
1179f8e6353SEvgeniy Ivanov 
1189f8e6353SEvgeniy Ivanov static int	load_bootstrap(ib_params *, char **,
1199f8e6353SEvgeniy Ivanov 				uint32_t *, uint32_t *, size_t *);
1209f8e6353SEvgeniy Ivanov 
1219f8e6353SEvgeniy Ivanov static int pmax_clearboot(ib_params *);
1229f8e6353SEvgeniy Ivanov static int pmax_setboot(ib_params *);
1239f8e6353SEvgeniy Ivanov 
1249f8e6353SEvgeniy Ivanov struct ib_mach ib_mach_pmax =
1259f8e6353SEvgeniy Ivanov 	{ "pmax", pmax_setboot, pmax_clearboot, no_editboot,
1269f8e6353SEvgeniy Ivanov 		IB_STAGE1START | IB_APPEND | IB_SUNSUM };
1279f8e6353SEvgeniy Ivanov 
1289f8e6353SEvgeniy Ivanov 
1299f8e6353SEvgeniy Ivanov static int
pmax_clearboot(ib_params * params)1309f8e6353SEvgeniy Ivanov pmax_clearboot(ib_params *params)
1319f8e6353SEvgeniy Ivanov {
1329f8e6353SEvgeniy Ivanov 	struct pmax_boot_block	bb;
1339f8e6353SEvgeniy Ivanov 	ssize_t			rv;
1349f8e6353SEvgeniy Ivanov 
1359f8e6353SEvgeniy Ivanov 	assert(params != NULL);
1369f8e6353SEvgeniy Ivanov 	assert(params->fsfd != -1);
1379f8e6353SEvgeniy Ivanov 	assert(params->filesystem != NULL);
1389f8e6353SEvgeniy Ivanov 	assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
1399f8e6353SEvgeniy Ivanov 
1409f8e6353SEvgeniy Ivanov 	rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
1419f8e6353SEvgeniy Ivanov 	if (rv == -1) {
1429f8e6353SEvgeniy Ivanov 		warn("Reading `%s'", params->filesystem);
1439f8e6353SEvgeniy Ivanov 		return (0);
1449f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(bb)) {
1459f8e6353SEvgeniy Ivanov 		warnx("Reading `%s': short read", params->filesystem);
1469f8e6353SEvgeniy Ivanov 		return (0);
1479f8e6353SEvgeniy Ivanov 	}
1489f8e6353SEvgeniy Ivanov 
1499f8e6353SEvgeniy Ivanov 	if (le32toh(bb.magic) != PMAX_BOOT_MAGIC) {
1509f8e6353SEvgeniy Ivanov 		warnx(
1519f8e6353SEvgeniy Ivanov 		    "Old boot block magic number invalid; boot block invalid");
1529f8e6353SEvgeniy Ivanov 		return (0);
1539f8e6353SEvgeniy Ivanov 	}
1549f8e6353SEvgeniy Ivanov 
1559f8e6353SEvgeniy Ivanov 	bb.map[0].num_blocks = bb.map[0].start_block = bb.mode = 0;
1569f8e6353SEvgeniy Ivanov 	bb.magic = htole32(PMAX_BOOT_MAGIC);
1579f8e6353SEvgeniy Ivanov 
1589f8e6353SEvgeniy Ivanov 	if (params->flags & IB_SUNSUM) {
1599f8e6353SEvgeniy Ivanov 		uint16_t	sum;
1609f8e6353SEvgeniy Ivanov 
1619f8e6353SEvgeniy Ivanov 		sum = compute_sunsum((uint16_t *)&bb);
1629f8e6353SEvgeniy Ivanov 		if (! set_sunsum(params, (uint16_t *)&bb, sum))
1639f8e6353SEvgeniy Ivanov 			return (0);
1649f8e6353SEvgeniy Ivanov 	}
1659f8e6353SEvgeniy Ivanov 
1669f8e6353SEvgeniy Ivanov 	if (params->flags & IB_VERBOSE)
1679f8e6353SEvgeniy Ivanov 		printf("%slearing boot block\n",
1689f8e6353SEvgeniy Ivanov 		    (params->flags & IB_NOWRITE) ? "Not c" : "C");
1699f8e6353SEvgeniy Ivanov 	if (params->flags & IB_NOWRITE)
1709f8e6353SEvgeniy Ivanov 		return (1);
1719f8e6353SEvgeniy Ivanov 
1729f8e6353SEvgeniy Ivanov 	rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
1739f8e6353SEvgeniy Ivanov 	if (rv == -1) {
1749f8e6353SEvgeniy Ivanov 		warn("Writing `%s'", params->filesystem);
1759f8e6353SEvgeniy Ivanov 		return (0);
1769f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(bb)) {
1779f8e6353SEvgeniy Ivanov 		warnx("Writing `%s': short write", params->filesystem);
1789f8e6353SEvgeniy Ivanov 		return (0);
1799f8e6353SEvgeniy Ivanov 	}
1809f8e6353SEvgeniy Ivanov 
1819f8e6353SEvgeniy Ivanov 	return (1);
1829f8e6353SEvgeniy Ivanov }
1839f8e6353SEvgeniy Ivanov 
1849f8e6353SEvgeniy Ivanov static int
pmax_setboot(ib_params * params)1859f8e6353SEvgeniy Ivanov pmax_setboot(ib_params *params)
1869f8e6353SEvgeniy Ivanov {
1879f8e6353SEvgeniy Ivanov 	struct pmax_boot_block	bb;
1889f8e6353SEvgeniy Ivanov 	uint32_t		startblock;
1899f8e6353SEvgeniy Ivanov 	int			retval;
1909f8e6353SEvgeniy Ivanov 	char			*bootstrapbuf;
191*84d9c625SLionel Sambuc 	size_t			bootstrapsize = 0;	/* XXX: gcc */
1929f8e6353SEvgeniy Ivanov 	uint32_t		bootstrapload, bootstrapexec;
1939f8e6353SEvgeniy Ivanov 	ssize_t			rv;
1949f8e6353SEvgeniy Ivanov 
1959f8e6353SEvgeniy Ivanov 	assert(params != NULL);
1969f8e6353SEvgeniy Ivanov 	assert(params->fsfd != -1);
1979f8e6353SEvgeniy Ivanov 	assert(params->filesystem != NULL);
1989f8e6353SEvgeniy Ivanov 	assert(params->s1fd != -1);
1999f8e6353SEvgeniy Ivanov 	assert(params->stage1 != NULL);
2009f8e6353SEvgeniy Ivanov 	assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
2019f8e6353SEvgeniy Ivanov 
2029f8e6353SEvgeniy Ivanov 	retval = 0;
2039f8e6353SEvgeniy Ivanov 	bootstrapbuf = NULL;
2049f8e6353SEvgeniy Ivanov 
2059f8e6353SEvgeniy Ivanov 	if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
2069f8e6353SEvgeniy Ivanov 	    &bootstrapexec, &bootstrapsize))
2079f8e6353SEvgeniy Ivanov 		goto done;
2089f8e6353SEvgeniy Ivanov 
2099f8e6353SEvgeniy Ivanov 	rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
2109f8e6353SEvgeniy Ivanov 	if (rv == -1) {
2119f8e6353SEvgeniy Ivanov 		warn("Reading `%s'", params->filesystem);
2129f8e6353SEvgeniy Ivanov 		goto done;
2139f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(bb)) {
2149f8e6353SEvgeniy Ivanov 		warnx("Reading `%s': short read", params->filesystem);
2159f8e6353SEvgeniy Ivanov 		goto done;
2169f8e6353SEvgeniy Ivanov 	}
2179f8e6353SEvgeniy Ivanov 
2189f8e6353SEvgeniy Ivanov 		/* fill in the updated boot block fields */
2199f8e6353SEvgeniy Ivanov 	if (params->flags & IB_APPEND) {
2209f8e6353SEvgeniy Ivanov 		if (! S_ISREG(params->fsstat.st_mode)) {
2219f8e6353SEvgeniy Ivanov 			warnx(
2229f8e6353SEvgeniy Ivanov 		    "`%s' must be a regular file to append a bootstrap",
2239f8e6353SEvgeniy Ivanov 			    params->filesystem);
2249f8e6353SEvgeniy Ivanov 			goto done;
2259f8e6353SEvgeniy Ivanov 		}
2269f8e6353SEvgeniy Ivanov 		startblock = howmany(params->fsstat.st_size,
2279f8e6353SEvgeniy Ivanov 		    PMAX_BOOT_BLOCK_BLOCKSIZE);
2289f8e6353SEvgeniy Ivanov 	} else if (params->flags & IB_STAGE1START) {
2299f8e6353SEvgeniy Ivanov 		startblock = params->s1start;
2309f8e6353SEvgeniy Ivanov 	} else {
2319f8e6353SEvgeniy Ivanov 		startblock = PMAX_BOOT_BLOCK_OFFSET / PMAX_BOOT_BLOCK_BLOCKSIZE
2329f8e6353SEvgeniy Ivanov 		    + 1;
2339f8e6353SEvgeniy Ivanov 	}
2349f8e6353SEvgeniy Ivanov 
2359f8e6353SEvgeniy Ivanov 	bb.map[0].start_block = htole32(startblock);
2369f8e6353SEvgeniy Ivanov 	bb.map[0].num_blocks =
2379f8e6353SEvgeniy Ivanov 	    htole32(howmany(bootstrapsize, PMAX_BOOT_BLOCK_BLOCKSIZE));
2389f8e6353SEvgeniy Ivanov 	bb.magic = htole32(PMAX_BOOT_MAGIC);
2399f8e6353SEvgeniy Ivanov 	bb.load_addr = htole32(bootstrapload);
2409f8e6353SEvgeniy Ivanov 	bb.exec_addr = htole32(bootstrapexec);
2419f8e6353SEvgeniy Ivanov 	bb.mode = htole32(PMAX_BOOTMODE_CONTIGUOUS);
2429f8e6353SEvgeniy Ivanov 
2439f8e6353SEvgeniy Ivanov 	if (params->flags & IB_SUNSUM) {
2449f8e6353SEvgeniy Ivanov 		uint16_t	sum;
2459f8e6353SEvgeniy Ivanov 
2469f8e6353SEvgeniy Ivanov 		sum = compute_sunsum((uint16_t *)&bb);
2479f8e6353SEvgeniy Ivanov 		if (! set_sunsum(params, (uint16_t *)&bb, sum))
2489f8e6353SEvgeniy Ivanov 			goto done;
2499f8e6353SEvgeniy Ivanov 	}
2509f8e6353SEvgeniy Ivanov 
2519f8e6353SEvgeniy Ivanov 	if (params->flags & IB_VERBOSE) {
2529f8e6353SEvgeniy Ivanov 		printf("Bootstrap start sector: %u\n",
2539f8e6353SEvgeniy Ivanov 		    le32toh(bb.map[0].start_block));
2549f8e6353SEvgeniy Ivanov 		printf("Bootstrap sector count: %u\n",
2559f8e6353SEvgeniy Ivanov 		    le32toh(bb.map[0].num_blocks));
2569f8e6353SEvgeniy Ivanov 		printf("Bootstrap load address: %#x\n",
2579f8e6353SEvgeniy Ivanov 		    le32toh(bb.load_addr));
2589f8e6353SEvgeniy Ivanov 		printf("Bootstrap exec address: %#x\n",
2599f8e6353SEvgeniy Ivanov 		    le32toh(bb.exec_addr));
2609f8e6353SEvgeniy Ivanov 		printf("%sriting bootstrap\n",
2619f8e6353SEvgeniy Ivanov 		    (params->flags & IB_NOWRITE) ? "Not w" : "W");
2629f8e6353SEvgeniy Ivanov 	}
2639f8e6353SEvgeniy Ivanov 	if (params->flags & IB_NOWRITE) {
2649f8e6353SEvgeniy Ivanov 		retval = 1;
2659f8e6353SEvgeniy Ivanov 		goto done;
2669f8e6353SEvgeniy Ivanov 	}
2679f8e6353SEvgeniy Ivanov 	rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
2689f8e6353SEvgeniy Ivanov 	     startblock * PMAX_BOOT_BLOCK_BLOCKSIZE);
2699f8e6353SEvgeniy Ivanov 	if (rv == -1) {
2709f8e6353SEvgeniy Ivanov 		warn("Writing `%s'", params->filesystem);
2719f8e6353SEvgeniy Ivanov 		goto done;
2729f8e6353SEvgeniy Ivanov 	} else if ((size_t)rv != bootstrapsize) {
2739f8e6353SEvgeniy Ivanov 		warnx("Writing `%s': short write", params->filesystem);
2749f8e6353SEvgeniy Ivanov 		goto done;
2759f8e6353SEvgeniy Ivanov 	}
2769f8e6353SEvgeniy Ivanov 
2779f8e6353SEvgeniy Ivanov 	if (params->flags & IB_VERBOSE)
2789f8e6353SEvgeniy Ivanov 		printf("Writing boot block\n");
2799f8e6353SEvgeniy Ivanov 	rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
2809f8e6353SEvgeniy Ivanov 	if (rv == -1) {
2819f8e6353SEvgeniy Ivanov 		warn("Writing `%s'", params->filesystem);
2829f8e6353SEvgeniy Ivanov 		goto done;
2839f8e6353SEvgeniy Ivanov 	} else if (rv != sizeof(bb)) {
2849f8e6353SEvgeniy Ivanov 		warnx("Writing `%s': short write", params->filesystem);
2859f8e6353SEvgeniy Ivanov 		goto done;
2869f8e6353SEvgeniy Ivanov 	} else {
2879f8e6353SEvgeniy Ivanov 		retval = 1;
2889f8e6353SEvgeniy Ivanov 	}
2899f8e6353SEvgeniy Ivanov 
2909f8e6353SEvgeniy Ivanov  done:
2919f8e6353SEvgeniy Ivanov 	if (bootstrapbuf)
2929f8e6353SEvgeniy Ivanov 		free(bootstrapbuf);
2939f8e6353SEvgeniy Ivanov 	return (retval);
2949f8e6353SEvgeniy Ivanov }
2959f8e6353SEvgeniy Ivanov 
2969f8e6353SEvgeniy Ivanov 
2979f8e6353SEvgeniy Ivanov #define MAX_SEGMENTS	10	/* We can load up to 10 segments */
2989f8e6353SEvgeniy Ivanov 
2999f8e6353SEvgeniy Ivanov struct seglist {
3009f8e6353SEvgeniy Ivanov 	Elf32_Addr	addr;
3019f8e6353SEvgeniy Ivanov 	Elf32_Off	f_offset;
3029f8e6353SEvgeniy Ivanov 	Elf32_Word	f_size;
3039f8e6353SEvgeniy Ivanov };
3049f8e6353SEvgeniy Ivanov 
3059f8e6353SEvgeniy Ivanov static int
load_bootstrap(ib_params * params,char ** data,uint32_t * loadaddr,uint32_t * execaddr,size_t * len)3069f8e6353SEvgeniy Ivanov load_bootstrap(ib_params *params, char **data,
3079f8e6353SEvgeniy Ivanov 	uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
3089f8e6353SEvgeniy Ivanov {
3099f8e6353SEvgeniy Ivanov 	int		i, nsegs;
3109f8e6353SEvgeniy Ivanov 	Elf32_Addr	lowaddr, highaddr;
3119f8e6353SEvgeniy Ivanov 	Elf32_Ehdr	ehdr;
3129f8e6353SEvgeniy Ivanov 	Elf32_Phdr	phdr;
3139f8e6353SEvgeniy Ivanov 	struct seglist	seglist[MAX_SEGMENTS];
3149f8e6353SEvgeniy Ivanov 
3159f8e6353SEvgeniy Ivanov 	if ((pread(params->s1fd, &ehdr, sizeof(ehdr), 0)) != sizeof(ehdr)) {
3169f8e6353SEvgeniy Ivanov 		warn("Reading `%s'", params->stage1);
3179f8e6353SEvgeniy Ivanov 		return (0);
3189f8e6353SEvgeniy Ivanov 	}
3199f8e6353SEvgeniy Ivanov 	if ((memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) ||
3209f8e6353SEvgeniy Ivanov 	    (ehdr.e_ident[EI_CLASS] != ELFCLASS32)) {
3219f8e6353SEvgeniy Ivanov 		warnx("No ELF header in `%s'", params->stage1);
3229f8e6353SEvgeniy Ivanov 		return (0);
3239f8e6353SEvgeniy Ivanov 	}
3249f8e6353SEvgeniy Ivanov 
3259f8e6353SEvgeniy Ivanov 	nsegs = highaddr = 0;
3269f8e6353SEvgeniy Ivanov 	lowaddr = (uint32_t) ULONG_MAX;
3279f8e6353SEvgeniy Ivanov 
3289f8e6353SEvgeniy Ivanov 	for (i = 0; i < le16toh(ehdr.e_phnum); i++) {
3299f8e6353SEvgeniy Ivanov 		if (pread(params->s1fd, &phdr, sizeof(phdr),
3309f8e6353SEvgeniy Ivanov 		    (off_t) le32toh(ehdr.e_phoff) + i * sizeof(phdr))
3319f8e6353SEvgeniy Ivanov 		    != sizeof(phdr)) {
3329f8e6353SEvgeniy Ivanov 			warn("Reading `%s'", params->stage1);
3339f8e6353SEvgeniy Ivanov 			return (0);
3349f8e6353SEvgeniy Ivanov 		}
3359f8e6353SEvgeniy Ivanov 		if (le32toh(phdr.p_type) != PT_LOAD)
3369f8e6353SEvgeniy Ivanov 			continue;
3379f8e6353SEvgeniy Ivanov 
3389f8e6353SEvgeniy Ivanov 		seglist[nsegs].addr = le32toh(phdr.p_paddr);
3399f8e6353SEvgeniy Ivanov 		seglist[nsegs].f_offset = le32toh(phdr.p_offset);
3409f8e6353SEvgeniy Ivanov 		seglist[nsegs].f_size = le32toh(phdr.p_filesz);
3419f8e6353SEvgeniy Ivanov 		nsegs++;
3429f8e6353SEvgeniy Ivanov 
3439f8e6353SEvgeniy Ivanov 		if (le32toh(phdr.p_paddr) < lowaddr)
3449f8e6353SEvgeniy Ivanov 			lowaddr = le32toh(phdr.p_paddr);
3459f8e6353SEvgeniy Ivanov 		if (le32toh(phdr.p_paddr) + le32toh(phdr.p_filesz) > highaddr)
3469f8e6353SEvgeniy Ivanov 			highaddr = le32toh(phdr.p_paddr) +
3479f8e6353SEvgeniy Ivanov 			    le32toh(phdr.p_filesz);
3489f8e6353SEvgeniy Ivanov 	}
3499f8e6353SEvgeniy Ivanov 
3509f8e6353SEvgeniy Ivanov 	*loadaddr = lowaddr;
3519f8e6353SEvgeniy Ivanov 	*execaddr = le32toh(ehdr.e_entry);
3529f8e6353SEvgeniy Ivanov 	*len = roundup(highaddr - lowaddr, PMAX_BOOT_BLOCK_BLOCKSIZE);
3539f8e6353SEvgeniy Ivanov 	if ((*data = malloc(*len)) == NULL) {
3549f8e6353SEvgeniy Ivanov 		warn("Allocating %lu bytes", (unsigned long) *len);
3559f8e6353SEvgeniy Ivanov 		return (0);
3569f8e6353SEvgeniy Ivanov 	}
3579f8e6353SEvgeniy Ivanov 
3589f8e6353SEvgeniy Ivanov 	/* Now load the bootstrap into memory */
3599f8e6353SEvgeniy Ivanov 	for (i = 0; i < nsegs; i++) {
3609f8e6353SEvgeniy Ivanov 		if ((Elf32_Word)pread(params->s1fd,
3619f8e6353SEvgeniy Ivanov 		    *data + seglist[i].addr - lowaddr,
3629f8e6353SEvgeniy Ivanov 		    seglist[i].f_size, (off_t)seglist[i].f_offset)
3639f8e6353SEvgeniy Ivanov 		    != seglist[i].f_size) {
3649f8e6353SEvgeniy Ivanov 			warn("Reading `%s'", params->stage1);
3659f8e6353SEvgeniy Ivanov 			return (0);
3669f8e6353SEvgeniy Ivanov 		}
3679f8e6353SEvgeniy Ivanov 	}
3689f8e6353SEvgeniy Ivanov 	return (1);
3699f8e6353SEvgeniy Ivanov }
370