|
 |
2ddfcf |
From 6b781d331bf52b01b9bafa6409ffb400f8c62895 Mon Sep 17 00:00:00 2001
|
|
 |
2ddfcf |
From: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
|
|
 |
2ddfcf |
Date: Wed, 19 Nov 2014 13:53:26 +0100
|
|
 |
2ddfcf |
Subject: [PATCH] imsm: support for OROMs shared by multiple HBAs
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
The IMSM platform code was based on an assumption that the OROM or UEFI
|
|
 |
2ddfcf |
capability structure (represented by struct imsm_orom) always belongs to
|
|
 |
2ddfcf |
only one HBA. This assumption is no longer valid, because of newer
|
|
 |
2ddfcf |
platforms with dual AHCI HBAs. Each HBA can have a separate OROM, but
|
|
 |
2ddfcf |
some versions have a combined OROM for both HBAs.
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
This patch implements this HBA-OROM relationship in struct orom_entry,
|
|
 |
2ddfcf |
which matches an OROM with a list of HBA PCI ids. All the detected
|
|
 |
2ddfcf |
orom_entries are stored and retrieved using a global array and the
|
|
 |
2ddfcf |
functions add_orom(), add_orom_device_id() and get_orom_by_device_id().
|
|
 |
2ddfcf |
This replaces the arrays: imsm_orom, populated_orom, imsm_efi,
|
|
 |
2ddfcf |
populated_efi.
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
The scan() function is extended to find all HBAs for an OROM. The list
|
|
 |
2ddfcf |
of their device ids is retrieved from the PCI Expansion ROM Data
|
|
 |
2ddfcf |
Structure, hence the additional field devListOffset in struct
|
|
 |
2ddfcf |
pciExpDataStructFormat.
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
In UEFI mode we can't read the PCI Expansion ROM Data Structure and the
|
|
 |
2ddfcf |
imsm_orom structures are stored in UEFI variables. They do not provide a
|
|
 |
2ddfcf |
similar device id list, so we also check the HBA PCI class to make sure
|
|
 |
2ddfcf |
that the HBA has RAID mode enabled.
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
In super-intel.c there are changes which allow spanning of IMSM
|
|
 |
2ddfcf |
containers over HBAs of the same type, but only if the HBAs share the
|
|
 |
2ddfcf |
same OROM. This is done by comparing imsm_orom pointers, which (outside
|
|
 |
2ddfcf |
of platform-intel.c) always point to the global array containing all the
|
|
 |
2ddfcf |
detected oroms. Additional warnings are added to
|
|
 |
2ddfcf |
validate_container_imsm() to warn about potentially dangerous operations
|
|
 |
2ddfcf |
in all the possible cases, e.g. when an array is assembled using disks
|
|
 |
2ddfcf |
attached to HBAs with separate OROMs.
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
|
|
 |
2ddfcf |
Signed-off-by: NeilBrown <neilb@suse.de>
|
|
 |
2ddfcf |
---
|
|
 |
2ddfcf |
platform-intel.c | 248 ++++++++++++++++++++++++++++++++-----------------------
|
|
 |
2ddfcf |
platform-intel.h | 5 +-
|
|
 |
2ddfcf |
super-intel.c | 134 +++++++++++++++++++++---------
|
|
 |
2ddfcf |
3 files changed, 243 insertions(+), 144 deletions(-)
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
diff --git a/platform-intel.c b/platform-intel.c
|
|
 |
2ddfcf |
index f347382..f779d02 100644
|
|
 |
2ddfcf |
--- a/platform-intel.c
|
|
 |
2ddfcf |
+++ b/platform-intel.c
|
|
 |
2ddfcf |
@@ -59,6 +59,7 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
|
 |
2ddfcf |
struct sys_dev *list = NULL;
|
|
 |
2ddfcf |
enum sys_dev_type type;
|
|
 |
2ddfcf |
unsigned long long dev_id;
|
|
 |
2ddfcf |
+ unsigned long long class;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
if (strcmp(driver, "isci") == 0)
|
|
 |
2ddfcf |
type = SYS_DEV_SAS;
|
|
 |
2ddfcf |
@@ -99,6 +100,9 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
|
 |
2ddfcf |
if (devpath_to_ll(path, "device", &dev_id) != 0)
|
|
 |
2ddfcf |
continue;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
+ if (devpath_to_ll(path, "class", &class) != 0)
|
|
 |
2ddfcf |
+ continue;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
/* start / add list entry */
|
|
 |
