Jump to content
Mork vom Ork

Patch for using NVMe under macOS Sierra is ready.

1,380 posts in this topic

Recommended Posts

Hi all, if someone is intrested here I made a tiny command line to show s.m.a.r.t. attributes also for nvme disks. Soon the code will be ported to the HWMonitor project, but I need tests as much as possible. Thanks and sorry for the OT

Share this post


Link to post
Share on other sites
Advertisement
On 12/26/2017 at 2:43 PM, dsarch said:

Hey! Now it is working =)

 

Jake Lo from osxlatitude.com helped me...

 

The problem is that I didn't created the patched DSDTs to go with SSDT_NVMe-Pcc.aml

 

Here is the complete clover folder for a Dell e7270 in case someone needs it.

 

E7270_NVME_10.12.6_dsarch.zip

 

Thanks =)

would you help me too  pls.. what do we do with ssdt nvme-pcc.aml

Share this post


Link to post
Share on other sites
On 7/14/2017 at 10:39 AM, jsl said:

Thanks which worked for Plextor M8PeG M.2 device.

Do you know how to fix Adata XPG SX8000 PCIe Gen3x4 M.2 2280 SSD ?

http://www.xpg.com/en/feature/423

Previous firmware version 2.1.3 was not compatible with Mac OS X at all.

Only newest version firmware 2.3.19 is compatible to 10.12.6 and 10.13.x.

 

Screen Shot 2018-04-17 at 12.32.38 PM.png

Edited by jsl2000
change attached photo

Share this post


Link to post
Share on other sites

Hello,

Help is much appreciated. I got Sierra 10.12.6 work with Pike's 17 patches. The MD5 doesn't match but tried it anyways.  Trying HackrNVMeFamily-10_12_6-spoof.kext works. Class Code now show  ff 08 01 00.

 

Does this mean everything works even with mismatched MD5?

Share this post


Link to post
Share on other sites
10 hours ago, ursdbz said:

Hello,

Help is much appreciated. I got Sierra 10.12.6 work with Pike's 17 patches. The MD5 doesn't match but tried it anyways.  Trying HackrNVMeFamily-10_12_6-spoof.kext works. Class Code now show  ff 08 01 00.

 

Does this mean everything works even with mismatched MD5?

 

You should run patch_nvme.sh with no parameters... (only --spoof).  This will let it pick the correct plist for patching.

Share this post


Link to post
Share on other sites

Tried it again but still gave me mismatched MD5. If i forced to use it, it still works. and ioreg show ff 08 01 00.

Screen Shot 2018-05-12 at 9.06.48 AM.png

Screen Shot 2018-05-12 at 9.07.20 AM.png

Share this post


Link to post
Share on other sites
39 minutes ago, ursdbz said:

Tried it again but still gave me mismatched MD5. If i forced to use it, it still works. and ioreg show ff 08 01 00.

Screen Shot 2018-05-12 at 9.06.48 AM.png

Screen Shot 2018-05-12 at 9.07.20 AM.png


The log you provided clearly shows no mismatch.  In fact, it says "matches expected MD5".

Why do you think there is a mismatch?

Share this post


Link to post
Share on other sites

i guess i didn't read it clearly. i thought the 2 md5 need to match. As they are vanilla vs patched MD5. Does this spoof method allows nvme to sleep or not (or power management to save 1w)? Thanks for pointing it out.

What is the main advantage of this method over pike's other than this is more up to date?

Edited by ursdbz

Share this post


Link to post
Share on other sites
2 hours ago, ursdbz said:

i guess i didn't read it clearly. i thought the 2 md5 need to match. As they are vanilla vs patched MD5. Does this spoof method allows nvme to sleep or not (or power management to save 1w)? Thanks for pointing it out.

What is the main advantage of this method over pike's other than this is more up to date?

 

There are two "expected" md5 values... one prior to patching, and one after patching (note that if the pre-patch one matches, the post-patch always will match, unless I made some sort of mistake in the plist).

 

HackrNVMeFamily spoofing has nothing to do with NVMe power management.

Share this post


Link to post
Share on other sites
On 5/12/2018 at 7:11 PM, ursdbz said:

