1263409Smarcel/*- 2263409Smarcel * Copyright (c) 2014 Juniper Networks, Inc. 3263409Smarcel * All rights reserved. 4263409Smarcel * 5263409Smarcel * Redistribution and use in source and binary forms, with or without 6263409Smarcel * modification, are permitted provided that the following conditions 7263409Smarcel * are met: 8263409Smarcel * 1. Redistributions of source code must retain the above copyright 9263409Smarcel * notice, this list of conditions and the following disclaimer. 10263409Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11263409Smarcel * notice, this list of conditions and the following disclaimer in the 12263409Smarcel * documentation and/or other materials provided with the distribution. 13263409Smarcel * 14263409Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15263409Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16263409Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17263409Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18263409Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19263409Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20263409Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21263409Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22263409Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23263409Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24263409Smarcel * SUCH DAMAGE. 25263409Smarcel */ 26263409Smarcel 27263409Smarcel#include <sys/cdefs.h> 28263409Smarcel__FBSDID("$FreeBSD$"); 29263409Smarcel 30263409Smarcel#include <sys/types.h> 31263442Smarcel#include <sys/disklabel.h> 32263669Smarcel#include <sys/endian.h> 33263442Smarcel#include <sys/errno.h> 34263409Smarcel#include <stdlib.h> 35263669Smarcel#include <string.h> 36263669Smarcel#include <unistd.h> 37263409Smarcel 38268161Smarcel#include "image.h" 39263409Smarcel#include "mkimg.h" 40263409Smarcel#include "scheme.h" 41263409Smarcel 42268161Smarcel#ifndef FS_NANDFS 43268161Smarcel#define FS_NANDFS 30 44268161Smarcel#endif 45268161Smarcel 46263409Smarcelstatic struct mkimg_alias bsd_aliases[] = { 47263669Smarcel { ALIAS_FREEBSD_NANDFS, ALIAS_INT2TYPE(FS_NANDFS) }, 48263669Smarcel { ALIAS_FREEBSD_SWAP, ALIAS_INT2TYPE(FS_SWAP) }, 49263669Smarcel { ALIAS_FREEBSD_UFS, ALIAS_INT2TYPE(FS_BSDFFS) }, 50263669Smarcel { ALIAS_FREEBSD_VINUM, ALIAS_INT2TYPE(FS_VINUM) }, 51263669Smarcel { ALIAS_FREEBSD_ZFS, ALIAS_INT2TYPE(FS_ZFS) }, 52263487Smarcel { ALIAS_NONE, 0 } 53263409Smarcel}; 54263409Smarcel 55272030Smarcelstatic lba_t 56272030Smarcelbsd_metadata(u_int where, lba_t blk) 57263409Smarcel{ 58263409Smarcel 59272030Smarcel if (where == SCHEME_META_IMG_START) 60272030Smarcel blk += BBSIZE / secsz; 61272030Smarcel else if (where == SCHEME_META_IMG_END) 62272030Smarcel blk = round_cylinder(blk); 63272030Smarcel else 64272030Smarcel blk = round_block(blk); 65272030Smarcel return (blk); 66263409Smarcel} 67263409Smarcel 68263442Smarcelstatic int 69268161Smarcelbsd_write(lba_t imgsz, void *bootcode) 70263442Smarcel{ 71263669Smarcel u_char *buf, *p; 72263669Smarcel struct disklabel *d; 73263669Smarcel struct partition *dp; 74263669Smarcel struct part *part; 75271843Smarcel int bsdparts, error, n; 76263669Smarcel uint16_t checksum; 77263669Smarcel 78263669Smarcel buf = malloc(BBSIZE); 79263669Smarcel if (buf == NULL) 80263669Smarcel return (ENOMEM); 81263669Smarcel if (bootcode != NULL) { 82263669Smarcel memcpy(buf, bootcode, BBSIZE); 83271846Smarcel memset(buf + secsz, 0, sizeof(struct disklabel)); 84263669Smarcel } else 85263669Smarcel memset(buf, 0, BBSIZE); 86263669Smarcel 87271843Smarcel bsdparts = nparts + 1; /* Account for c partition */ 88271843Smarcel if (bsdparts < MAXPARTITIONS) 89271843Smarcel bsdparts = MAXPARTITIONS; 90263849Smarcel 91263898Smarcel d = (void *)(buf + secsz); 92263669Smarcel le32enc(&d->d_magic, DISKMAGIC); 93263669Smarcel le32enc(&d->d_secsize, secsz); 94263849Smarcel le32enc(&d->d_nsectors, nsecs); 95263849Smarcel le32enc(&d->d_ntracks, nheads); 96263849Smarcel le32enc(&d->d_ncylinders, ncyls); 97263849Smarcel le32enc(&d->d_secpercyl, nsecs * nheads); 98263669Smarcel le32enc(&d->d_secperunit, imgsz); 99263669Smarcel le16enc(&d->d_rpm, 3600); 100263669Smarcel le32enc(&d->d_magic2, DISKMAGIC); 101271843Smarcel le16enc(&d->d_npartitions, bsdparts); 102263669Smarcel le32enc(&d->d_bbsize, BBSIZE); 103263669Smarcel 104263893Smarcel dp = &d->d_partitions[RAW_PART]; 105263893Smarcel le32enc(&dp->p_size, imgsz); 106263669Smarcel STAILQ_FOREACH(part, &partlist, link) { 107263893Smarcel n = part->index + ((part->index >= RAW_PART) ? 1 : 0); 108263893Smarcel dp = &d->d_partitions[n]; 109263669Smarcel le32enc(&dp->p_size, part->size); 110263669Smarcel le32enc(&dp->p_offset, part->block); 111271846Smarcel le32enc(&dp->p_fsize, 0); 112263669Smarcel dp->p_fstype = ALIAS_TYPE2INT(part->type); 113271846Smarcel dp->p_frag = 0; 114271846Smarcel le16enc(&dp->p_cpg, 0); 115263669Smarcel } 116263669Smarcel 117271843Smarcel dp = &d->d_partitions[bsdparts]; 118263669Smarcel checksum = 0; 119271843Smarcel for (p = (void *)d; p < (u_char *)dp; p += 2) 120263669Smarcel checksum ^= le16dec(p); 121263669Smarcel le16enc(&d->d_checksum, checksum); 122263669Smarcel 123268161Smarcel error = image_write(0, buf, BBSIZE / secsz); 124263669Smarcel free(buf); 125263669Smarcel return (error); 126263442Smarcel} 127263442Smarcel 128263409Smarcelstatic struct mkimg_scheme bsd_scheme = { 129263409Smarcel .name = "bsd", 130263440Smarcel .description = "BSD disk label", 131263409Smarcel .aliases = bsd_aliases, 132263440Smarcel .metadata = bsd_metadata, 133263442Smarcel .write = bsd_write, 134263893Smarcel .nparts = 19, 135263700Smarcel .bootcode = BBSIZE, 136263700Smarcel .maxsecsz = 512 137263409Smarcel}; 138263409Smarcel 139263409SmarcelSCHEME_DEFINE(bsd_scheme); 140