1d71142f3SPoul-Henning Kamp /*- 2d71142f3SPoul-Henning Kamp * Copyright (c) 2003 Poul-Henning Kamp 3d71142f3SPoul-Henning Kamp * Copyright (c) 2002 Networks Associates Technology, Inc. 4d71142f3SPoul-Henning Kamp * All rights reserved. 5d71142f3SPoul-Henning Kamp * 6d71142f3SPoul-Henning Kamp * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7d71142f3SPoul-Henning Kamp * and NAI Labs, the Security Research Division of Network Associates, Inc. 8d71142f3SPoul-Henning Kamp * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9d71142f3SPoul-Henning Kamp * DARPA CHATS research program. 10d71142f3SPoul-Henning Kamp * 11d71142f3SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 12d71142f3SPoul-Henning Kamp * modification, are permitted provided that the following conditions 13d71142f3SPoul-Henning Kamp * are met: 14d71142f3SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 15d71142f3SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 16d71142f3SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 17d71142f3SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 18d71142f3SPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 19d71142f3SPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 20d71142f3SPoul-Henning Kamp * products derived from this software without specific prior written 21d71142f3SPoul-Henning Kamp * permission. 22d71142f3SPoul-Henning Kamp * 23d71142f3SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24d71142f3SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25d71142f3SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26d71142f3SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27d71142f3SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28d71142f3SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29d71142f3SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30d71142f3SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31d71142f3SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32d71142f3SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33d71142f3SPoul-Henning Kamp * SUCH DAMAGE. 34d71142f3SPoul-Henning Kamp * 35d71142f3SPoul-Henning Kamp * $FreeBSD$ 36d71142f3SPoul-Henning Kamp */ 37d71142f3SPoul-Henning Kamp 38d71142f3SPoul-Henning Kamp #include <stdio.h> 39d71142f3SPoul-Henning Kamp #include <stdlib.h> 40d71142f3SPoul-Henning Kamp #include <unistd.h> 41d71142f3SPoul-Henning Kamp #include <stdint.h> 42d71142f3SPoul-Henning Kamp #include <string.h> 43d71142f3SPoul-Henning Kamp #include <ctype.h> 44d71142f3SPoul-Henning Kamp #include <errno.h> 45d71142f3SPoul-Henning Kamp #include <paths.h> 46d71142f3SPoul-Henning Kamp #include <fcntl.h> 47d71142f3SPoul-Henning Kamp #include <err.h> 48d71142f3SPoul-Henning Kamp #include <bsdxml.h> 49d71142f3SPoul-Henning Kamp #include <sys/types.h> 50d71142f3SPoul-Henning Kamp #include <sys/stat.h> 51d71142f3SPoul-Henning Kamp #include <sys/queue.h> 52d71142f3SPoul-Henning Kamp #include <sys/sbuf.h> 53d71142f3SPoul-Henning Kamp #include <sys/mman.h> 54d71142f3SPoul-Henning Kamp 55d71142f3SPoul-Henning Kamp struct sector { 56d71142f3SPoul-Henning Kamp LIST_ENTRY(sector) sectors; 57d71142f3SPoul-Henning Kamp off_t offset; 58d71142f3SPoul-Henning Kamp unsigned char *data; 59d71142f3SPoul-Henning Kamp }; 60d71142f3SPoul-Henning Kamp 61d71142f3SPoul-Henning Kamp struct simdisk_softc { 62d71142f3SPoul-Henning Kamp int sectorsize; 63d71142f3SPoul-Henning Kamp off_t mediasize; 64d71142f3SPoul-Henning Kamp off_t lastsector; 65d71142f3SPoul-Henning Kamp LIST_HEAD(,sector) sectors; 66d71142f3SPoul-Henning Kamp struct sbuf *sbuf; 67d71142f3SPoul-Henning Kamp struct sector *sp; 68d71142f3SPoul-Henning Kamp u_int fwsectors; 69d71142f3SPoul-Henning Kamp u_int fwheads; 70d71142f3SPoul-Henning Kamp u_int fwcylinders; 71d71142f3SPoul-Henning Kamp }; 72d71142f3SPoul-Henning Kamp 73d71142f3SPoul-Henning Kamp static void 74d71142f3SPoul-Henning Kamp g_simdisk_insertsector(struct simdisk_softc *sc, struct sector *dsp) 75d71142f3SPoul-Henning Kamp { 76d71142f3SPoul-Henning Kamp struct sector *dsp2, *dsp3; 77d71142f3SPoul-Henning Kamp 78d71142f3SPoul-Henning Kamp if (sc->lastsector < dsp->offset) 79d71142f3SPoul-Henning Kamp sc->lastsector = dsp->offset; 80d71142f3SPoul-Henning Kamp if (LIST_EMPTY(&sc->sectors)) { 81d71142f3SPoul-Henning Kamp LIST_INSERT_HEAD(&sc->sectors, dsp, sectors); 82d71142f3SPoul-Henning Kamp return; 83d71142f3SPoul-Henning Kamp } 84d71142f3SPoul-Henning Kamp dsp3 = NULL; 85d71142f3SPoul-Henning Kamp LIST_FOREACH(dsp2, &sc->sectors, sectors) { 86d71142f3SPoul-Henning Kamp dsp3 = dsp2; 87d71142f3SPoul-Henning Kamp if (dsp2->offset > dsp->offset) { 88d71142f3SPoul-Henning Kamp LIST_INSERT_BEFORE(dsp2, dsp, sectors); 89d71142f3SPoul-Henning Kamp return; 90d71142f3SPoul-Henning Kamp } 91d71142f3SPoul-Henning Kamp } 92d71142f3SPoul-Henning Kamp LIST_INSERT_AFTER(dsp3, dsp, sectors); 93d71142f3SPoul-Henning Kamp } 94d71142f3SPoul-Henning Kamp 95d71142f3SPoul-Henning Kamp static void 96d71142f3SPoul-Henning Kamp startElement(void *userData, const char *name, const char **atts __unused) 97d71142f3SPoul-Henning Kamp { 98d71142f3SPoul-Henning Kamp struct simdisk_softc *sc; 99d71142f3SPoul-Henning Kamp 100d71142f3SPoul-Henning Kamp sc = userData; 101d71142f3SPoul-Henning Kamp if (!strcasecmp(name, "sector")) { 102d71142f3SPoul-Henning Kamp sc->sp = calloc(1, sizeof(*sc->sp) + sc->sectorsize); 103d71142f3SPoul-Henning Kamp sc->sp->data = (u_char *)(sc->sp + 1); 104d71142f3SPoul-Henning Kamp } 105d71142f3SPoul-Henning Kamp sbuf_clear(sc->sbuf); 106d71142f3SPoul-Henning Kamp } 107d71142f3SPoul-Henning Kamp 108d71142f3SPoul-Henning Kamp static void 109d71142f3SPoul-Henning Kamp endElement(void *userData, const char *name) 110d71142f3SPoul-Henning Kamp { 111d71142f3SPoul-Henning Kamp struct simdisk_softc *sc; 112d71142f3SPoul-Henning Kamp char *p; 113d71142f3SPoul-Henning Kamp u_char *q; 114d71142f3SPoul-Henning Kamp int i, j; 115d71142f3SPoul-Henning Kamp off_t o; 116d71142f3SPoul-Henning Kamp 117d71142f3SPoul-Henning Kamp sc = userData; 118d71142f3SPoul-Henning Kamp 119d71142f3SPoul-Henning Kamp if (!strcasecmp(name, "comment")) { 120d71142f3SPoul-Henning Kamp sbuf_clear(sc->sbuf); 121d71142f3SPoul-Henning Kamp return; 122d71142f3SPoul-Henning Kamp } 123d71142f3SPoul-Henning Kamp sbuf_finish(sc->sbuf); 124d71142f3SPoul-Henning Kamp if (!strcasecmp(name, "sectorsize")) { 125d71142f3SPoul-Henning Kamp sc->sectorsize = strtoul(sbuf_data(sc->sbuf), &p, 0); 126d71142f3SPoul-Henning Kamp if (*p != '\0') 127d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on sectorsize"); 128d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "mediasize")) { 129d71142f3SPoul-Henning Kamp o = strtoull(sbuf_data(sc->sbuf), &p, 0); 130d71142f3SPoul-Henning Kamp if (*p != '\0') 131d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on mediasize"); 132d71142f3SPoul-Henning Kamp if (o > 0) 133d71142f3SPoul-Henning Kamp sc->mediasize = o; 134d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "fwsectors")) { 135d71142f3SPoul-Henning Kamp sc->fwsectors = strtoul(sbuf_data(sc->sbuf), &p, 0); 136d71142f3SPoul-Henning Kamp if (*p != '\0') 137d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on fwsectors"); 138d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "fwheads")) { 139d71142f3SPoul-Henning Kamp sc->fwheads = strtoul(sbuf_data(sc->sbuf), &p, 0); 140d71142f3SPoul-Henning Kamp if (*p != '\0') 141d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on fwheads"); 142d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "fwcylinders")) { 143d71142f3SPoul-Henning Kamp sc->fwcylinders = strtoul(sbuf_data(sc->sbuf), &p, 0); 144d71142f3SPoul-Henning Kamp if (*p != '\0') 145d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on fwcylinders"); 146d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "offset")) { 147d71142f3SPoul-Henning Kamp sc->sp->offset= strtoull(sbuf_data(sc->sbuf), &p, 0); 148d71142f3SPoul-Henning Kamp if (*p != '\0') 149d71142f3SPoul-Henning Kamp errx(1, "strtoul croaked on offset"); 150d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "fill")) { 151d71142f3SPoul-Henning Kamp j = strtoul(sbuf_data(sc->sbuf), NULL, 16); 152d71142f3SPoul-Henning Kamp memset(sc->sp->data, j, sc->sectorsize); 153d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "hexdata")) { 154d71142f3SPoul-Henning Kamp q = sc->sp->data; 155d71142f3SPoul-Henning Kamp p = sbuf_data(sc->sbuf); 156d71142f3SPoul-Henning Kamp for (i = 0; i < sc->sectorsize; i++) { 157d71142f3SPoul-Henning Kamp if (!isxdigit(*p)) 158d71142f3SPoul-Henning Kamp errx(1, "I croaked on hexdata %d:(%02x)", i, *p); 159d71142f3SPoul-Henning Kamp if (isdigit(*p)) 160d71142f3SPoul-Henning Kamp j = (*p - '0') << 4; 161d71142f3SPoul-Henning Kamp else 162d71142f3SPoul-Henning Kamp j = (tolower(*p) - 'a' + 10) << 4; 163d71142f3SPoul-Henning Kamp p++; 164d71142f3SPoul-Henning Kamp if (!isxdigit(*p)) 165d71142f3SPoul-Henning Kamp errx(1, "I croaked on hexdata %d:(%02x)", i, *p); 166d71142f3SPoul-Henning Kamp if (isdigit(*p)) 167d71142f3SPoul-Henning Kamp j |= *p - '0'; 168d71142f3SPoul-Henning Kamp else 169d71142f3SPoul-Henning Kamp j |= tolower(*p) - 'a' + 10; 170d71142f3SPoul-Henning Kamp p++; 171d71142f3SPoul-Henning Kamp *q++ = j; 172d71142f3SPoul-Henning Kamp } 173d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "sector")) { 174d71142f3SPoul-Henning Kamp g_simdisk_insertsector(sc, sc->sp); 175d71142f3SPoul-Henning Kamp sc->sp = NULL; 176d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "diskimage")) { 177d71142f3SPoul-Henning Kamp } else if (!strcasecmp(name, "FreeBSD")) { 178d71142f3SPoul-Henning Kamp } else { 179d71142f3SPoul-Henning Kamp printf("<%s>[[%s]]\n", name, sbuf_data(sc->sbuf)); 180d71142f3SPoul-Henning Kamp } 181d71142f3SPoul-Henning Kamp sbuf_clear(sc->sbuf); 182d71142f3SPoul-Henning Kamp } 183d71142f3SPoul-Henning Kamp 184d71142f3SPoul-Henning Kamp static void 185d71142f3SPoul-Henning Kamp characterData(void *userData, const XML_Char *s, int len) 186d71142f3SPoul-Henning Kamp { 187d71142f3SPoul-Henning Kamp const char *b, *e; 188d71142f3SPoul-Henning Kamp struct simdisk_softc *sc; 189d71142f3SPoul-Henning Kamp 190d71142f3SPoul-Henning Kamp sc = userData; 191d71142f3SPoul-Henning Kamp b = s; 192d71142f3SPoul-Henning Kamp e = s + len - 1; 193d71142f3SPoul-Henning Kamp while (isspace(*b) && b < e) 194d71142f3SPoul-Henning Kamp b++; 195d71142f3SPoul-Henning Kamp while (isspace(*e) && e > b) 196d71142f3SPoul-Henning Kamp e--; 197d71142f3SPoul-Henning Kamp if (e != b || !isspace(*b)) 198d71142f3SPoul-Henning Kamp sbuf_bcat(sc->sbuf, b, e - b + 1); 199d71142f3SPoul-Henning Kamp } 200d71142f3SPoul-Henning Kamp 201d71142f3SPoul-Henning Kamp static struct simdisk_softc * 202d71142f3SPoul-Henning Kamp g_simdisk_xml_load(const char *file) 203d71142f3SPoul-Henning Kamp { 204d71142f3SPoul-Henning Kamp XML_Parser parser = XML_ParserCreate(NULL); 205d71142f3SPoul-Henning Kamp struct stat st; 206d71142f3SPoul-Henning Kamp char *p; 207d71142f3SPoul-Henning Kamp struct simdisk_softc *sc; 208d71142f3SPoul-Henning Kamp int fd, i; 209d71142f3SPoul-Henning Kamp 210d71142f3SPoul-Henning Kamp sc = calloc(1, sizeof *sc); 211d71142f3SPoul-Henning Kamp sc->sbuf = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 212d71142f3SPoul-Henning Kamp LIST_INIT(&sc->sectors); 213d71142f3SPoul-Henning Kamp XML_SetUserData(parser, sc); 214d71142f3SPoul-Henning Kamp XML_SetElementHandler(parser, startElement, endElement); 215d71142f3SPoul-Henning Kamp XML_SetCharacterDataHandler(parser, characterData); 216d71142f3SPoul-Henning Kamp 217d71142f3SPoul-Henning Kamp fd = open(file, O_RDONLY); 218d71142f3SPoul-Henning Kamp if (fd < 0) 219d71142f3SPoul-Henning Kamp err(1, file); 220d71142f3SPoul-Henning Kamp fstat(fd, &st); 221d71142f3SPoul-Henning Kamp p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0); 222d71142f3SPoul-Henning Kamp i = XML_Parse(parser, p, st.st_size, 1); 223d71142f3SPoul-Henning Kamp if (i != 1) 224d71142f3SPoul-Henning Kamp errx(1, "XML_Parse complains: return %d", i); 225d71142f3SPoul-Henning Kamp munmap(p, st.st_size); 226d71142f3SPoul-Henning Kamp close(fd); 227d71142f3SPoul-Henning Kamp XML_ParserFree(parser); 228d71142f3SPoul-Henning Kamp return (sc); 229d71142f3SPoul-Henning Kamp } 230d71142f3SPoul-Henning Kamp 231d71142f3SPoul-Henning Kamp int 232d71142f3SPoul-Henning Kamp main(int argc, char **argv) 233d71142f3SPoul-Henning Kamp { 234d71142f3SPoul-Henning Kamp struct simdisk_softc *sc; 235d71142f3SPoul-Henning Kamp char buf[BUFSIZ]; 236d71142f3SPoul-Henning Kamp int error, fd; 237d71142f3SPoul-Henning Kamp struct sector *dsp; 238d71142f3SPoul-Henning Kamp 239d71142f3SPoul-Henning Kamp if (argc != 3) 240d71142f3SPoul-Henning Kamp errx(1, "Usage: %s mddevice xmlfile", argv[0]); 241d71142f3SPoul-Henning Kamp 242d71142f3SPoul-Henning Kamp sc = g_simdisk_xml_load(argv[2]); 243d71142f3SPoul-Henning Kamp if (sc->mediasize == 0) 244d71142f3SPoul-Henning Kamp sc->mediasize = sc->lastsector + sc->sectorsize * 10; 245d71142f3SPoul-Henning Kamp if (sc->sectorsize == 0) 246d71142f3SPoul-Henning Kamp sc->sectorsize = 512; 247d71142f3SPoul-Henning Kamp sprintf(buf, "mdconfig -a -t malloc -s %jd -S %d", 248d71142f3SPoul-Henning Kamp (intmax_t)sc->mediasize / sc->sectorsize, sc->sectorsize); 249d71142f3SPoul-Henning Kamp if (sc->fwsectors && sc->fwheads) 250d71142f3SPoul-Henning Kamp sprintf(buf + strlen(buf), " -x %d -y %d", 251d71142f3SPoul-Henning Kamp sc->fwsectors, sc->fwheads); 252d71142f3SPoul-Henning Kamp sprintf(buf + strlen(buf), " -u %s", argv[1]); 253d71142f3SPoul-Henning Kamp error = system(buf); 254d71142f3SPoul-Henning Kamp if (error) 255d71142f3SPoul-Henning Kamp return (error); 256d71142f3SPoul-Henning Kamp fd = open(argv[1], O_RDWR); 257d71142f3SPoul-Henning Kamp if (fd < 0 && errno == ENOENT) { 258d71142f3SPoul-Henning Kamp sprintf(buf, "%s%s", _PATH_DEV, argv[1]); 259d71142f3SPoul-Henning Kamp fd = open(buf, O_RDWR); 260d71142f3SPoul-Henning Kamp } 261d71142f3SPoul-Henning Kamp if (fd < 0) 262d71142f3SPoul-Henning Kamp err(1, "Could not open %s", argv[1]); 263d71142f3SPoul-Henning Kamp LIST_FOREACH(dsp, &sc->sectors, sectors) { 264d71142f3SPoul-Henning Kamp lseek(fd, dsp->offset, SEEK_SET); 265d71142f3SPoul-Henning Kamp error = write(fd, dsp->data, sc->sectorsize); 266d71142f3SPoul-Henning Kamp if (error != sc->sectorsize) 267d71142f3SPoul-Henning Kamp err(1, "write sectordata failed"); 268d71142f3SPoul-Henning Kamp } 269d71142f3SPoul-Henning Kamp close(fd); 270d71142f3SPoul-Henning Kamp exit (0); 271d71142f3SPoul-Henning Kamp } 272