diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile
index d402d679a316d20832067f15b9f629ffad2d8f96..1252d768c42d4edf6c88d207fc1dfa3ef28b0f44 100644
--- a/drivers/scsi/isci/Makefile
+++ b/drivers/scsi/isci/Makefile
@@ -9,7 +9,7 @@ EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/
 obj-$(CONFIG_SCSI_ISCI) += isci.o
 isci-objs := init.o phy.o request.o sata.o \
 	     remote_device.o port.o timers.o \
-	     host.o task.o events.o \
+	     host.o task.o events.o probe_roms.o \
 	     core/scic_sds_controller.o  \
 	     core/scic_sds_remote_device.o    \
 	     core/scic_sds_request.o \
diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h
index 485fefc08883b4bae4da56b7efb754f9c3cb6e1a..5e1345daf01481bfed7d3a332e525cda2f73e35d 100644
--- a/drivers/scsi/isci/core/scic_config_parameters.h
+++ b/drivers/scsi/isci/core/scic_config_parameters.h
@@ -68,6 +68,7 @@
 #include "sci_status.h"
 #include "intel_sas.h"
 #include "sci_controller_constants.h"
+#include "probe_roms.h"
 
 struct scic_sds_controller;
 
@@ -223,44 +224,6 @@ union scic_user_parameters {
  */
 #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
 
-/**
- * struct scic_sds_oem_parameters - This structure delineates the various OEM
- *    parameters that must be set the core user.
- *
- *
- */
-struct scic_sds_oem_parameters {
-	struct {
-		/**
-		 * This field indicates whether Spread Spectrum Clocking (SSC)
-		 * should be enabled or disabled.
-		 */
-		bool do_enable_ssc;
-
-	} controller;
-
-	struct {
-		/**
-		 * This field specifies the phys to be contained inside a port.
-		 * The bit position in the mask specifies the index of the phy
-		 * to be contained in the port.  Multiple bits (i.e. phys)
-		 * can be contained in a single port.
-		 */
-		u8 phy_mask;
-
-	} ports[SCI_MAX_PORTS];
-
-	struct sci_phy_oem_params {
-		/**
-		 * This field specifies the SAS address to be transmitted on
-		 * for this phy index.
-		 */
-		struct sci_sas_address sas_address;
-
-	} phys[SCI_MAX_PHYS];
-
-};
-
 /**
  * This structure/union specifies the various different OEM parameter sets
  *    available.  Each type is specific to a hardware controller version.
@@ -273,7 +236,7 @@ union scic_oem_parameters {
 	 * Storage Controller Unit (SCU) Driver Standard (SDS) version
 	 * 1.
 	 */
-	struct scic_sds_oem_parameters sds1;
+	struct scic_sds_oem_params sds1;
 
 };
 
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
index 799a04bc09383f7820f616f5aed2903bec2ab84f..e7f3711b4afc2c7b7fbba5106244e68cab2765ca 100644
--- a/drivers/scsi/isci/core/scic_sds_controller.c
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -2039,10 +2039,8 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co
 
 	/* Initialize all of the phy parameter information. */
 	for (index = 0; index < SCI_MAX_PHYS; index++) {
-		/*
-		 * Default to 3G (i.e. Gen 2) for now.  User can override if
-		 * they choose. */
-		scic->user_parameters.sds1.phys[index].max_speed_generation = 2;
+		/* Default to 6G (i.e. Gen 3) for now. */
+		scic->user_parameters.sds1.phys[index].max_speed_generation = 3;
 
 		/* the frequencies cannot be 0 */
 		scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
index 442caac9675d643ad5012a184763da138dcf6c35..f8f96d6eb7df59b1f0898d64a556315e41045912 100644
--- a/drivers/scsi/isci/firmware/create_fw.c
+++ b/drivers/scsi/isci/firmware/create_fw.c
@@ -6,157 +6,30 @@
 #include <fcntl.h>
 #include <string.h>
 #include <errno.h>
+#include <asm/types.h>
+#include <strings.h>
+#include <stdint.h>
 
-char blob_name[] = "isci_firmware.bin";
-char id[] = "#SCU MAGIC#";
-unsigned char version = 1;
-unsigned char sub_version = 0;
-
-
-/*
- * For all defined arrays:
- * elements 0-3 are for SCU0, ports 0-3
- * elements 4-7 are for SCU1, ports 0-3
- *
- * valid configurations for one SCU are:
- *  P0  P1  P2  P3
- * ----------------
- * 0xF,0x0,0x0,0x0 # 1 x4 port
- * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
- *                 # ports
- * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
- *                 # port
- * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
- * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
- *
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value assigned to UNINIT_PARAM (255).
- */
-unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 };
-
-
-/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */
-unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 };
-
-/*
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value "0000000000000000". SAS address of zero's is
- * considered invalid and will not be used.
- */
-unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL,
-				  0x5FCFFFFFF1000000ULL,
-				  0x5FCFFFFFF2000000ULL,
-				  0x5FCFFFFFF3000000ULL,
-				  0x5FCFFFFFF4000000ULL,
-				  0x5FCFFFFFF5000000ULL,
-				  0x5FCFFFFFF6000000ULL,
-				  0x5FCFFFFFF7000000ULL };
-
-int write_blob(void)
+#include "create_fw.h"
+#include "../probe_roms.h"
+
+int write_blob(struct isci_orom *isci_orom)
 {
 	FILE *fd;
 	int err;
+	size_t count;
 
 	fd = fopen(blob_name, "w+");
 	if (!fd) {
 		perror("Open file for write failed");
+		fclose(fd);
 		return -EIO;
 	}
 
-	/* write id */
-	err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd);
-	if (err == 0) {
-		perror("write id failed");
-		return err;
-	}
-
-	/* write version */
-	err = fwrite((void *)&version, sizeof(version), 1, fd);
-	if (err == 0) {
-		perror("write version failed");
-		return err;
-	}
-
-	/* write sub version */
-	err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd);
-	if (err == 0) {
-		perror("write subversion failed");
-		return err;
-	}
-
-	/* write phy mask header */
-	err = fputc(0x1, fd);
-	if (err == EOF) {
-		perror("write phy mask header failed");
-		return -EIO;
-	}
-
-	/* write size */
-	err = fputc(8, fd);
-	if (err == EOF) {
-		perror("write phy mask size failed");
-		return -EIO;
-	}
-
-	/* write phy masks */
-	err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd);
-	if (err == 0) {
-		perror("write phy_mask failed");
-		return err;
-	}
-
-	/* write phy gen header */
-	err = fputc(0x2, fd);
-	if (err == EOF) {
-		perror("write phy gen header failed");
-		return -EIO;
-	}
-
-	/* write size */
-	err = fputc(8, fd);
-	if (err == EOF) {
-		perror("write phy gen size failed");
-		return -EIO;
-	}
-
-	/* write phy_gen */
-	err = fwrite((void *)phy_gen,
-		     1,
-		     sizeof(phy_gen),
-		     fd);
-	if (err == 0) {
-		perror("write phy_gen failed");
-		return err;
-	}
-
-	/* write phy gen header */
-	err = fputc(0x3, fd);
-	if (err == EOF) {
-		perror("write sas addr header failed");
-		return -EIO;
-	}
-
-	/* write size */
-	err = fputc(8, fd);
-	if (err == EOF) {
-		perror("write sas addr size failed");
-		return -EIO;
-	}
-
-	/* write sas_addr */
-	err = fwrite((void *)sas_addr,
-		     1,
-		     sizeof(sas_addr),
-		     fd);
-	if (err == 0) {
-		perror("write sas_addr failed");
-		return err;
-	}
-
-	/* write end header */
-	err = fputc(0xff, fd);
-	if (err == EOF) {
-		perror("write end header failed");
+	count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
+	if (count != 1) {
+		perror("Write data failed");
+		fclose(fd);
 		return -EIO;
 	}
 
@@ -165,13 +38,53 @@ int write_blob(void)
 	return 0;
 }
 