Tried it again but still gave me mismatched MD5. If i forced to use it, it still works. and ioreg show ff 08 01 00.

Screen Shot 2018-05-12 at 9.06.48 AM.png

Screen Shot 2018-05-12 at 9.07.20 AM.png

4k drive. just in case, to make thungs easier....

Share this post


Link to post
Share on other sites

Finally solved the KP when using ./patch_nvme.sh (w/o --spoof) if vanilla IONVMEFamily.kext exist.

 

Rehabman modified the Info.plist that causes panic if vanilla IONVMEFamily.kext exist.

			<key>CFBundleIdentifier</key>
			<string>com.apple.hack.HackrNVMeFamily</string>

 I changed it back to Apple's original:

			<key>CFBundleIdentifier</key>
			<string>com.apple.iokit.IONVMeFamily</string>

Now no more KP even IONVMEFamily.kext exist!. I don't even have to use the --spoof or the SSDT_NVMe-Pcc.aml

 

NOTE: This work in /L/E or /S/L/E only!

Edited by ellaosx

Share this post


Link to post
Share on other sites

Hello RehabMan / Others involved,


Regarding the Plextor/LiteOn/Hynix "special patch", I see it mentioned as "IONVMeFamily Preferred Block Size patch".

However I can't see the relation of this patch to block size (I think the description is wrong), and I also don't understand why we need 4 variants (0x01, 0x02, 0x04, 0x08).

 

If we look at what we are patching (for High Sierra, which by the way is the same for Mojave Beta1): 

...
8A 48 1A (mov cl, byte [rax+0x1a])
F6 C1 10 (test cl, 0x10)
0F 85 41 01 00 00 (jne some_32bit_offset)
80 E1 0F (and cl, 0xf)
0F B6 C9 (movzx ecx, cl)
...

 

The test in this code is on byte 26 (0x1a) of the Identify Namespace, which represents Formatted LBA Size (FLBAS). Its structure is something like this:

struct {
    UCHAR   LbaFormatIndex              : 4;
    UCHAR   MetadataInExtendedDataLBA   : 1;
    UCHAR   Reserved                    : 3;
} FLBAS;    // byte 26    M - Formatted LBA Size (FLBAS)

Bits 3-0 indicate the index of the chosen format variant for the namespace, and Bit 4 indicates whether metadata for a command is transferred as part of an extended data LBA.

The test instruction of original code checks if Bit 4 (0x10) of FLBAS is set to 1 (this bit corresponds to MetadataInExtendedDataLBA), and if it is, the jne instruction performs the jump.

 

The problem here is that OSX decides that metadata should be used, only by the data at byte 26 (FLBAS), which these drives don't properly respect, and doesn't perform further checks.

Linux driver, for example, takes that value into consideration only if the active LBA Format data structure has MS (metadata size) > 0:

NVME_NS_FLBAS_LBA_MASK = 0xf;
NVME_NS_FLBAS_META_EXT = 0x10;
...
ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);  
ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);

 

Or another possible place to check, would be byte 27 of the Identify Namespace (MC), that shows the metadata capabilities (but not necessarily the active setting):

struct {
    UCHAR MetadataInExtendedDataLBA : 1;
    UCHAR MetadataInSeperateBuffer : 1;
    UCHAR Reserved : 6;
} MC;    // byte 27    M - Metadata Capabilities (MC)

 

Under linux, we can easily see the inconsistency for this drive:

$ sudo nvme id-ns /dev/nvme0n1
NVME Identify Namespace 1:
...
flbas   : 0x11
mc      : 0
...
lbaf  0 : ms:0   lbads:9  rp:0x1 
lbaf  1 : ms:0   lbads:12 rp:0 (in use)

FLBAS bit 4 is set to 1, but MC bit 0 is set to 0. We can also see the two available LBA formats (512 and 4K), none of which allows metadata (ms=0, which stands for metadata size, clearly means unsupported)

 

