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