ursdbz Posted May 12, 2018 Share Posted May 12, 2018 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? Link to comment Share on other sites More sharing options...
RehabMan Posted May 12, 2018 Share Posted May 12, 2018 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. 1 Link to comment Share on other sites More sharing options...
ursdbz Posted May 12, 2018 Share Posted May 12, 2018 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. Link to comment Share on other sites More sharing options...
RehabMan Posted May 12, 2018 Share Posted May 12, 2018 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. The log you provided clearly shows no mismatch. In fact, it says "matches expected MD5". Why do you think there is a mismatch? 1 Link to comment Share on other sites More sharing options...
ursdbz Posted May 12, 2018 Share Posted May 12, 2018 (edited) 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 May 12, 2018 by ursdbz Link to comment Share on other sites More sharing options...
RehabMan Posted May 12, 2018 Share Posted May 12, 2018 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. 2 Link to comment Share on other sites More sharing options...
nos1609 Posted May 26, 2018 Share Posted May 26, 2018 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. 4k drive. just in case, to make thungs easier.... Link to comment Share on other sites More sharing options...
LockDown Posted June 2, 2018 Share Posted June 2, 2018 (edited) 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 June 2, 2018 by ellaosx Link to comment Share on other sites More sharing options...
Pene Posted June 7, 2018 Share Posted June 7, 2018 (edited) 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 February 9, 2019 by Pene 2 4 Link to comment Share on other sites More sharing options...
Pene Posted June 13, 2018 Share Posted June 13, 2018 (edited) 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 June 13, 2018 by Pene 1 1 Link to comment Share on other sites More sharing options...
RehabMan Posted June 25, 2018 Share Posted June 25, 2018 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. Link to comment Share on other sites More sharing options...
Pene Posted June 27, 2018 Share Posted June 27, 2018 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 Link to comment Share on other sites More sharing options...
RehabMan Posted June 28, 2018 Share Posted June 28, 2018 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. Link to comment Share on other sites More sharing options...
kostas1976 Posted July 18, 2018 Share Posted July 18, 2018 (edited) [SOLVED] Hello RehabMan, this is my file witch needs patch. It is Sierra 10.12.6 2018-004 IONVMeFamily.kext.zip Edited August 15, 2018 by kostas1976 Issue solved Link to comment Share on other sites More sharing options...
iapple0520 Posted August 27, 2018 Share Posted August 27, 2018 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. Link to comment Share on other sites More sharing options...
zcream Posted September 3, 2018 Share Posted September 3, 2018 (edited) 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 September 3, 2018 by zcream Link to comment Share on other sites More sharing options...
zcream Posted September 3, 2018 Share Posted September 3, 2018 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) Link to comment Share on other sites More sharing options...
gwincraft Posted September 15, 2018 Share Posted September 15, 2018 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.15960xGTX 960 in PCIe_3Samsung 960 Evo in M.2 SlotIntel P3500 in a PCIe riser card in PCIe_1Booting (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 } }) } } Link to comment Share on other sites More sharing options...
LockDown Posted October 7, 2018 Share Posted October 7, 2018 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) Link to comment Share on other sites More sharing options...
c-3po Posted December 9, 2018 Share Posted December 9, 2018 I believe a new patch is needed for 10.12.6 with Security Update 2018-006 (16G1710). IONVMeFamily_kext_-_10.12.6_(16G1710).zip Link to comment Share on other sites More sharing options...
c-3po Posted December 11, 2018 Share Posted December 11, 2018 On 12/9/2018 at 4:23 PM, c-3po said: I believe a new patch is needed for 10.12.6 with Security Update 2018-006 (16G1710). IONVMeFamily_kext_-_10.12.6_(16G1710).zip Thank you very much. Link to comment Share on other sites More sharing options...
magyara Posted December 23, 2018 Share Posted December 23, 2018 Hi guys, I'm kinda new to hack-intoshing... 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 Link to comment Share on other sites More sharing options...
c-3po Posted January 31, 2019 Share Posted January 31, 2019 A new patch is needed for Security Update 2019-001 (16G1815) of Sierra. Pretty please. IONVMeFamily kext from 16G1815.zip Link to comment Share on other sites More sharing options...
LockDown Posted January 31, 2019 Share Posted January 31, 2019 @c-3po The patches are still the same from the previous one Link to comment Share on other sites More sharing options...
vicsandr Posted February 4, 2019 Share Posted February 4, 2019 (edited) I am attempting to use an OWC Aura Pro X SSD NVMe (Silicon Motion pci126f,2260) on a a PCIe adapter in a MacPro1,1 running MacOS 10.11.6 (15G22010). I built the kext in patch_nvme adding the devid to the script and using the spoof; installed it disabling SIP and modifying the attributes (correctly I think): sudo chmod -R 755 and sudo chown -R root:wheel. Unfortunately System Information/Hardware/PCI shows that the NVM Express Controller device is present but that the driver is not installed. Can someone walk me through the troubleshooting to determine why the kext will not load? Thanks. Edited February 5, 2019 by vicsandr Link to comment Share on other sites More sharing options...
Recommended Posts