So, in the above code (when unpatched), FLBAS bit 4 would trigger the jump, although no metadata is present in extended data LBA, leading to an assert (as probably OSX NVME driver doesn't support such metadata).

 

Anyway, about the proposed patch: it is clear that in the patch we reverse bit 4 (0x10) of FLBAS to disable checking for metadata, but my question is, why additionally in the presented patch variants we also add tests on bits 0-3 of FLBAS, which may just trigger as well the assert? (each of the 4 variants 0x01 0x02, 0x04, 0x08 adds a test on one of the bits 0-3, when the original check does not test at all against LbaFormatIndex, so I can't really see the logic in that). It is clear that the "proper" solution would be to add further checks for metadata presence, but as the intention here seems just to disable checking for metadata, why not, for example, just reverse bit 4 (0x00) instead of all the variants? This would result in something like this, and should work for all cases (the relevant code is the same for 10.12.x->10.14b1):

      <dict>
        <key>Comment</key>
        <string>IONVMeFamily: Ignore FLBAS bit:4 being set - for Plextor/LiteOn/Hynix</string>
        <key>Disabled</key>
        <false/>
        <key>Name</key>
        <string>IONVMeFamily</string>
        <key>Find</key>
        <data>SBr2wRAPhQ==</data>
        <key>Replace</key>
        <data>SBr2wQAPhQ==</data>
      </dict>

 

 

Edit (Feb 2019): Updated the Find/Replace pattern above to be compatible also with the coming 10.14.4 (it remains compatible also with older versions), as the underlying code described at the beginning of this post was changed into the following equivalent:

...
0F B6 48 1A (movzx ecx, byte [rax+0x1a])
F6 C1 10 (test cl, 0x10)
0F 85 44 01 00 00 (jne some_32bit_offset)
83 E1 0F (and ecx, 0xf)
...

 

Edited by Pene

Share this post


Link to post
Share on other sites
On 3/3/2017 at 9:35 PM, nos1609 said:

Small update

List of suitable NVMe SSDs for that conversion:

  • Toshiba XG3
  • Toshiba XG4
  • Toshiba XG5
  • Toshiba XG5-P
  • OCZ RD400
  • Intel SSD750
  • WD Black PCIe SSD
  • WD Black NVMe SSD
  • SanDisk Extreme PRO M 2 NVMe 3D
  • SK Hynix PC300
  • SK Hynix PC401
  • Kingston KC1000

 

Just for the list, the Plextor M9Pe is also 4K capable for this conversion (the older Plextor M8Pe is not!)

 

I also updated my post above with some further information, among which the available formats for this drives can be seen.

Edited by Pene

Share this post


Link to post
Share on other sites
On 6/7/2018 at 3:58 PM, Pene said:

Hello RehabMan / Others involved,


Regarding the Plextor/LiteOn/Hynix "special patch", I see it mentioned as "IONVMeFamily Preferred Block Size patch".

However I can't see the relation of this patch to block size (I think the description is wrong), and I also don't understand why we need 4 variants (0x01, 0x02, 0x04, 0x08).

 

If we look at what we are patching (for High Sierra, which by the way is the same for Mojave Beta1): 


...
8A 48 1A (mov cl, byte [rax+0x1a])
F6 C1 10 (test cl, 0x10)
0F 85 41 01 00 00 (jne some_32bit_offset)
80 E1 0F (and cl, 0xf)
0F B6 C9 (movzx ecx, cl)
...

 

The test in this code is on byte 26 (0x1a) of the Identify Namespace, which represents Formatted LBA Size (FLBAS). Its structure is something like this:


struct {
    UCHAR   LbaFormatIndex              : 4;
    UCHAR   MetadataInExtendedDataLBA   : 1;
    UCHAR   Reserved                    : 3;
} FLBAS;    // byte 26    M - Formatted LBA Size (FLBAS)

Bits 3-0 indicate the index of the chosen format variant for the namespace, and Bit 4 indicates whether metadata for a command is transferred as part of an extended data LBA.

The test instruction of original code checks if Bit 4 (0x10) of FLBAS is set to 1 (this bit corresponds to MetadataInExtendedDataLBA), and if it is, the jne instruction performs the jump.

 

The problem here is that OSX decides that metadata should be used, only by the data at byte 26 (FLBAS), which these drives don't properly respect, and doesn't perform further checks.

Linux driver, for example, takes that value into consideration only if the active LBA Format data structure has MS (metadata size) > 0:


NVME_NS_FLBAS_LBA_MASK = 0xf;
NVME_NS_FLBAS_META_EXT = 0x10;
...
ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);  
ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);

 

