Thunderbolt 3 very likely, but not confirmed yet…

I had only read the title of this article macOS Sierra Code Confirms Thunderbolt 3 and 10Gb/s USB 3.1 Transfer Speeds in Future Macs) from macrumors.com (brought to you by 9to5mac.com) and boy was I surprised. I thought that I had missed something. Then I fired up my data scraper and… found nothing!

Ehm. Guys. Where is this mysterious “Thunderbolt 3” string?

Fact checkers can verify this themselves by following this simple procedure:

1.) cd /S*/L*/SystemProfiler/SPThunderboltReporter.spreporter/C*/R*/English.lproj
2.) sudo plutil -convert xml1 Localizable.strings
3.) open Localizable.strings

Lo and behold:

	<key>Up to 10 Gb/s x1</key>
	<string>Up to 10 Gb/s x1</string>
	<key>Up to 10 Gb/s x2</key>
	<string>Up to 10 Gb/s x2</string>
	<key>Up to 20 Gb/s x1</key>
	<string>Up to 20 Gb/s x1</string>
	<key>Up to 20 Gb/s x2</key>
	<string>Up to 20 Gb/s x2</string>

That is what I found there. There is no 40 Gb/s x4 or anything.

So let’s check out what Jeff Benjamin actually wrote:

For example, it’s possible that we could see support for Thunderbolt 3 in the highly anticipated MacBook Pro refresh. It’s worth noting that 10 Gbps USB 3.1 Gen 2 is built in to Thunderbolt 3.

I agree. That is very well possible. Perhaps even likely since Thunderbolt is a highly anticipated feature, but what macrumors.com concluded is not correct. You cannot conclude that from that data. To me it’s more like this; The minute we find references of Kaby Lake… then Thunderbolt 3 is confirmed, but for now… everything is still speculation.

Note: The “Up to 10 Gb/sec” string can be found in:
/S*/L*/SystemProfiler/SPUSBReporter.spreporter/C*/R*/English.lproj/Localizable.strings

Update: Take a look at the next picture. Taken from an Intel slide:
IntelConfirmsThunderbolt3ForApple.
You could say that this confirms that the next MacBook (Pro) will come with Thunderbolt 3 support, and it is very likely, but we don’t know for what model(s) and what processor it will use. Only Apple knows…

macOS Sierra uses new boot args structure…

I compiled RevoBoot on macOS Sierra with the latest Xcode-Beta command line tools installed but instead of booting it immediately rebooted.

Went on looking for the problem and it turned out to be a simple boot args change. Yup. We now have two Boot Video structures:

/*
 * Video information.. 
 */

struct Boot_VideoV1 {
	uint32_t	v_baseAddr;	/* Base address of video memory */
	uint32_t	v_display;	/* Display Code (if Applicable */
	uint32_t	v_rowBytes;	/* Number of bytes per pixel row */
	uint32_t	v_width;	/* Width */
	uint32_t	v_height;	/* Height */
	uint32_t	v_depth;	/* Pixel Depth */
};
typedef struct Boot_VideoV1	Boot_VideoV1;

struct Boot_Video {
	uint32_t	v_display;	/* Display Code (if Applicable */
	uint32_t	v_rowBytes;	/* Number of bytes per pixel row */
	uint32_t	v_width;	/* Width */
	uint32_t	v_height;	/* Height */
	uint32_t	v_depth;	/* Pixel Depth */
	uint32_t	v_resv[7];	/* Reserved */
	uint64_t	v_baseAddr;	/* Base address of video memory */
};
typedef struct Boot_Video	Boot_Video;

Boot_VideoV1 basically replaces the old Boot_Video and is used for backward compatibility. The new Boot_Video structure has slightly changed. The first thing you should notice is that there is a new reserved field, for seven 32-bit variables. The second change is that this new structure now uses a 64-bit VRAM address instead of a 32-bit address. Possibly only used by new Apple hardware with a new version of their own EFI.

