Jump to content

Patch for using NVMe under macOS Sierra is ready.


1,382 posts in this topic

Recommended Posts

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

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.

  • Like 1
Link to comment
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?

  • Like 1
Link to comment
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
Link to comment
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.

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

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
Link to comment
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
  • Like 2
  • Thanks 4
Link to comment
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
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...
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

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

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

  • 3 weeks later...
  • 1 month later...
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

Link to comment
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
Link to comment
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)

Link to comment
Share on other sites

  • 2 weeks later...

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

Link to comment
Share on other sites

  • 4 weeks later...
  • 2 months later...
  • 2 weeks later...

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

Link to comment
Share on other sites

  • 1 month later...

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 by vicsandr
Link to comment
Share on other sites

 Share

×
×
  • Create New...