static int
-read_gpt(struct biosdisk *d)
+read_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t rf_size)
{
struct biosdisk_extinfo ed;
daddr_t gptsector[2];
int i, error;
@@ -379,25 +477,32 @@
if (d->ll.type != BIOSDISK_TYPE_HD)
/* No GPT on floppy and CD */
return -1;
- gptsector[0] = GPT_HDR_BLKNO;
- if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) {
- gptsector[1] = ed.totsec - 1;
- /* Sanity check values returned from BIOS */
- if (ed.sbytes >= 512 && (ed.sbytes & (ed.sbytes - 1)) == 0)
- d->ll.secsize = ed.sbytes;
+ if (rf_offset && rf_size) {
+ gptsector[0] = rf_offset + GPT_HDR_BLKNO;
+ gptsector[1] = rf_offset + rf_size - 1;
} else {
+ gptsector[0] = GPT_HDR_BLKNO;
+ if (set_geometry(&d->ll, &ed) == 0 &&
+ d->ll.flags & BIOSDISK_INT13EXT) {
+ gptsector[1] = ed.totsec - 1;
+ /* Sanity check values returned from BIOS */
+ if (ed.sbytes >= 512 &&
+ (ed.sbytes & (ed.sbytes - 1)) == 0)
+ d->ll.secsize = ed.sbytes;
+ } else {
#ifdef DISK_DEBUG
- printf("Unable to determine extended disk geometry - "
- "using CHS\n");
+ printf("Unable to determine extended disk geometry - "
+ "using CHS\n");
#endif
- /* at least try some other reasonable values then */
- gptsector[1] = d->ll.chs_sectors - 1;
+ /* at least try some other reasonable values then */
+ gptsector[1] = d->ll.chs_sectors - 1;
+ }
}
for (i = 0; i < __arraycount(gptsector); i++) {
- error = check_gpt(d, gptsector[i]);
+ error = check_gpt(d, rf_offset, gptsector[i]);
if (error == 0)
break;
}
/* Determine likely partition for possible sector number of dos
* partition.
@@ -783,9 +1030,9 @@
return 0;
#else
struct biosdisk *d;
int partition = 0;
-#ifdef EFIBOOT
+#ifndef NO_GPT
int candidate = 0;
#endif
#ifdef DISK_DEBUG
@@ -796,13 +1043,13 @@
d = alloc_biosdisk(biosdev);
if (d == NULL)
return 0;
- if (read_partitions(d) == 0) {
+ if (read_partitions(d, 0, 0) == 0) {
for (partition = (BIOSDISKNPART-1); --partition;) {
if (d->part[partition].fstype == FS_UNUSED)
continue;
-#ifdef EFIBOOT
+#ifndef NO_GPT
switch (d->part[partition].fstype) {
case FS_BSDFFS:
case FS_BSDLFS:
case FS_RAID:
@@ -823,23 +1070,23 @@
if (d->part[partition].offset == sector)
break;
#endif
}
-#ifdef EFIBOOT
+#ifndef NO_GPT
found:
if (partition == 0 && candidate != 0)
partition = candidate;
#endif
}
#ifdef _STANDALONE
bi_wedge.startblk = d->part[partition].offset;
bi_wedge.nblks = d->part[partition].size;
@@ -955,12 +1282,312 @@
f->f_devdata = d;
out:
va_end(ap);
if (error)
- dealloc(d, sizeof(*d));
+ dealloc_biosdisk(d);
+ return error;
+}
+
+#ifndef NO_GPT
+static int
+biosdisk_find_name(const char *fname, int *biosdev,
+ daddr_t *offset, daddr_t *size)
+{
+ struct biosdisk *d;
+ char name[MAXDEVNAME + 1];
+ char *sep;
+#ifndef NO_RAIDFRAME
+ struct raidframe raidframe[RAIDFRAME_NDEV];
+ int raidframe_count = 0;
+#endif
+ int i;
+ int part;
+ int ret = -1;
+
+ /* Strip leadinf NAME= and cut after the coloon included */
+ strlcpy(name, fname + 5, MAXDEVNAME);
+ sep = strchr(name, ':');
+ if (sep)
+ *sep = '\0';
+
+ for (i = 0; i < MAX_BIOSDISKS; i++) {
+ d = alloc(sizeof(*d));
+ if (d == NULL) {
+ printf("Out of memory\n");
+ goto out;
+ }
+
+ memset(d, 0, sizeof(*d));
+ d->ll.dev = 0x80 + i; /* hd/cd */
+ if (set_geometry(&d->ll, NULL))
+ goto next_disk;
+
+ if (d->ll.type != BIOSDISK_TYPE_HD)
+ goto next_disk;
+
+ if (read_partitions(d, 0, 0) != 0)
+ goto next_disk;
+
+ for (part = 0; part < BIOSDISKNPART; part++) {
+ if (d->part[part].size == 0)
+ continue;
+ if (d->part[part].fstype == FS_UNUSED)
+ continue;
+#ifndef NO_RAIDFRAME
+ if (d->part[part].fstype == FS_RAID) {
+ raidframe_probe(raidframe,
+ &raidframe_count, d, part);
+ /*
+ * Do not match RAID partition for a name,
+ * we want to report an inner partition.
+ */
+ continue;
+ }
+#endif
+ if (d->part[part].part_name != NULL &&
+ strcmp(d->part[part].part_name, name) == 0) {
+ *biosdev = d->ll.dev;
+ *offset = d->part[part].offset;
+ *size = d->part[part].size;
+ ret = 0;
+ goto out;
+ }
+
+ }
+next_disk:
+ dealloc_biosdisk(d);
+ d = NULL;
+ }
+
+#ifndef NO_RAIDFRAME
+ for (i = 0; i < raidframe_count; i++) {
+ int candidate = -1;
+
+ if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) {
+ printf("Out of memory\n");
+ goto out;
+ }
+
+ if (read_partitions(d,
+ raidframe[i].offset + RF_PROTECTED_SECTORS,
+ raidframe[i].size) != 0)
+ goto next_raidframe;
+
+ for (part = 0; part < BIOSDISKNPART; part++) {
+ bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME;
+ if (d->part[part].size == 0)
+ continue;
+ if (d->part[part].fstype == FS_UNUSED)
+ continue;
+ if (d->part[part].part_name == NULL)
+ continue;
+ if (strcmp(d->part[part].part_name, name) == 0) {
+ *biosdev = raidframe[i].biosdev;
+ *offset = raidframe[i].offset
+ + RF_PROTECTED_SECTORS
+ + d->part[part].offset;
+ *size = d->part[part].size;
+ ret = 0;
+ goto out;
+ }
+ if (strcmp(raidframe[i].parent_name, name) == 0) {
+ if (candidate == -1 || bootme)
+ candidate = part;
+ continue;
+ }
+ }
+
+ if (candidate != -1) {
+ *biosdev = raidframe[i].biosdev;
+ *offset = raidframe[i].offset
+ + RF_PROTECTED_SECTORS
+ + d->part[candidate].offset;
+ *size = d->part[candidate].size;
+ ret = 0;
+ goto out;
+ }
+
+next_raidframe:
+ dealloc_biosdisk(d);
+ d = NULL;
+ }
+#endif
+
+out:
+ if (d != NULL)
+ dealloc_biosdisk(d);
+
+ return ret;
+}
+#endif
+
+#ifndef NO_RAIDFRAME
+static int
+biosdisk_find_raid(const char *name, int *biosdev,
+ daddr_t *offset, daddr_t *size)
+{
+ struct biosdisk *d = NULL;
+ struct raidframe raidframe[RAIDFRAME_NDEV];
+ int raidframe_count = 0;
+ int i;
+ int target_unit = 0;
+ int target_part;
+ int part;
+ int ret = -1;
+
+ if (strstr(name, "raid") != name)
+ goto out;
+
+#define isnum(c) ((c) >= '0' && (c) <= '9')
+ i = 4; /* skip leading "raid" */
+ if (!isnum(name[i]))
+ goto out;
+ do {
+ target_unit *= 10;
+ target_unit += name[i++] - '0';
+ } while (isnum(name[i]));
+
+#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
+
+ if (!isvalidpart(name[i]))
+ goto out;
+ target_part = name[i] - 'a';
+
+ for (i = 0; i < MAX_BIOSDISKS; i++) {
+ d = alloc(sizeof(*d));
+ if (d == NULL) {
+ printf("Out of memory\n");
+ goto out;
+ }
+
+ memset(d, 0, sizeof(*d));
+ d->ll.dev = 0x80 + i; /* hd/cd */
+ if (set_geometry(&d->ll, NULL))
+ goto next_disk;
+
+ if (d->ll.type != BIOSDISK_TYPE_HD)
+ goto next_disk;
+
+ if (read_partitions(d, 0, 0) != 0)
+ goto next_disk;
+
+ for (part = 0; part < BIOSDISKNPART; part++) {
+ if (d->part[part].size == 0)
+ continue;
+ if (d->part[part].fstype != FS_RAID)
+ continue;
+ raidframe_probe(raidframe,
+ &raidframe_count, d, part);
+
+ }
+next_disk:
+ dealloc_biosdisk(d);
+ d = NULL;
+ }
+
+ for (i = 0; i < raidframe_count; i++) {
+ if (raidframe[i].last_unit != target_unit)
+ continue;
+
+ if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) {
+ printf("Out of memory\n");
+ goto out;
+ }
+
+ if (read_partitions(d,
+ raidframe[i].offset + RF_PROTECTED_SECTORS,
+ raidframe[i].size) != 0)
+ goto next_raidframe;
+
+ for (part = 0; part < BIOSDISKNPART; part++) {
+ if (d->part[part].size == 0)
+ continue;
+ if (d->part[part].fstype == FS_UNUSED)
+ continue;
+ if (part == target_part) {
+ *biosdev = raidframe[i].biosdev;
+ *offset = raidframe[i].offset
+ + RF_PROTECTED_SECTORS
+ + d->part[part].offset;
+ *size = d->part[part].size;
+ ret = 0;
+ goto out;
+ }
+ }
+next_raidframe:
+ dealloc_biosdisk(d);
+ d = NULL;
+ }
+out:
+ if (d != NULL)
+ dealloc_biosdisk(d);
+
+ return ret;
+}
+#endif
+
+int
+biosdisk_open_name(struct open_file *f, const char *name)
+{
+#if defined(NO_GPT) && defined(NO_RAIDFRAME)
+ return ENXIO;
+#else
+ struct biosdisk *d = NULL;
+ int biosdev;
+ daddr_t offset;
+ daddr_t size;
+ int error = -1;
+
+#ifndef NO_GPT
+ if (strstr(name, "NAME=") == name)
+ error = biosdisk_find_name(name, &biosdev, &offset, &size);
+#endif
+#ifndef NO_RAIDFRAME
+ if (strstr(name, "raid") == name)
+ error = biosdisk_find_raid(name, &biosdev, &offset, &size);
+#endif
+
+ if (error != 0) {
+ printf("partition %s not found\n", name);
+ error = ENXIO;
+ goto out;
+ }
+
+ d = alloc_biosdisk(biosdev);
+ if (d == NULL) {
+ error = ENXIO;
+ goto out;
+ }
+
+#ifdef _STANDALONE
+ bi_disk.biosdev = d->ll.dev;
+ bi_disk.partition = 0;
+ bi_disk.labelsector = -1;
+
+ bi_wedge.biosdev = d->ll.dev;
+ bi_wedge.matchblk = offset;
+ bi_wedge.matchnblks = 1;
+#endif
+
+ d->boff = offset;
+
+#ifdef _STANDALONE
+ bi_wedge.startblk = offset;
+ bi_wedge.nblks = size;
+
+ add_biosdisk_bootinfo();
+#endif
+
+ f->f_devdata = d;
+out:
+ if (error && d != NULL)
+ dealloc_biosdisk(d);
return error;
+#endif
}
+
+
#ifndef LIBSA_NO_FS_CLOSE
int
biosdisk_close(struct open_file *f)
{
@@ -969,9 +1596,9 @@
/* let the floppy drive go off */
if (d->ll.type == BIOSDISK_TYPE_FD)
wait_sec(3); /* 2s is enough on all PCs I found */
- dealloc(d, sizeof(*d));
+ dealloc_biosdisk(d);
f->f_devdata = NULL;
return 0;
}
#endif
Index: sys/arch/i386/stand/lib/biosdisk.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/stand/lib/biosdisk.h,v
retrieving revision 1.10
diff -U4 -r1.10 biosdisk.h
--- sys/arch/i386/stand/lib/biosdisk.h 2 Apr 2018 09:44:18 -0000 1.10
+++ sys/arch/i386/stand/lib/biosdisk.h 10 Aug 2019 01:47:34 -0000
@@ -24,27 +24,35 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/