Anyway. I made the changes for RevoBoot in bootstruct.h and a couple of other files and I also fixed it for the macosxbootloader.

Great. No reboot anymore.

The winner of the #1 give away is…

The e-mail to the winner was sent a minute ago. Yes. You are the lucky one; Vince

You have 48 hours to reply to the e-mail and provide a shipping address!

Edit: Sorry. I made a typo in the name. It is Vince instead of Vance.

p.s. To the rest of you… note the #1 in the title. Good luck next time. It probably won’t be as big as this one. Not without sponsors😉

Update: Vince replied in time, but he is on holiday – on a campsite – and he won’t return before August 23. Ok. No problem. We will store the box for you and ship it the day after we return from our holiday.

XCPM Screenshots of i7-6850K

Someone e-mailed me and asked me if XCPM is really working. Sure. Let me grab some pictures for you. Hold on. Working remotely here…

Idle
Let’s start with a picture of the processor running idle at less than 3 Watts.
Intel_i7_6850K_Idle
I have seen it run at an even lower wattage, but it is hard to capture (working remotely here).

Normal
Here is a picture of the processor after a Geekbench 3 test run.
Intel_i7_6850K_Normal
Pretty normal read out but…

Sustained Turbo
Some people are looking for a sustained turbo ratio, and that is possible with a trick.
Intel_i7_6850K_SustainedTurbo
But I am not going to tell you how that is done. For one simple reason…

Smoked
No. You really shouldn’t see something like this.
Intel_i7_6900K_Smoked
Running hot for a long period of time will degrade your processor, and eventually it will get smoked. Totally. Sans warranty from Intel I suppose.

Say what? Yup. That’s about it for now.

Quirks:

1.) When I select the XMP profile in the BIOS, then the Current Package Power in the Intel Power Gadget is broken. Far too low. Like 0.6W instead of a normal value.

Idle without C-States
IntelPowerGadget_CStatesFailure
Here we see that the Temperature in centigrade and the Power usage in Watt is higher without C-States enabled.

Checks for two unused processor models found…

Well hello. I almost forgot to share something with you, and that is that I found processor checks in macOS Sierra DP4 for two unused Intel processors. And it’s still there in DP5.

Ok. One check is definitely for a Broadwell based processor – follows the same path – and the other either for a Skylake based processor, or perhaps a Kaby Lake processor. Thing is. The latter shares a lot with Skylake (based) processors, and there isn’t a whole lot of code that we can check, so this one is still a bit of a mystery to me.

Now you ask; When and where did you find it Pike?

You (should) know that I added XCPM support for unsupported Processors for the new Broadwell E processors, and people reported succes with Haswell E and other (slightly older) processor models as well. That was when my eye first caught the checks. I first mentioned it in the comments section (see my reply to racermaster). Now take a look at the next image:

What Apple does is to set a bit in the CPU-bits field for every processor that supports the MSR. The selection is made based on the processor model number in _xcpm_bootstrap, and here is what Apple currently uses for XCPM supported processor models:

Haswell (0x3c) = 0x04
Crystalwell (0x46) = 0x08
Haswell-ULT (0x45) = 0x10
Broadwell-H (0x47) = 0x40
Broadwell (0x3d) = 0x80
Skylake (0x4e) = 0x200
Skylake-DT (0x5e) = 0x1000

Currently there is no model check for 0x100 and 0x2000 in _xcpm_bootstrap, but they do get checked in _xcpm_init_complete and _xcpm_monitor_init. The bits corresponding to 0x100 and 0x2000 are also set in most of the programmed MSRs (data from DP4).

xxd -s 0x82d010 -l 528 -u /System/Library/Kernels/kernel