+void set_binary_values(struct isci_orom *isci_orom)
+{
+	int ctrl_idx, phy_idx, port_idx;
+
+	/* setting OROM signature */
+	strncpy(isci_orom->hdr.signature, sig, strlen(sig));
+	isci_orom->hdr.version = 0x10;
+	isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
+	isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
+	isci_orom->hdr.num_elements = num_elements;
+
+	for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
+		isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
+		isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
+			max_num_concurrent_dev_spin_up;
+		isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
+			enable_ssc;
+
+		for (port_idx = 0; port_idx < 4; port_idx++)
+			isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
+				phy_mask[ctrl_idx][port_idx];
+
+		for (phy_idx = 0; phy_idx < 4; phy_idx++) {
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
+				(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
+				(__u32)(sas_addr[ctrl_idx][phy_idx]);
+		}
+	}
+}
+
 int main(void)
 {
 	int err;
+	struct isci_orom *isci_orom;
+
+	isci_orom = malloc(sizeof(struct isci_orom));
+	memset(isci_orom, 0, sizeof(struct isci_orom));
 
-	err = write_blob();
-	if (err < 0)
+	set_binary_values(isci_orom);
+
+	err = write_blob(isci_orom);
+	if (err < 0) {
+		free(isci_orom);
 		return err;
+	}
 
+	free(isci_orom);
 	return 0;
 }
diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h
new file mode 100644
index 0000000000000000000000000000000000000000..bedbe4fad181a927d59dde656f2469d32b759d29
--- /dev/null
+++ b/drivers/scsi/isci/firmware/create_fw.h
@@ -0,0 +1,67 @@
+#ifndef _CREATE_FW_H_
+#define _CREATE_FW_H_
+
+
+/* we are configuring for 2 SCUs */
+static const int num_elements = 2;
+
+/*
+ * For all defined arrays:
+ * elements 0-3 are for SCU0, ports 0-3
+ * elements 4-7 are for SCU1, ports 0-3
+ *
+ * valid configurations for one SCU are:
+ *  P0  P1  P2  P3
+ * ----------------
+ * 0xF,0x0,0x0,0x0 # 1 x4 port
+ * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
+ *                 # ports
+ * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
+ *                 # port
+ * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
+ * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
+ *
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value assigned to UNINIT_PARAM (255).
+ */
+#ifdef MPC
+static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
+				     {1, 2, 4, 8} };
+#else	/* APC (default) */
+static const __u8 phy_mask[2][4];
+#endif
+
+/* discovery mode type (port auto config mode by default ) */
+static const int mode_type;
+
+/* Maximum number of concurrent device spin up */
+static const int max_num_concurrent_dev_spin_up = 1;
+
+/* enable of ssc operation */
+static const int enable_ssc;
+
+/* AFE_TX_AMP_CONTROL */
+static const unsigned int afe_tx_amp_control0 = 0x000e7c03;
+static const unsigned int afe_tx_amp_control1 = 0x000e7c03;
+static const unsigned int afe_tx_amp_control2 = 0x000e7c03;
+static const unsigned int afe_tx_amp_control3 = 0x000e7c03;
+
+/*
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value "0000000000000000". SAS address of zero's is
+ * considered invalid and will not be used.
+ */
+static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000000ULL,
+						     0x5FCFFFFFF1000000ULL,
+						     0x5FCFFFFFF2000000ULL,
+						     0x5FCFFFFFF3000000ULL },
+						   { 0x5FCFFFFFF4000000ULL,
+						     0x5FCFFFFFF5000000ULL,
+						     0x5FCFFFFFF6000000ULL,
+						     0x5FCFFFFFF7000000ULL } };
+
+static const char blob_name[] = "isci_firmware.bin";
+static const char sig[] = "ISCUOEMB";
+static const unsigned char version = 1;
+
+#endif
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index dc231c22ea933a567502789ccddda8a7f07281d0..bb5b54d361b0add7f5b4fdf6e51bc34e8c0079c1 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -61,6 +61,7 @@
 #include "port.h"
 #include "request.h"
 #include "host.h"
+#include "probe_roms.h"
 
 irqreturn_t isci_msix_isr(int vec, void *data)
 {
@@ -419,6 +420,7 @@ int isci_host_init(struct isci_host *isci_host)
 	struct scic_sds_controller *controller;
 	union scic_oem_parameters scic_oem_params;
 	union scic_user_parameters scic_user_params;
+	struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev);
 
 	isci_timer_list_construct(isci_host);
 
