Module Name:    src
Committed By:   manu
Date:           Thu Sep 28 15:46:55 UTC 2023

Modified Files:
        src/sys/arch/i386/stand/lib: biosdisk.c

Log Message:
Align the behavior of different boot methods in RAIDframe

We enforce the documented and paritally implemented behavior when
looking for the kernel in RAID 1 sets without a partition name given.
We search for:
- A GPT partition with bootme attribute set
- A FFS or LFS patititon
- The first partition


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/sys/arch/i386/stand/lib/biosdisk.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/stand/lib/biosdisk.c
diff -u src/sys/arch/i386/stand/lib/biosdisk.c:1.58 src/sys/arch/i386/stand/lib/biosdisk.c:1.59
--- src/sys/arch/i386/stand/lib/biosdisk.c:1.58	Tue May  3 10:09:40 2022
+++ src/sys/arch/i386/stand/lib/biosdisk.c	Thu Sep 28 15:46:55 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosdisk.c,v 1.58 2022/05/03 10:09:40 jmcneill Exp $	*/
+/*	$NetBSD: biosdisk.c,v 1.59 2023/09/28 15:46:55 manu Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998
@@ -105,6 +105,7 @@
 struct biosdisk {
 	struct biosdisk_ll ll;
 	daddr_t         boff;
+	daddr_t         size;
 	char            buf[BIOSDISK_BUFSIZE];
 #if !defined(NO_DISKLABEL) || !defined(NO_GPT)
 	struct biosdisk_partition part[BIOSDISKNPART];
@@ -666,6 +667,7 @@ read_label(struct biosdisk *d, daddr_t o
 	dflt_lbl.d_npartitions = 8;
 
 	d->boff = 0;
+	d->size = 0;
 
 	if (d->ll.type != BIOSDISK_TYPE_HD)
 		/* No label on floppy and CD */
@@ -1208,7 +1210,7 @@ add_biosdisk_bootinfo(void)
 #endif
 
 #ifndef NO_GPT
-static daddr_t
+static void
 raidframe_part_offset(struct biosdisk *d, int part)
 {
 	struct biosdisk raidframe;
@@ -1221,8 +1223,10 @@ raidframe_part_offset(struct biosdisk *d
 
 	rf_offset = d->part[part].offset + RF_PROTECTED_SECTORS;
 	rf_size = d->part[part].size;
-	if (read_gpt(&raidframe, rf_offset, rf_size) != 0)
-		return RF_PROTECTED_SECTORS;
+	if (read_gpt(&raidframe, rf_offset, rf_size) != 0) {
+		d->boff += RF_PROTECTED_SECTORS;
+		return;
+	}
 
 	candidate = 0;
 	for (i = 0; i < BIOSDISKNPART; i++) {
@@ -1231,12 +1235,20 @@ raidframe_part_offset(struct biosdisk *d
 		if (raidframe.part[i].fstype == FS_UNUSED)
 			continue;
 #ifndef NO_GPT
-		if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME)
+		if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME) {
 			candidate = i;
+			break;
+		}
 #endif
+		if (raidframe.part[i].fstype == FS_BSDFFS ||
+		    raidframe.part[i].fstype == FS_BSDLFS) {
+			if (candidate == 0)
+				candidate = i;
+		}
 	}
 
-	return RF_PROTECTED_SECTORS + raidframe.part[candidate].offset;
+	d->boff += RF_PROTECTED_SECTORS + raidframe.part[candidate].offset;
+	d->size = raidframe.part[candidate].size;
 }
 #endif
 
@@ -1285,17 +1297,18 @@ biosdisk_open(struct open_file *f, ...)
 	}
 
 	d->boff = d->part[partition].offset;
+	d->size = d->part[partition].size;
 
 	if (d->part[partition].fstype == FS_RAID)
 #ifndef NO_GPT
-		d->boff += raidframe_part_offset(d, partition);
+		raidframe_part_offset(d, partition);
 #else
 		d->boff += RF_PROTECTED_SECTORS;
 #endif
 
 #ifdef _STANDALONE
-	bi_wedge.startblk = d->part[partition].offset;
-	bi_wedge.nblks = d->part[partition].size;
+	bi_wedge.startblk = d->boff;
+	bi_wedge.nblks = d->size;
 #endif
 
 nolabel:
@@ -1389,6 +1402,8 @@ next_disk:
 
 #ifndef NO_RAIDFRAME
 	for (i = 0; i < raidframe_count; i++) {
+		int first_bootme = -1;
+		int first_ffs = -1;
 		int candidate = -1;
 
 		if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) {
@@ -1402,12 +1417,20 @@ next_disk:
 			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 (first_bootme == -1 && 
+			    d->part[part].attr & GPT_ENT_ATTR_BOOTME)
+				first_bootme = part;
+
+			if (first_ffs == -1 && 
+			    (d->part[part].fstype == FS_BSDFFS ||
+			     d->part[part].fstype == FS_BSDLFS))
+				first_ffs = part;
+
 			if (d->part[part].part_name != NULL &&
 			    strcmp(d->part[part].part_name, name) == 0) {
 				*biosdev = raidframe[i].biosdev;
@@ -1418,11 +1441,13 @@ next_disk:
 				ret = 0;
 				goto out;
 			}
-			if (strcmp(raidframe[i].parent_name, name) == 0) {
-				if (candidate == -1 || bootme)
-					candidate = part;
-				continue;
-			}
+		}
+
+		if (strcmp(raidframe[i].parent_name, name) == 0) {
+			if (first_bootme != -1)
+				candidate = first_bootme;
+			else if (first_ffs != -1)
+				candidate = first_ffs;
 		}
 
 		if (candidate != -1) {
@@ -1514,6 +1539,10 @@ next_disk:
 	}
 
 	for (i = 0; i < raidframe_count; i++) {
+		int first_bootme = -1;
+		int first_ffs = -1;
+		int candidate = -1;
+
 		if (raidframe[i].last_unit != target_unit)
 			continue;
 
@@ -1532,6 +1561,15 @@ next_disk:
 				continue;
 			if (d->part[part].fstype == FS_UNUSED)
 				continue;
+
+			if (first_bootme == -1 &&
+			    d->part[part].attr & GPT_ENT_ATTR_BOOTME)
+				first_bootme = part;
+
+			if (first_ffs == -1 &&
+			    (d->part[part].fstype == FS_BSDFFS ||
+			     d->part[part].fstype == FS_BSDLFS))
+				first_ffs = part;
 			if (part == target_part) {
 				*biosdev = raidframe[i].biosdev;
 				*offset = raidframe[i].offset
@@ -1542,6 +1580,22 @@ next_disk:
 				goto out;
 			}
 		}
+
+		if (first_bootme != -1)
+			candidate = first_bootme;
+		else if (first_ffs != -1)
+			candidate = first_ffs;
+
+		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;
@@ -1567,11 +1621,11 @@ biosdisk_open_name(struct open_file *f, 
 	int error = -1;
 
 #ifndef NO_GPT
-	if (strstr(name, "NAME=") == name)
+	if (error && strstr(name, "NAME=") == name)
 		error = biosdisk_find_name(name, &biosdev, &offset, &size);
 #endif
 #ifndef NO_RAIDFRAME
-	if (strstr(name, "raid") == name)
+	if (error && strstr(name, "raid") == name)
 		error = biosdisk_find_raid(name, &biosdev, &offset, &size);
 #endif
 

Reply via email to