changeset 9974:206607ab68be

6850448 fwflash does not work on drives with efi labels 6851822 core dump in fwflash's sd.so plugin
author XinChen <Xin.Chen@Sun.COM>
date Fri, 26 Jun 2009 13:51:20 +0800
parents 7911cfe2424f
children 9a78e9b6760d
files usr/src/cmd/fwflash/plugins/transport/common/sd.c
diffstat 1 files changed, 70 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fwflash/plugins/transport/common/sd.c	Thu Jun 25 21:42:33 2009 -0700
+++ b/usr/src/cmd/fwflash/plugins/transport/common/sd.c	Fri Jun 26 13:51:20 2009 +0800
@@ -67,21 +67,25 @@
 		free((thisdev));	\
 		FW_SD_FREE_DEVPATH((devpath))	\
 	}
-#define	FW_SD_FREE_ACC_NAME(thisdev, devpath) {	\
-		free((thisdev)->access_devname);	\
-		FW_SD_FREE_DEVICELIST(thisdev, devpath)	\
-	}
 #define	FW_SD_FREE_DRV_NAME(thisdev, devpath) {	\
 		free((thisdev)->drvname);	\
-		FW_SD_FREE_ACC_NAME((thisdev), (devpath))	\
+		FW_SD_FREE_DEVICELIST((thisdev), (devpath))	\
 	}
 #define	FW_SD_FREE_CLS_NAME(thisdev, devpath) {	\
 		free((thisdev)->classname);	\
 		FW_SD_FREE_DRV_NAME((thisdev), (devpath))	\
 	}
+#define	FW_SD_FREE_ACC_NAME(thisdev, devpath) {	\
+		free((thisdev)->access_devname);	\
+		FW_SD_FREE_CLS_NAME(thisdev, devpath)	\
+	}
+#define	FW_SD_FREE_ADDR(thisdev, devpath) {	\
+		free((thisdev)->addresses[0]);	\
+		FW_SD_FREE_ACC_NAME(thisdev, devpath)	\
+	}
 #define	FW_SD_FREE_IDENT(thisdev, devpath) {	\
 		free((thisdev)->ident);	\
-		FW_SD_FREE_CLS_NAME((thisdev), (devpath))	\
+		FW_SD_FREE_ADDR((thisdev), (devpath))	\
 	}
 #define	FW_SD_FREE_IDENT_VID(thisdev, devpath) {	\
 		free((thisdev)->ident->vid);	\
@@ -114,7 +118,7 @@
 void fw_cleanup(struct devicelist *thisdev);
 
 /* helper functions */
-static char *find_link(di_node_t bnode);
+static char *find_link(di_node_t bnode, char *acc_devname);
 static int link_cb(di_devlink_t devlink, void *arg);
 static int sd_idtfy_custmz(struct devicelist *device, char *sp);
 
@@ -269,23 +273,21 @@
 		return (FWFLASH_FAILURE);
 	}
 
-	if ((devpath = calloc(1, MAXPATHLEN + 1)) == NULL) {
-		logmsg(MSG_ERROR,
-		    gettext("%s: Unable to allocate space for a device node\n"),
-		    driver);
-		return (FWFLASH_FAILURE);
-	}
-
 	if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
 		logmsg(MSG_ERROR, gettext("%s: failed to initialize "
 		    "libscsi\n"), newdev->drvname);