@@ -461,31 +463,32 @@ int isci_host_init(struct isci_host *isci_host)
 	sci_object_set_association(isci_host->core_controller,
 				   (void *)isci_host);
 
-	/* grab initial values stored in the controller object for OEM and USER
-	 * parameters */
-	scic_oem_parameters_get(controller, &scic_oem_params);
+	/*
+	 * grab initial values stored in the controller object for OEM and USER
+	 * parameters
+	 */
 	scic_user_parameters_get(controller, &scic_user_params);
+	status = scic_user_parameters_set(isci_host->core_controller,
+					  &scic_user_params);
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+			 "%s: scic_user_parameters_set failed\n",
+			 __func__);
+		return -ENODEV;
+	}
+
+	scic_oem_parameters_get(controller, &scic_oem_params);
 
-	if (isci_firmware) {
-		/* grab any OEM and USER parameters specified in binary blob */
+	/* grab any OEM parameters specified in orom */
+	if (pci_info->orom) {
 		status = isci_parse_oem_parameters(&scic_oem_params,
-						   isci_host->id,
-						   isci_firmware);
+						   pci_info->orom,
+						   isci_host->id);
 		if (status != SCI_SUCCESS) {
 			dev_warn(&isci_host->pdev->dev,
 				 "parsing firmware oem parameters failed\n");
 			return -EINVAL;
 		}
-
-		status = isci_parse_user_parameters(&scic_user_params,
-						    isci_host->id,
-						    isci_firmware);
-		if (status != SCI_SUCCESS) {
-			dev_warn(&isci_host->pdev->dev,
-				 "%s: isci_parse_user_parameters"
-				 " failed\n", __func__);
-			return -EINVAL;
-		}
 	} else {
 		status = scic_oem_parameters_set(isci_host->core_controller,
 						 &scic_oem_params);
@@ -495,16 +498,6 @@ int isci_host_init(struct isci_host *isci_host)
 				 __func__);
 			return -ENODEV;
 		}
-
-
-		status = scic_user_parameters_set(isci_host->core_controller,
-						  &scic_user_params);
-		if (status != SCI_SUCCESS) {
-			dev_warn(&isci_host->pdev->dev,
-				 "%s: scic_user_parameters_set failed\n",
-				 __func__);
-			return -ENODEV;
-		}
 	}
 
 	tasklet_init(&isci_host->completion_tasklet,
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 889a7850255ae7bb17072f34f6ff387456f850bc..d012b69d8d61eddd85a63b4ae445d62e13d422e0 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -140,8 +140,8 @@ static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int
 
 struct isci_pci_info {
 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
-	int core_lib_array_index;
 	struct isci_host *hosts[SCI_MAX_CONTROLLERS];
+	struct isci_orom *orom;
 };
 
 static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 3f2bb137bcb1839563f7eb9e78a5aaf5e93b01f1..65519321e1cc942ca42bedeabfcb41b598322a1f 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -56,12 +56,15 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/efi.h>
 #include <asm/string.h>
 #include "isci.h"
 #include "task.h"
 #include "sci_controller_constants.h"
 #include "scic_remote_device.h"
 #include "sci_environment.h"
+#include "probe_roms.h"
 
 static struct scsi_transport_template *isci_transport_template;
 
@@ -373,85 +376,6 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
 	return err;
 }
 
