[OpenBIOS] [PATCH] Rework mac-parts.c to use CHRP-compliant partition search, followed by Apple OF partition search.

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Thu Dec 6 00:24:58 CET 2012


The confusion from the previous refactoring of mac-parts.c came from the fact
that it must support searching for a boot partition using the algorithm
specified in the OF CHRP bindings supplement, as well as Apple's brute-force
partition-type search.

This patch corrects mac-parts.c so that it will first attempt to find a CHRP
boot partition, and if it does not exist or fails to boot, fall back to the
first partition that would be considered valid by Apple's OF.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
 openbios-devel/packages/mac-parts.c |  191 +++++++++++++++++++++--------------
 1 file changed, 113 insertions(+), 78 deletions(-)

diff --git a/openbios-devel/packages/mac-parts.c b/openbios-devel/packages/mac-parts.c
index a286870..9501bfd 100644
--- a/openbios-devel/packages/mac-parts.c
+++ b/openbios-devel/packages/mac-parts.c
@@ -51,10 +51,11 @@ macparts_open( macparts_info_t *di )
 	char *str = my_args_copy();
 	char *argstr = strdup("");
 	char *parstr = strdup("");
-	int bs, parnum=-1;
+	int bs, parnum=-1, apple_parnum=-1;
+	int parlist[2], parlist_size = 0;
 	desc_map_t dmap;
 	part_entry_t par;
-	int ret = 0;
+	int ret = 0, i = 0, j = 0;
 	int want_bootcode = 0;
 	phandle_t ph;
 	ducell offs = 0, size = -1;
@@ -161,101 +162,135 @@ macparts_open( macparts_info_t *di )
 		DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par.pmMapBlkCnt));
 
 		/* No partition was explicitly requested so let's find a suitable partition... */