//
// _xcpm_SMT_scope_msrs
//
0082D010: 2E 00 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D020: 00 04 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D030: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D040: A0 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D050: 00 00 00 00 | 40 00 00 00 | 01 00 05 00 | 00 00 00 00
0082D060: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D070: B0 01 00 00 | 90 01 00 00 | 00 00 00 00 | 00 00 00 00
0082D080: 0F 00 00 00 | 00 00 00 00 | 0F 00 00 00 | 00 00 00 00
0082D090: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D0A0: B0 01 00 00 | 4C 22 00 00 | 00 00 00 00 | 00 00 00 00
0082D0B0: 0F 00 00 00 | 00 00 00 00 | 05 00 00 00 | 00 00 00 00
0082D0C0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D0D0: B0 01 00 00 | 00 10 00 00 | 00 00 00 00 | 00 00 00 00
0082D0E0: 0F 00 00 00 | 00 00 00 00 | 01 00 00 00 | 00 00 00 00
0082D0F0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D100: 09 06 00 00 | 90 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D110: FF 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D120: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D130: 8D 03 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D140: FF FF FF FF | FF FF FF FF | 33 03 00 00 | 00 00 00 00
0082D150: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D160: 8F 03 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D170: FF FF FF FF | FF FF FF FF | 0F 00 00 00 | 07 00 00 00
0082D180: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D190: 87 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D1A0: FF FF FF FF | FF FF FF FF | 24 27 43 00 | 00 00 00 00
0082D1B0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D1C0: 88 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D1D0: FF FF FF FF | FF FF FF FF | D0 81 43 00 | 00 00 00 00
0082D1E0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D1F0: 89 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D200: FF FF FF FF | FF FF FF FF | D0 82 43 00 | 00 00 00 00
0082D210: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

xxd -s 0x82d220 -l 96 -u /System/Library/Kernels/kernel

//
// _xcpm_core_scope_msrs
//
0082D220: E2 00 00 00 | 4C 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D230: 0F 04 00 00 | 00 00 00 00 | 05 00 00 1E | 00 00 00 00
0082D240: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D250: E2 00 00 00 | 90 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D260: 0F 04 00 00 | 00 00 00 00 | 08 00 00 7E | 00 00 00 00
0082D270: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

xxd -s 0x82d280 -l 336 -u /System/Library/Kernels/kernel

//
// _xcpm_pkg_scope_msrs
//
0082D280: A0 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D290: 00 00 00 00 | 40 00 00 00 | 01 00 05 00 | 00 00 00 00
0082D2A0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D2B0: FC 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D2C0: 00 00 10 00 | 00 00 00 00 | 1A 00 04 00 | 00 00 00 00
0082D2D0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D2E0: AA 01 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D2F0: 00 00 00 00 | 00 00 00 00 | 01 00 00 00 | 00 00 00 00
0082D300: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D310: 20 06 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D320: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D330: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D340: 4C 06 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D350: FF 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D360: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D370: 3A 06 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D380: 1F 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0082D390: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

0082D3A0: 42 06 00 00 | DC 33 00 00 | 00 00 00 00 | 00 00 00 00
0082D3B0: 1F 00 00 00 | 00 00 00 00 | 18 00 00 00 | 00 00 00 00
0082D3C0: 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

As you can see here, all but four MSRs include the bits for unused processor models. The big question now is; why? To get ready for new hardware perhaps?

Anyway. It looks like it that 0x100 is reserved for another Broadwell based processor – since that follows the same route as the Broadwell (0x80) processor – and the other value (0x2000) follows the same route as the Skylake (0x200) processor – though knowing Apple… anything is possible. Draw your own conclusions😉

Edit: Clearing a bit for a matching processor model in the CPU-bits field will stop it from being programmed. As in. It won’t write to MSR 0x00 (zero) when you nullify the 32-bit MSR and 32-bit CPU-bits fields. I can’t remember who it was that thought that it worked like that. Fact is. It never did and I told you so back in 2013 (see Update-4).

Here is some pseudo C code from the disassembled routine that programs the MSRs:

void _xcpm_program_msrs(uint8_t * aTableAddress, uint8_t aNumberOfMSRs, uint32_t aTargetMSR)
{
	uint8_t * msr_table		= aTableAddress;

	uint8_t number_of_msrs		= aNumberOfMSRs;

	uint32_t target_msr		= aTargetMSR;

	uint64_t msr_value		= 0;
	uint64_t msr_and_value		= 0;
	uint64_t initial_msr_value	= 0;

	if (number_of_msrs > 0)
	{
		msr_table += 0x28;
		//
		// Main do while loop.
		//
		do
		{
			uint32_t xcpm_cpu_model = *(int32_t *)_xcpm_cpu_model;
			//
			// Checks for matching processor model and target MSR.
			//
			if ( ((*(uint32_t *)(msr_table - 0x24) & xcpm_cpu_model) != 0x0) && 
			     (((target_msr == 0x0) || (*(int32_t *)(msr_table - 0x28) == target_msr))) )
			{
				//
				// Get MSR number field from table.
				//
				int msr = *(uint32_t *)(msr_table - 0x28);

				if (*(int32_t *)0xffffff8000a2ce00 != 0x0)
				{
					printf("xcpm_program_msrs: programming MSR 0x%x\n", msr);
				}
				//
				// Read initial value of MSR.
				//
				initial_msr_value = rdmsr64(msr);
				//
				// Keep value in the "initial value" field.
				//
				*(msr_table - 0x08) = initial_msr_value;
				//
				// Get "AND value" field from table.
				//
				msr_and_value = *(msr_table - 0x18);
				//
				// Update value of MSR (NOT, AND and OR).
				//
				new_msr_value = !initial_msr_value & msr_and_value | *(msr_table - 0x10);
				//
				// Write back modified value of MSR.
				//
				wrmsr64(msr, new_msr_value);
				//
				// Read value of MSR and store it in the "result" field.
				//
				*msr_table = rdmsr64(msr);
			}

			msr_table += 0x30; // Move on to the next MSR.
			number_of_msrs-—; // One MSR less to program.

		} while (number_of_msrs > 0);
	}

	return;
}

This routine is being called from _xcpm_init in the kernel:

ffffff8000428489	leaq	_xcpm_pkg_scope_msrs(%rip), %rdi	// arg0 = address of data block
ffffff8000428490	movl	$0x7, %esi 							// arg1 = 7 (number of MSRs)
ffffff8000428495	xorl	%edx, %edx							// arg2 = 0 (no MSR specified/program all MSRs)
ffffff8000428497	callq	0xffffff8000428130 					// _xcpm_program_msrs subroutine

../..

ffffff80004284b1	leaq	_xcpm_core_scope_msrs(%rip), %rdi	// arg0 = address of data block
ffffff80004284b8	movl	$0x2, %esi 							// arg1 = 2 (number of MSRs)
ffffff80004284bd	xorl	%edx, %edx 							// arg2 = 0 (no MSR specified/program all MSRs)
ffffff80004284bf	callq	0xffffff8000428130 					// _xcpm_program_msrs subroutine

ffffff80004284c4	leaq	_xcpm_SMT_scope_msrs(%rip), %rdi	// arg0 = address of data block
ffffff80004284cb	movl	$0xb, %esi 							// arg1 = 11 (number of MSRs)
ffffff80004284d0	xorl	%edx, %edx 							// arg2 = 0 (no MSR specified/program all MSRs)
ffffff80004284d2	callq	0xffffff8000428130 					// _xcpm_program_msrs subroutine

Note the callq 0xffffff8000428130 because that is the one you are looking for, but be aware of the fact that the addresses are different for each Developer Preview/Public Beta of macOS Sierra.

Everyone appreciates courtesy…

Everyone appreciates courtesy. Don’t you? I for one certainly do but apparently not everyone understands what it takes. The long hours that are required to keep things going. And then to remove my name from my patches… tsk tsk. That is not done.

I don’t care if it is done deliberately or not. I don’t care of you are stupid, ignorant or a tard. If you use my work, then you need to keep my name in there, or everyone will eventually pay the price for it.

Remember. My policy is one of zero tolerance!