-		FW_SD_FREE_DEVPATH(devpath)
 		return (FWFLASH_FAILURE);
 	}
 
 	/* we've found one, at least */
 	for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) {
-		devpath = di_devfs_path(thisnode);
+		/* Need to free by di_devfs_path_free */
+		if ((devpath = di_devfs_path(thisnode)) == NULL) {
+			logmsg(MSG_INFO, "unable to get device path for "
+			    "current node with errno %d\n", errno);
+			continue;
+		};
+
 		/*
 		 * We check if this is removable device, in which case
 		 * we really aren't interested, so exit stage left
@@ -295,6 +297,7 @@
 			logmsg(MSG_INFO,
 			    "%s: not interested in removable media device\n"
 			    "%s\n", driver, devpath);
+			FW_SD_FREE_DEVPATH(devpath)
 			continue;
 		}
 
@@ -309,36 +312,13 @@
 			return (FWFLASH_FAILURE);
 		}
 
-		if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
-			logmsg(MSG_ERROR,
-			    gettext("%s: Unable to allocate space for a devfs "
-			    "name\n"), driver);
-			libscsi_fini(handle);
-			FW_SD_FREE_DEVICELIST(newdev, devpath)
-			return (FWFLASH_FAILURE);
-		}
-
-		/* save the /devices name */
-		(void) snprintf(newdev->access_devname, MAXPATHLEN,
-		    "%s%s:c,raw", devprefix, devpath);
-
-		/* and the /dev/rdsk/ name */
-		newdev->addresses[0] = calloc(1, MAXPATHLEN);
-		if (newdev->addresses[0])
-			newdev->addresses[0] = find_link(thisnode);
-		if (newdev->addresses[0] == NULL) {
-			libscsi_fini(handle);
-			FW_SD_FREE_DEVICELIST(newdev, devpath)
-			return (FWFLASH_FAILURE);
-		}
-
 		if ((newdev->drvname = calloc(1, strlen(driver) + 1))
 		    == NULL) {
 			logmsg(MSG_ERROR,
 			    gettext("%s: Unable to allocate space to store a "
 			    "driver name\n"), driver);
 			libscsi_fini(handle);
-			FW_SD_FREE_ACC_NAME(newdev, devpath)
+			FW_SD_FREE_DEVICELIST(newdev, devpath)
 			return (FWFLASH_FAILURE);
 		}
 		(void) strlcpy(newdev->drvname, driver, strlen(driver) + 1);
@@ -354,6 +334,42 @@
 		}
 		(void) strlcpy(newdev->classname, driver, strlen(driver) + 1);
 
+		/* Get the access name for current node */
+		if ((newdev->access_devname = calloc(1, MAXPATHLEN)) == NULL) {
+			logmsg(MSG_ERROR,
+			    gettext("%s: Unable to allocate space for a devfs "
+			    "name\n"), driver);
+			libscsi_fini(handle);
+			FW_SD_FREE_CLS_NAME(newdev, devpath)
+			return (FWFLASH_FAILURE);
+		}
+
+		/* The slice number may be 2 or 0, we will try 2 first */
+		(void) snprintf(newdev->access_devname, MAXPATHLEN,
+		    "%s%s:c,raw", devprefix, devpath);
+		if ((target = libscsi_open(handle, NULL,
+		    newdev->access_devname)) == NULL) {
+			/* try 0 for EFI label */
+			(void) snprintf(newdev->access_devname, MAXPATHLEN,
+			    "%s%s:a,raw", devprefix, devpath);
+			if ((target = libscsi_open(handle, NULL,
+			    newdev->access_devname)) == NULL) {
+				logmsg(MSG_INFO,
+				    "%s: unable to open device %s\n",
+				    newdev->drvname, newdev->access_devname);
+				FW_SD_FREE_ACC_NAME(newdev, devpath)
+				continue;
+			}
+		}
+
+		/* and the /dev/rdsk/ name */
+		if ((newdev->addresses[0] = find_link(thisnode,
+		    newdev->access_devname)) == NULL) {
+			libscsi_fini(handle);
+			FW_SD_FREE_ACC_NAME(newdev, devpath)
+			return (FWFLASH_FAILURE);
+		}
+
 		/*
 		 * Only alloc as much as we truly need, and DON'T forget
 		 * that libdevinfo manages the memory!
@@ -363,21 +379,13 @@
 			    gettext("%s: Unable to allocate space for SCSI "
 			    "INQUIRY data\n"), driver);
 			libscsi_fini(handle);
-			FW_SD_FREE_CLS_NAME(newdev, devpath)
+			FW_SD_FREE_ADDR(newdev, devpath)
 			return (FWFLASH_FAILURE);
 		}
 
 		/* We don't use new->ident->encap_ident currently */
 
 		/* Retrive information by using libscsi */