-		for (parnum = 1; parnum <= __be32_to_cpu(par.pmMapBlkCnt); parnum++) {
-			SEEK( bs * parnum );
+		for (i = 1; i <= __be32_to_cpu(par.pmMapBlkCnt); i++) {
+			SEEK( bs * i );
 			READ( &par, sizeof(par) );
-			if( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
+			if ( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
                             !__be32_to_cpu(par.pmPartBlkCnt) )
-				break;
+				continue;
 
-			DPRINTF("found partition type: %s with status %x\n", par.pmPartType, __be32_to_cpu(par.pmPartStatus));
+			DPRINTF("found partition %d type: %s with status %x\n", i, par.pmPartType, __be32_to_cpu(par.pmPartStatus));
 
 			/* If we have a valid, allocated and readable partition... */
 			if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
 			(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
 			(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
-				offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
-				size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
-
-				/* If the filename was set to %BOOT, we actually want the bootcode */
-				if (want_bootcode && (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid)) {
-					offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs;
-					size = (long long)__be32_to_cpu(par.pmBootSize);
-
-					goto found;
-				} else {
-					/* Otherwise we were passed a filename and path. So let's
-					   choose the first partition with a valid filesystem */
-					DPUSH( offs );
-					PUSH_ih( my_parent() );
-					parword("find-filesystem");
+
+				/* Unfortunately Apple's OF implementation doesn't follow the OF PowerPC CHRP bindings
+				 * and instead will brute-force boot the first valid partition it finds with a
+				 * type of either "Apple_Boot", "Apple_HFS" or "DOS_FAT_". Here we store the id
+				 * of the first partition that matches these criteria to use as a fallback later
+				 * if required. */
 				
-					ph = POP_ph();
-					if (ph)
-						goto found;
+				if (apple_parnum == -1 &&
+				    (strcmp(par.pmPartType, "Apple_Boot") == 0 || 
+				    strcmp(par.pmPartType, "Apple_HFS") == 0 ||
+				    strcmp(par.pmPartType, "DOS_FAT_") == 0)) {
+					apple_parnum = i;
+					
+					DPRINTF("Located Apple OF fallback partition %d\n", apple_parnum);
+				}
+				
+				/* If the partition is also bootable and the pmProcessor field matches "PowerPC" (insensitive
+				 * match), then according to the CHRP bindings this is our chosen partition */
+				for (j = 0; j < strlen(par.pmProcessor); j++) {
+				    par.pmProcessor[j] = tolower(par.pmProcessor[j]);
+				}				
+				
+				if ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid) &&
+				    strcmp(par.pmProcessor, "powerpc") == 0) {
+				    parnum = i;
+				
+				    DPRINTF("Located CHRP-compliant boot partition %d\n", parnum);
 				}
 			}
 		}
+		
+		/* If we found a valid CHRP partition, add it to the list */
+		if (parnum > 0) {
+		    parlist[parlist_size++] = parnum;
+		}
 
+		/* If we found an Apple OF fallback partition, add it to the list */
+		if (apple_parnum > 0 && apple_parnum != parnum) {
+		    parlist[parlist_size++] = apple_parnum;
+		}
+		
 	} else {
 		/* Another partition was explicitly requested */
-		SEEK( bs * parnum );
-		READ( &par, sizeof(par) );
-
-		if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
-			    (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
-			    (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
-
-			offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
-			size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
-		}
+		parlist[parlist_size++] = parnum;
+		
+		DPRINTF("Partition %d explicitly requested\n", parnum);
 	}
 
-	/* If we couldn't find a partition, exit */
-	if (size == -1) {
-		DPRINTF("Unable to automatically find partition!\n");
+	/* Attempt to use our CHRP partition, optionally followed by our Apple OF fallback partition */
+	for (j = 0; j < parlist_size; j++) {
+	
+	    /* Make sure our partition is valid */
+	    parnum = parlist[j];
+	    
+	    DPRINTF("Selected partition %d to boot\n", parnum);
+	    
+	    SEEK( bs * parnum );
+	    READ( &par, sizeof(par) );	
+
+	    if(! ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
+			(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
+			(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable)) ) {
+		DPRINTF("Partition %d is not valid, allocated and readable\n", parnum);
 		goto out;
+	    }
+	    
+	    ret = -1;
+
+	    offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
+	    size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;	
+	    
+	    if (want_bootcode) {
+		offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs;
+		size = (long long)__be32_to_cpu(par.pmBootSize);
+	    }
+	    
+	    di->blocksize = (unsigned int)bs;	
+	    
+	    di->offs_hi = offs >> BITS;
+	    di->offs_lo = offs & (ucell) -1;
+
+	    di->size_hi = size >> BITS;
+	    di->size_lo = size & (ucell) -1;
+
+	    /* We have a valid partition - so probe for a filesystem at the current offset */
+	    DPRINTF("mac-parts: about to probe for fs\n");
+	    DPUSH( offs );
+	    PUSH_ih( my_parent() );
+	    parword("find-filesystem");
+	    DPRINTF("mac-parts: done fs probe\n");
+
+	    ph = POP_ph();
+	    if( ph ) {
+		    DPRINTF("mac-parts: filesystem found on partition %d with ph " FMT_ucellx " and args %s\n", parnum, ph, argstr);
+		    di->filesystem_ph = ph;
+
+		    /* If the filename was %BOOT then it's not a real filename, so clear argstr before
+		    attempting interpose */
+		    if (want_bootcode) {
+			    argstr = strdup("");
+		    }
+		    
+		    /* If we have been asked to open a particular file, interpose the filesystem package with 
+		    the passed filename as an argument */
+		    if (strlen(argstr)) {
+			    push_str( argstr );
+			    PUSH_ph( ph );
+			    fword("interpose");
+		    }
+		    
+		    goto out;
+	    } else {
+		    DPRINTF("mac-parts: no filesystem found on partition %d; bypassing misc-files interpose\n", parnum);
+	    }
 	}
-
-found:
-
-	ret = -1;
-	di->blocksize = (unsigned int)bs;
-
-	di->offs_hi = offs >> BITS;
-	di->offs_lo = offs & (ucell) -1;
-
-	di->size_hi = size >> BITS;
-	di->size_lo = size & (ucell) -1;
-
-	/* We have a valid partition - so probe for a filesystem at the current offset */
-	DPRINTF("mac-parts: about to probe for fs\n");
-	DPUSH( offs );
-	PUSH_ih( my_parent() );
-	parword("find-filesystem");
-	DPRINTF("mac-parts: done fs probe\n");
-
-	ph = POP_ph();
-	if( ph ) {
-		DPRINTF("mac-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
-		di->filesystem_ph = ph;
-
-		/* If the filename was %BOOT then it's not a real filename, so clear argstr before
-		   attempting interpose */
-		if (want_bootcode)
-			argstr = strdup("");
-
-		/* If we have been asked to open a particular file, interpose the filesystem package with 
-		   the passed filename as an argument */
-		if (strlen(argstr)) {
-			push_str( argstr );
-			PUSH_ph( ph );
-			fword("interpose");
-		}
-	} else {
-		DPRINTF("mac-parts: no filesystem found; bypassing misc-files interpose\n");
-	}
-
+	    
 	free( str );
 
 out:
-- 
1.7.10.4




More information about the OpenBIOS mailing list