scheme.c revision 263466
1/*- 2 * Copyright (c) 2013,2014 Juniper Networks, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/types.h> 31#include <sys/linker_set.h> 32#include <sys/queue.h> 33#include <err.h> 34#include <errno.h> 35#include <stdint.h> 36#include <string.h> 37#include <unistd.h> 38 39#include "mkimg.h" 40#include "scheme.h" 41 42static struct mkimg_scheme *scheme; 43static u_int secsz = 512; 44 45int 46scheme_select(const char *spec) 47{ 48 struct mkimg_scheme *s, **iter; 49 50 SET_FOREACH(iter, schemes) { 51 s = *iter; 52 if (strcasecmp(spec, s->name) == 0) { 53 scheme = s; 54 return (0); 55 } 56 } 57 return (EINVAL); 58} 59 60struct mkimg_scheme * 61scheme_selected(void) 62{ 63 64 return (scheme); 65} 66 67int 68scheme_check_part(struct part *p) 69{ 70 struct mkimg_alias *alias, *iter; 71 72 warnx("part(%s): index=%u, type=`%s', offset=%ju, size=%ju", 73 scheme->name, p->index, p->alias, (uintmax_t)p->offset, 74 (uintmax_t)p->size); 75 76 /* Check the partition type alias */ 77 alias = NULL; 78 iter = scheme->aliases; 79 while (iter->name != NULL) { 80 if (strcasecmp(p->alias, iter->name) == 0) { 81 alias = iter; 82 break; 83 } 84 iter++; 85 } 86 if (alias == NULL) 87 return (EINVAL); 88 p->type = iter->type; 89 90 /* Validate the optional label. */ 91 if (p->label != NULL) { 92 if (strlen(p->label) > scheme->labellen) 93 return (EOPNOTSUPP); 94 } 95 96 return (0); 97} 98 99u_int 100scheme_max_parts(void) 101{ 102 103 return (scheme->nparts); 104} 105 106uint64_t 107scheme_round(uint64_t sz) 108{ 109 110 sz = (sz + secsz - 1) & ~(secsz - 1); 111 return (sz); 112} 113 114off_t 115scheme_first_offset(u_int parts) 116{ 117 u_int secs; 118 119 secs = scheme->metadata(SCHEME_META_IMG_START, parts, secsz) + 120 scheme->metadata(SCHEME_META_PART_BEFORE, 0, secsz); 121 return (secs * secsz); 122} 123 124off_t 125scheme_next_offset(off_t off, uint64_t sz) 126{ 127 u_int secs; 128 129 secs = scheme->metadata(SCHEME_META_PART_AFTER, 0, secsz) + 130 scheme->metadata(SCHEME_META_PART_BEFORE, 0, secsz); 131 sz += (secs * secsz); 132 return (off + sz); 133} 134 135int 136scheme_write(int fd, off_t off) 137{ 138 u_int secs; 139 int error; 140 141 /* Fixup offset: it has an extra metadata before the partition */ 142 secs = scheme->metadata(SCHEME_META_PART_BEFORE, 0, secsz); 143 off -= (secs * secsz); 144 145 secs = scheme->metadata(SCHEME_META_IMG_END, nparts, secsz); 146 off += (secs * secsz); 147 if (ftruncate(fd, off) == -1) 148 return (errno); 149 150 error = scheme->write(fd, off, nparts, secsz); 151 return (error); 152} 153