freebsd-dev/sys/kern/subr_diskmbr.c

545 lines
16 KiB
C
Raw Normal View History

/*-
* Copyright (c) 1994 Bruce D. Evans.
* All rights reserved.
*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
* from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
1999-08-28 01:08:13 +00:00
* $FreeBSD$
*/
#include <sys/param.h>
Divorce "dev_t" from the "major|minor" bitmap, which is now called udev_t in the kernel but still called dev_t in userland. Provide functions to manipulate both types: major() umajor() minor() uminor() makedev() umakedev() dev2udev() udev2dev() For now they're functions, they will become in-line functions after one of the next two steps in this process. Return major/minor/makedev to macro-hood for userland. Register a name in cdevsw[] for the "filedescriptor" driver. In the kernel the udev_t appears in places where we have the major/minor number combination, (ie: a potential device: we may not have the driver nor the device), like in inodes, vattr, cdevsw registration and so on, whereas the dev_t appears where we carry around a reference to a actual device. In the future the cdevsw and the aliased-from vnode will be hung directly from the dev_t, along with up to two softc pointers for the device driver and a few houskeeping bits. This will essentially replace the current "alias" check code (same buck, bigger bang). A little stunt has been provided to try to catch places where the wrong type is being used (dev_t vs udev_t), if you see something not working, #undef DEVT_FASCIST in kern/kern_conf.c and see if it makes a difference. If it does, please try to track it down (many hands make light work) or at least try to reproduce it as simply as possible, and describe how to do that. Without DEVT_FASCIST I belive this patch is a no-op. Stylistic/posixoid comments about the userland view of the <sys/*.h> files welcome now, from userland they now contain the end result. Next planned step: make all dev_t's refer to the same devsw[] which means convert BLK's to CHR's at the perimeter of the vnodes and other places where they enter the game (bootdev, mknod, sysctl).
1999-05-11 19:55:07 +00:00
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
#ifdef PC98
1999-09-04 14:21:42 +00:00
#define PC98_ATCOMPAT
#define dsinit atcompat_dsinit
#endif
#include <sys/disklabel.h>
#define DOSPTYP_EXTENDED 5
#define DOSPTYP_EXTENDEDX 15
#define DOSPTYP_ONTRACK 84
#include <sys/diskslice.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#define TRACE(str) do { if (dsi_debug) printf str; } while (0)
static volatile u_char dsi_debug;
/*
* This is what we have embedded in every boot1 for supporting the bogus
* "Dangerously Dedicated" mode. However, the old table is broken because
* it has an illegal geometry in it - it specifies 256 heads (heads = end
* head + 1) which causes nasty stuff when that wraps to zero in bios code.
* eg: divide by zero etc. This caused the dead-thinkpad problem, numerous
* SCSI bios crashes, EFI to crash, etc.
*
* We still have to recognize the old table though, even though we stopped
* inflicting it apon the world.
*/
static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
};
static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, },
};
2002-03-19 21:25:46 +00:00
static int check_part(char *sname, struct dos_partition *dp,
u_long offset, int nsectors, int ntracks,
2002-03-19 21:25:46 +00:00
u_long mbr_offset);
static void mbr_extended(dev_t dev, struct disklabel *lp,
1999-09-04 14:21:42 +00:00
struct diskslices *ssp, u_long ext_offset,
u_long ext_size, u_long base_ext_offset,
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
int nsectors, int ntracks, u_long mbr_offset,
2002-03-19 21:25:46 +00:00
int level);
static int mbr_setslice(char *sname, struct disklabel *lp,
struct diskslice *sp, struct dos_partition *dp,
2002-03-19 21:25:46 +00:00
u_long br_offset);
static int
check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
char *sname;
struct dos_partition *dp;
u_long offset;
int nsectors;
int ntracks;
u_long mbr_offset;
{
int chs_ecyl;
int chs_esect;
int chs_scyl;
int chs_ssect;
int error;
u_long esector;
u_long esector1;
u_long secpercyl;
u_long ssector;
u_long ssector1;
secpercyl = (u_long)nsectors * ntracks;
chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
chs_ssect = DPSECT(dp->dp_ssect);
ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl
+ mbr_offset;
ssector1 = offset + dp->dp_start;
/*
* If ssector1 is on a cylinder >= 1024, then ssector can't be right.
* Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
* apart from the cylinder being reduced modulo 1024. Always allow
* 1023/255/63, because this is the official way to represent
* pure-LBA for the starting position.
*/
if ((ssector < ssector1
&& ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
&& chs_scyl == 1023)
|| (secpercyl != 0
&& (ssector1 - ssector) % (1024 * secpercyl) == 0)))
|| (dp->dp_scyl == 255 && dp->dp_shd == 255
&& dp->dp_ssect == 255)) {
TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
ssector = ssector1;
}
chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect);
chs_esect = DPSECT(dp->dp_esect);
esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl
+ mbr_offset;
esector1 = ssector1 + dp->dp_size - 1;
/*
* Allow certain bogus C/H/S values for esector, as above. However,
* heads == 255 isn't really legal and causes some BIOS crashes. The
* correct value to indicate a pure-LBA end is 1023/heads-1/sectors -
* usually 1023/254/63. "heads" is base 0, "sectors" is base 1.
*/
if ((esector < esector1
&& ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
&& chs_ecyl == 1023)
|| (secpercyl != 0
&& (esector1 - esector) % (1024 * secpercyl) == 0)))
|| (dp->dp_ecyl == 255 && dp->dp_ehd == 255
&& dp->dp_esect == 255)) {
TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
esector = esector1;
}
error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
if (bootverbose)
printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n",
1998-07-11 07:46:16 +00:00
sname, dp->dp_typ, ssector1, esector1,
(u_long)dp->dp_size, error ? "" : ": OK");
if (ssector != ssector1 && bootverbose)
printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
sname, chs_scyl, dp->dp_shd, chs_ssect,
ssector, ssector1);
if (esector != esector1 && bootverbose)
printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect,
esector, esector1);
return (error);
}
int
dsinit(dev, lp, sspp)
dev_t dev;
struct disklabel *lp;
struct diskslices **sspp;
{
struct buf *bp;
u_char *cp;
int dospart;
struct dos_partition *dp;
struct dos_partition *dp0;
struct dos_partition dpcopy[NDOSPART];
int error;
int max_ncyls;
int max_nsectors;
int max_ntracks;
u_long mbr_offset;
1995-02-22 22:46:48 +00:00
char partname[2];
u_long secpercyl;
1995-02-22 22:46:48 +00:00
char *sname;
struct diskslice *sp;
struct diskslices *ssp;
mbr_offset = DOSBBSECTOR;
reread_mbr:
/* Read master boot record. */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
bp->b_blkno = mbr_offset;
bp->b_bcount = lp->d_secsize;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp, 1);
if (bufwait(bp) != 0) {
diskerr(&bp->b_io, "reading primary partition table: error",
2000-11-26 19:29:15 +00:00
0, (struct disklabel *)NULL);
printf("\n");
error = EIO;
goto done;
}
/* Weakly verify it. */
cp = bp->b_data;
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
if (bootverbose)
printf("%s: invalid primary partition table: no magic\n",
sname);
error = EINVAL;
goto done;
}
1999-09-04 14:21:42 +00:00
/* Make a copy of the partition table to avoid alignment problems. */
memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
dp0 = &dpcopy[0];
/* Check for "Ontrack Diskmanager". */
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
if (dp->dp_typ == DOSPTYP_ONTRACK) {
if (bootverbose)
printf(
"%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
mbr_offset = 63;
goto reread_mbr;
}
}
if (bcmp(dp0, historical_bogus_partition_table,
sizeof historical_bogus_partition_table) == 0 ||
bcmp(dp0, historical_bogus_partition_table_fixed,
sizeof historical_bogus_partition_table_fixed) == 0) {
if (bootverbose)
printf(
"%s: invalid primary partition table: Dangerously Dedicated (ignored)\n",
sname);
error = EINVAL;
goto done;
}
/* Guess the geometry. */
/*
* TODO:
* Perhaps skip entries with 0 size.
* Perhaps only look at entries of type DOSPTYP_386BSD.
*/
max_ncyls = 0;
max_nsectors = 0;
max_ntracks = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
int ncyls;
int nsectors;
int ntracks;
ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
if (max_ncyls < ncyls)
max_ncyls = ncyls;
nsectors = DPSECT(dp->dp_esect);
if (max_nsectors < nsectors)
max_nsectors = nsectors;
ntracks = dp->dp_ehd + 1;
if (max_ntracks < ntracks)
max_ntracks = ntracks;
}
/*
* Check that we have guessed the geometry right by checking the
* partition entries.
*/
/*
* TODO:
* As above.
* Check for overlaps.
* Check against d_secperunit if the latter is reliable.
*/
error = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
&& dp->dp_start == 0 && dp->dp_size == 0)
continue;
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
/*
* Temporarily ignore errors from this check. We could
* simplify things by accepting the table eariler if we
* always ignore errors here. Perhaps we should always
* accept the table if the magic is right but not let
* bad entries affect the geometry.
*/
check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
mbr_offset);
}
if (error != 0)
goto done;
/*
* Accept the DOS partition table.
* First adjust the label (we have been careful not to change it
* before we can guarantee success).
*/
secpercyl = (u_long)max_nsectors * max_ntracks;
if (secpercyl != 0) {
lp->d_nsectors = max_nsectors;
lp->d_ntracks = max_ntracks;
lp->d_secpercyl = secpercyl;
lp->d_ncylinders = lp->d_secperunit / secpercyl;
}
/*
* We are passed a pointer to a suitably initialized minimal
* slices "struct" with no dangling pointers in it. Replace it
* by a maximal one. This usually oversizes the "struct", but
* enlarging it while searching for logical drives would be
* inconvenient.
*/
free(*sspp, M_DEVBUF);
ssp = dsmakeslicestruct(MAX_SLICES, lp);
*sspp = ssp;
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
(void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
}
ssp->dss_nslices = BASE_SLICE + NDOSPART;
/* Handle extended partitions. */
sp -= NDOSPART;
for (dospart = 0; dospart < NDOSPART; dospart++, sp++)
if (sp->ds_type == DOSPTYP_EXTENDED ||
sp->ds_type == DOSPTYP_EXTENDEDX)
mbr_extended(bp->b_dev, lp, ssp,
1999-09-04 14:21:42 +00:00
sp->ds_offset, sp->ds_size, sp->ds_offset,
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
max_nsectors, max_ntracks, mbr_offset, 1);
/*
* mbr_extended() abuses ssp->dss_nslices for the number of slices
* that would be found if there were no limit on the number of slices
* in *ssp. Cut it back now.
*/
if (ssp->dss_nslices > MAX_SLICES)
ssp->dss_nslices = MAX_SLICES;
done:
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
if (error == EINVAL)
error = 0;
return (error);
}
void
1999-09-04 14:21:42 +00:00
mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
ntracks, mbr_offset, level)
dev_t dev;
struct disklabel *lp;
struct diskslices *ssp;
u_long ext_offset;
u_long ext_size;
u_long base_ext_offset;
int nsectors;
int ntracks;
u_long mbr_offset;
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
int level;
{
struct buf *bp;
u_char *cp;
int dospart;
struct dos_partition *dp;
struct dos_partition dpcopy[NDOSPART];
u_long ext_offsets[NDOSPART];
u_long ext_sizes[NDOSPART];
char partname[2];
int slice;
char *sname;
struct diskslice *sp;
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
if (level >= 16) {
printf(
"%s: excessive recursion in search for slices; aborting search\n",
devtoname(dev));
return;
}
/* Read extended boot record. */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
bp->b_blkno = ext_offset;
bp->b_bcount = lp->d_secsize;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp, 1);
if (bufwait(bp) != 0) {
diskerr(&bp->b_io, "reading extended partition table: error",
2000-11-26 19:29:15 +00:00
0, (struct disklabel *)NULL);
printf("\n");
goto done;
}
/* Weakly verify it. */
cp = bp->b_data;
if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART,
partname);
if (bootverbose)
printf("%s: invalid extended partition table: no magic\n",
sname);
goto done;
}
1999-09-04 14:21:42 +00:00
/* Make a copy of the partition table to avoid alignment problems. */
memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
slice = ssp->dss_nslices;
for (dospart = 0, dp = &dpcopy[0]; dospart < NDOSPART;
dospart++, dp++) {
ext_sizes[dospart] = 0;
if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
&& dp->dp_start == 0 && dp->dp_size == 0)
continue;
if (dp->dp_typ == DOSPTYP_EXTENDED ||
dp->dp_typ == DOSPTYP_EXTENDEDX) {
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
static char buf[32];
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
RAW_PART, partname);
snprintf(buf, sizeof(buf), "%s", sname);
if (strlen(buf) < sizeof buf - 11)
strcat(buf, "<extended>");
check_part(buf, dp, base_ext_offset, nsectors,
ntracks, mbr_offset);
ext_offsets[dospart] = base_ext_offset + dp->dp_start;
ext_sizes[dospart] = dp->dp_size;
} else {
sname = dsname(dev, dkunit(dev), slice, RAW_PART,
partname);
check_part(sname, dp, ext_offset, nsectors, ntracks,
mbr_offset);
if (slice >= MAX_SLICES) {
printf("%s: too many slices\n", sname);
slice++;
continue;
}
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
sp = &ssp->dss_slices[slice];
if (mbr_setslice(sname, lp, sp, dp, ext_offset) != 0)
continue;
slice++;
}
}
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
ssp->dss_nslices = slice;
/* If we found any more slices, recursively find all the subslices. */
for (dospart = 0; dospart < NDOSPART; dospart++)
if (ext_sizes[dospart] != 0)
1999-09-04 14:21:42 +00:00
mbr_extended(dev, lp, ssp, ext_offsets[dospart],
ext_sizes[dospart], base_ext_offset,
Quick fix for stack overflow when there are more than about 25 slices. Using recursion to traverse the recursive data structure for extended partitions was never good, but when slice support was implemented in 1995, the recursion worked for the default maximum number of slices (32), and standard fdisk utilities didn't support creating more than the default number. Even then, corrupt extended partitions could cause endless recursion, because we attempt to check all slices, even ones which we don't turn into devices. The recursion has succumbed to creeping features. The stack requirements for each level had grown to 204 bytes on i386's. Most of the growth was caused by adding a 64-byte copy of the DOSpartition table to each frame. The kernel stack size has shrunk to about 5K on i386's. Most of the shrinkage was caused by the growth of `struct sigacts' by 2388 bytes to support 128 signals. Linux fdisk (a 1997 version at least) can now create 60 slices (4 standard ones, 56 for logical drives within extended partitions, and it seems to be leaving room to map the 4 BSD partitions on my test drive), and Linux (2.2.29 and 2.3.35 at least) now reports all these slices at boot time. The fix limits the recursion to 16 levels (4 + 16 slices) and recovers 32 bytes per level caused by gcc pessimizing for space. Switching to a static buffer doesn't cause any problems due to recursion, since the buffer is not passed down. Using a static buffer is wrong in general because it requires the giant lock to protect it. However, this problem is small compared with using a static buffer for dsname(). We sometimes neglect to copy the result of dsname() before sleeping. Also fixed slice names when we find more than MAX_SLICES (32) slices. The number of the last slice found was not passed passed recursively. The limit on the recursion now prevents finding more than 32 slices with a standard extended partition data structure anyway.
2000-01-27 05:11:29 +00:00
nsectors, ntracks, mbr_offset, ++level);
done:
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
}
static int
mbr_setslice(sname, lp, sp, dp, br_offset)
char *sname;
struct disklabel *lp;
struct diskslice *sp;
struct dos_partition *dp;
u_long br_offset;
{
u_long offset;
u_long size;
offset = br_offset + dp->dp_start;
if (offset > lp->d_secperunit || offset < br_offset) {
printf(
"%s: slice starts beyond end of the disk: rejecting it\n",
sname);
return (1);
}
size = lp->d_secperunit - offset;
if (size >= dp->dp_size)
size = dp->dp_size;
else
printf(
"%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n",
sname, (u_long)dp->dp_size, size);
sp->ds_offset = offset;
sp->ds_size = size;
sp->ds_type = dp->dp_typ;
#ifdef PC98_ATCOMPAT
/* Fake FreeBSD(98). */
if (sp->ds_type == DOSPTYP_386BSD)
sp->ds_type = 0x94;
#endif
#if 0
lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
#endif
return (0);
}
#ifdef __alpha__
void
alpha_fix_srm_checksum(bp)
struct buf *bp;
{
1999-09-04 14:21:42 +00:00
u_int64_t *p;
u_int64_t sum;
int i;
1999-11-09 21:35:10 +00:00
p = (u_int64_t *) bp->b_data;
1999-09-04 14:21:42 +00:00
sum = 0;
for (i = 0; i < 63; i++)
sum += p[i];
p[63] = sum;
}
#endif