-/**
- * isci_parse_oem_parameters() - This method will take OEM parameters
- *    from the module init parameters and copy them to oem_params. This will
- *    only copy values that are not set to the module parameter default values
- * @oem_parameters: This parameter specifies the controller default OEM
- *    parameters. It is expected that this has been initialized to the default
- *    parameters for the controller
- *
- *
- */
-enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params,
-					  int scu_index,
-					  struct isci_firmware *fw)
-{
-	int i;
-
-	/* check for valid inputs */
-	if (!(scu_index >= 0
-	      && scu_index < SCI_MAX_CONTROLLERS
-	      && oem_params != NULL)) {
-		return SCI_FAILURE;
-	}
-
-	for (i = 0; i < SCI_MAX_PHYS; i++) {
-		int array_idx = i + (SCI_MAX_PHYS * scu_index);
-		u64 sas_addr = fw->sas_addrs[array_idx];
-
-		if (sas_addr != 0) {
-			oem_params->sds1.phys[i].sas_address.low =
-				(u32)(sas_addr & 0xffffffff);
-			oem_params->sds1.phys[i].sas_address.high =
-				(u32)((sas_addr >> 32) & 0xffffffff);
-		}
-	}
-
-	for (i = 0; i < SCI_MAX_PORTS; i++) {
-		int array_idx = i + (SCI_MAX_PORTS * scu_index);
-		u32 pmask = fw->phy_masks[array_idx];
-
-		oem_params->sds1.ports[i].phy_mask = pmask;
-	}
-
-	return SCI_SUCCESS;
-}
-
-/**
- * isci_parse_user_parameters() - This method will take user parameters
- *    from the module init parameters and copy them to user_params. This will
- *    only copy values that are not set to the module parameter default values
- * @user_parameters: This parameter specifies the controller default user
- *    parameters. It is expected that this has been initialized to the default
- *    parameters for the controller
- *
- *
- */
-enum sci_status isci_parse_user_parameters(
-	union scic_user_parameters *user_params,
-	int scu_index,
-	struct isci_firmware *fw)
-{
-	int i;
-
-	if (!(scu_index >= 0
-	      && scu_index < SCI_MAX_CONTROLLERS
-	      && user_params != NULL)) {
-		return SCI_FAILURE;
-	}
-
-	for (i = 0; i < SCI_MAX_PORTS; i++) {
-		int array_idx = i + (SCI_MAX_PORTS * scu_index);
-		u32 gen = fw->phy_gens[array_idx];
-
-		user_params->sds1.phys[i].max_speed_generation = gen;
-
-	}
-
-	return SCI_SUCCESS;
-}
-
 static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
 {
 	struct isci_host *isci_host;
@@ -535,73 +459,13 @@ static void check_si_rev(struct pci_dev *pdev)
 		
 }
 
-static int isci_verify_firmware(const struct firmware *fw,
-				struct isci_firmware *isci_fw)
-{
-	const u8 *tmp;
-
-	if (fw->size < ISCI_FIRMWARE_MIN_SIZE)
-		return -EINVAL;
-
-	tmp = fw->data;
-
-	/* 12th char should be the NULL terminate for the ID string */
-	if (tmp[11] != '\0')
-		return -EINVAL;
-
-	if (strncmp("#SCU MAGIC#", tmp, 11) != 0)
-		return -EINVAL;
-
-	isci_fw->id = tmp;
-	isci_fw->version = fw->data[ISCI_FW_VER_OFS];
-	isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS];
-
-	tmp = fw->data + ISCI_FW_DATA_OFS;
-
-	while (*tmp != ISCI_FW_HDR_EOF) {
-		switch (*tmp) {
-		case ISCI_FW_HDR_PHYMASK:
-			tmp++;
-			isci_fw->phy_masks_size = *tmp;
-			tmp++;
-			isci_fw->phy_masks = (const u32 *)tmp;
-			tmp += sizeof(u32) * isci_fw->phy_masks_size;
-			break;
-
-		case ISCI_FW_HDR_PHYGEN:
-			tmp++;
-			isci_fw->phy_gens_size = *tmp;
-			tmp++;
-			isci_fw->phy_gens = (const u32 *)tmp;
-			tmp += sizeof(u32) * isci_fw->phy_gens_size;
-			break;
-
-		case ISCI_FW_HDR_SASADDR:
-			tmp++;
-			isci_fw->sas_addrs_size = *tmp;
-			tmp++;
-			isci_fw->sas_addrs = (const u64 *)tmp;
-			tmp += sizeof(u64) * isci_fw->sas_addrs_size;
-			break;
-
-		default:
-			pr_err("bad field in firmware binary blob\n");
-			return -EINVAL;
-		}
-	}
-
-	pr_info("isci firmware v%u.%u loaded.\n",
-	       isci_fw->version, isci_fw->subversion);
-
-	return SCI_SUCCESS;
-}
-
 static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct isci_pci_info *pci_info;
 	int err, i;
 	struct isci_host *isci_host;
 	const struct firmware *fw = NULL;
