1 /* $NetBSD: disksubr.c,v 1.5 1995/11/30 00:57:35 jtc Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Leo Weppelman. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/buf.h> 35 #include <sys/disklabel.h> 36 #include <machine/tospart.h> 37 38 /* 39 * This is ugly, but as long as disklabel(8) uses 40 * BBSIZE from ufs/ffs/fs.h, there's no alternative. 41 */ 42 #include <ufs/ffs/fs.h> 43 #if BBSIZE < 8192 44 #error BBSIZE in /sys/ufs/ffs/fs.h must be at least 8192 bytes 45 #endif 46 47 #if 0 48 #define MACHDSBR_DEBUG(x) printf x 49 #else 50 #define MACHDSBR_DEBUG(x) 51 #endif 52 53 static int real_label __P((dev_t, void (*)(), u_int32_t, struct disklabel *)); 54 static void chck_label __P((struct disklabel *, struct cpu_disklabel *)); 55 static void fake_label __P((struct disklabel *, struct tos_table *)); 56 static int rd_rootparts __P((dev_t, void (*)(), u_int32_t, u_int32_t, 57 struct tos_table *)); 58 static int rd_extparts __P((dev_t, void (*)(), u_int32_t, u_int32_t, 59 u_int32_t, struct tos_table *)); 60 static int add_tospart __P((struct tos_part *, struct tos_table *)); 61 62 /* 63 * XXX unknown function but needed for /sys/scsi to link 64 */ 65 int 66 dk_establish() 67 { 68 return(-1); 69 } 70 71 /* 72 * Determine the size of the transfer, and make sure it is 73 * within the boundaries of the partition. Adjust transfer 74 * if needed, and signal errors or early completion. 75 */ 76 int 77 bounds_check_with_label(bp, lp, wlabel) 78 struct buf *bp; 79 struct disklabel *lp; 80 int wlabel; 81 { 82 struct partition *pp; 83 u_int32_t maxsz, sz; 84 85 pp = &lp->d_partitions[DISKPART(bp->b_dev)]; 86 if (bp->b_flags & B_RAW) { 87 if (bp->b_bcount & (lp->d_secsize - 1)) { 88 bp->b_error = EINVAL; 89 bp->b_flags |= B_ERROR; 90 return (-1); 91 } 92 maxsz = pp->p_size * (lp->d_secsize / DEV_BSIZE); 93 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 94 } else { 95 maxsz = pp->p_size; 96 sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize; 97 } 98 99 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 100 if (bp->b_blkno == maxsz) { 101 /* 102 * trying to get one block beyond return EOF. 103 */ 104 bp->b_resid = bp->b_bcount; 105 return(0); 106 } 107 sz = maxsz - bp->b_blkno; 108 if (sz <= 0 || bp->b_blkno < 0) { 109 bp->b_error = EINVAL; 110 bp->b_flags |= B_ERROR; 111 return(-1); 112 } 113 /* 114 * adjust count down 115 */ 116 if (bp->b_flags & B_RAW) 117 bp->b_bcount = sz << DEV_BSHIFT; 118 else bp->b_bcount = sz * lp->d_secsize; 119 } 120 121 /* 122 * calc cylinder for disksort to order transfers with 123 */ 124 bp->b_cylinder = (bp->b_blkno + pp->p_offset) / lp->d_secpercyl; 125 return(1); 126 } 127 128 /* 129 * Attempt to read a disk label from a device using the 130 * indicated strategy routine. The label must be partly 131 * set up before this: 132 * secpercyl and anything required in the strategy routine 133 * (e.g. sector size) must be filled in before calling us. 134 * Returns NULL on success and an error string on failure. 135 */ 136 char * 137 readdisklabel(dev, strat, lp, clp) 138 dev_t dev; 139 void (*strat)(); 140 struct disklabel *lp; 141 struct cpu_disklabel *clp; 142 { 143 struct tos_table tt; 144 int i; 145 146 bzero(clp, sizeof *clp); 147 148 /* 149 * Give some guaranteed validity to the disk label. 150 */ 151 if (lp->d_secsize == 0) 152 lp->d_secsize = DEV_BSIZE; 153 if (lp->d_secperunit == 0) 154 lp->d_secperunit = 0x1fffffff; 155 if (lp->d_secpercyl == 0) 156 return("Zero secpercyl"); 157 for (i = 0; i < MAXPARTITIONS; ++i) { 158 lp->d_partitions[i].p_size = 0; 159 lp->d_partitions[i].p_offset = 0; 160 lp->d_partitions[i].p_fstype = FS_UNUSED; 161 } 162 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; 163 lp->d_npartitions = RAW_PART + 1; 164 lp->d_bbsize = BBSIZE; 165 lp->d_sbsize = SBSIZE; 166 167 MACHDSBR_DEBUG(("unit: %lu secsize: %lu secperunit: %lu\n", 168 (u_long)DISKUNIT(dev), (u_long)lp->d_secsize, 169 (u_long)lp->d_secperunit)); 170 171 /* 172 * Try the simple case (boot block at sector 0) first. 173 */ 174 if(real_label(dev, strat, LABELSECTOR, lp)) { 175 MACHDSBR_DEBUG(("Normal volume: boot block at sector 0\n")); 176 return(NULL); 177 } 178 /* 179 * The vendor specific (TOS) partition layout requires a 512 180 * byte sector size. 181 */ 182 tt.tt_cdl = clp; 183 tt.tt_nroots = tt.tt_nparts = 0; 184 if (lp->d_secsize != TOS_BSIZE || (i = rd_rootparts(dev, strat, 185 lp->d_secpercyl, lp->d_secperunit, &tt)) == 2) { 186 MACHDSBR_DEBUG(("Uninitialised volume\n")); 187 lp->d_partitions[RAW_PART+1].p_size 188 = lp->d_partitions[RAW_PART].p_size; 189 lp->d_partitions[RAW_PART+1].p_offset 190 = lp->d_partitions[RAW_PART].p_offset; 191 lp->d_partitions[RAW_PART+1].p_fstype = FS_BSDFFS; 192 lp->d_npartitions = RAW_PART + 2; 193 goto done; 194 } 195 if (!i) 196 return("Invalid TOS partition table"); 197 /* 198 * TOS format, search for a partition with id NBD or RAW, which 199 * contains a NetBSD boot block with a valid disk label in it. 200 */ 201 MACHDSBR_DEBUG(("AHDI partition table: ")); 202 clp->cd_bblock = NO_BOOT_BLOCK; 203 for (i = 0; i < tt.tt_nparts; ++i) { 204 struct tos_part *tp = &tt.tt_parts[i]; 205 u_int32_t id = *((u_int32_t *)&tp->tp_flg); 206 if (id != PID_NBD && id != PID_RAW) 207 continue; 208 if (!real_label(dev, strat, tp->tp_st, lp)) { 209 /* 210 * No disk label, but if this is the first NBD partition 211 * on this volume, we'll mark it anyway as a possible 212 * destination for future writedisklabel() calls, just 213 * in case there is no valid disk label on any of the 214 * other AHDI partitions. 215 */ 216 if (id == PID_NBD 217 && clp->cd_bblock == NO_BOOT_BLOCK) 218 clp->cd_bblock = tp->tp_st; 219 continue; 220 } 221 /* 222 * Found a valid disk label, mark this TOS partition for 223 * writedisklabel(), and check for possibly dangerous 224 * overlap between TOS and NetBSD partition layout. 225 */ 226 MACHDSBR_DEBUG(("found real disklabel\n")); 227 clp->cd_bblock = tp->tp_st; 228 chck_label(lp, clp); 229 return(NULL); 230 } 231 /* 232 * No disk label on this volume, use the TOS partition 233 * layout to create a fake disk label. If there is no 234 * NBD partition on this volume either, subsequent 235 * writedisklabel() calls will fail. 236 */ 237 MACHDSBR_DEBUG(("creating fake disklabel\n")); 238 fake_label(lp, &tt); 239 240 /* 241 * Calulate new checksum. 242 */ 243 done: 244 lp->d_magic = lp->d_magic2 = DISKMAGIC; 245 lp->d_checksum = 0; 246 lp->d_checksum = dkcksum(lp); 247 248 return(NULL); 249 } 250 251 /* 252 * Check new disk label for sensibility before setting it. 253 */ 254 int 255 setdisklabel(olp, nlp, openmask, clp) 256 struct disklabel *olp, *nlp; 257 u_long openmask; 258 struct cpu_disklabel *clp; 259 { 260 /* special case to allow disklabel to be invalidated */ 261 if (nlp->d_magic == 0xffffffff) { 262 *olp = *nlp; 263 return(0); 264 } 265 266 /* sanity clause */ 267 if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 268 || (nlp->d_secsize % DEV_BSIZE) != 0 || dkcksum(nlp) != 0 269 || nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC) 270 return(EINVAL); 271 272 if (clp->cd_bblock) 273 chck_label(nlp, clp); 274 275 while (openmask) { 276 struct partition *op, *np; 277 int i = ffs(openmask) - 1; 278 openmask &= ~(1 << i); 279 if (i >= nlp->d_npartitions) 280 return(EBUSY); 281 op = &olp->d_partitions[i]; 282 np = &nlp->d_partitions[i]; 283 if (np->p_offset != op->p_offset || np->p_size < op->p_size) 284 return(EBUSY); 285 /* 286 * Copy internally-set partition information 287 * if new label doesn't include it. XXX 288 */ 289 if (np->p_fstype == FS_UNUSED && op->p_fstype != FS_UNUSED) { 290 np->p_fstype = op->p_fstype; 291 np->p_fsize = op->p_fsize; 292 np->p_frag = op->p_frag; 293 np->p_cpg = op->p_cpg; 294 } 295 } 296 nlp->d_checksum = 0; 297 nlp->d_checksum = dkcksum(nlp); 298 *olp = *nlp; 299 return(0); 300 } 301 302 /* 303 * Write disk label back to device after modification. 304 */ 305 int 306 writedisklabel(dev, strat, lp, clp) 307 dev_t dev; 308 void (*strat)(); 309 struct disklabel *lp; 310 struct cpu_disklabel *clp; 311 { 312 struct buf *bp; 313 u_int32_t bbo; 314 int rv; 315 316 bbo = clp->cd_bblock; 317 if (bbo == NO_BOOT_BLOCK) 318 return(ENXIO); 319 320 bp = geteblk(BBSIZE); 321 bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART); 322 bp->b_flags = B_BUSY | B_READ; 323 bp->b_bcount = BBSIZE; 324 bp->b_blkno = bbo; 325 bp->b_cylinder = bbo / lp->d_secpercyl; 326 (*strat)(bp); 327 rv = biowait(bp); 328 if (!rv) { 329 struct disklabel *nlp = (struct disklabel *) 330 ((char *)bp->b_data + LABELOFFSET); 331 *nlp = *lp; 332 bp->b_flags = B_BUSY | B_WRITE; 333 bp->b_bcount = BBSIZE; 334 bp->b_blkno = bbo; 335 bp->b_cylinder = bbo / lp->d_secpercyl; 336 (*strat)(bp); 337 rv = biowait(bp); 338 } 339 bp->b_flags |= B_INVAL | B_AGE; 340 brelse(bp); 341 return(rv); 342 } 343 344 /* 345 * Read bootblock at block `offset' and check 346 * if it contains a valid disklabel. 347 * Returns 0 if an error occured, 1 if successfull. 348 */ 349 static int 350 real_label(dev, strat, offset, lp) 351 dev_t dev; 352 void (*strat)(); 353 u_int32_t offset; 354 struct disklabel *lp; 355 { 356 struct buf *bp; 357 int rv = 0; 358 359 bp = geteblk(BBSIZE); 360 bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART); 361 bp->b_flags = B_BUSY | B_READ; 362 bp->b_bcount = BBSIZE; 363 bp->b_blkno = offset; 364 bp->b_cylinder = offset / lp->d_secpercyl; 365 (*strat)(bp); 366 if (!biowait(bp)) { 367 struct disklabel *nlp = (struct disklabel *) 368 ((char *)bp->b_data + LABELOFFSET); 369 if (nlp->d_magic == DISKMAGIC && nlp->d_magic2 == DISKMAGIC 370 && dkcksum(nlp) == 0 && nlp->d_npartitions <= MAXPARTITIONS) { 371 *lp = *nlp; 372 rv = 1; 373 } 374 } 375 bp->b_flags = B_INVAL | B_AGE | B_READ; 376 brelse(bp); 377 return(rv); 378 } 379 380 /* 381 * Check for consistency between the NetBSD partition table 382 * and the TOS auxilary root sectors. There's no good reason 383 * to force such consistency, but issueing a warning may help 384 * an inexperienced sysadmin to prevent corruption of TOS 385 * partitions. 386 */ 387 static void 388 chck_label(lp, clp) 389 struct disklabel *lp; 390 struct cpu_disklabel *clp; 391 { 392 u_int32_t *rp; 393 int i; 394 395 for (i = 0; i < lp->d_npartitions; ++i) { 396 struct partition *p = &lp->d_partitions[i]; 397 if (p->p_size == 0 || i == RAW_PART) 398 continue; 399 if ( (p->p_offset <= clp->cd_bslst 400 && p->p_offset + p->p_size > clp->cd_bslst) 401 || (p->p_offset > clp->cd_bslst 402 && clp->cd_bslst + clp->cd_bslsize > p->p_offset)) { 403 uprintf("Warning: NetBSD partition %c includes" 404 " AHDI bad sector list\n", 'a'+i); 405 } 406 for (rp = &clp->cd_roots[0]; *rp; ++rp) { 407 if (*rp >= p->p_offset 408 && *rp < p->p_offset + p->p_size) { 409 uprintf("Warning: NetBSD partition %c" 410 " includes AHDI auxilary root\n", 'a'+i); 411 } 412 } 413 } 414 } 415 416 /* 417 * Map the partition table from TOS to the NetBSD table. 418 * 419 * This means: 420 * Part 0 : Root 421 * Part 1 : Swap 422 * Part 2 : Whole disk 423 * Part 3.. : User partitions 424 * 425 * When more than one root partition is found, only the first one will 426 * be recognized as such. The others are mapped as user partitions. 427 */ 428 static void 429 fake_label(lp, tt) 430 struct disklabel *lp; 431 struct tos_table *tt; 432 { 433 int i, have_root, user_part; 434 435 user_part = RAW_PART; 436 have_root = (tt->tt_bblock != NO_BOOT_BLOCK); 437 438 for (i = 0; i < tt->tt_nparts; ++i) { 439 struct tos_part *tp = &tt->tt_parts[i]; 440 int fst, pno = -1; 441 442 switch (*((u_int32_t *)&tp->tp_flg)) { 443 case PID_NBD: 444 /* 445 * If this partition has been marked as the 446 * first NBD partition, it will be the root 447 * partition. 448 */ 449 if (tp->tp_st == tt->tt_bblock) 450 pno = 0; 451 /* FALL THROUGH */ 452 case PID_NBR: 453 /* 454 * If there is no NBD partition and this is 455 * the first NBR partition, it will be the 456 * root partition. 457 */ 458 if (!have_root) { 459 have_root = 1; 460 pno = 0; 461 } 462 /* FALL THROUGH */ 463 case PID_NBU: 464 fst = FS_BSDFFS; 465 break; 466 case PID_NBS: 467 case PID_SWP: 468 if (lp->d_partitions[1].p_size == 0) 469 pno = 1; 470 fst = FS_SWAP; 471 break; 472 case PID_BGM: 473 case PID_GEM: 474 fst = FS_MSDOS; 475 break; 476 default: 477 fst = FS_OTHER; 478 break; 479 } 480 if (pno < 0) { 481 if((pno = user_part + 1) >= MAXPARTITIONS) 482 continue; 483 user_part = pno; 484 } 485 lp->d_partitions[pno].p_size = tp->tp_size; 486 lp->d_partitions[pno].p_offset = tp->tp_st; 487 lp->d_partitions[pno].p_fstype = fst; 488 } 489 lp->d_npartitions = user_part + 1; 490 } 491 492 /* 493 * Create a list of TOS partitions in tos_table `tt'. 494 * Returns 0 if an error occured, 1 if successfull, 495 * or 2 if no TOS partition table exists. 496 */ 497 static int 498 rd_rootparts(dev, strat, spc, spu, tt) 499 dev_t dev; 500 void (*strat)(); 501 u_int32_t spc, spu; 502 struct tos_table *tt; 503 { 504 struct tos_root *root; 505 struct buf *bp; 506 int i, j, rv = 0; 507 508 bp = geteblk(TOS_BSIZE); 509 bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART); 510 bp->b_flags = B_BUSY | B_READ; 511 bp->b_bcount = TOS_BSIZE; 512 bp->b_blkno = TOS_BBLOCK; 513 bp->b_cylinder = TOS_BBLOCK / spc; 514 (*strat)(bp); 515 if (biowait(bp)) 516 goto done; 517 root = (struct tos_root *)bp->b_data; 518 519 MACHDSBR_DEBUG(("hdsize: %lu bsl-start: %lu bsl-size: %lu\n", 520 (u_long)root->tr_hdsize, (u_long)root->tr_bslst, 521 (u_long)root->tr_bslsize)); 522 523 if (!root->tr_hdsize || (!root->tr_bslsize && root->tr_bslst)) { 524 rv = 2; goto done; 525 } 526 for (i = 0; i < NTOS_PARTS; ++i) { 527 struct tos_part *part = &root->tr_parts[i]; 528 if (!(part->tp_flg & 1)) /* skip invalid entries */ 529 continue; 530 MACHDSBR_DEBUG((" %c%c%c %9lu %9lu\n", 531 part->tp_id[0], part->tp_id[1], part->tp_id[2], 532 (u_long)part->tp_st, (u_long)part->tp_size)); 533 if (part->tp_st == 0 || part->tp_st >= spu 534 || part->tp_size == 0 || part->tp_size >= spu 535 || part->tp_st + part->tp_size > spu) 536 goto done; 537 if ( (part->tp_st <= root->tr_bslst 538 && part->tp_st + part->tp_size > root->tr_bslst) 539 || (part->tp_st > root->tr_bslst 540 && root->tr_bslst + root->tr_bslsize > part->tp_st)) 541 goto done; 542 if (add_tospart(part, tt) && !rd_extparts(dev, strat, 543 spc, part->tp_st, part->tp_size, tt)) 544 goto done; 545 } 546 if (tt->tt_nparts > MAX_TOS_PARTS) 547 goto done; /* too many partitions for us */ 548 /* 549 * Allthough the AHDI 3.0 specifications do not prohibit 550 * a root sector with only invalid partition entries in 551 * it, this situation would be most unlikely. 552 */ 553 if (!tt->tt_nparts) { 554 rv = 2; goto done; 555 } 556 for (i = 0; i < tt->tt_nparts; ++i) { 557 struct tos_part *p1 = &tt->tt_parts[i]; 558 for (j = 0; j < i; ++j) { 559 struct tos_part *p2 = &tt->tt_parts[j]; 560 if ( (p1->tp_st <= p2->tp_st 561 && p1->tp_st + p1->tp_size > p2->tp_st) 562 || (p1->tp_st > p2->tp_st 563 && p2->tp_st + p2->tp_size > p1->tp_st)) 564 goto done; 565 } 566 } 567 tt->tt_bslsize = root->tr_bslsize; 568 tt->tt_bslst = root->tr_bslst; 569 rv = 1; 570 done: 571 bp->b_flags = B_INVAL | B_AGE | B_READ; 572 brelse(bp); 573 return(rv); 574 } 575 576 /* 577 * Add all subpartitions within an extended 578 * partition to tos_table `tt'. 579 * Returns 0 if an error occured, 1 if successfull. 580 */ 581 static int 582 rd_extparts(dev, strat, spc, extst, extsize, tt) 583 dev_t dev; 584 void (*strat)(); 585 u_int32_t spc, extst, extsize; 586 struct tos_table *tt; 587 { 588 struct buf *bp; 589 u_int32_t subst = extst, subsize = extsize; 590 int rv = 0; 591 592 bp = geteblk(TOS_BSIZE); 593 bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART); 594 595 for (;;) { 596 struct tos_root *root = (struct tos_root *)bp->b_data; 597 struct tos_part *part = root->tr_parts; 598 599 MACHDSBR_DEBUG(("auxilary root at sector %lu\n",(u_long)subst)); 600 bp->b_flags = B_BUSY | B_READ; 601 bp->b_bcount = TOS_BSIZE; 602 bp->b_blkno = subst; 603 bp->b_cylinder = subst / spc; 604 (*strat)(bp); 605 if (biowait(bp)) 606 goto done; 607 /* 608 * The first entry in an auxilary root sector must be 609 * marked as valid. The entry must describe a normal 610 * partition. The partition must not extend beyond 611 * the boundaries of the subpartition that it's 612 * part of. 613 */ 614 MACHDSBR_DEBUG((" %c%c%c %9lu %9lu\n", 615 part->tp_id[0], part->tp_id[1], part->tp_id[2], 616 (u_long)part->tp_st, (u_long)part->tp_size)); 617 if (!(part->tp_flg & 1) 618 #if 0 /* LWP: Temporary hack */ 619 || part->tp_st == 0 || part->tp_st >= subsize 620 || part->tp_size == 0 || part->tp_size >= subsize 621 || part->tp_st + part->tp_size > subsize) { 622 #else 623 || part->tp_st == 0 624 || part->tp_size == 0 625 || part->tp_size >= extsize) { 626 #endif 627 MACHDSBR_DEBUG(("first entry exceeds parent\n")); 628 goto done; 629 } 630 part->tp_st += subst; 631 if (add_tospart(part++, tt)) { 632 MACHDSBR_DEBUG(("first entry is XGM\n")); 633 goto done; 634 } 635 /* 636 * If the second entry in an auxilary rootsector is 637 * marked as invalid, we've reached the end of the 638 * linked list of subpartitions. 639 */ 640 if (!(part->tp_flg & 1)) { 641 rv = 1; 642 goto done; 643 } 644 /* 645 * If marked valid, the second entry in an auxilary 646 * rootsector must describe a subpartition (id XGM). 647 * The subpartition must not extend beyond the 648 * boundaries of the extended partition that 649 * it's part of. 650 */ 651 MACHDSBR_DEBUG((" %c%c%c %9lu %9lu\n", 652 part->tp_id[0], part->tp_id[1], part->tp_id[2], 653 (u_long)part->tp_st, (u_long)part->tp_size)); 654 #if 0 /* LWP: Temporary hack */ 655 if (part->tp_st == 0 || part->tp_st >= extsize 656 || part->tp_size == 0 || part->tp_size >= extsize 657 || part->tp_st + part->tp_size > extsize) { 658 #else 659 if (part->tp_st == 0 660 || part->tp_st >= extsize 661 || part->tp_size == 0) { 662 #endif 663 MACHDSBR_DEBUG(("second entry exceeds parent\n")); 664 goto done; 665 } 666 part->tp_st += extst; 667 if (!add_tospart(part, tt)) { 668 MACHDSBR_DEBUG(("second entry is not XGM\n")); 669 goto done; 670 } 671 subst = part->tp_st; 672 subsize = part->tp_size; 673 } 674 done: 675 bp->b_flags = B_INVAL | B_AGE | B_READ; 676 brelse(bp); 677 return(rv); 678 } 679 680 /* 681 * Add a TOS partition or an auxilary root sector 682 * to the appropriate list in tos_table `tt'. 683 * Returns 1 if `tp' is an XGM partition, otherwise 0. 684 */ 685 static int 686 add_tospart (tp, tt) 687 struct tos_part *tp; 688 struct tos_table *tt; 689 { 690 u_int32_t i; 691 692 tp->tp_flg = 0; 693 i = *((u_int32_t *)&tp->tp_flg); 694 if (i == PID_XGM) { 695 i = tt->tt_nroots++; 696 if (i < MAX_TOS_ROOTS) 697 tt->tt_roots[i] = tp->tp_st; 698 return 1; 699 } 700 i = tt->tt_nparts++; 701 if (i < MAX_TOS_PARTS) 702 tt->tt_parts[i] = *tp; 703 return 0; 704 } 705