1*a5eb4ea3SMarcel Moolenaar /*- 2*a5eb4ea3SMarcel Moolenaar * Copyright (c) 2013,2014 Juniper Networks, Inc. 3*a5eb4ea3SMarcel Moolenaar * All rights reserved. 4*a5eb4ea3SMarcel Moolenaar * 5*a5eb4ea3SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6*a5eb4ea3SMarcel Moolenaar * modification, are permitted provided that the following conditions 7*a5eb4ea3SMarcel Moolenaar * are met: 8*a5eb4ea3SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 9*a5eb4ea3SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 10*a5eb4ea3SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 11*a5eb4ea3SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 12*a5eb4ea3SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 13*a5eb4ea3SMarcel Moolenaar * 14*a5eb4ea3SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*a5eb4ea3SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*a5eb4ea3SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*a5eb4ea3SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*a5eb4ea3SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*a5eb4ea3SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*a5eb4ea3SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*a5eb4ea3SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*a5eb4ea3SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*a5eb4ea3SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*a5eb4ea3SMarcel Moolenaar * SUCH DAMAGE. 25*a5eb4ea3SMarcel Moolenaar */ 26*a5eb4ea3SMarcel Moolenaar 27*a5eb4ea3SMarcel Moolenaar #include <sys/cdefs.h> 28*a5eb4ea3SMarcel Moolenaar __FBSDID("$FreeBSD$"); 29*a5eb4ea3SMarcel Moolenaar 30*a5eb4ea3SMarcel Moolenaar #include <sys/types.h> 31*a5eb4ea3SMarcel Moolenaar #include <sys/linker_set.h> 32*a5eb4ea3SMarcel Moolenaar #include <sys/queue.h> 33*a5eb4ea3SMarcel Moolenaar #include <sys/stat.h> 34*a5eb4ea3SMarcel Moolenaar #include <err.h> 35*a5eb4ea3SMarcel Moolenaar #include <errno.h> 36*a5eb4ea3SMarcel Moolenaar #include <stdint.h> 37*a5eb4ea3SMarcel Moolenaar #include <stdlib.h> 38*a5eb4ea3SMarcel Moolenaar #include <string.h> 39*a5eb4ea3SMarcel Moolenaar #include <unistd.h> 40*a5eb4ea3SMarcel Moolenaar 41*a5eb4ea3SMarcel Moolenaar #include "mkimg.h" 42*a5eb4ea3SMarcel Moolenaar #include "scheme.h" 43*a5eb4ea3SMarcel Moolenaar 44*a5eb4ea3SMarcel Moolenaar static struct { 45*a5eb4ea3SMarcel Moolenaar const char *name; 46*a5eb4ea3SMarcel Moolenaar enum alias alias; 47*a5eb4ea3SMarcel Moolenaar } scheme_alias[] = { 48*a5eb4ea3SMarcel Moolenaar { "ebr", ALIAS_EBR }, 49*a5eb4ea3SMarcel Moolenaar { "efi", ALIAS_EFI }, 50*a5eb4ea3SMarcel Moolenaar { "fat32", ALIAS_FAT32 }, 51*a5eb4ea3SMarcel Moolenaar { "freebsd", ALIAS_FREEBSD }, 52*a5eb4ea3SMarcel Moolenaar { "freebsd-boot", ALIAS_FREEBSD_BOOT }, 53*a5eb4ea3SMarcel Moolenaar { "freebsd-nandfs", ALIAS_FREEBSD_NANDFS }, 54*a5eb4ea3SMarcel Moolenaar { "freebsd-swap", ALIAS_FREEBSD_SWAP }, 55*a5eb4ea3SMarcel Moolenaar { "freebsd-ufs", ALIAS_FREEBSD_UFS }, 56*a5eb4ea3SMarcel Moolenaar { "freebsd-vinum", ALIAS_FREEBSD_VINUM }, 57*a5eb4ea3SMarcel Moolenaar { "freebsd-zfs", ALIAS_FREEBSD_ZFS }, 58*a5eb4ea3SMarcel Moolenaar { "mbr", ALIAS_MBR }, 59*a5eb4ea3SMarcel Moolenaar { NULL, ALIAS_NONE } /* Keep last! */ 60*a5eb4ea3SMarcel Moolenaar }; 61*a5eb4ea3SMarcel Moolenaar 62*a5eb4ea3SMarcel Moolenaar static struct mkimg_scheme *scheme; 63*a5eb4ea3SMarcel Moolenaar static void *bootcode; 64*a5eb4ea3SMarcel Moolenaar 65*a5eb4ea3SMarcel Moolenaar static enum alias 66*a5eb4ea3SMarcel Moolenaar scheme_parse_alias(const char *name) 67*a5eb4ea3SMarcel Moolenaar { 68*a5eb4ea3SMarcel Moolenaar u_int idx; 69*a5eb4ea3SMarcel Moolenaar 70*a5eb4ea3SMarcel Moolenaar idx = 0; 71*a5eb4ea3SMarcel Moolenaar while (scheme_alias[idx].name != NULL) { 72*a5eb4ea3SMarcel Moolenaar if (strcasecmp(scheme_alias[idx].name, name) == 0) 73*a5eb4ea3SMarcel Moolenaar return (scheme_alias[idx].alias); 74*a5eb4ea3SMarcel Moolenaar idx++; 75*a5eb4ea3SMarcel Moolenaar } 76*a5eb4ea3SMarcel Moolenaar return (ALIAS_NONE); 77*a5eb4ea3SMarcel Moolenaar } 78*a5eb4ea3SMarcel Moolenaar 79*a5eb4ea3SMarcel Moolenaar int 80*a5eb4ea3SMarcel Moolenaar scheme_select(const char *spec) 81*a5eb4ea3SMarcel Moolenaar { 82*a5eb4ea3SMarcel Moolenaar struct mkimg_scheme *s, **iter; 83*a5eb4ea3SMarcel Moolenaar 84*a5eb4ea3SMarcel Moolenaar SET_FOREACH(iter, schemes) { 85*a5eb4ea3SMarcel Moolenaar s = *iter; 86*a5eb4ea3SMarcel Moolenaar if (strcasecmp(spec, s->name) == 0) { 87*a5eb4ea3SMarcel Moolenaar scheme = s; 88*a5eb4ea3SMarcel Moolenaar return (0); 89*a5eb4ea3SMarcel Moolenaar } 90*a5eb4ea3SMarcel Moolenaar } 91*a5eb4ea3SMarcel Moolenaar return (EINVAL); 92*a5eb4ea3SMarcel Moolenaar } 93*a5eb4ea3SMarcel Moolenaar 94*a5eb4ea3SMarcel Moolenaar struct mkimg_scheme * 95*a5eb4ea3SMarcel Moolenaar scheme_selected(void) 96*a5eb4ea3SMarcel Moolenaar { 97*a5eb4ea3SMarcel Moolenaar 98*a5eb4ea3SMarcel Moolenaar return (scheme); 99*a5eb4ea3SMarcel Moolenaar } 100*a5eb4ea3SMarcel Moolenaar 101*a5eb4ea3SMarcel Moolenaar int 102*a5eb4ea3SMarcel Moolenaar scheme_bootcode(int fd) 103*a5eb4ea3SMarcel Moolenaar { 104*a5eb4ea3SMarcel Moolenaar struct stat sb; 105*a5eb4ea3SMarcel Moolenaar int error; 106*a5eb4ea3SMarcel Moolenaar 107*a5eb4ea3SMarcel Moolenaar if (fd == -1) 108*a5eb4ea3SMarcel Moolenaar return (0); 109*a5eb4ea3SMarcel Moolenaar if (scheme->bootcode == 0) 110*a5eb4ea3SMarcel Moolenaar return (ENXIO); 111*a5eb4ea3SMarcel Moolenaar 112*a5eb4ea3SMarcel Moolenaar error = fstat(fd, &sb); 113*a5eb4ea3SMarcel Moolenaar if (error) 114*a5eb4ea3SMarcel Moolenaar return (error); 115*a5eb4ea3SMarcel Moolenaar if (sb.st_size > scheme->bootcode) 116*a5eb4ea3SMarcel Moolenaar return (EFBIG); 117*a5eb4ea3SMarcel Moolenaar 118*a5eb4ea3SMarcel Moolenaar bootcode = malloc(scheme->bootcode); 119*a5eb4ea3SMarcel Moolenaar if (bootcode == NULL) 120*a5eb4ea3SMarcel Moolenaar return (ENOMEM); 121*a5eb4ea3SMarcel Moolenaar memset(bootcode, 0, scheme->bootcode); 122*a5eb4ea3SMarcel Moolenaar if (read(fd, bootcode, sb.st_size) != sb.st_size) { 123*a5eb4ea3SMarcel Moolenaar free(bootcode); 124*a5eb4ea3SMarcel Moolenaar bootcode = NULL; 125*a5eb4ea3SMarcel Moolenaar return (errno); 126*a5eb4ea3SMarcel Moolenaar } 127*a5eb4ea3SMarcel Moolenaar return (0); 128*a5eb4ea3SMarcel Moolenaar } 129*a5eb4ea3SMarcel Moolenaar 130*a5eb4ea3SMarcel Moolenaar int 131*a5eb4ea3SMarcel Moolenaar scheme_check_part(struct part *p) 132*a5eb4ea3SMarcel Moolenaar { 133*a5eb4ea3SMarcel Moolenaar struct mkimg_alias *iter; 134*a5eb4ea3SMarcel Moolenaar enum alias alias; 135*a5eb4ea3SMarcel Moolenaar 136*a5eb4ea3SMarcel Moolenaar /* Check the partition type alias */ 137*a5eb4ea3SMarcel Moolenaar alias = scheme_parse_alias(p->alias); 138*a5eb4ea3SMarcel Moolenaar if (alias == ALIAS_NONE) 139*a5eb4ea3SMarcel Moolenaar return (EINVAL); 140*a5eb4ea3SMarcel Moolenaar 141*a5eb4ea3SMarcel Moolenaar iter = scheme->aliases; 142*a5eb4ea3SMarcel Moolenaar while (iter->alias != ALIAS_NONE) { 143*a5eb4ea3SMarcel Moolenaar if (alias == iter->alias) 144*a5eb4ea3SMarcel Moolenaar break; 145*a5eb4ea3SMarcel Moolenaar iter++; 146*a5eb4ea3SMarcel Moolenaar } 147*a5eb4ea3SMarcel Moolenaar if (iter->alias == ALIAS_NONE) 148*a5eb4ea3SMarcel Moolenaar return (EINVAL); 149*a5eb4ea3SMarcel Moolenaar p->type = iter->type; 150*a5eb4ea3SMarcel Moolenaar 151*a5eb4ea3SMarcel Moolenaar /* Validate the optional label. */ 152*a5eb4ea3SMarcel Moolenaar if (p->label != NULL) { 153*a5eb4ea3SMarcel Moolenaar if (strlen(p->label) > scheme->labellen) 154*a5eb4ea3SMarcel Moolenaar return (EINVAL); 155*a5eb4ea3SMarcel Moolenaar } 156*a5eb4ea3SMarcel Moolenaar 157*a5eb4ea3SMarcel Moolenaar return (0); 158*a5eb4ea3SMarcel Moolenaar } 159*a5eb4ea3SMarcel Moolenaar 160*a5eb4ea3SMarcel Moolenaar u_int 161*a5eb4ea3SMarcel Moolenaar scheme_max_parts(void) 162*a5eb4ea3SMarcel Moolenaar { 163*a5eb4ea3SMarcel Moolenaar 164*a5eb4ea3SMarcel Moolenaar return (scheme->nparts); 165*a5eb4ea3SMarcel Moolenaar } 166*a5eb4ea3SMarcel Moolenaar 167*a5eb4ea3SMarcel Moolenaar u_int 168*a5eb4ea3SMarcel Moolenaar scheme_max_secsz(void) 169*a5eb4ea3SMarcel Moolenaar { 170*a5eb4ea3SMarcel Moolenaar 171*a5eb4ea3SMarcel Moolenaar return (scheme->maxsecsz); 172*a5eb4ea3SMarcel Moolenaar } 173*a5eb4ea3SMarcel Moolenaar 174*a5eb4ea3SMarcel Moolenaar lba_t 175*a5eb4ea3SMarcel Moolenaar scheme_metadata(u_int where, lba_t start) 176*a5eb4ea3SMarcel Moolenaar { 177*a5eb4ea3SMarcel Moolenaar lba_t secs; 178*a5eb4ea3SMarcel Moolenaar 179*a5eb4ea3SMarcel Moolenaar secs = scheme->metadata(where); 180*a5eb4ea3SMarcel Moolenaar return (round_block(start + secs)); 181*a5eb4ea3SMarcel Moolenaar } 182*a5eb4ea3SMarcel Moolenaar 183*a5eb4ea3SMarcel Moolenaar int 184*a5eb4ea3SMarcel Moolenaar scheme_write(int fd, lba_t end) 185*a5eb4ea3SMarcel Moolenaar { 186*a5eb4ea3SMarcel Moolenaar u_int cylsz; 187*a5eb4ea3SMarcel Moolenaar int error; 188*a5eb4ea3SMarcel Moolenaar 189*a5eb4ea3SMarcel Moolenaar cylsz = nsecs * nheads; 190*a5eb4ea3SMarcel Moolenaar ncyls = (end + cylsz - 1) / cylsz; 191*a5eb4ea3SMarcel Moolenaar 192*a5eb4ea3SMarcel Moolenaar if (ftruncate(fd, end * secsz) == -1) 193*a5eb4ea3SMarcel Moolenaar return (errno); 194*a5eb4ea3SMarcel Moolenaar 195*a5eb4ea3SMarcel Moolenaar error = scheme->write(fd, end, bootcode); 196*a5eb4ea3SMarcel Moolenaar return (error); 197*a5eb4ea3SMarcel Moolenaar } 198