1113290Sphk/*- 2113290Sphk * Copyright (c) 2003 Poul-Henning Kamp 3113290Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 4113290Sphk * All rights reserved. 5113290Sphk * 6113290Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7113290Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 8113290Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9113290Sphk * DARPA CHATS research program. 10113290Sphk * 11113290Sphk * Redistribution and use in source and binary forms, with or without 12113290Sphk * modification, are permitted provided that the following conditions 13113290Sphk * are met: 14113290Sphk * 1. Redistributions of source code must retain the above copyright 15113290Sphk * notice, this list of conditions and the following disclaimer. 16113290Sphk * 2. Redistributions in binary form must reproduce the above copyright 17113290Sphk * notice, this list of conditions and the following disclaimer in the 18113290Sphk * documentation and/or other materials provided with the distribution. 19113290Sphk * 3. The names of the authors may not be used to endorse or promote 20113290Sphk * products derived from this software without specific prior written 21113290Sphk * permission. 22113290Sphk * 23113290Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24113290Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25113290Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26113290Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27113290Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28113290Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29113290Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30113290Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31113290Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32113290Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33113290Sphk * SUCH DAMAGE. 34113290Sphk * 35113290Sphk * $FreeBSD$ 36113290Sphk */ 37113290Sphk 38113290Sphk#include <stdio.h> 39113290Sphk#include <stdlib.h> 40113290Sphk#include <unistd.h> 41113290Sphk#include <stdint.h> 42113290Sphk#include <string.h> 43113290Sphk#include <ctype.h> 44113290Sphk#include <errno.h> 45113290Sphk#include <paths.h> 46113290Sphk#include <fcntl.h> 47113290Sphk#include <err.h> 48113290Sphk#include <bsdxml.h> 49113290Sphk#include <sys/types.h> 50113290Sphk#include <sys/stat.h> 51113290Sphk#include <sys/queue.h> 52113290Sphk#include <sys/sbuf.h> 53113290Sphk#include <sys/mman.h> 54113290Sphk 55113290Sphkstruct sector { 56113290Sphk LIST_ENTRY(sector) sectors; 57113290Sphk off_t offset; 58113290Sphk unsigned char *data; 59113290Sphk}; 60113290Sphk 61113290Sphkstruct simdisk_softc { 62113290Sphk int sectorsize; 63113290Sphk off_t mediasize; 64113290Sphk off_t lastsector; 65113290Sphk LIST_HEAD(,sector) sectors; 66113290Sphk struct sbuf *sbuf; 67113290Sphk struct sector *sp; 68113290Sphk u_int fwsectors; 69113290Sphk u_int fwheads; 70113290Sphk u_int fwcylinders; 71113290Sphk}; 72113290Sphk 73113290Sphkstatic void 74113290Sphkg_simdisk_insertsector(struct simdisk_softc *sc, struct sector *dsp) 75113290Sphk{ 76113290Sphk struct sector *dsp2, *dsp3; 77113290Sphk 78113290Sphk if (sc->lastsector < dsp->offset) 79113290Sphk sc->lastsector = dsp->offset; 80113290Sphk if (LIST_EMPTY(&sc->sectors)) { 81113290Sphk LIST_INSERT_HEAD(&sc->sectors, dsp, sectors); 82113290Sphk return; 83113290Sphk } 84113290Sphk dsp3 = NULL; 85113290Sphk LIST_FOREACH(dsp2, &sc->sectors, sectors) { 86113290Sphk dsp3 = dsp2; 87113290Sphk if (dsp2->offset > dsp->offset) { 88113290Sphk LIST_INSERT_BEFORE(dsp2, dsp, sectors); 89113290Sphk return; 90113290Sphk } 91113290Sphk } 92113290Sphk LIST_INSERT_AFTER(dsp3, dsp, sectors); 93113290Sphk} 94113290Sphk 95113290Sphkstatic void 96113290SphkstartElement(void *userData, const char *name, const char **atts __unused) 97113290Sphk{ 98113290Sphk struct simdisk_softc *sc; 99113290Sphk 100113290Sphk sc = userData; 101113290Sphk if (!strcasecmp(name, "sector")) { 102113290Sphk sc->sp = calloc(1, sizeof(*sc->sp) + sc->sectorsize); 103113290Sphk sc->sp->data = (u_char *)(sc->sp + 1); 104113290Sphk } 105113290Sphk sbuf_clear(sc->sbuf); 106113290Sphk} 107113290Sphk 108113290Sphkstatic void 109113290SphkendElement(void *userData, const char *name) 110113290Sphk{ 111113290Sphk struct simdisk_softc *sc; 112113290Sphk char *p; 113113290Sphk u_char *q; 114113290Sphk int i, j; 115113290Sphk off_t o; 116113290Sphk 117113290Sphk sc = userData; 118113290Sphk 119113290Sphk if (!strcasecmp(name, "comment")) { 120113290Sphk sbuf_clear(sc->sbuf); 121113290Sphk return; 122113290Sphk } 123113290Sphk sbuf_finish(sc->sbuf); 124113290Sphk if (!strcasecmp(name, "sectorsize")) { 125113290Sphk sc->sectorsize = strtoul(sbuf_data(sc->sbuf), &p, 0); 126113290Sphk if (*p != '\0') 127113290Sphk errx(1, "strtoul croaked on sectorsize"); 128113290Sphk } else if (!strcasecmp(name, "mediasize")) { 129113290Sphk o = strtoull(sbuf_data(sc->sbuf), &p, 0); 130113290Sphk if (*p != '\0') 131113290Sphk errx(1, "strtoul croaked on mediasize"); 132113290Sphk if (o > 0) 133113290Sphk sc->mediasize = o; 134113290Sphk } else if (!strcasecmp(name, "fwsectors")) { 135113290Sphk sc->fwsectors = strtoul(sbuf_data(sc->sbuf), &p, 0); 136113290Sphk if (*p != '\0') 137113290Sphk errx(1, "strtoul croaked on fwsectors"); 138113290Sphk } else if (!strcasecmp(name, "fwheads")) { 139113290Sphk sc->fwheads = strtoul(sbuf_data(sc->sbuf), &p, 0); 140113290Sphk if (*p != '\0') 141113290Sphk errx(1, "strtoul croaked on fwheads"); 142113290Sphk } else if (!strcasecmp(name, "fwcylinders")) { 143113290Sphk sc->fwcylinders = strtoul(sbuf_data(sc->sbuf), &p, 0); 144113290Sphk if (*p != '\0') 145113290Sphk errx(1, "strtoul croaked on fwcylinders"); 146113290Sphk } else if (!strcasecmp(name, "offset")) { 147113290Sphk sc->sp->offset= strtoull(sbuf_data(sc->sbuf), &p, 0); 148113290Sphk if (*p != '\0') 149113290Sphk errx(1, "strtoul croaked on offset"); 150113290Sphk } else if (!strcasecmp(name, "fill")) { 151113290Sphk j = strtoul(sbuf_data(sc->sbuf), NULL, 16); 152113290Sphk memset(sc->sp->data, j, sc->sectorsize); 153113290Sphk } else if (!strcasecmp(name, "hexdata")) { 154113290Sphk q = sc->sp->data; 155113290Sphk p = sbuf_data(sc->sbuf); 156113290Sphk for (i = 0; i < sc->sectorsize; i++) { 157113290Sphk if (!isxdigit(*p)) 158113290Sphk errx(1, "I croaked on hexdata %d:(%02x)", i, *p); 159113290Sphk if (isdigit(*p)) 160113290Sphk j = (*p - '0') << 4; 161113290Sphk else 162113290Sphk j = (tolower(*p) - 'a' + 10) << 4; 163113290Sphk p++; 164113290Sphk if (!isxdigit(*p)) 165113290Sphk errx(1, "I croaked on hexdata %d:(%02x)", i, *p); 166113290Sphk if (isdigit(*p)) 167113290Sphk j |= *p - '0'; 168113290Sphk else 169113290Sphk j |= tolower(*p) - 'a' + 10; 170113290Sphk p++; 171113290Sphk *q++ = j; 172113290Sphk } 173113290Sphk } else if (!strcasecmp(name, "sector")) { 174113290Sphk g_simdisk_insertsector(sc, sc->sp); 175113290Sphk sc->sp = NULL; 176113290Sphk } else if (!strcasecmp(name, "diskimage")) { 177113290Sphk } else if (!strcasecmp(name, "FreeBSD")) { 178113290Sphk } else { 179113290Sphk printf("<%s>[[%s]]\n", name, sbuf_data(sc->sbuf)); 180113290Sphk } 181113290Sphk sbuf_clear(sc->sbuf); 182113290Sphk} 183113290Sphk 184113290Sphkstatic void 185113290SphkcharacterData(void *userData, const XML_Char *s, int len) 186113290Sphk{ 187113290Sphk const char *b, *e; 188113290Sphk struct simdisk_softc *sc; 189113290Sphk 190113290Sphk sc = userData; 191113290Sphk b = s; 192113290Sphk e = s + len - 1; 193113290Sphk while (isspace(*b) && b < e) 194113290Sphk b++; 195113290Sphk while (isspace(*e) && e > b) 196113290Sphk e--; 197113290Sphk if (e != b || !isspace(*b)) 198113290Sphk sbuf_bcat(sc->sbuf, b, e - b + 1); 199113290Sphk} 200113290Sphk 201113290Sphkstatic struct simdisk_softc * 202113290Sphkg_simdisk_xml_load(const char *file) 203113290Sphk{ 204113290Sphk XML_Parser parser = XML_ParserCreate(NULL); 205113290Sphk struct stat st; 206113290Sphk char *p; 207113290Sphk struct simdisk_softc *sc; 208113290Sphk int fd, i; 209113290Sphk 210113290Sphk sc = calloc(1, sizeof *sc); 211181463Sdes sc->sbuf = sbuf_new_auto(); 212113290Sphk LIST_INIT(&sc->sectors); 213113290Sphk XML_SetUserData(parser, sc); 214113290Sphk XML_SetElementHandler(parser, startElement, endElement); 215113290Sphk XML_SetCharacterDataHandler(parser, characterData); 216113290Sphk 217113290Sphk fd = open(file, O_RDONLY); 218113290Sphk if (fd < 0) 219113290Sphk err(1, file); 220113290Sphk fstat(fd, &st); 221113290Sphk p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0); 222113290Sphk i = XML_Parse(parser, p, st.st_size, 1); 223113290Sphk if (i != 1) 224113290Sphk errx(1, "XML_Parse complains: return %d", i); 225113290Sphk munmap(p, st.st_size); 226113290Sphk close(fd); 227113290Sphk XML_ParserFree(parser); 228113290Sphk return (sc); 229113290Sphk} 230113290Sphk 231113290Sphkint 232113290Sphkmain(int argc, char **argv) 233113290Sphk{ 234113290Sphk struct simdisk_softc *sc; 235113290Sphk char buf[BUFSIZ]; 236113290Sphk int error, fd; 237113290Sphk struct sector *dsp; 238113290Sphk 239113290Sphk if (argc != 3) 240113290Sphk errx(1, "Usage: %s mddevice xmlfile", argv[0]); 241113290Sphk 242113290Sphk sc = g_simdisk_xml_load(argv[2]); 243113290Sphk if (sc->mediasize == 0) 244113290Sphk sc->mediasize = sc->lastsector + sc->sectorsize * 10; 245113290Sphk if (sc->sectorsize == 0) 246113290Sphk sc->sectorsize = 512; 247113290Sphk sprintf(buf, "mdconfig -a -t malloc -s %jd -S %d", 248113290Sphk (intmax_t)sc->mediasize / sc->sectorsize, sc->sectorsize); 249113290Sphk if (sc->fwsectors && sc->fwheads) 250113290Sphk sprintf(buf + strlen(buf), " -x %d -y %d", 251113290Sphk sc->fwsectors, sc->fwheads); 252113290Sphk sprintf(buf + strlen(buf), " -u %s", argv[1]); 253113290Sphk error = system(buf); 254113290Sphk if (error) 255113290Sphk return (error); 256113290Sphk fd = open(argv[1], O_RDWR); 257113290Sphk if (fd < 0 && errno == ENOENT) { 258113290Sphk sprintf(buf, "%s%s", _PATH_DEV, argv[1]); 259113290Sphk fd = open(buf, O_RDWR); 260113290Sphk } 261113290Sphk if (fd < 0) 262113290Sphk err(1, "Could not open %s", argv[1]); 263113290Sphk LIST_FOREACH(dsp, &sc->sectors, sectors) { 264113290Sphk lseek(fd, dsp->offset, SEEK_SET); 265113290Sphk error = write(fd, dsp->data, sc->sectorsize); 266113290Sphk if (error != sc->sectorsize) 267113290Sphk err(1, "write sectordata failed"); 268113290Sphk } 269113290Sphk close(fd); 270113290Sphk exit (0); 271113290Sphk} 272