2ddfcf |
if (!head) {
|
|
 |
2ddfcf |
head = xmalloc(sizeof(*head));
|
|
 |
2ddfcf |
@@ -114,6 +118,7 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
list->dev_id = (__u16) dev_id;
|
|
 |
2ddfcf |
+ list->class = (__u32) class;
|
|
 |
2ddfcf |
list->type = type;
|
|
 |
2ddfcf |
list->path = realpath(path, NULL);
|
|
 |
2ddfcf |
list->next = NULL;
|
|
 |
2ddfcf |
@@ -127,16 +132,6 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
|
 |
2ddfcf |
static struct sys_dev *intel_devices=NULL;
|
|
 |
2ddfcf |
static time_t valid_time = 0;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-static enum sys_dev_type device_type_by_id(__u16 device_id)
|
|
 |
2ddfcf |
-{
|
|
 |
2ddfcf |
- struct sys_dev *iter;
|
|
 |
2ddfcf |
-
|
|
 |
2ddfcf |
- for(iter = intel_devices; iter != NULL; iter = iter->next)
|
|
 |
2ddfcf |
- if (iter->dev_id == device_id)
|
|
 |
2ddfcf |
- return iter->type;
|
|
 |
2ddfcf |
- return SYS_DEV_UNKNOWN;
|
|
 |
2ddfcf |
-}
|
|
 |
2ddfcf |
-
|
|
 |
2ddfcf |
static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
char path[strlen(dev_path) + strlen(entry) + 2];
|
|
 |
2ddfcf |
@@ -209,16 +204,79 @@ struct pciExpDataStructFormat {
|
|
 |
2ddfcf |
__u8 ver[4];
|
|
 |
2ddfcf |
__u16 vendorID;
|
|
 |
2ddfcf |
__u16 deviceID;
|
|
 |
2ddfcf |
+ __u16 devListOffset;
|
|
 |
2ddfcf |
} __attribute__ ((packed));
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-static struct imsm_orom imsm_orom[SYS_DEV_MAX];
|
|
 |
2ddfcf |
-static int populated_orom[SYS_DEV_MAX];
|
|
 |
2ddfcf |
+struct devid_list {
|
|
 |
2ddfcf |
+ __u16 devid;
|
|
 |
2ddfcf |
+ struct devid_list *next;
|
|
 |
2ddfcf |
+};
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+struct orom_entry {
|
|
 |
2ddfcf |
+ struct imsm_orom orom;
|
|
 |
2ddfcf |
+ struct devid_list *devid_list;
|
|
 |
2ddfcf |
+};
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+static struct orom_entry oroms[SYS_DEV_MAX];
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+const struct imsm_orom *get_orom_by_device_id(__u16 dev_id)
|
|
 |
2ddfcf |
+{
|
|
 |
2ddfcf |
+ int i;
|
|
 |
2ddfcf |
+ struct devid_list *list;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (i = 0; i < SYS_DEV_MAX; i++) {
|
|
 |
2ddfcf |
+ for (list = oroms[i].devid_list; list; list = list->next) {
|
|
 |
2ddfcf |
+ if (list->devid == dev_id)
|
|
 |
2ddfcf |
+ return &oroms[i].orom;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ return NULL;
|
|
 |
2ddfcf |
+}
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+static const struct imsm_orom *add_orom(const struct imsm_orom *orom)
|
|
 |
2ddfcf |
+{
|
|
 |
2ddfcf |
+ int i;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (i = 0; i < SYS_DEV_MAX; i++) {
|
|
 |
2ddfcf |
+ if (&oroms[i].orom == orom)
|
|
 |
2ddfcf |
+ return orom;
|
|
 |
2ddfcf |
+ if (oroms[i].orom.signature[0] == 0) {
|
|
 |
2ddfcf |
+ oroms[i].orom = *orom;
|
|
 |
2ddfcf |
+ return &oroms[i].orom;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ return NULL;
|
|
 |
2ddfcf |
+}
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+static void add_orom_device_id(const struct imsm_orom *orom, __u16 dev_id)
|
|
 |
2ddfcf |
+{
|
|
 |
2ddfcf |
+ int i;
|
|
 |
2ddfcf |
+ struct devid_list *list;
|
|
 |
2ddfcf |
+ struct devid_list *prev = NULL;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (i = 0; i < SYS_DEV_MAX; i++) {
|
|
 |
2ddfcf |
+ if (&oroms[i].orom == orom) {
|
|
 |
2ddfcf |
+ for (list = oroms[i].devid_list; list; prev = list, list = list->next) {
|
|
 |
2ddfcf |
+ if (list->devid == dev_id)
|
|
 |
2ddfcf |
+ return;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ list = xmalloc(sizeof(struct devid_list));
|
|
 |
2ddfcf |
+ list->devid = dev_id;
|
|
 |
2ddfcf |
+ list->next = NULL;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (prev == NULL)
|
|
 |
2ddfcf |
+ oroms[i].devid_list = list;
|
|
 |
2ddfcf |
+ else
|
|
 |
2ddfcf |
+ prev->next = list;
|
|
 |
2ddfcf |
+ return;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
static int scan(const void *start, const void *end, const void *data)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
int offset;
|
|
 |
2ddfcf |
- const struct imsm_orom *imsm_mem;
|
|
 |
2ddfcf |
- int dev;
|
|
 |
2ddfcf |
+ const struct imsm_orom *imsm_mem = NULL;
|
|
 |
2ddfcf |
int len = (end - start);
|
|
 |
2ddfcf |
struct pciExpDataStructFormat *ptr= (struct pciExpDataStructFormat *)data;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
@@ -231,81 +289,83 @@ static int scan(const void *start, const void *end, const void *data)
|
|
 |
2ddfcf |
(ulong) __le16_to_cpu(ptr->vendorID),
|
|
 |
2ddfcf |
(ulong) __le16_to_cpu(ptr->deviceID));
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if (__le16_to_cpu(ptr->vendorID) == 0x8086) {
|
|
 |
2ddfcf |
- /* serach attached intel devices by device id from OROM */
|
|
 |
2ddfcf |
- dev = device_type_by_id(__le16_to_cpu(ptr->deviceID));
|
|
 |
2ddfcf |
- if (dev == SYS_DEV_UNKNOWN)
|
|
 |
2ddfcf |
- return 0;
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
- else
|
|
 |
2ddfcf |
+ if (__le16_to_cpu(ptr->vendorID) != 0x8086)
|
|
 |
2ddfcf |
return 0;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
for (offset = 0; offset < len; offset += 4) {
|
|
 |
2ddfcf |
- imsm_mem = start + offset;
|
|
 |
2ddfcf |
- if ((memcmp(imsm_mem->signature, "$VER", 4) == 0)) {
|
|
 |
2ddfcf |
- imsm_orom[dev] = *imsm_mem;
|
|
 |
2ddfcf |
- populated_orom[dev] = 1;
|
|
 |
2ddfcf |
- return populated_orom[SYS_DEV_SATA] && populated_orom[SYS_DEV_SAS];
|
|
 |
2ddfcf |
+ const void *mem = start + offset;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if ((memcmp(mem, IMSM_OROM_SIGNATURE, 4) == 0)) {
|
|
 |
2ddfcf |
+ imsm_mem = mem;
|
|
 |
2ddfcf |
+ break;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (!imsm_mem)
|
|
 |
2ddfcf |
+ return 0;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ const struct imsm_orom *orom = add_orom(imsm_mem);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (ptr->devListOffset) {
|
|
 |
2ddfcf |
+ const __u16 *dev_list = (void *)ptr + ptr->devListOffset;
|
|
 |
2ddfcf |
+ int i;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (i = 0; dev_list[i] != 0; i++)
|
|
 |
2ddfcf |
+ add_orom_device_id(orom, dev_list[i]);
|
|
 |
2ddfcf |
+ } else {
|
|
 |
2ddfcf |
+ add_orom_device_id(orom, __le16_to_cpu(ptr->deviceID));
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
return 0;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-const struct imsm_orom *imsm_platform_test(enum sys_dev_type hba_id, int *populated,
|
|
 |
2ddfcf |
- struct imsm_orom *imsm_orom)
|
|
 |
2ddfcf |
+const struct imsm_orom *imsm_platform_test(struct sys_dev *hba)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
- memset(imsm_orom, 0, sizeof(*imsm_orom));
|
|
 |
2ddfcf |
- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
- IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5;
|
|
 |
2ddfcf |
- imsm_orom->sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB |
|
|
 |
2ddfcf |
- IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB |
|
|
 |
2ddfcf |
- IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB |
|
|
 |
2ddfcf |
- IMSM_OROM_SSS_256kB | IMSM_OROM_SSS_512kB |
|
|
 |
2ddfcf |
- IMSM_OROM_SSS_1MB | IMSM_OROM_SSS_2MB;
|
|
 |
2ddfcf |
- imsm_orom->dpa = IMSM_OROM_DISKS_PER_ARRAY;
|
|
 |
2ddfcf |
- imsm_orom->tds = IMSM_OROM_TOTAL_DISKS;
|
|
 |
2ddfcf |
- imsm_orom->vpa = IMSM_OROM_VOLUMES_PER_ARRAY;
|
|
 |
2ddfcf |
- imsm_orom->vphba = IMSM_OROM_VOLUMES_PER_HBA;
|
|
 |
2ddfcf |
- imsm_orom->attr = imsm_orom->rlc | IMSM_OROM_ATTR_ChecksumVerify;
|
|
 |
2ddfcf |
- *populated = 1;
|
|
 |
2ddfcf |
+ struct imsm_orom orom = {
|
|
 |
2ddfcf |
+ .signature = IMSM_OROM_SIGNATURE,
|
|
 |
2ddfcf |
+ .rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
+ IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5,
|
|
 |
2ddfcf |
+ .sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB |
|
|
 |
2ddfcf |
+ IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB |
|
|
 |
2ddfcf |
+ IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB |
|
|
 |
2ddfcf |
+ IMSM_OROM_SSS_256kB | IMSM_OROM_SSS_512kB |
|
|
 |
2ddfcf |
+ IMSM_OROM_SSS_1MB | IMSM_OROM_SSS_2MB,
|
|
 |
2ddfcf |
+ .dpa = IMSM_OROM_DISKS_PER_ARRAY,
|
|
 |
2ddfcf |
+ .tds = IMSM_OROM_TOTAL_DISKS,
|
|
 |
2ddfcf |
+ .vpa = IMSM_OROM_VOLUMES_PER_ARRAY,
|
|
 |
2ddfcf |
+ .vphba = IMSM_OROM_VOLUMES_PER_HBA
|
|
 |
2ddfcf |
+ };
|
|
 |
2ddfcf |
+ orom.attr = orom.rlc | IMSM_OROM_ATTR_ChecksumVerify;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
if (check_env("IMSM_TEST_OROM_NORAID5")) {
|
|
 |
2ddfcf |
- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
+ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
IMSM_OROM_RLC_RAID10;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
- if (check_env("IMSM_TEST_AHCI_EFI_NORAID5") && (hba_id == SYS_DEV_SAS)) {
|
|
 |
2ddfcf |
- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
+ if (check_env("IMSM_TEST_AHCI_EFI_NORAID5") && (hba->type == SYS_DEV_SAS)) {
|
|
 |
2ddfcf |
+ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
IMSM_OROM_RLC_RAID10;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
- if (check_env("IMSM_TEST_SCU_EFI_NORAID5") && (hba_id == SYS_DEV_SATA)) {
|
|
 |
2ddfcf |
- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
+ if (check_env("IMSM_TEST_SCU_EFI_NORAID5") && (hba->type == SYS_DEV_SATA)) {
|
|
 |
2ddfcf |
+ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
|
 |
2ddfcf |
IMSM_OROM_RLC_RAID10;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- return imsm_orom;
|
|
 |
2ddfcf |
+ const struct imsm_orom *ret = add_orom(&orom;;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ add_orom_device_id(ret, hba->dev_id);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ return ret;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id)
|
|
 |
2ddfcf |
+static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
unsigned long align;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if (hba_id >= SYS_DEV_MAX)
|
|
 |
2ddfcf |
- return NULL;
|
|
 |
2ddfcf |
+ if (check_env("IMSM_TEST_OROM"))
|
|
 |
2ddfcf |
+ return imsm_platform_test(hba);
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- /* it's static data so we only need to read it once */
|
|
 |
2ddfcf |
- if (populated_orom[hba_id]) {
|
|
 |
2ddfcf |
- dprintf("OROM CAP: %p, pid: %d pop: %d\n",
|
|
 |
2ddfcf |
- &imsm_orom[hba_id], (int) getpid(), populated_orom[hba_id]);
|
|
 |
2ddfcf |
- return &imsm_orom[hba_id];
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
- if (check_env("IMSM_TEST_OROM")) {
|
|
 |
2ddfcf |
- dprintf("OROM CAP: %p, pid: %d pop: %d\n",
|
|
 |
2ddfcf |
- &imsm_orom[hba_id], (int) getpid(), populated_orom[hba_id]);
|
|
 |
2ddfcf |
- return imsm_platform_test(hba_id, &populated_orom[hba_id], &imsm_orom[hba_id]);
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
/* return empty OROM capabilities in EFI test mode */
|
|
 |
2ddfcf |
- if (check_env("IMSM_TEST_AHCI_EFI") ||
|
|
 |
2ddfcf |
- check_env("IMSM_TEST_SCU_EFI"))
|
|
 |
2ddfcf |
+ if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI"))
|
|
 |
2ddfcf |
return NULL;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
find_intel_devices();
|
|
 |
2ddfcf |
@@ -325,9 +385,7 @@ static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id)
|
|
 |
2ddfcf |
scan_adapter_roms(scan);
|
|
 |
2ddfcf |
probe_roms_exit();
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if (populated_orom[hba_id])
|
|
 |
2ddfcf |
- return &imsm_orom[hba_id];
|
|
 |
2ddfcf |
- return NULL;
|
|
 |
2ddfcf |
+ return get_orom_by_device_id(hba->dev_id);
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
#define GUID_STR_MAX 37 /* according to GUID format:
|
|
 |
2ddfcf |
@@ -347,9 +405,7 @@ static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id)
|
|
 |
2ddfcf |
#define VENDOR_GUID \
|
|
 |
2ddfcf |
EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6)
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-int populated_efi[SYS_DEV_MAX] = { 0, 0 };
|
|
 |
2ddfcf |
-
|
|
 |
2ddfcf |
-static struct imsm_orom imsm_efi[SYS_DEV_MAX];
|
|
 |
2ddfcf |
+#define PCI_CLASS_RAID_CNTRL 0x010400
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struct efi_guid guid)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
@@ -395,54 +451,40 @@ int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struc
|
|
 |
2ddfcf |
return 0;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-const struct imsm_orom *find_imsm_efi(enum sys_dev_type hba_id)
|
|
 |
2ddfcf |
+const struct imsm_orom *find_imsm_efi(struct sys_dev *hba)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
- if (hba_id >= SYS_DEV_MAX)
|
|
 |
2ddfcf |
- return NULL;
|
|
 |
2ddfcf |
+ struct imsm_orom orom;
|
|
 |
2ddfcf |
+ const struct imsm_orom *ret;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- dprintf("EFI CAP: %p, pid: %d pop: %d\n",
|
|
 |
2ddfcf |
- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]);
|
|
 |
2ddfcf |
+ if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI"))
|
|
 |
2ddfcf |
+ return imsm_platform_test(hba);
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- /* it's static data so we only need to read it once */
|
|
 |
2ddfcf |
- if (populated_efi[hba_id]) {
|
|
 |
2ddfcf |
- dprintf("EFI CAP: %p, pid: %d pop: %d\n",
|
|
 |
2ddfcf |
- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]);
|
|
 |
2ddfcf |
- return &imsm_efi[hba_id];
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
- if (check_env("IMSM_TEST_AHCI_EFI") ||
|
|
 |
2ddfcf |
- check_env("IMSM_TEST_SCU_EFI")) {
|
|
 |
2ddfcf |
- dprintf("OROM CAP: %p, pid: %d pop: %d\n",
|
|
 |
2ddfcf |
- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]);
|
|
 |
2ddfcf |
- return imsm_platform_test(hba_id, &populated_efi[hba_id], &imsm_efi[hba_id]);
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
/* OROM test is set, return that there is no EFI capabilities */
|
|
 |
2ddfcf |
if (check_env("IMSM_TEST_OROM"))
|
|
 |
2ddfcf |
return NULL;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if (read_efi_variable(&imsm_efi[hba_id], sizeof(imsm_efi[0]), hba_id == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID)) {
|
|
 |
2ddfcf |
- populated_efi[hba_id] = 0;
|
|
 |
2ddfcf |
+ if (hba->type == SYS_DEV_SATA && hba->class != PCI_CLASS_RAID_CNTRL)
|
|
 |
2ddfcf |
return NULL;
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- populated_efi[hba_id] = 1;
|
|
 |
2ddfcf |
- return &imsm_efi[hba_id];
|
|
 |
2ddfcf |
-}
|
|
 |
2ddfcf |
+ if (read_efi_variable(&orom, sizeof(orom), hba->type == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID))
|
|
 |
2ddfcf |
+ return NULL;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-/*
|
|
 |
2ddfcf |
- * backward interface compatibility
|
|
 |
2ddfcf |
- */
|
|
 |
2ddfcf |
-const struct imsm_orom *find_imsm_orom(void)
|
|
 |
2ddfcf |
-{
|
|
 |
2ddfcf |
- return find_imsm_hba_orom(SYS_DEV_SATA);
|
|
 |
2ddfcf |
+ ret = add_orom(&orom;;
|
|
 |
2ddfcf |
+ add_orom_device_id(ret, hba->dev_id);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ return ret;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
-const struct imsm_orom *find_imsm_capability(enum sys_dev_type hba_id)
|
|
 |
2ddfcf |
+const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
- const struct imsm_orom *cap=NULL;
|
|
 |
2ddfcf |
+ const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (cap)
|
|
 |
2ddfcf |
+ return cap;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if ((cap = find_imsm_efi(hba_id)) != NULL)
|
|
 |
2ddfcf |
+ if ((cap = find_imsm_efi(hba)) != NULL)
|
|
 |
2ddfcf |
return cap;
|
|
 |
2ddfcf |
- if ((cap = find_imsm_hba_orom(hba_id)) != NULL)
|
|
 |
2ddfcf |
+ if ((cap = find_imsm_hba_orom(hba)) != NULL)
|
|
 |
2ddfcf |
return cap;
|
|
 |
2ddfcf |
return NULL;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
diff --git a/platform-intel.h b/platform-intel.h
|
|
 |
2ddfcf |
index 8226be3..e41f386 100644
|
|
 |
2ddfcf |
--- a/platform-intel.h
|
|
 |
2ddfcf |
+++ b/platform-intel.h
|
|
 |
2ddfcf |
@@ -22,6 +22,7 @@
|
|
 |
2ddfcf |
/* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */
|
|
 |
2ddfcf |
struct imsm_orom {
|
|
 |
2ddfcf |
__u8 signature[4];
|
|
 |
2ddfcf |
+ #define IMSM_OROM_SIGNATURE "$VER"
|
|
 |
2ddfcf |
__u8 table_ver_major; /* Currently 2 (can change with future revs) */
|
|
 |
2ddfcf |
__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
|
|
 |
2ddfcf |
__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
|
|
 |
2ddfcf |
@@ -180,6 +181,7 @@ struct sys_dev {
|
|
 |
2ddfcf |
char *path;
|
|
 |
2ddfcf |
char *pci_id;
|
|
 |
2ddfcf |
__u16 dev_id;
|
|
 |
2ddfcf |
+ __u32 class;
|
|
 |
2ddfcf |
struct sys_dev *next;
|
|
 |
2ddfcf |
};
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
@@ -201,10 +203,11 @@ static inline char *guid_str(char *buf, struct efi_guid guid)
|
|
 |
2ddfcf |
char *diskfd_to_devpath(int fd);
|
|
 |
2ddfcf |
struct sys_dev *find_driver_devices(const char *bus, const char *driver);
|
|
 |
2ddfcf |
struct sys_dev *find_intel_devices(void);
|
|
 |
2ddfcf |
-const struct imsm_orom *find_imsm_capability(enum sys_dev_type hba_id);
|
|
 |
2ddfcf |
+const struct imsm_orom *find_imsm_capability(struct sys_dev *hba);
|
|
 |
2ddfcf |
const struct imsm_orom *find_imsm_orom(void);
|
|
 |
2ddfcf |
int disk_attached_to_hba(int fd, const char *hba_path);
|
|
 |
2ddfcf |
int devt_attached_to_hba(dev_t dev, const char *hba_path);
|
|
 |
2ddfcf |
char *devt_to_devpath(dev_t dev);
|
|
 |
2ddfcf |
int path_attached_to_hba(const char *disk_path, const char *hba_path);
|
|
 |
2ddfcf |
const char *get_sys_dev_type(enum sys_dev_type);
|
|
 |
2ddfcf |
+const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
|
|
 |
2ddfcf |
diff --git a/super-intel.c b/super-intel.c
|
|
 |
2ddfcf |
index e28ac7d..dabf011 100644
|
|
 |
2ddfcf |
--- a/super-intel.c
|
|
 |
2ddfcf |
+++ b/super-intel.c
|
|
 |
2ddfcf |
@@ -555,11 +555,26 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device
|
|
 |
2ddfcf |
if (super->hba == NULL) {
|
|
 |
2ddfcf |
super->hba = alloc_intel_hba(device);
|
|
 |
2ddfcf |
return 1;
|
|
 |
2ddfcf |
- } else
|
|
 |
2ddfcf |
- /* IMSM metadata disallows to attach disks to multiple
|
|
 |
2ddfcf |
- * controllers.
|
|
 |
2ddfcf |
- */
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ hba = super->hba;
|
|
 |
2ddfcf |
+ /* Intel metadata allows for all disks attached to the same type HBA.
|
|
 |
2ddfcf |
+ * Do not sypport odf HBA types mixing
|
|
 |
2ddfcf |
+ */
|
|
 |
2ddfcf |
+ if (device->type != hba->type)
|
|
 |
2ddfcf |
+ return 2;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ /* Multiple same type HBAs can be used if they share the same OROM */
|
|
 |
2ddfcf |
+ const struct imsm_orom *device_orom = get_orom_by_device_id(device->dev_id);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (device_orom != super->orom)
|
|
 |
2ddfcf |
return 2;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ while (hba->next)
|
|
 |
2ddfcf |
+ hba = hba->next;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ hba->next = alloc_intel_hba(device);
|
|
 |
2ddfcf |
+ return 1;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
|
|
 |
2ddfcf |
@@ -1886,13 +1901,12 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
|
|
 |
2ddfcf |
if (!list)
|
|
 |
2ddfcf |
return 2;
|
|
 |
2ddfcf |
for (hba = list; hba; hba = hba->next) {
|
|
 |
2ddfcf |
- orom = find_imsm_capability(hba->type);
|
|
 |
2ddfcf |
- if (!orom) {
|
|
 |
2ddfcf |
- result = 2;
|
|
 |
2ddfcf |
+ if (find_imsm_capability(hba)) {
|
|
 |
2ddfcf |
+ result = 0;
|
|
 |
2ddfcf |
break;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
else
|
|
 |
2ddfcf |
- result = 0;
|
|
 |
2ddfcf |
+ result = 2;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
return result;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
@@ -1909,7 +1923,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
|
|
 |
2ddfcf |
for (hba = list; hba; hba = hba->next) {
|
|
 |
2ddfcf |
if (controller_path && (compare_paths(hba->path,controller_path) != 0))
|
|
 |
2ddfcf |
continue;
|
|
 |
2ddfcf |
- orom = find_imsm_capability(hba->type);
|
|
 |
2ddfcf |
+ orom = find_imsm_capability(hba);
|
|
 |
2ddfcf |
if (!orom)
|
|
 |
2ddfcf |
pr_err("imsm capabilities not found for controller: %s (type %s)\n",
|
|
 |
2ddfcf |
hba->path, get_sys_dev_type(hba->type));
|
|
 |
2ddfcf |
@@ -1954,7 +1968,7 @@ static int export_detail_platform_imsm(int verbose, char *controller_path)
|
|
 |
2ddfcf |
for (hba = list; hba; hba = hba->next) {
|
|
 |
2ddfcf |
if (controller_path && (compare_paths(hba->path,controller_path) != 0))
|
|
 |
2ddfcf |
continue;
|
|
 |
2ddfcf |
- orom = find_imsm_capability(hba->type);
|
|
 |
2ddfcf |
+ orom = find_imsm_capability(hba);
|
|
 |
2ddfcf |
if (!orom) {
|
|
 |
2ddfcf |
if (verbose > 0)
|
|
 |
2ddfcf |
pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path);
|
|
 |
2ddfcf |
@@ -3087,13 +3101,18 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
|
|
 |
2ddfcf |
* use the same Intel hba
|
|
 |
2ddfcf |
* If not on Intel hba at all, allow anything.
|
|
 |
2ddfcf |
*/
|
|
 |
2ddfcf |
- if (!check_env("IMSM_NO_PLATFORM")) {
|
|
 |
2ddfcf |
- if (first->hba && sec->hba &&
|
|
 |
2ddfcf |
- strcmp(first->hba->path, sec->hba->path) != 0) {
|
|
 |
2ddfcf |
+ if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) {
|
|
 |
2ddfcf |
+ if (first->hba->type != sec->hba->type) {
|
|
 |
2ddfcf |
+ fprintf(stderr,
|
|
 |
2ddfcf |
+ "HBAs of devices do not match %s != %s\n",
|
|
 |
2ddfcf |
+ get_sys_dev_type(first->hba->type),
|
|
 |
2ddfcf |
+ get_sys_dev_type(sec->hba->type));
|
|
 |
2ddfcf |
+ return 3;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ if (first->orom != sec->orom) {
|
|
 |
2ddfcf |
fprintf(stderr,
|
|
 |
2ddfcf |
- "HBAs of devices does not match %s != %s\n",
|
|
 |
2ddfcf |
- first->hba ? first->hba->path : NULL,
|
|
 |
2ddfcf |
- sec->hba ? sec->hba->path : NULL);
|
|
 |
2ddfcf |
+ "HBAs of devices do not match %s != %s\n",
|
|
 |
2ddfcf |
+ first->hba->pci_id, sec->hba->pci_id);
|
|
 |
2ddfcf |
return 3;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
@@ -3832,14 +3851,13 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
|
|
 |
2ddfcf |
fprintf(stderr, ", ");
|
|
 |
2ddfcf |
hba = hba->next;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
-
|
|
 |
2ddfcf |
- fprintf(stderr, ").\n");
|
|
 |
2ddfcf |
- cont_err("Mixing devices attached to multiple controllers "
|
|
 |
2ddfcf |
- "is not allowed.\n");
|
|
 |
2ddfcf |
+ fprintf(stderr, ").\n"
|
|
 |
2ddfcf |
+ " Mixing devices attached to different controllers "
|
|
 |
2ddfcf |
+ "is not allowed.\n");
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
return 2;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
- super->orom = find_imsm_capability(hba_name->type);
|
|
 |
2ddfcf |
+ super->orom = find_imsm_capability(hba_name);
|
|
 |
2ddfcf |
if (!super->orom)
|
|
 |
2ddfcf |
return 3;
|
|
 |
2ddfcf |
return 0;
|
|
 |
2ddfcf |
@@ -9061,32 +9079,68 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
|
|
 |
2ddfcf |
******************************************************************************/
|
|
 |
2ddfcf |
int validate_container_imsm(struct mdinfo *info)
|
|
 |
2ddfcf |
{
|
|
 |
2ddfcf |
- if (!check_env("IMSM_NO_PLATFORM")) {
|
|
 |
2ddfcf |
- struct sys_dev *idev;
|
|
 |
2ddfcf |
- struct mdinfo *dev;
|
|
 |
2ddfcf |
- char *hba_path = NULL;
|
|
 |
2ddfcf |
- char *dev_path = devt_to_devpath(makedev(info->disk.major,
|
|
 |
2ddfcf |
- info->disk.minor));
|
|
 |
2ddfcf |
+ if (check_env("IMSM_NO_PLATFORM"))
|
|
 |
2ddfcf |
+ return 0;
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- for (idev = find_intel_devices(); idev; idev = idev->next) {
|
|
 |
2ddfcf |
- if (strstr(dev_path, idev->path)) {
|
|
 |
2ddfcf |
- hba_path = idev->path;
|
|
 |
2ddfcf |
- break;
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
+ struct sys_dev *idev;
|
|
 |
2ddfcf |
+ struct sys_dev *hba = NULL;
|
|
 |
2ddfcf |
+ struct sys_dev *intel_devices = find_intel_devices();
|
|
 |
2ddfcf |
+ char *dev_path = devt_to_devpath(makedev(info->disk.major,
|
|
 |
2ddfcf |
+ info->disk.minor));
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (idev = intel_devices; idev; idev = idev->next) {
|
|
 |
2ddfcf |
+ if (dev_path && strstr(dev_path, idev->path)) {
|
|
 |
2ddfcf |
+ hba = idev;
|
|
 |
2ddfcf |
+ break;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+ if (dev_path)
|
|
 |
2ddfcf |
free(dev_path);
|
|
 |
2ddfcf |
|
|
 |
2ddfcf |
- if (hba_path) {
|
|
 |
2ddfcf |
- for (dev = info->next; dev; dev = dev->next) {
|
|
 |
2ddfcf |
- if (!devt_attached_to_hba(makedev(dev->disk.major,
|
|
 |
2ddfcf |
- dev->disk.minor), hba_path)) {
|
|
 |
2ddfcf |
- pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n"
|
|
 |
2ddfcf |
- " This operation is not supported and can lead to data loss.\n");
|
|
 |
2ddfcf |
- return 1;
|
|
 |
2ddfcf |
- }
|
|
 |
2ddfcf |
+ if (!hba) {
|
|
 |
2ddfcf |
+ pr_err("WARNING - Cannot detect HBA for device %s!\n",
|
|
 |
2ddfcf |
+ devid2kname(makedev(info->disk.major, info->disk.minor)));
|
|
 |
2ddfcf |
+ return 1;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id);
|
|
 |
2ddfcf |
+ struct mdinfo *dev;
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ for (dev = info->next; dev; dev = dev->next) {
|
|
 |
2ddfcf |
+ dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor));
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ struct sys_dev *hba2 = NULL;
|
|
 |
2ddfcf |
+ for (idev = intel_devices; idev; idev = idev->next) {
|
|
 |
2ddfcf |
+ if (dev_path && strstr(dev_path, idev->path)) {
|
|
 |
2ddfcf |
+ hba2 = idev;
|
|
 |
2ddfcf |
+ break;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
+ if (dev_path)
|
|
 |
2ddfcf |
+ free(dev_path);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ const struct imsm_orom *orom2 = hba2 == NULL ? NULL :
|
|
 |
2ddfcf |
+ get_orom_by_device_id(hba2->dev_id);
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (hba2 && hba->type != hba2->type) {
|
|
 |
2ddfcf |
+ pr_err("WARNING - HBAs of devices do not match %s != %s\n",
|
|
 |
2ddfcf |
+ get_sys_dev_type(hba->type), get_sys_dev_type(hba2->type));
|
|
 |
2ddfcf |
+ return 1;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (orom != orom2) {
|
|
 |
2ddfcf |
+ pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n"
|
|
 |
2ddfcf |
+ " This operation is not supported and can lead to data loss.\n");
|
|
 |
2ddfcf |
+ return 1;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
+ if (!orom) {
|
|
 |
2ddfcf |
+ pr_err("WARNING - IMSM container assembled with disks under HBAs without IMSM platform support!\n"
|
|
 |
2ddfcf |
+ " This operation is not supported and can lead to data loss.\n");
|
|
 |
2ddfcf |
+ return 1;
|
|
 |
2ddfcf |
+ }
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
+
|
|
 |
2ddfcf |
return 0;
|
|
 |
2ddfcf |
}
|
|
 |
2ddfcf |
#ifndef MDASSEMBLE
|
|
 |
2ddfcf |
--
|
|
 |
2ddfcf |
2.4.3
|
|
 |
2ddfcf |
|