+	struct isci_orom *orom;
 
 	check_si_rev(pdev);
 
@@ -610,33 +474,32 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
 		return -ENOMEM;
 	pci_set_drvdata(pdev, pci_info);
 
-	err = request_firmware(&fw, ISCI_FW_NAME, &pdev->dev);
-	if (err) {
-		dev_warn(&pdev->dev,
-			 "Loading firmware failed, using default values\n");
-		dev_warn(&pdev->dev,
-			 "Default OEM configuration being used:"
-			 " 4 narrow ports, and default SAS Addresses\n");
-	} else {
-		isci_firmware = devm_kzalloc(&pdev->dev,
-					     sizeof(struct isci_firmware),
-					     GFP_KERNEL);
-		if (isci_firmware) {
-			err = isci_verify_firmware(fw, isci_firmware);
-			if (err != SCI_SUCCESS) {
-				dev_warn(&pdev->dev,
-					 "firmware verification failed\n");
-				dev_warn(&pdev->dev,
-					 "Default OEM configuration being used:"
-					 " 4 narrow ports, and default SAS "
-					 "Addresses\n");
-				devm_kfree(&pdev->dev, isci_firmware);
-				isci_firmware = NULL;
-			}
+	if (efi_enabled) {
+		/* do EFI parsing here */
+		orom = NULL;
+	} else
+		orom = isci_request_oprom(pdev);
+
+	if (!orom) {
+		orom = isci_request_firmware(pdev, fw);
+		if (!orom) {
+			/* TODO convert this to WARN_TAINT_ONCE once the
+			 * orom/efi parameter support is widely available
+			 */
+			dev_warn(&pdev->dev,
+				 "Loading user firmware failed, using default "
+				 "values\n");
+			dev_warn(&pdev->dev,
+				 "Default OEM configuration being used: 4 "
+				 "narrow ports, and default SAS Addresses\n");
 		}
-		release_firmware(fw);
 	}
 
+	if (orom)
+		dev_info(&pdev->dev, "sas parameters (version: %#x) loaded\n",
+			 orom->hdr.version);
+	pci_info->orom = orom;
+
 	err = isci_pci_init(pdev);
 	if (err)
 		return err;
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index b3f63f1a46cfeebd40240f08c657636db09e6bd0..83422d43c1d3819428912416a121c5059576f2d4 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -61,7 +61,6 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/firmware.h>
 #include <linux/bug.h>
 #include <scsi/libsas.h>
 #include <scsi/scsi.h>
@@ -76,34 +75,6 @@
 #include "task.h"
 #include "sata.h"
 
-extern struct isci_firmware *isci_firmware;
-
-#define ISCI_FW_NAME		"isci/isci_firmware.bin"
-
-#define ISCI_FIRMWARE_MIN_SIZE	149
-
-#define ISCI_FW_IDSIZE		12
-#define ISCI_FW_VER_OFS		ISCI_FW_IDSIZE
-#define ISCI_FW_SUBVER_OFS	ISCI_FW_VER_OFS + 1
-#define ISCI_FW_DATA_OFS	ISCI_FW_SUBVER_OFS + 1
-
-#define ISCI_FW_HDR_PHYMASK	0x1
-#define ISCI_FW_HDR_PHYGEN	0x2
-#define ISCI_FW_HDR_SASADDR	0x3
-#define ISCI_FW_HDR_EOF		0xff
-
-struct isci_firmware {
-	const u8 *id;
-	u8 version;
-	u8 subversion;
-	const u32 *phy_masks;
-	u8 phy_masks_size;
-	const u32 *phy_gens;
-	u8 phy_gens_size;
-	const u64 *sas_addrs;
-	u8 sas_addrs_size;
-};
-
 irqreturn_t isci_msix_isr(int vec, void *data);
 irqreturn_t isci_intx_isr(int vec, void *data);
 irqreturn_t isci_error_isr(int vec, void *data);
@@ -113,14 +84,4 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic);
 bool scic_sds_controller_error_isr(struct scic_sds_controller *scic);
 void scic_sds_controller_error_handler(struct scic_sds_controller *scic);
 
-enum sci_status isci_parse_oem_parameters(
-	union scic_oem_parameters *oem_params,
-	int scu_index,
-	struct isci_firmware *fw);
-
-enum sci_status isci_parse_user_parameters(
-	union scic_user_parameters *user_params,
-	int scu_index,
-	struct isci_firmware *fw);
-
 #endif  /* __ISCI_H__ */
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
new file mode 100644
index 0000000000000000000000000000000000000000..0b90e7c546c0a2babcf5b4342d17c1791e75bb0c
--- /dev/null
+++ b/drivers/scsi/isci/probe_roms.c
@@ -0,0 +1,133 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ */
+
+/* probe_roms - scan for oem parameters */
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/uaccess.h>
+#include <asm/probe_roms.h>
+
+#include "isci.h"
+#include "task.h"
+#include "sci_controller_constants.h"
+#include "scic_remote_device.h"
+#include "sci_environment.h"
+#include "probe_roms.h"
+
+struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
+{
+	void __iomem *oprom = pci_map_biosrom(pdev);
+	struct isci_orom *rom = NULL;
+	size_t len, i;
+
+	if (!oprom)
+		return NULL;
+
+	len = pci_biosrom_size(pdev);
+	rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL);
+
+	for (i = 0; i < len && rom; i += ISCI_ROM_SIG_SIZE) {
+		memcpy_fromio(rom->hdr.signature, oprom + i, ISCI_ROM_SIG_SIZE);
+		if (memcmp(rom->hdr.signature, ISCI_ROM_SIG,
+			   ISCI_ROM_SIG_SIZE) == 0) {
+			size_t copy_len = min(len - i, sizeof(*rom));
+
+			memcpy_fromio(rom, oprom + i, copy_len);
+			break;
+		}
+	}
+
+	if (i >= len) {
+		dev_err(&pdev->dev, "oprom parse error\n");
+		devm_kfree(&pdev->dev, rom);
+		rom = NULL;
+	}
+	pci_unmap_biosrom(oprom);
+
+	return rom;
+}
+
+/**
+ * isci_parse_oem_parameters() - This method will take OEM parameters
+ *    from the module init parameters and copy them to oem_params. This will
+ *    only copy values that are not set to the module parameter default values
+ * @oem_parameters: This parameter specifies the controller default OEM
+ *    parameters. It is expected that this has been initialized to the default
+ *    parameters for the controller
+ *
+ *
+ */
+enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params,
+					  struct isci_orom *orom, int scu_index)
+{
+	int i;
+
+	/* check for valid inputs */
+	if (!(scu_index >= 0
+	      && scu_index < SCI_MAX_CONTROLLERS
+	      && oem_params != NULL))
+		return -EINVAL;
+
+	for (i = 0; i < SCI_MAX_PHYS; i++) {
+		oem_params->sds1.phys[i].sas_address.low =
+			orom->ctrl[scu_index].phys[i].sas_address.low;
+		oem_params->sds1.phys[i].sas_address.high =
+			orom->ctrl[scu_index].phys[i].sas_address.high;
+	}
+
+	for (i = 0; i < SCI_MAX_PORTS; i++)
+		oem_params->sds1.ports[i].phy_mask =
+			orom->ctrl[scu_index].ports[i].phy_mask;
+
+	return 0;
+}
+
+struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
+{
+	struct isci_orom *orom = NULL, *data;
+
+	if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
+		return NULL;
+
+	if (fw->size < sizeof(*orom))
+		goto out;
+
+	data = (struct isci_orom *)fw->data;
+
+	if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
+		    strlen(ISCI_ROM_SIG)) != 0)
+		goto out;
+
+	orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
+	if (!orom)
+		goto out;
+
+	memcpy(orom, fw->data, fw->size);
+
+ out:
+	release_firmware(fw);
+
+	return orom;
+}
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
new file mode 100644
index 0000000000000000000000000000000000000000..76651c01895ae711c3f127b8a76fe1f7a2989c35
--- /dev/null
+++ b/drivers/scsi/isci/probe_roms.h
@@ -0,0 +1,130 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _ISCI_PROBE_ROMS_H_
+#define _ISCI_PROBE_ROMS_H_
+
+#ifdef __KERNEL__
+#include <linux/firmware.h>
+#include <linux/pci.h>
+
+struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
+
+union scic_oem_parameters;
+struct isci_orom;
+
+enum sci_status isci_parse_oem_parameters(
+	union scic_oem_parameters *oem_params,
+	struct isci_orom *orom,
+	int scu_index);
+struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
+int isci_get_efi_var(struct pci_dev *pdev);
+#else
+#define SCI_MAX_PORTS 4
+#define SCI_MAX_PHYS 4
+#endif
+
+#define ISCI_FW_NAME		"isci/isci_firmware.bin"
+
+#define ROMSIGNATURE		0xaa55
+
+#define ISCI_ROM_SIG		"ISCUOEMB"
+#define ISCI_ROM_SIG_SIZE	8
+
+#define ISCI_EFI_VENDOR_GUID	NULL_GUID
+#define ISCI_EFI_ATTRIBUTES	0
+#define ISCI_EFI_VAR_NAME	"isci_oemb"
+
+struct sci_bios_oem_param_block_hdr {
+	uint8_t signature[ISCI_ROM_SIG_SIZE];
+	uint16_t total_block_length;
+	uint8_t hdr_length;
+	uint8_t version;
+	uint8_t preboot_source;
+	uint8_t num_elements;
+	uint8_t element_length;
+	uint8_t reserved[8];
+} __attribute__ ((packed));
+
+struct scic_sds_oem_params {
+	struct {
+		uint8_t mode_type;
+		uint8_t max_concurrent_dev_spin_up;
+		uint8_t do_enable_ssc;
+		uint8_t reserved;
+	} controller;
+
+	struct {
+		uint8_t phy_mask;
+	} ports[SCI_MAX_PORTS];
+
+	struct sci_phy_oem_params {
+		struct {
+			uint32_t high;
+			uint32_t low;
+		} sas_address;
+
+		uint32_t afe_tx_amp_control0;
+		uint32_t afe_tx_amp_control1;
+		uint32_t afe_tx_amp_control2;
+		uint32_t afe_tx_amp_control3;
+	} phys[SCI_MAX_PHYS];
+} __attribute__ ((packed));
+
+struct isci_orom {
+	struct sci_bios_oem_param_block_hdr hdr;
+	struct scic_sds_oem_params ctrl[2];
+} __attribute__ ((packed));
+
+#endif
diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex
index 9fc9e60f399cd1656aec68c0ae691e56a3380c91..7f12b39e79101024705190c1db256a4344f9c922 100644
--- a/firmware/isci/isci_firmware.bin.ihex
+++ b/firmware/isci/isci_firmware.bin.ihex
@@ -1,11 +1,16 @@
-:1000000023534355204D4147494323000100010834
-:1000100001000000020000000400000008000000D1
-:1000200001000000020000000400000008000000C1
-:1000300002080300000003000000030000000300AA
-:1000400000000300000003000000030000000300A4
-:1000500000000308000000F0FFFFCF5F000000F188
-:10006000FFFFCF5F000000F2FFFFCF5F000000F353
-:10007000FFFFCF5F000000F4FFFFCF5F000000F53F
-:10008000FFFFCF5F000000F6FFFFCF5F000000F72B
-:05009000FFFFCF5FFF40
+:10000000495343554F454D42E70017100002000089
+:10001000000000000000000001000000000000FFE0
+:10002000FFCF5F000000F0000000000000000000B3
+:1000300000000000000000FFFFCF5F000000F100A3
+:10004000000000000000000000000000000000FFB1
+:10005000FFCF5F000000F200000000000000000081
+:1000600000000000000000FFFFCF5F000000F30071
+:100070000000000000000000000000000000000080
+:1000800001000000000000FFFFCF5F000000F4004F
+:10009000000000000000000000000000000000FF61
+:1000A000FFCF5F000000F50000000000000000002E
+:1000B00000000000000000FFFFCF5F000000F6001E
+:1000C000000000000000000000000000000000FF31
+:1000D000FFCF5F000000F7000000000000000000FC
+:0700E0000000000000000019
 :00000001FF