1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

DISK: Add 2.11 BSD and Net BSD file system recognizers

Both NetBSD and OpenBSD have identical partition information
Report both names when such a file system is found
This commit is contained in:
Mark Pizzolato 2022-06-11 21:40:02 -07:00
parent 9ca26e5b47
commit 5448965f70
2 changed files with 294 additions and 1 deletions

View File

@ -238,7 +238,7 @@ Host platforms which have libSDL2 available can leverage this functionality.
RAW Disk Access (including CDROM)
Virtual Disk Container files, including differencing disks
File System type detection to accurately autosize disks.
Recognized file systems are: DEC ODS1, DEC ODS2, DEC RT11, DEC RSTS, DEC RSX11, Ultrix Partitions, ISO 9660
Recognized file systems are: DEC ODS1, DEC ODS2, DEC RT11, DEC RSTS, DEC RSX11, Ultrix Partitions, ISO 9660, BSD 2.11 partitions and NetBSD partitions
#### Tape Extensions
AWS format tape support

View File

@ -1554,6 +1554,297 @@ if (readonly)
return ret_val;
}
/* 2.11 BSD Volume Recognizer - Structure Info gathered from: the 2.11 BSD disklabel section 5 man page */
#define BSD_DISKMAGIC ((uint32) 0x82564557) /* The disk label magic number */
#define BSD_211_MAXPARTITIONS 8
typedef struct BSD_211_disklabel {
uint32 d_magic; /* the magic number */
uint8 d_type; /* drive type */
uint8 d_subtype; /* controller/d_type specific */
char d_typename[16]; /* type name, e.g. "eagle" */
/*
* d_packname contains the pack identifier and is returned when
* the disklabel is read off the disk or in-core copy.
* d_boot0 is the (optional) name of the primary (block 0) bootstrap
* as found in /mdec. This is returned when using
* getdiskbyname(3) to retrieve the values from /etc/disktab.
*/
char d_packname[16]; /* pack identifier */
/* disk geometry: */
uint16 d_secsize; /* # of bytes per sector */
uint16 d_nsectors; /* # of data sectors per track */
uint16 d_ntracks; /* # of tracks per cylinder */
uint16 d_ncylinders; /* # of data cylinders per unit */
uint16 d_secpercyl; /* # of data sectors per cylinder */
uint32 d_secperunit; /* # of data sectors per unit */
/*
* Spares (bad sector replacements) below
* are not counted in d_nsectors or d_secpercyl.
* Spare sectors are assumed to be physical sectors
* which occupy space at the end of each track and/or cylinder.
*/
uint16 d_sparespertrack; /* # of spare sectors per track */
uint16 d_sparespercyl; /* # of spare sectors per cylinder */
/*
* Alternate cylinders include maintenance, replacement,
* configuration description areas, etc.
*/
uint16 d_acylinders; /* # of alt. cylinders per unit */
/* hardware characteristics: */
/*
* d_interleave, d_trackskew and d_cylskew describe perturbations
* in the media format used to compensate for a slow controller.
* Interleave is physical sector interleave, set up by the formatter
* or controller when formatting. When interleaving is in use,
* logically adjacent sectors are not physically contiguous,
* but instead are separated by some number of sectors.
* It is specified as the ratio of physical sectors traversed
* per logical sector. Thus an interleave of 1:1 implies contiguous
* layout, while 2:1 implies that logical sector 0 is separated
* by one sector from logical sector 1.
* d_trackskew is the offset of sector 0 on track N
* relative to sector 0 on track N-1 on the same cylinder.
* Finally, d_cylskew is the offset of sector 0 on cylinder N
* relative to sector 0 on cylinder N-1.
*/
uint16 d_rpm; /* rotational speed */
uint8 d_interleave; /* hardware sector interleave */
uint8 d_trackskew; /* sector 0 skew, per track */
uint8 d_cylskew; /* sector 0 skew, per cylinder */
uint8 d_headswitch; /* head swith time, usec */
uint16 d_trkseek; /* track-to-track seek, msec */
uint16 d_flags; /* generic flags */
#define NDDATA 5
uint32 d_drivedata[NDDATA]; /* drive-type specific information */
#define NSPARE 5
uint32 d_spare[NSPARE]; /* reserved for future use */
uint32 d_magic2; /* the magic number (again) */
uint16 d_checksum; /* xor of data incl. partitions */
/* filesystem and partition information: */
uint16 d_npartitions; /* number of partitions in following */
uint8 d_bbsize; /* size of boot area at sn0, bytes */
uint8 d_sbsize; /* max size of fs superblock, bytes */
struct { /* the partition table */
uint32 p_size; /* number of sectors in partition */
uint32 p_offset; /* starting sector */
uint16 p_fsize; /* filesystem basic fragment size */
uint8 p_fstype; /* filesystem type, see below */
uint8 p_frag; /* filesystem fragments per block */
} d_partitions[BSD_211_MAXPARTITIONS];/* actually may be more */
} BSD_211_disklabel;
static t_offset get_BSD_211_filesystem_size (UNIT *uptr, uint32 physsectsz, t_bool *readonly)
{
DEVICE *dptr;
t_addr saved_capac;
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */
uint8 sector_buf[512];
BSD_211_disklabel *Label = (BSD_211_disklabel *)sector_buf;
t_offset ret_val = (t_offset)-1;
uint16 i;
uint32 max_lbn = 0, max_lbn_partnum = 0;
t_seccnt sects_read;
uint16 sum = 0;
uint16 *pdata;
#define WORDSWAP(l) (((l >> 16) & 0xFFFF) | ((l & 0xFFFF) << 16))
if ((dptr = find_dev_from_unit (uptr)) == NULL)
return ret_val;
saved_capac = uptr->capac;
uptr->capac = temp_capac;
if ((_DEC_rdsect (uptr, 1, sector_buf, &sects_read, 512 / ctx->sector_size, physsectsz)) ||
(sects_read != (512 / ctx->sector_size)))
goto Return_Cleanup;
/* Confirm the Label magic numbers */
if ((WORDSWAP(Label->d_magic) != BSD_DISKMAGIC) ||
(WORDSWAP(Label->d_magic2) != BSD_DISKMAGIC))
goto Return_Cleanup;
/* Verify the label checksum */
if (Label->d_npartitions > BSD_211_MAXPARTITIONS)
goto Return_Cleanup;
pdata = (uint16 *)Label;
for (sum = 0, pdata = (uint16 *)Label; pdata < (uint16 *)&Label->d_partitions[Label->d_npartitions]; pdata++)
sum ^= *pdata;
if (sum != 0)
goto Return_Cleanup;
/* Walk through the partitions */
for (i = 0; i < Label->d_npartitions; i++) {
uint32 end_lbn = WORDSWAP (Label->d_partitions[i].p_offset) + WORDSWAP (Label->d_partitions[i].p_size);
if (end_lbn > max_lbn) {
max_lbn = end_lbn;
max_lbn_partnum = i;
}
}
sim_messagef (SCPE_OK, "%s: '%s' Contains BSD 2.11 partitions\n", sim_uname (uptr), uptr->filename);
sim_messagef (SCPE_OK, "Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn);
ret_val = ((t_offset)max_lbn) * 512;
Return_Cleanup:
uptr->capac = saved_capac;
if (readonly)
*readonly = sim_disk_wrp (uptr);
return ret_val;
}
/* NetBSD Volume Recognizer - Structure Info gathered from: the NetBSD disklabel section 5 man page */
#define NETBSD_MAXPARTITIONS 22
typedef struct NetBSD_disklabel {
uint32 d_magic; /* the magic number */
uint16 d_type; /* drive type */
uint16 d_subtype; /* controller/d_type specific */
char d_typename[16]; /* type name, e.g. "eagle" */
/*
* d_packname contains the pack identifier and is returned when
* the disklabel is read off the disk or in-core copy.
* d_boot0 is the (optional) name of the primary (block 0) bootstrap
* as found in /mdec. This is returned when using
* getdiskbyname(3) to retrieve the values from /etc/disktab.
*/
char d_packname[16]; /* pack identifier */
/* disk geometry: */
uint32 d_secsize; /* # of bytes per sector */
uint32 d_nsectors; /* # of data sectors per track */
uint32 d_ntracks; /* # of tracks per cylinder */
uint32 d_ncylinders; /* # of data cylinders per unit */
uint32 d_secpercyl; /* # of data sectors per cylinder */
uint32 d_secperunit; /* # of data sectors per unit */
/*
* Spares (bad sector replacements) below
* are not counted in d_nsectors or d_secpercyl.
* Spare sectors are assumed to be physical sectors
* which occupy space at the end of each track and/or cylinder.
*/
uint16 d_sparespertrack; /* # of spare sectors per track */
uint16 d_sparespercyl; /* # of spare sectors per cylinder */
/*
* Alternate cylinders include maintenance, replacement,
* configuration description areas, etc.
*/
uint32 d_acylinders; /* # of alt. cylinders per unit */
/* hardware characteristics: */
/*
* d_interleave, d_trackskew and d_cylskew describe perturbations
* in the media format used to compensate for a slow controller.
* Interleave is physical sector interleave, set up by the formatter
* or controller when formatting. When interleaving is in use,
* logically adjacent sectors are not physically contiguous,
* but instead are separated by some number of sectors.
* It is specified as the ratio of physical sectors traversed
* per logical sector. Thus an interleave of 1:1 implies contiguous
* layout, while 2:1 implies that logical sector 0 is separated
* by one sector from logical sector 1.
* d_trackskew is the offset of sector 0 on track N
* relative to sector 0 on track N-1 on the same cylinder.
* Finally, d_cylskew is the offset of sector 0 on cylinder N
* relative to sector 0 on cylinder N-1.
*/
uint16 d_rpm; /* rotational speed */
uint16 d_interleave; /* hardware sector interleave */
uint16 d_trackskew; /* sector 0 skew, per track */
uint16 d_cylskew; /* sector 0 skew, per cylinder */
uint32 d_headswitch; /* head swith time, usec */
uint32 d_trkseek; /* track-to-track seek, msec */
uint32 d_flags; /* generic flags */
#define NDDATA 5
uint32 d_drivedata[NDDATA]; /* drive-type specific information */
#define NSPARE 5
uint32 d_spare[NSPARE]; /* reserved for future use */
uint32 d_magic2; /* the magic number (again) */
uint16 d_checksum; /* xor of data incl. partitions */
/* filesystem and partition information: */
uint16 d_npartitions; /* number of partitions in following */
uint32 d_bbsize; /* size of boot area at sn0, bytes */
uint32 d_sbsize; /* max size of fs superblock, bytes */
struct { /* the partition table */
uint32 p_size; /* number of sectors in partition */
uint32 p_offset; /* starting sector */
uint32 p_fsize; /* filesystem basic fragment size */
uint8 p_fstype; /* filesystem type, see below */
uint8 p_frag; /* filesystem fragments per block */
union {
uint16 cpg; /* UFS: FS cylinders per group */
uint16 sgs; /* LFS: FS segment shift */
} __partition_u1;
#define p_cpg __partition_ul.cpg
#define p_sgs __partition_ul.sgs
} d_partitions[NETBSD_MAXPARTITIONS];/* actually may be more */
} NetBSD_disklabel;
static t_offset get_NetBSD_filesystem_size (UNIT *uptr, uint32 physsectsz, t_bool *readonly)
{
DEVICE *dptr;
t_addr saved_capac;
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */
uint8 sector_buf[512];
NetBSD_disklabel *Label = (NetBSD_disklabel *)(&sector_buf[64]);
t_offset ret_val = (t_offset)-1;
uint16 i = sizeof (NetBSD_disklabel);
uint32 max_lbn = 0, max_lbn_partnum = 0;
t_seccnt sects_read;
uint16 sum = 0;
uint16 *pdata;
if ((dptr = find_dev_from_unit (uptr)) == NULL)
return ret_val;
saved_capac = uptr->capac;
uptr->capac = temp_capac;
if ((_DEC_rdsect (uptr, 0, (uint8 *)sector_buf, &sects_read, 512 / ctx->sector_size, physsectsz)) ||
(sects_read != (512 / ctx->sector_size)))
goto Return_Cleanup;
/* Confirm the Label magic numbers */
if ((Label->d_magic != BSD_DISKMAGIC) ||
(Label->d_magic2 != BSD_DISKMAGIC))
goto Return_Cleanup;
/* Verify the label checksum */
if (Label->d_npartitions > NETBSD_MAXPARTITIONS)
goto Return_Cleanup;
pdata = (uint16 *)Label;
for (sum = 0, pdata = (uint16 *)Label; pdata < (uint16 *)&Label->d_partitions[Label->d_npartitions]; pdata++)
sum ^= *pdata;
if (sum != 0)
goto Return_Cleanup;
/* Walk through the partitions */
for (i = 0; i < Label->d_npartitions; i++) {
uint32 end_lbn = Label->d_partitions[i].p_offset + Label->d_partitions[i].p_size;
if (end_lbn > max_lbn) {
max_lbn = end_lbn;
max_lbn_partnum = i;
}
}
sim_messagef (SCPE_OK, "%s: '%s' Contains NET/Open BSD partitions\n", sim_uname (uptr), uptr->filename);
sim_messagef (SCPE_OK, "Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn);
ret_val = ((t_offset)max_lbn) * 512;
Return_Cleanup:
uptr->capac = saved_capac;
if (readonly)
*readonly = sim_disk_wrp (uptr);
return ret_val;
}
#pragma pack(push,1)
/*
* The first logical block of device cluster 1 is either:
@ -2272,6 +2563,8 @@ static FILESYSTEM_CHECK checks[] = {
&get_ultrix_filesystem_size,
&get_iso9660_filesystem_size,
&get_rsts_filesystem_size,
&get_BSD_211_filesystem_size,
&get_NetBSD_filesystem_size,
&get_rt11_filesystem_size, /* This should be the last entry
in the table to reduce the
possibility of matching an RT-11