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 \
 
 #include "sci_status.h"
 #include "intel_sas.h"
 #include "sci_controller_constants.h"
+#include "probe_roms.h"
 
 struct scic_sds_controller;
 
  */
 #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.
         * Storage Controller Unit (SCU) Driver Standard (SDS) version
         * 1.
         */
-       struct scic_sds_oem_parameters sds1;
+       struct scic_sds_oem_params sds1;
 
 };
 
 
 
        /* 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;
 
 #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;
        }
 
        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;
 }
 
--- /dev/null
+#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
 
 #include "port.h"
 #include "request.h"
 #include "host.h"
+#include "probe_roms.h"
 
 irqreturn_t isci_msix_isr(int vec, void *data)
 {
        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);
 
        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);
                                 __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,
 
 
 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)
 
 #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;
 
        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;
                
 }
 
-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);
 
                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;
 
 #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>
 #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);
 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__ */
 
--- /dev/null
+/*
+ * 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;
+}
 
--- /dev/null
+/*
+ * 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
 
-: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