1 1.39 pooka /* $NetBSD: rump_allserver.c,v 1.39 2015/04/16 10:05:43 pooka Exp $ */ 2 1.1 pooka 3 1.1 pooka /*- 4 1.16 pooka * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.24 pooka #include <rump/rumpuser_port.h> 29 1.24 pooka 30 1.1 pooka #ifndef lint 31 1.39 pooka __RCSID("$NetBSD: rump_allserver.c,v 1.39 2015/04/16 10:05:43 pooka Exp $"); 32 1.1 pooka #endif /* !lint */ 33 1.1 pooka 34 1.1 pooka #include <sys/types.h> 35 1.24 pooka #include <sys/stat.h> 36 1.24 pooka 37 1.6 pooka #include <dlfcn.h> 38 1.1 pooka #include <errno.h> 39 1.9 pooka #include <fcntl.h> 40 1.4 pooka #include <semaphore.h> 41 1.33 pooka #include <signal.h> 42 1.1 pooka #include <stdio.h> 43 1.1 pooka #include <stdlib.h> 44 1.24 pooka #include <stdint.h> 45 1.1 pooka #include <string.h> 46 1.1 pooka #include <unistd.h> 47 1.24 pooka 48 1.24 pooka #include <rump/rump.h> 49 1.24 pooka #include <rump/rump_syscalls.h> 50 1.27 pooka #include <rump/rumpdefs.h> 51 1.30 pooka #include <rump/rumperr.h> 52 1.1 pooka 53 1.22 joerg __dead static void 54 1.1 pooka usage(void) 55 1.1 pooka { 56 1.1 pooka 57 1.38 pooka #ifndef HAVE_GETPROGNAME 58 1.24 pooka #define getprogname() "rump_server" 59 1.24 pooka #endif 60 1.13 wiz fprintf(stderr, "usage: %s [-s] [-c ncpu] [-d drivespec] [-l libs] " 61 1.12 pooka "[-m modules] bindurl\n", getprogname()); 62 1.1 pooka exit(1); 63 1.1 pooka } 64 1.1 pooka 65 1.22 joerg __dead static void 66 1.30 pooka diedie(int sflag, const char *reason, int error, const char *errstr) 67 1.2 pooka { 68 1.2 pooka 69 1.29 bad if (reason != NULL) 70 1.29 bad fputs(reason, stderr); 71 1.30 pooka if (errstr) { 72 1.30 pooka fprintf(stderr, ": %s", errstr); 73 1.30 pooka } 74 1.29 bad fputc('\n', stderr); 75 1.2 pooka if (!sflag) 76 1.2 pooka rump_daemonize_done(error); 77 1.2 pooka exit(1); 78 1.2 pooka } 79 1.2 pooka 80 1.30 pooka __dead static void 81 1.30 pooka die(int sflag, int error, const char *reason) 82 1.30 pooka { 83 1.30 pooka 84 1.30 pooka diedie(sflag, reason, error, error == 0 ? NULL : strerror(error)); 85 1.30 pooka } 86 1.30 pooka 87 1.30 pooka __dead static void 88 1.30 pooka die_rumperr(int sflag, int error, const char *reason) 89 1.30 pooka { 90 1.30 pooka 91 1.30 pooka diedie(sflag, reason, error, error == 0 ? NULL : rump_strerror(error)); 92 1.30 pooka } 93 1.30 pooka 94 1.4 pooka static sem_t sigsem; 95 1.4 pooka static void 96 1.4 pooka sigreboot(int sig) 97 1.4 pooka { 98 1.4 pooka 99 1.4 pooka sem_post(&sigsem); 100 1.4 pooka } 101 1.4 pooka 102 1.9 pooka static const char *const disktokens[] = { 103 1.9 pooka #define DKEY 0 104 1.9 pooka "key", 105 1.9 pooka #define DFILE 1 106 1.9 pooka "hostpath", 107 1.9 pooka #define DSIZE 2 108 1.18 pooka #define DSIZE_E -1 109 1.9 pooka "size", 110 1.14 pooka #define DOFFSET 3 111 1.14 pooka "offset", 112 1.16 pooka #define DLABEL 4 113 1.16 pooka "disklabel", 114 1.17 pooka #define DTYPE 5 115 1.17 pooka "type", 116 1.9 pooka NULL 117 1.9 pooka }; 118 1.9 pooka 119 1.9 pooka struct etfsreg { 120 1.9 pooka const char *key; 121 1.9 pooka const char *hostpath; 122 1.9 pooka off_t flen; 123 1.14 pooka off_t foffset; 124 1.16 pooka char partition; 125 1.9 pooka enum rump_etfs_type type; 126 1.9 pooka }; 127 1.9 pooka 128 1.17 pooka struct etfstype { 129 1.17 pooka const char *name; 130 1.17 pooka enum rump_etfs_type type; 131 1.17 pooka } etfstypes[] = { 132 1.17 pooka { "blk", RUMP_ETFS_BLK }, 133 1.17 pooka { "chr", RUMP_ETFS_CHR }, 134 1.17 pooka { "reg", RUMP_ETFS_REG }, 135 1.17 pooka }; 136 1.17 pooka 137 1.28 pooka static void processlabel(int, int, int, off_t *, off_t *); 138 1.28 pooka 139 1.34 pooka #define ALLOCCHUNK 32 140 1.34 pooka 141 1.1 pooka int 142 1.1 pooka main(int argc, char *argv[]) 143 1.1 pooka { 144 1.2 pooka const char *serverurl; 145 1.9 pooka struct etfsreg *etfs = NULL; 146 1.9 pooka unsigned netfs = 0, curetfs = 0; 147 1.1 pooka int error; 148 1.34 pooka int ch, sflag, onthepath; 149 1.24 pooka unsigned i; 150 1.34 pooka char **modarray = NULL, **libarray = NULL; 151 1.35 pooka unsigned nmods = 0, curmod = 0, nlibs = 0, curlib = 0, libidx; 152 1.35 pooka unsigned liblast = -1; /* XXXgcc */ 153 1.24 pooka 154 1.1 pooka setprogname(argv[0]); 155 1.2 pooka sflag = 0; 156 1.20 pooka while ((ch = getopt(argc, argv, "c:d:l:m:r:sv")) != -1) { 157 1.2 pooka switch (ch) { 158 1.12 pooka case 'c': 159 1.12 pooka setenv("RUMP_NCPU", optarg, 1); 160 1.12 pooka break; 161 1.9 pooka case 'd': { 162 1.9 pooka char *options, *value; 163 1.9 pooka char *key, *hostpath; 164 1.14 pooka long long flen, foffset; 165 1.16 pooka char partition; 166 1.17 pooka int ftype; 167 1.9 pooka 168 1.14 pooka flen = foffset = 0; 169 1.16 pooka partition = 0; 170 1.9 pooka key = hostpath = NULL; 171 1.17 pooka ftype = -1; 172 1.9 pooka options = optarg; 173 1.9 pooka while (*options) { 174 1.9 pooka switch (getsubopt(&options, 175 1.9 pooka __UNCONST(disktokens), &value)) { 176 1.9 pooka case DKEY: 177 1.11 pooka if (key != NULL) { 178 1.11 pooka fprintf(stderr, 179 1.11 pooka "key already given\n"); 180 1.11 pooka usage(); 181 1.11 pooka } 182 1.9 pooka key = value; 183 1.9 pooka break; 184 1.16 pooka 185 1.9 pooka case DFILE: 186 1.11 pooka if (hostpath != NULL) { 187 1.11 pooka fprintf(stderr, 188 1.11 pooka "hostpath already given\n"); 189 1.11 pooka usage(); 190 1.11 pooka } 191 1.9 pooka hostpath = value; 192 1.9 pooka break; 193 1.16 pooka 194 1.9 pooka case DSIZE: 195 1.11 pooka if (flen != 0) { 196 1.11 pooka fprintf(stderr, 197 1.11 pooka "size already given\n"); 198 1.11 pooka usage(); 199 1.11 pooka } 200 1.19 pooka if (strcmp(value, "host") == 0) { 201 1.18 pooka if (foffset != 0) { 202 1.18 pooka fprintf(stderr, 203 1.18 pooka "cannot specify " 204 1.18 pooka "offset with " 205 1.21 pooka "size=host\n"); 206 1.18 pooka usage(); 207 1.18 pooka } 208 1.18 pooka flen = DSIZE_E; 209 1.18 pooka } else { 210 1.38 pooka #ifdef HAVE_STRSUFTOLL 211 1.18 pooka /* XXX: off_t max? */ 212 1.18 pooka flen = strsuftoll("-d size", 213 1.18 pooka value, 0, LLONG_MAX); 214 1.24 pooka #else 215 1.24 pooka flen = strtoull(value, 216 1.24 pooka NULL, 10); 217 1.24 pooka #endif 218 1.18 pooka } 219 1.9 pooka break; 220 1.14 pooka case DOFFSET: 221 1.14 pooka if (foffset != 0) { 222 1.14 pooka fprintf(stderr, 223 1.14 pooka "offset already given\n"); 224 1.14 pooka usage(); 225 1.14 pooka } 226 1.18 pooka if (flen == DSIZE_E) { 227 1.18 pooka fprintf(stderr, "cannot " 228 1.18 pooka "specify offset with " 229 1.21 pooka "size=host\n"); 230 1.18 pooka usage(); 231 1.18 pooka } 232 1.38 pooka #ifdef HAVE_STRSUFTOLL 233 1.14 pooka /* XXX: off_t max? */ 234 1.14 pooka foffset = strsuftoll("-d offset", value, 235 1.14 pooka 0, LLONG_MAX); 236 1.24 pooka #else 237 1.24 pooka foffset = strtoull(value, NULL, 10); 238 1.24 pooka #endif 239 1.14 pooka break; 240 1.16 pooka 241 1.16 pooka case DLABEL: 242 1.16 pooka if (foffset != 0 || flen != 0) { 243 1.16 pooka fprintf(stderr, 244 1.16 pooka "disklabel needs to be " 245 1.16 pooka "used alone\n"); 246 1.16 pooka usage(); 247 1.16 pooka } 248 1.16 pooka if (strlen(value) != 1 || 249 1.16 pooka *value < 'a' || *value > 'z') { 250 1.16 pooka fprintf(stderr, 251 1.16 pooka "invalid label part\n"); 252 1.16 pooka usage(); 253 1.16 pooka } 254 1.16 pooka partition = *value; 255 1.16 pooka break; 256 1.16 pooka 257 1.17 pooka case DTYPE: 258 1.17 pooka if (ftype != -1) { 259 1.17 pooka fprintf(stderr, 260 1.17 pooka "type already specified\n"); 261 1.17 pooka usage(); 262 1.17 pooka } 263 1.17 pooka 264 1.17 pooka for (i = 0; 265 1.17 pooka i < __arraycount(etfstypes); 266 1.17 pooka i++) { 267 1.17 pooka if (strcmp(etfstypes[i].name, 268 1.17 pooka value) == 0) 269 1.17 pooka break; 270 1.17 pooka } 271 1.17 pooka if (i == __arraycount(etfstypes)) { 272 1.17 pooka fprintf(stderr, 273 1.17 pooka "invalid type %s\n", value); 274 1.17 pooka usage(); 275 1.17 pooka } 276 1.17 pooka ftype = etfstypes[i].type; 277 1.17 pooka break; 278 1.17 pooka 279 1.9 pooka default: 280 1.9 pooka fprintf(stderr, "invalid dtoken\n"); 281 1.9 pooka usage(); 282 1.9 pooka break; 283 1.9 pooka } 284 1.9 pooka } 285 1.9 pooka 286 1.16 pooka if (key == NULL || hostpath == NULL || 287 1.39 pooka (flen == 0 288 1.39 pooka && partition == 0 && ftype != RUMP_ETFS_REG)) { 289 1.9 pooka fprintf(stderr, "incomplete drivespec\n"); 290 1.9 pooka usage(); 291 1.9 pooka } 292 1.17 pooka if (ftype == -1) 293 1.17 pooka ftype = RUMP_ETFS_BLK; 294 1.9 pooka 295 1.9 pooka if (netfs - curetfs == 0) { 296 1.34 pooka etfs = realloc(etfs, 297 1.34 pooka (netfs+ALLOCCHUNK)*sizeof(*etfs)); 298 1.9 pooka if (etfs == NULL) 299 1.26 pooka die(1, errno, "realloc etfs"); 300 1.34 pooka netfs += ALLOCCHUNK; 301 1.9 pooka } 302 1.9 pooka 303 1.9 pooka etfs[curetfs].key = key; 304 1.9 pooka etfs[curetfs].hostpath = hostpath; 305 1.9 pooka etfs[curetfs].flen = flen; 306 1.14 pooka etfs[curetfs].foffset = foffset; 307 1.16 pooka etfs[curetfs].partition = partition; 308 1.17 pooka etfs[curetfs].type = ftype; 309 1.9 pooka curetfs++; 310 1.9 pooka 311 1.9 pooka break; 312 1.9 pooka } 313 1.6 pooka case 'l': 314 1.34 pooka if (nlibs - curlib == 0) { 315 1.34 pooka libarray = realloc(libarray, 316 1.34 pooka (nlibs+ALLOCCHUNK) * sizeof(char *)); 317 1.34 pooka if (libarray == NULL) 318 1.34 pooka die(1, errno, "realloc"); 319 1.34 pooka nlibs += ALLOCCHUNK; 320 1.8 pooka } 321 1.34 pooka libarray[curlib++] = optarg; 322 1.6 pooka break; 323 1.34 pooka case 'm': 324 1.7 pooka if (nmods - curmod == 0) { 325 1.7 pooka modarray = realloc(modarray, 326 1.34 pooka (nmods+ALLOCCHUNK) * sizeof(char *)); 327 1.7 pooka if (modarray == NULL) 328 1.26 pooka die(1, errno, "realloc"); 329 1.34 pooka nmods += ALLOCCHUNK; 330 1.7 pooka } 331 1.7 pooka modarray[curmod++] = optarg; 332 1.34 pooka break; 333 1.20 pooka case 'r': 334 1.20 pooka setenv("RUMP_MEMLIMIT", optarg, 1); 335 1.20 pooka break; 336 1.2 pooka case 's': 337 1.2 pooka sflag = 1; 338 1.2 pooka break; 339 1.20 pooka case 'v': 340 1.20 pooka setenv("RUMP_VERBOSE", "1", 1); 341 1.20 pooka break; 342 1.2 pooka default: 343 1.2 pooka usage(); 344 1.2 pooka /*NOTREACHED*/ 345 1.2 pooka } 346 1.2 pooka } 347 1.2 pooka 348 1.2 pooka argc -= optind; 349 1.2 pooka argv += optind; 350 1.2 pooka 351 1.2 pooka if (argc != 1) 352 1.1 pooka usage(); 353 1.1 pooka 354 1.34 pooka /* 355 1.34 pooka * Automatically "resolve" component dependencies, i.e. 356 1.34 pooka * try to load libs in a loop until all are loaded or a 357 1.34 pooka * full loop completes with no loads (latter case is an error). 358 1.34 pooka */ 359 1.34 pooka for (onthepath = 1, nlibs = curlib; onthepath && nlibs > 0;) { 360 1.34 pooka onthepath = 0; 361 1.34 pooka for (libidx = 0; libidx < curlib; libidx++) { 362 1.34 pooka /* loaded already? */ 363 1.34 pooka if (libarray[libidx] == NULL) 364 1.34 pooka continue; 365 1.34 pooka 366 1.34 pooka /* try to load */ 367 1.34 pooka liblast = libidx; 368 1.34 pooka if (dlopen(libarray[libidx], 369 1.34 pooka RTLD_LAZY|RTLD_GLOBAL) == NULL) { 370 1.34 pooka char pb[MAXPATHLEN]; 371 1.34 pooka /* try to mimic linker -l syntax */ 372 1.34 pooka snprintf(pb, sizeof(pb), 373 1.34 pooka "lib%s.so", libarray[libidx]); 374 1.34 pooka if (dlopen(pb, RTLD_LAZY|RTLD_GLOBAL) == NULL) 375 1.34 pooka continue; 376 1.34 pooka } 377 1.34 pooka 378 1.34 pooka /* managed to load that one */ 379 1.34 pooka libarray[libidx] = NULL; 380 1.34 pooka nlibs--; 381 1.34 pooka onthepath = 1; 382 1.34 pooka } 383 1.34 pooka } 384 1.34 pooka if (nlibs > 0) { 385 1.34 pooka fprintf(stderr, 386 1.34 pooka "failed to load -libraries, last error from \"%s\":\n", 387 1.34 pooka libarray[liblast]); 388 1.34 pooka fprintf(stderr, " %s", dlerror()); 389 1.34 pooka die(1, 0, NULL); 390 1.34 pooka } 391 1.34 pooka free(libarray); 392 1.34 pooka 393 1.2 pooka serverurl = argv[0]; 394 1.2 pooka 395 1.2 pooka if (!sflag) { 396 1.2 pooka error = rump_daemonize_begin(); 397 1.2 pooka if (error) 398 1.30 pooka die_rumperr(1, error, "rump daemonize"); 399 1.2 pooka } 400 1.2 pooka 401 1.1 pooka error = rump_init(); 402 1.1 pooka if (error) 403 1.30 pooka die_rumperr(sflag, error, "rump init failed"); 404 1.7 pooka 405 1.9 pooka /* load modules */ 406 1.7 pooka for (i = 0; i < curmod; i++) { 407 1.27 pooka struct rump_modctl_load ml; 408 1.7 pooka 409 1.7 pooka #define ETFSKEY "/module.mod" 410 1.7 pooka if ((error = rump_pub_etfs_register(ETFSKEY, 411 1.7 pooka modarray[0], RUMP_ETFS_REG)) != 0) 412 1.30 pooka die_rumperr(sflag, 413 1.30 pooka error, "module etfs register failed"); 414 1.7 pooka memset(&ml, 0, sizeof(ml)); 415 1.7 pooka ml.ml_filename = ETFSKEY; 416 1.30 pooka /* 417 1.30 pooka * XXX: since this is a syscall, error namespace depends 418 1.30 pooka * on loaded emulations. revisit and fix. 419 1.30 pooka */ 420 1.27 pooka if (rump_sys_modctl(RUMP_MODCTL_LOAD, &ml) == -1) 421 1.7 pooka die(sflag, errno, "module load failed"); 422 1.7 pooka rump_pub_etfs_remove(ETFSKEY); 423 1.9 pooka #undef ETFSKEY 424 1.9 pooka } 425 1.34 pooka free(modarray); 426 1.9 pooka 427 1.9 pooka /* register host drives */ 428 1.9 pooka for (i = 0; i < curetfs; i++) { 429 1.14 pooka struct stat sb; 430 1.16 pooka off_t foffset, flen, fendoff; 431 1.18 pooka int fd, oflags; 432 1.9 pooka 433 1.18 pooka oflags = etfs[i].flen == DSIZE_E ? 0 : O_CREAT; 434 1.18 pooka fd = open(etfs[i].hostpath, O_RDWR | oflags, 0644); 435 1.9 pooka if (fd == -1) 436 1.18 pooka die(sflag, errno, "etfs hostpath open"); 437 1.16 pooka 438 1.16 pooka if (etfs[i].partition) { 439 1.28 pooka processlabel(sflag, fd, etfs[i].partition - 'a', 440 1.28 pooka &foffset, &flen); 441 1.16 pooka } else { 442 1.16 pooka foffset = etfs[i].foffset; 443 1.16 pooka flen = etfs[i].flen; 444 1.16 pooka } 445 1.16 pooka 446 1.14 pooka if (fstat(fd, &sb) == -1) 447 1.14 pooka die(sflag, errno, "fstat etfs hostpath"); 448 1.18 pooka if (flen == DSIZE_E) { 449 1.21 pooka if (sb.st_size == 0) 450 1.21 pooka die(sflag, EINVAL, "size=host, but cannot " 451 1.21 pooka "query non-zero size"); 452 1.18 pooka flen = sb.st_size; 453 1.18 pooka } 454 1.18 pooka fendoff = foffset + flen; 455 1.16 pooka if (S_ISREG(sb.st_mode) && sb.st_size < fendoff) { 456 1.16 pooka if (ftruncate(fd, fendoff) == -1) 457 1.14 pooka die(sflag, errno, "truncate"); 458 1.14 pooka } 459 1.9 pooka close(fd); 460 1.9 pooka 461 1.14 pooka if ((error = rump_pub_etfs_register_withsize(etfs[i].key, 462 1.16 pooka etfs[i].hostpath, etfs[i].type, foffset, flen)) != 0) 463 1.30 pooka die_rumperr(sflag, error, "etfs register"); 464 1.7 pooka } 465 1.7 pooka 466 1.2 pooka error = rump_init_server(serverurl); 467 1.1 pooka if (error) 468 1.30 pooka die_rumperr(sflag, error, "rump server init failed"); 469 1.2 pooka 470 1.2 pooka if (!sflag) 471 1.3 pooka rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS); 472 1.2 pooka 473 1.4 pooka sem_init(&sigsem, 0, 0); 474 1.4 pooka signal(SIGTERM, sigreboot); 475 1.4 pooka signal(SIGINT, sigreboot); 476 1.4 pooka sem_wait(&sigsem); 477 1.4 pooka 478 1.4 pooka rump_sys_reboot(0, NULL); 479 1.5 pooka /*NOTREACHED*/ 480 1.5 pooka 481 1.4 pooka return 0; 482 1.1 pooka } 483 1.28 pooka 484 1.28 pooka /* 485 1.28 pooka * Copyright (c) 1987, 1988, 1993 486 1.28 pooka * The Regents of the University of California. All rights reserved. 487 1.28 pooka * 488 1.28 pooka * Redistribution and use in source and binary forms, with or without 489 1.28 pooka * modification, are permitted provided that the following conditions 490 1.28 pooka * are met: 491 1.28 pooka * 1. Redistributions of source code must retain the above copyright 492 1.28 pooka * notice, this list of conditions and the following disclaimer. 493 1.28 pooka * 2. Redistributions in binary form must reproduce the above copyright 494 1.28 pooka * notice, this list of conditions and the following disclaimer in the 495 1.28 pooka * documentation and/or other materials provided with the distribution. 496 1.28 pooka * 3. Neither the name of the University nor the names of its contributors 497 1.28 pooka * may be used to endorse or promote products derived from this software 498 1.28 pooka * without specific prior written permission. 499 1.28 pooka * 500 1.28 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 501 1.28 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 502 1.28 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 503 1.28 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 504 1.28 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 505 1.28 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 506 1.28 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 507 1.28 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 508 1.28 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 509 1.28 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 510 1.28 pooka * SUCH DAMAGE. 511 1.28 pooka * 512 1.28 pooka * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 513 1.28 pooka */ 514 1.28 pooka 515 1.28 pooka #define RUMPSERVER_MAXPARTITIONS 22 516 1.28 pooka #define RUMPSERVER_DISKMAGIC ((uint32_t)0x82564557) /* magic */ 517 1.28 pooka #define RUMPSERVER_DEVSHIFT 9 518 1.28 pooka 519 1.28 pooka struct rumpserver_disklabel { 520 1.28 pooka uint32_t d_magic; /* the magic number */ 521 1.28 pooka uint16_t d_type; /* drive type */ 522 1.28 pooka uint16_t d_subtype; /* controller/d_type specific */ 523 1.28 pooka char d_typename[16]; /* type name, e.g. "eagle" */ 524 1.28 pooka 525 1.28 pooka /* 526 1.28 pooka * d_packname contains the pack identifier and is returned when 527 1.28 pooka * the disklabel is read off the disk or in-core copy. 528 1.28 pooka * d_boot0 and d_boot1 are the (optional) names of the 529 1.28 pooka * primary (block 0) and secondary (block 1-15) bootstraps 530 1.28 pooka * as found in /usr/mdec. These are returned when using 531 1.28 pooka * getdiskbyname(3) to retrieve the values from /etc/disktab. 532 1.28 pooka */ 533 1.28 pooka union { 534 1.28 pooka char un_d_packname[16]; /* pack identifier */ 535 1.28 pooka struct { 536 1.28 pooka char *un_d_boot0; /* primary bootstrap name */ 537 1.28 pooka char *un_d_boot1; /* secondary bootstrap name */ 538 1.28 pooka } un_b; 539 1.28 pooka } d_un; 540 1.28 pooka #define d_packname d_un.un_d_packname 541 1.28 pooka #define d_boot0 d_un.un_b.un_d_boot0 542 1.28 pooka #define d_boot1 d_un.un_b.un_d_boot1 543 1.28 pooka 544 1.28 pooka /* disk geometry: */ 545 1.28 pooka uint32_t d_secsize; /* # of bytes per sector */ 546 1.28 pooka uint32_t d_nsectors; /* # of data sectors per track */ 547 1.28 pooka uint32_t d_ntracks; /* # of tracks per cylinder */ 548 1.28 pooka uint32_t d_ncylinders; /* # of data cylinders per unit */ 549 1.28 pooka uint32_t d_secpercyl; /* # of data sectors per cylinder */ 550 1.28 pooka uint32_t d_secperunit; /* # of data sectors per unit */ 551 1.28 pooka 552 1.28 pooka /* 553 1.28 pooka * Spares (bad sector replacements) below are not counted in 554 1.28 pooka * d_nsectors or d_secpercyl. Spare sectors are assumed to 555 1.28 pooka * be physical sectors which occupy space at the end of each 556 1.28 pooka * track and/or cylinder. 557 1.28 pooka */ 558 1.28 pooka uint16_t d_sparespertrack; /* # of spare sectors per track */ 559 1.28 pooka uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ 560 1.28 pooka /* 561 1.28 pooka * Alternative cylinders include maintenance, replacement, 562 1.28 pooka * configuration description areas, etc. 563 1.28 pooka */ 564 1.28 pooka uint32_t d_acylinders; /* # of alt. cylinders per unit */ 565 1.28 pooka 566 1.28 pooka /* hardware characteristics: */ 567 1.28 pooka /* 568 1.28 pooka * d_interleave, d_trackskew and d_cylskew describe perturbations 569 1.28 pooka * in the media format used to compensate for a slow controller. 570 1.28 pooka * Interleave is physical sector interleave, set up by the 571 1.28 pooka * formatter or controller when formatting. When interleaving is 572 1.28 pooka * in use, logically adjacent sectors are not physically 573 1.28 pooka * contiguous, but instead are separated by some number of 574 1.28 pooka * sectors. It is specified as the ratio of physical sectors 575 1.28 pooka * traversed per logical sector. Thus an interleave of 1:1 576 1.28 pooka * implies contiguous layout, while 2:1 implies that logical 577 1.28 pooka * sector 0 is separated by one sector from logical sector 1. 578 1.28 pooka * d_trackskew is the offset of sector 0 on track N relative to 579 1.28 pooka * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew 580 1.28 pooka * is the offset of sector 0 on cylinder N relative to sector 0 581 1.28 pooka * on cylinder N-1. 582 1.28 pooka */ 583 1.28 pooka uint16_t d_rpm; /* rotational speed */ 584 1.28 pooka uint16_t d_interleave; /* hardware sector interleave */ 585 1.28 pooka uint16_t d_trackskew; /* sector 0 skew, per track */ 586 1.28 pooka uint16_t d_cylskew; /* sector 0 skew, per cylinder */ 587 1.28 pooka uint32_t d_headswitch; /* head switch time, usec */ 588 1.28 pooka uint32_t d_trkseek; /* track-to-track seek, usec */ 589 1.28 pooka uint32_t d_flags; /* generic flags */ 590 1.28 pooka #define NDDATA 5 591 1.28 pooka uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ 592 1.28 pooka #define NSPARE 5 593 1.28 pooka uint32_t d_spare[NSPARE]; /* reserved for future use */ 594 1.28 pooka uint32_t d_magic2; /* the magic number (again) */ 595 1.28 pooka uint16_t d_checksum; /* xor of data incl. partitions */ 596 1.28 pooka 597 1.28 pooka /* filesystem and partition information: */ 598 1.28 pooka uint16_t d_npartitions; /* number of partitions in following */ 599 1.28 pooka uint32_t d_bbsize; /* size of boot area at sn0, bytes */ 600 1.28 pooka uint32_t d_sbsize; /* max size of fs superblock, bytes */ 601 1.28 pooka struct rumpserver_partition { /* the partition table */ 602 1.28 pooka uint32_t p_size; /* number of sectors in partition */ 603 1.28 pooka uint32_t p_offset; /* starting sector */ 604 1.28 pooka union { 605 1.28 pooka uint32_t fsize; /* FFS, ADOS: 606 1.28 pooka filesystem basic fragment size */ 607 1.28 pooka uint32_t cdsession; /* ISO9660: session offset */ 608 1.28 pooka } __partition_u2; 609 1.28 pooka #define p_fsize __partition_u2.fsize 610 1.28 pooka #define p_cdsession __partition_u2.cdsession 611 1.28 pooka uint8_t p_fstype; /* filesystem type, see below */ 612 1.28 pooka uint8_t p_frag; /* filesystem fragments per block */ 613 1.28 pooka union { 614 1.28 pooka uint16_t cpg; /* UFS: FS cylinders per group */ 615 1.28 pooka uint16_t sgs; /* LFS: FS segment shift */ 616 1.28 pooka } __partition_u1; 617 1.28 pooka #define p_cpg __partition_u1.cpg 618 1.28 pooka #define p_sgs __partition_u1.sgs 619 1.28 pooka } d_partitions[RUMPSERVER_MAXPARTITIONS]; /* actually may be more */ 620 1.28 pooka }; 621 1.28 pooka 622 1.28 pooka 623 1.28 pooka /* for swapping disklabel, so don't care about perf, just portability */ 624 1.28 pooka #define bs32(x) \ 625 1.28 pooka ((((x) & 0xff000000) >> 24)| \ 626 1.28 pooka (((x) & 0x00ff0000) >> 8) | \ 627 1.28 pooka (((x) & 0x0000ff00) << 8) | \ 628 1.28 pooka (((x) & 0x000000ff) << 24)) 629 1.28 pooka #define bs16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) 630 1.28 pooka 631 1.28 pooka /* 632 1.28 pooka * From: 633 1.28 pooka * $NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp 634 1.28 pooka */ 635 1.28 pooka 636 1.28 pooka /*- 637 1.28 pooka * Copyright (c) 1991, 1993 638 1.28 pooka * The Regents of the University of California. All rights reserved. 639 1.28 pooka * 640 1.28 pooka * Redistribution and use in source and binary forms, with or without 641 1.28 pooka * modification, are permitted provided that the following conditions 642 1.28 pooka * are met: 643 1.28 pooka * 1. Redistributions of source code must retain the above copyright 644 1.28 pooka * notice, this list of conditions and the following disclaimer. 645 1.28 pooka * 2. Redistributions in binary form must reproduce the above copyright 646 1.28 pooka * notice, this list of conditions and the following disclaimer in the 647 1.28 pooka * documentation and/or other materials provided with the distribution. 648 1.28 pooka * 3. Neither the name of the University nor the names of its contributors 649 1.28 pooka * may be used to endorse or promote products derived from this software 650 1.28 pooka * without specific prior written permission. 651 1.28 pooka * 652 1.28 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 653 1.28 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 654 1.28 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 655 1.28 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 656 1.28 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 657 1.28 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 658 1.28 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 659 1.28 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 660 1.28 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 661 1.28 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 662 1.28 pooka * SUCH DAMAGE. 663 1.28 pooka */ 664 1.28 pooka 665 1.28 pooka static uint16_t 666 1.28 pooka rs_dl_dkcksum(struct rumpserver_disklabel *lp, int imswapped) 667 1.28 pooka { 668 1.28 pooka uint16_t *start, *end; 669 1.28 pooka uint16_t sum; 670 1.28 pooka uint16_t npart; 671 1.28 pooka 672 1.28 pooka if (imswapped) 673 1.28 pooka npart = bs16(lp->d_npartitions); 674 1.28 pooka else 675 1.28 pooka npart = lp->d_npartitions; 676 1.28 pooka 677 1.28 pooka sum = 0; 678 1.28 pooka start = (uint16_t *)(void *)lp; 679 1.28 pooka end = (uint16_t *)(void *)&lp->d_partitions[npart]; 680 1.28 pooka while (start < end) { 681 1.28 pooka if (imswapped) 682 1.28 pooka sum ^= bs16(*start); 683 1.28 pooka else 684 1.28 pooka sum ^= *start; 685 1.28 pooka start++; 686 1.28 pooka } 687 1.28 pooka return (sum); 688 1.28 pooka } 689 1.28 pooka 690 1.28 pooka /* 691 1.28 pooka * From: 692 1.28 pooka * NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp 693 1.28 pooka */ 694 1.28 pooka 695 1.28 pooka /*- 696 1.28 pooka * Copyright (c) 2002 The NetBSD Foundation, Inc. 697 1.28 pooka * All rights reserved. 698 1.28 pooka * 699 1.28 pooka * This code is derived from software contributed to The NetBSD Foundation 700 1.28 pooka * by Roland C. Dowdeswell. 701 1.28 pooka * 702 1.28 pooka * Redistribution and use in source and binary forms, with or without 703 1.28 pooka * modification, are permitted provided that the following conditions 704 1.28 pooka * are met: 705 1.28 pooka * 1. Redistributions of source code must retain the above copyright 706 1.28 pooka * notice, this list of conditions and the following disclaimer. 707 1.28 pooka * 2. Redistributions in binary form must reproduce the above copyright 708 1.28 pooka * notice, this list of conditions and the following disclaimer in the 709 1.28 pooka * documentation and/or other materials provided with the distribution. 710 1.28 pooka * 711 1.28 pooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 712 1.28 pooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 713 1.28 pooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 714 1.28 pooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 715 1.28 pooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 716 1.28 pooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 717 1.28 pooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 718 1.28 pooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 719 1.28 pooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 720 1.28 pooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 721 1.28 pooka * POSSIBILITY OF SUCH DAMAGE. 722 1.28 pooka */ 723 1.28 pooka 724 1.28 pooka static int 725 1.28 pooka rs_dl_scan(struct rumpserver_disklabel *lp, int *isswapped, 726 1.28 pooka char *buf, size_t buflen) 727 1.28 pooka { 728 1.28 pooka size_t i; 729 1.28 pooka int imswapped; 730 1.28 pooka uint16_t npart; 731 1.28 pooka 732 1.28 pooka /* scan for the correct magic numbers. */ 733 1.28 pooka 734 1.28 pooka for (i=0; i <= buflen - sizeof(*lp); i += 4) { 735 1.28 pooka memcpy(lp, buf + i, sizeof(*lp)); 736 1.28 pooka if (lp->d_magic == RUMPSERVER_DISKMAGIC && 737 1.28 pooka lp->d_magic2 == RUMPSERVER_DISKMAGIC) { 738 1.28 pooka imswapped = 0; 739 1.28 pooka goto sanity; 740 1.28 pooka } 741 1.28 pooka if (lp->d_magic == bs32(RUMPSERVER_DISKMAGIC) && 742 1.28 pooka lp->d_magic2 == bs32(RUMPSERVER_DISKMAGIC)) { 743 1.28 pooka imswapped = 1; 744 1.28 pooka goto sanity; 745 1.28 pooka } 746 1.28 pooka } 747 1.28 pooka 748 1.28 pooka return 1; 749 1.28 pooka 750 1.28 pooka sanity: 751 1.28 pooka if (imswapped) 752 1.28 pooka npart = bs16(lp->d_npartitions); 753 1.28 pooka else 754 1.28 pooka npart = lp->d_npartitions; 755 1.28 pooka /* we've found something, let's sanity check it */ 756 1.28 pooka if (npart > RUMPSERVER_MAXPARTITIONS 757 1.28 pooka || rs_dl_dkcksum(lp, imswapped)) 758 1.28 pooka return 1; 759 1.28 pooka 760 1.28 pooka *isswapped = imswapped; 761 1.28 pooka return 0; 762 1.28 pooka } 763 1.28 pooka 764 1.28 pooka static void 765 1.28 pooka processlabel(int sflag, int fd, int partition, off_t *foffp, off_t *flenp) 766 1.28 pooka { 767 1.28 pooka struct rumpserver_disklabel dl; 768 1.28 pooka char buf[1<<16]; 769 1.28 pooka uint32_t foffset, flen; 770 1.28 pooka int imswapped; 771 1.28 pooka 772 1.28 pooka if (pread(fd, buf, sizeof(buf), 0) == -1) 773 1.28 pooka die(sflag, errno, "could not read disk device"); 774 1.28 pooka if (rs_dl_scan(&dl, &imswapped, buf, sizeof(buf))) 775 1.28 pooka die(sflag, ENOENT, "disklabel not found"); 776 1.28 pooka 777 1.28 pooka if (partition >= dl.d_npartitions) 778 1.28 pooka die(sflag, ENOENT, "partition not available"); 779 1.28 pooka 780 1.28 pooka foffset = dl.d_partitions[partition].p_offset << RUMPSERVER_DEVSHIFT; 781 1.28 pooka flen = dl.d_partitions[partition].p_size << RUMPSERVER_DEVSHIFT; 782 1.28 pooka if (imswapped) { 783 1.28 pooka foffset = bs32(foffset); 784 1.28 pooka flen = bs32(flen); 785 1.28 pooka } 786 1.28 pooka 787 1.28 pooka *foffp = (off_t)foffset; 788 1.28 pooka *flenp = (off_t)flen; 789 1.28 pooka } 790