-		if ((target = libscsi_open(handle, NULL,
-		    newdev->access_devname)) == NULL) {
-			logmsg(MSG_INFO, "%s: unable to open device %s\n",
-			    newdev->drvname, newdev->access_devname);
-			FW_SD_FREE_IDENT(newdev, devpath)
-			continue;
-		}
-
 		/* Vendor ID */
 		sp_temp = (char *)libscsi_vendor(target);
 		if (strncmp(sp_temp, "ATA", 3) == 0) {
@@ -412,7 +420,10 @@
 		if (fw_sata_disk) {
 			sp_temp_cut = strchr(sp_temp, ' ');
 			if (!sp_temp_cut) {
-				/* Customize strings for special SATA disks */
+				/*
+				 * There is no SPACE character in the PID field
+				 * Customize strings for special SATA disks
+				 */
 				if (sd_idtfy_custmz(newdev, sp_temp)
 				    != FWFLASH_SUCCESS) {
 					libscsi_close(handle, target);
@@ -520,9 +531,9 @@
 		newdev->plugin = self;
 
 		TAILQ_INSERT_TAIL(fw_devices, newdev, nextdev);
+		FW_SD_FREE_DEVPATH(devpath)
 	}
 	libscsi_fini(handle);
-	FW_SD_FREE_DEVPATH(devpath)
 
 	/* Check if sd targets presented are all unflashable. */
 	if (idx == start)
@@ -642,31 +653,23 @@
 }
 
 static char *
-find_link(di_node_t bnode)
+find_link(di_node_t bnode, char *acc_devname)
 {
 	di_minor_t devminor = DI_MINOR_NIL;
-	di_devlink_handle_t	hdl;
-	char *devfspath = NULL;
-	char *minorpath = NULL;
+	di_devlink_handle_t hdl;
 	char *cbresult = NULL;
 	char linkname[] = "^rdsk/\0";
 
-	devfspath = di_devfs_path(bnode);
 	if (bnode == DI_NODE_NIL) {
 		logmsg(MSG_ERROR,
 		    gettext("find_link must be called with non-null "
 		    "di_node_t\n"));
-		FW_SD_FREE_DEVPATH(devfspath)
 		return (NULL);
 	}
 
-	logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath);
-
-	if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) ||
-	    ((minorpath = calloc(1, MAXPATHLEN)) == NULL)) {
+	if ((cbresult = calloc(1, MAXPATHLEN)) == NULL) {
 		logmsg(MSG_ERROR, gettext("unable to allocate space for dev "
 		    "link\n"));
-		FW_SD_FREE_DEVPATH(devfspath)
 		return (NULL);
 	}
 
@@ -683,19 +686,17 @@
 			    gettext("unable to take devlink snapshot: %s\n"),
 			    strerror(errno));
 		}
-		FW_SD_FREE_DEVPATH(devfspath)
+		free(cbresult);
 		return (NULL);
 	}
 
-	(void) snprintf(minorpath, MAXPATHLEN, "%s:c,raw", devfspath);
-
 	errno = 0;
-	if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK,
-	    (void *)cbresult, link_cb) < 0) {
+	if (di_devlink_walk(hdl, linkname, acc_devname + strlen(devprefix),
+	    DI_PRIMARY_LINK, (void *)cbresult, link_cb) < 0) {
 		logmsg(MSG_ERROR,
 		    gettext("Unable to walk devlink snapshot for %s: %s\n"),
-		    minorpath, strerror(errno));
-		FW_SD_FREE_DEVPATH(devfspath)
+		    acc_devname, strerror(errno));
+		free(cbresult);
 		return (NULL);
 	}
 
@@ -704,8 +705,6 @@
 		    gettext("Unable to close devlink snapshot: %s\n"),
 		    strerror(errno));
 	}
-	free(minorpath); /* don't need this now */
-	FW_SD_FREE_DEVPATH(devfspath)
 
 	logmsg(MSG_INFO, "cbresult: %s\n", cbresult);
 	return (cbresult);