Or another possible place to check, would be byte 27 of the Identify Namespace (MC), that shows the metadata capabilities (but not necessarily the active setting):


struct {
    UCHAR MetadataInExtendedDataLBA : 1;
    UCHAR MetadataInSeperateBuffer : 1;
    UCHAR Reserved : 6;
} MC;    // byte 27    M - Metadata Capabilities (MC)

 

Under linux, we can easily see the inconsistency for this drive:


$ sudo nvme id-ns /dev/nvme0n1
NVME Identify Namespace 1:
...
flbas   : 0x11
mc      : 0
...
lbaf  0 : ms:0   lbads:9  rp:0x1 
lbaf  1 : ms:0   lbads:12 rp:0 (in use)

FLBAS bit 4 is set to 1, but MC bit 0 is set to 0. We can also see the two available LBA formats (512 and 4K), none of which allows metadata (ms=0, which stands for metadata size, clearly means unsupported)

 

So, in the above code (when unpatched), FLBAS bit 4 would trigger the jump, although no metadata is present in extended data LBA, leading to an assert (as probably OSX NVME driver doesn't support such metadata).

 

Anyway, about the proposed patch: it is clear that in the patch we reverse bit 4 (0x10) of FLBAS to disable checking for metadata, but my question is, why additionally in the presented patch variants we also add tests on bits 0-3 of FLBAS, which may just trigger as well the assert? (each of the 4 variants 0x01 0x02, 0x04, 0x08 adds a test on one of the bits 0-3, when the original check does not test at all against LbaFormatIndex, so I can't really see the logic in that). It is clear that the "proper" solution would be to add further checks for metadata presence, but as the intention here seems just to disable checking for metadata, why not, for example, just reverse bit 4 (0x00) instead of all the variants? This would result in something like this, and should work for all cases (the relevant code is the same for 10.12.x->10.14b1):


      <dict>
        <key>Comment</key>
        <string>IONVMeFamily: Ignore FLBAS bit:4 being set - for Plextor/LiteOn/Hynix</string>
        <key>Disabled</key>
        <false/>
        <key>Name</key>
        <string>IONVMeFamily</string>
        <key>Find</key>
        <data>ikga9sEQ</data>
        <key>Replace</key>
        <data>ikga9sEA</data>
      </dict>

 

 

I added your proposed patch to config_patches.plist in the patch-nvme github.

I don't have the hardware to test, but now the patch is easily available and called out in the README if someone wishes to test it.

Share this post


Link to post
Share on other sites

Thanks, it's good audience!

I was more hoping for a reply regarding the reason for having the at all multiple variants in the original patch and its relation to "block size", but this is good nonetheless :)

Share this post


Link to post
Share on other sites
3 hours ago, Pene said:

Thanks, it's good audience!

I was more hoping for a reply regarding the reason for having the at all multiple variants in the original patch and its relation to "block size", but this is good nonetheless :)

 

That is a question for PikeRAlpha...  They are his patches.

Share this post


Link to post
Share on other sites
On 6/8/2018 at 6:58 AM, Pene said:

Hello RehabMan / Others involved,


Regarding the Plextor/LiteOn/Hynix "special patch", I see it mentioned as "IONVMeFamily Preferred Block Size patch".

However I can't see the relation of this patch to block size (I think the description is wrong), and I also don't understand why we need 4 variants (0x01, 0x02, 0x04, 0x08).

 

If we look at what we are patching (for High Sierra, which by the way is the same for Mojave Beta1): 


...
8A 48 1A (mov cl, byte [rax+0x1a])
F6 C1 10 (test cl, 0x10)
0F 85 41 01 00 00 (jne some_32bit_offset)
80 E1 0F (and cl, 0xf)
0F B6 C9 (movzx ecx, cl)
...

 

The test in this code is on byte 26 (0x1a) of the Identify Namespace, which represents Formatted LBA Size (FLBAS). Its structure is something like this:


struct {
    UCHAR   LbaFormatIndex              : 4;
    UCHAR   MetadataInExtendedDataLBA   : 1;
    UCHAR   Reserved                    : 3;
} FLBAS;    // byte 26    M - Formatted LBA Size (FLBAS)

Bits 3-0 indicate the index of the chosen format variant for the namespace, and Bit 4 indicates whether metadata for a command is transferred as part of an extended data LBA.

The test instruction of original code checks if Bit 4 (0x10) of FLBAS is set to 1 (this bit corresponds to MetadataInExtendedDataLBA), and if it is, the jne instruction performs the jump.

 

The problem here is that OSX decides that metadata should be used, only by the data at byte 26 (FLBAS), which these drives don't properly respect, and doesn't perform further checks.

Linux driver, for example, takes that value into consideration only if the active LBA Format data structure has MS (metadata size) > 0:


NVME_NS_FLBAS_LBA_MASK = 0xf;
NVME_NS_FLBAS_META_EXT = 0x10;
...
ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);  
ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);

 

Or another possible place to check, would be byte 27 of the Identify Namespace (MC), that shows the metadata capabilities (but not necessarily the active setting):


struct {
    UCHAR MetadataInExtendedDataLBA : 1;
    UCHAR MetadataInSeperateBuffer : 1;
    UCHAR Reserved : 6;
} MC;    // byte 27    M - Metadata Capabilities (MC)

 

Under linux, we can easily see the inconsistency for this drive:


$ sudo nvme id-ns /dev/nvme0n1
NVME Identify Namespace 1:
...
flbas   : 0x11
mc      : 0
...
lbaf  0 : ms:0   lbads:9  rp:0x1 
lbaf  1 : ms:0   lbads:12 rp:0 (in use)

FLBAS bit 4 is set to 1, but MC bit 0 is set to 0. We can also see the two available LBA formats (512 and 4K), none of which allows metadata (ms=0, which stands for metadata size, clearly means unsupported)

 

So, in the above code (when unpatched), FLBAS bit 4 would trigger the jump, although no metadata is present in extended data LBA, leading to an assert (as probably OSX NVME driver doesn't support such metadata).

 

Anyway, about the proposed patch: it is clear that in the patch we reverse bit 4 (0x10) of FLBAS to disable checking for metadata, but my question is, why additionally in the presented patch variants we also add tests on bits 0-3 of FLBAS, which may just trigger as well the assert? (each of the 4 variants 0x01 0x02, 0x04, 0x08 adds a test on one of the bits 0-3, when the original check does not test at all against LbaFormatIndex, so I can't really see the logic in that). It is clear that the "proper" solution would be to add further checks for metadata presence, but as the intention here seems just to disable checking for metadata, why not, for example, just reverse bit 4 (0x00) instead of all the variants? This would result in something like this, and should work for all cases (the relevant code is the same for 10.12.x->10.14b1):


      <dict>
        <key>Comment</key>
        <string>IONVMeFamily: Ignore FLBAS bit:4 being set - for Plextor/LiteOn/Hynix</string>
        <key>Disabled</key>
        <false/>
        <key>Name</key>
        <string>IONVMeFamily</string>
        <key>Find</key>
        <data>ikga9sEQ</data>
        <key>Replace</key>
        <data>ikga9sEA</data>
      </dict>

 

 

Hi all,

 

I use IONVMeFamily: Ignore FLBAS bit:4 being set Patch and it works great on 10.13.5,10.13.6 for my Plextor M8P and M9P NVMe SSD (512G, 1T) on MBPR 2016 15"

however, I change my laptop these week to MBPR 2018 15"

with the same patch, it doesn;t work... and I can't figure out what the reason.

Does anyone have some ideas about it..? Thanks!

 

Attachment is my IOREG screenshot.

螢幕快照 2018-08-27 下午4.03.28.jpg

螢幕快照 2018-08-27 下午4.03.36.jpg

Share this post


Link to post
Share on other sites

Hi. I am just about to install Sierra on a Sabertooth x79 build with Intel 750 400GB. I have attached the Info.plist and version.plist from the installer. I believe its version 10.12.6 - 3 

Could someone give me the patched kext ?

Alternatively, could someone state how I could  patch it myself as the script does not detect it ?

Info.plist

version.plist

IONVMeFamily.kext.zip

Edited by zcream

Share this post


Link to post
Share on other sites

All good. 10_12_6 worked. I extracted the original kext using pacifist.

 

./patch_nvme.sh --unpatched /Users/admin/Desktop/IONVMeFamily.kext 10_12_6

Creating patched HackrNVMeFamily-10_12_6.kext from /Users/admin/Desktop/IONVMeFamily.kext

Vanilla MD5 matches expected MD5 entry (c506f1fc40026c0262a736f0be318223)

Patched MD5 matches expected MD5 entry (ff9c55bf11e522dd86e3dc5b2df7ff24)

Share this post


Link to post
Share on other sites

RehabMan, your guide is amazing!

Using your spoofed method, I have my x99 build booting off a new Samsung 960 Evo!

I have a question regarding using a second NVMe drive though. First let me detail a few things out.

Hardware:
x99eWS/USB3.1
5960x
GTX 960 in PCIe_3
Samsung 960 Evo in M.2 Slot
Intel P3500 in a PCIe riser card in PCIe_1
Booting (for now) from a SATA SSD.

Running 10.12.6.

Using the spoof kext + ssdt method, I had the system recognizing and booting great off the 960 Evo.

When I added the Intel P3500, the system would kernel panic midway through the apple logo load, so I switched back to a standard SSD with no ssdt associated with nvme patching. Once I did that, the system booted and automatically detected the P3500, although it was seen as an external drive. Then I did the following:

1) Use IOreg to find the ACPI path to the Intel P3500. This was tricky because of the PCI switch it is behind.
2) Craft a new nvme-ssdt to inject (code below).
3) Reboot.