Thanks!

IONVMeFamily.kext changes in Sierra DP4 (build 16A270f)

Here is the slightly modified data that you can use in your KernelAndKextPatches section of Clover config for macOS Sierra DP4:

	<key>KextsToPatch</key>
	<array>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#1</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>ibPwAgAAweAMBQAQAACJgw==</data>
			<key>Replace</key>
			<data>ibPwAgAAweAJBQAQAACJgw==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#2</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>D7aMiIIAAACD+QwPhTIBAA==</data>
			<key>Replace</key>
			<data>D7aMiIIAAACD+QkPhTIBAA==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#3</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>AMeDpAAAAAAQAABIi0gISA==</data>
			<key>Replace</key>
			<data>AMeDpAAAAAACAABIi0gISA==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#4</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>SYnGTYX2dGFBwecMSWP/vg==</data>
			<key>Replace</key>
			<data>SYnGTYX2dGFBwecJSWP/vg==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#5</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>hv8PAABIwegMD7cPgeH/Dw==</data>
			<key>Replace</key>
			<data>hv8PAABIwegJD7cPgeH/Dw==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#6_7</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>icGB4f8PAABIAdFIgfn/DwAAdzs=</data>
			<key>Replace</key>
			<data>icGB4f8BAABIAdFIgfn/AQAAdzs=</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#8</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>SYHF/w8AAEnB7QxJiwQkSA==</data>
			<key>Replace</key>
			<data>SYHF/w8AAEnB7QlJiwQkSA==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#9_10</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>BgIAAEyNuAAQAABMiflIgeEA8P//SYmGGgEAAEmJjiIBAABBvAAQAABJKfQ=</data>
			<key>Replace</key>
			<data>BgIAAEyNuAACAABMiflIgeEA8P//SYmGGgEAAEmJjiIBAABBvAACAABJKfQ=</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#11</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>AABJiY4iAQAAugAQAABIKQ==</data>
			<key>Replace</key>
			<data>AABJiY4iAQAAugACAABIKQ==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#12</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>yAAAAEkp17gAEAAATYskJA==</data>
			<key>Replace</key>
			<data>yAAAAEkp17gAAgAATYskJA==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#13</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>4b+AQBUGTYnWugAQAABFMQ==</data>
			<key>Replace</key>
			<data>4b+AQBUGTYnWugACAABFMQ==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#14</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>iWTY+EmBxAAQAABJgccA8A==</data>
			<key>Replace</key>
			<data>iWTY+EmBxAACAABJgccA8A==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#15</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>Bf8PAABIwegMZvfB/w8PlQ==</data>
			<key>Replace</key>
			<data>Bf8PAABIwegJZvfB/w8PlQ==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#16</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>weIIQQ+2wcHgDEQJ0EQJwA==</data>
			<key>Replace</key>
			<data>weIIQQ+2wcHgCUQJ0EQJwA==</data>
		</dict>
		<dict>
			<key>Comment</key>
			<string>IONVMeFamily Pike R. Alpha Patch#17</string>
			<key>Disabled</key>
			<false/>
			<key>Name</key>
			<string>IONVMeFamily</string>
			<key>Find</key>
			<data>RYTJD5XAD7bAweAMRAnYRA==</data>
			<key>Replace</key>
			<data>RYTJD5XAD7bAweAJRAnYRA==</data>
		</dict>
	</array>

Note that I removed the Info.plist patch, because that is no longer required. Not since DP2 anymore, which is when Apple fixed the IOPCIClassMatch error.

Another thing that changed is the first patch. Ok. It’s only a single byte that changed, but just so that you know what changed.

Edit: I don’t use Clover myself, and I prefer a dummy kext with the patched binary in it. Similar to what I use for AppleHDA8Series.sh but now even cleaner.

You may also want to add the patch to solve the orange drive icon (external drive) and you can do that by adding this patch but you should be using a tiny SSDT with these properties in it. Either that or a modified DSDT.