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/diskmbr.h> 32263674Smarcel#include <sys/endian.h> 33263442Smarcel#include <sys/errno.h> 34263409Smarcel#include <stdlib.h> 35263674Smarcel#include <string.h> 36263674Smarcel#include <unistd.h> 37263409Smarcel 38268161Smarcel#include "image.h" 39263409Smarcel#include "mkimg.h" 40263409Smarcel#include "scheme.h" 41263409Smarcel 42292341Semaste#ifndef DOSPTYP_FAT16B 43292341Semaste#define DOSPTYP_FAT16B 0x06 44292341Semaste#endif 45268161Smarcel#ifndef DOSPTYP_FAT32 46268161Smarcel#define DOSPTYP_FAT32 0x0b 47268161Smarcel#endif 48268161Smarcel 49263409Smarcelstatic struct mkimg_alias ebr_aliases[] = { 50292341Semaste { ALIAS_FAT16B, ALIAS_INT2TYPE(DOSPTYP_FAT16B) }, 51263674Smarcel { ALIAS_FAT32, ALIAS_INT2TYPE(DOSPTYP_FAT32) }, 52263674Smarcel { ALIAS_FREEBSD, ALIAS_INT2TYPE(DOSPTYP_386BSD) }, 53263487Smarcel { ALIAS_NONE, 0 } 54263409Smarcel}; 55263409Smarcel 56272030Smarcelstatic lba_t 57272030Smarcelebr_metadata(u_int where, lba_t blk) 58263409Smarcel{ 59263409Smarcel 60272030Smarcel blk += (where == SCHEME_META_PART_BEFORE) ? 1 : 0; 61272030Smarcel return (round_track(blk)); 62263409Smarcel} 63263409Smarcel 64263674Smarcelstatic void 65272776Smarcelebr_chs(u_char *cylp, u_char *hdp, u_char *secp, lba_t lba) 66263674Smarcel{ 67272776Smarcel u_int cyl, hd, sec; 68263674Smarcel 69272776Smarcel mkimg_chs(lba, 1023, &cyl, &hd, &sec); 70272776Smarcel *cylp = cyl; 71272776Smarcel *hdp = hd; 72272776Smarcel *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0); 73263674Smarcel} 74263674Smarcel 75263442Smarcelstatic int 76268161Smarcelebr_write(lba_t imgsz __unused, void *bootcode __unused) 77263442Smarcel{ 78263674Smarcel u_char *ebr; 79263674Smarcel struct dos_partition *dp; 80263674Smarcel struct part *part, *next; 81272776Smarcel lba_t block, size; 82263674Smarcel int error; 83263674Smarcel 84263674Smarcel ebr = malloc(secsz); 85263674Smarcel if (ebr == NULL) 86263674Smarcel return (ENOMEM); 87263674Smarcel memset(ebr, 0, secsz); 88263674Smarcel le16enc(ebr + DOSMAGICOFFSET, DOSMAGIC); 89263674Smarcel 90263674Smarcel error = 0; 91263674Smarcel STAILQ_FOREACH_SAFE(part, &partlist, link, next) { 92263843Smarcel block = part->block - nsecs; 93272776Smarcel size = round_track(part->size); 94263674Smarcel dp = (void *)(ebr + DOSPARTOFF); 95263843Smarcel ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect, nsecs); 96263674Smarcel dp->dp_typ = ALIAS_TYPE2INT(part->type); 97263674Smarcel ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect, 98272776Smarcel part->block + size - 1); 99263843Smarcel le32enc(&dp->dp_start, nsecs); 100272776Smarcel le32enc(&dp->dp_size, size); 101263674Smarcel 102263674Smarcel /* Add link entry */ 103263674Smarcel if (next != NULL) { 104272776Smarcel size = round_track(next->size); 105263674Smarcel dp++; 106263674Smarcel ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect, 107263843Smarcel next->block - nsecs); 108263674Smarcel dp->dp_typ = DOSPTYP_EXT; 109263674Smarcel ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect, 110272776Smarcel next->block + size - 1); 111263843Smarcel le32enc(&dp->dp_start, next->block - nsecs); 112272776Smarcel le32enc(&dp->dp_size, size + nsecs); 113263674Smarcel } 114263674Smarcel 115268161Smarcel error = image_write(block, ebr, 1); 116263674Smarcel if (error) 117263674Smarcel break; 118263674Smarcel 119263674Smarcel memset(ebr + DOSPARTOFF, 0, 2 * DOSPARTSIZE); 120263674Smarcel } 121263674Smarcel 122263674Smarcel free(ebr); 123263674Smarcel return (error); 124263442Smarcel} 125263442Smarcel 126263409Smarcelstatic struct mkimg_scheme ebr_scheme = { 127263409Smarcel .name = "ebr", 128263409Smarcel .description = "Extended Boot Record", 129263409Smarcel .aliases = ebr_aliases, 130263440Smarcel .metadata = ebr_metadata, 131263442Smarcel .write = ebr_write, 132263700Smarcel .nparts = 4096, 133263700Smarcel .maxsecsz = 4096 134263409Smarcel}; 135263409Smarcel 136263409SmarcelSCHEME_DEFINE(ebr_scheme); 137