However, when I do this, my Samsung 960 Evo goes back to working perfectly, but now the Intel P3500 doesn't show up as a block storage device. I'm confident that I created the nvme-ssdt properly, since the system no longer kernel panics on boot, and since IOreg seems to find both devices just fine. Have I done something wrong?

 

DefinitionBlock ("", "SSDT", 2, "hack", "NVMe-Pcc", 0x00000000)
{
    External (_SB_.PCI0.BR1B.H000, DeviceObj)    // (from opcode)
    External (_SB_.PCI0.BR2A.H000, DeviceObj)    // (from opcode)

    Device (_SB.PCI0.BR2A.H000.PBR8)
    {
        Name (_ADR, 0x00080000)  // _ADR: Address
        Device (SSD0)
        {
            Name (_ADR, Zero)  // _ADR: Address
        }
    }

    Method (_SB.PCI0.BR2A.H000.PBR8.SSD0._DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
    {
        If (LNot (Arg2))
        {
            Return (Buffer (One)
            {
                 0x03                                           
            })
        }

        Return (Package (0x04)
        {
            "class-code", 
            Buffer (0x04)
            {
                 0xFF, 0x08, 0x01, 0x00                         
            }, 

            "built-in", 
            Buffer (One)
            {
                 0x00                                           
            }
        })
    }

    Method (_SB.PCI0.BR1B.H000._DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
    {
        If (LNot (Arg2))
        {
            Return (Buffer (One)
            {
                 0x03                                           
            })
        }

        Return (Package (0x04)
        {
            "class-code", 
            Buffer (0x04)
            {
                 0xFF, 0x08, 0x01, 0x00                         
            }, 

            "built-in", 
            Buffer (One)
            {
                 0x00                                           
            }
        })
    }
}

 

Default IOreg1.png

Default IOreg2.png

hackrnvme spoof1.png

hackrnvme spoof2.png

Share this post


Link to post
Share on other sites

Trying to format my wd black in linux and getting this error.

 

NVME Admin command error:ACCESS_DENIED: Access to the namespace and/or LBA range is denied due to lack of access rights(4286)

 

 

Share this post


Link to post
Share on other sites

Hi guys, 

 

I'm kinda new to hack-intoshing... :D

I just managed to build a PC which is succesfully running Mojave, with ASUS Prime Z370-a board. I just purchased a SK-Hynix PC300 NVMe drive. It shows up in bios, but macOS can not see it. Could anyone explain how could I fix it?

thank you

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×