Apple IGPU saved-config data

I own two new Mac Book Pro’s. One IGPU only (MacBookPro13,1) and one with a Radeon Pro 460 with 4GB (MacBookPro13,3). Both of them use device-properties to inject saved-config. The injected data is related to the display hardware and I like to find out what that data is and where that it is used. Let’s start with a grep:

grep -r saved-config /System/Library/Extensions

Here is the output:

AMDFramebuffer.kext
AMDSupport.kext
AppleIntelBDWGraphicsFramebuffer.kext
AppleIntelFramebufferAzul.kext
AppleIntelFramebufferCapri.kext
AppleIntelHDGraphicsFB.kext
AppleIntelSKLGraphicsFramebuffer.kext
AppleIntelSNBGraphicsFB.kext
NVDAResman.kext
NVDAResmanTesla.kext
NVDAResmanWeb.kext

This basically tells us the names of the kexts that are using the data, but now we have to find out what the data is. Here is the data that gets injected on the MacBookPro13,3:

47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 06 00 1b 19 00 6c 05
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 00 06 10 30 a0 02
03 40 00 00 00 00 00 00 00 00 02 c0 eb 9a 13 40 0b 08 07 50 00 00 00 34 00 00 00
08 00 20 00 26 00 08 00 20 0d 34 08 69 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00

And here the data that is injected on the MacBookPro13,1

47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00 26 19 00 6c 05
69 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 00 06 10 34 a0 02
03 40 00 00 00 00 00 00 00 00 02 90 6c 8a 0f 00 0a 40 06 50 00 00 00 2e 00 00 00
08 00 20 00 20 00 08 00 40 0b 08 07 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00

I could not find anything, not a single Apple document nor source code/header file that explains it, but I may have missed it. In which case I would love to hear from you.

Ok. So assuming that there is no documentation, we have to dig into other resources to get an idea what it may be. And this is what I figured out so far:

47 00 00 00 (unknown)

00 00 00 00 (_reservedA[10])
00 00 00 00
00 00 00 00

00 00 03 00 (version?)

06 00 1b 19 (AAPL,ig-platform-id)

00 (unknown)

6c 05 (BCL frequency/maximum?)

00 00 (BCL frequency/minimum)

00 00 (unknown)

00 00 00 00 (_reservedB[10])
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

01 01 01 01 (standard timing related info?)

00 (unknown)

06 10 (DisplayVendor)

30 a0 (DisplayProductID)

02 03 40 00 00 00 00 00 00 00 00 02 (unknown)

c0 eb 9a 13 (IOFBCurrentPixelClock)

40 0b (horizontalActive = 2880 pixels)

08 07 (verticalActive = 1800 pixels)

50 00 (horizontalBlanking in pixels)

00 (horizontalBorderLeft in pixels)

00 (horizontalBorderRight in pixels)

34 00 (verticalBlanking in pixels)

00 (verticalBorderTop in pixels)

00 (verticalBorderBottom in pixels)

08 00 (horizontalSyncOffset in pixels)

20 00 (horizontalSyncPulseWidth/Sync Width)

26 00 (verticalSyncOffset in pixels)

08 00 (verticalSyncPulseWidth/Sync Width)

20 0d (horizontalScaled = 3360)

34 08 (verticalScaled = 2100)

69 00 (bytes per row == ( (horizontalActive * depth) >> 3) )

00 00 00 00 (_reservedC[25])
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

Mostly basic stuff. Things that you could have come up yourself, but since I like to document things, and let other people confirm my findings.

Edit: I changed the border info. It’s now broken up into two horizontal and vertical border settings. I also figured out the unknown value at the bottom (row bytes).

The red unknown values are my next targets and I think that one of them is used for screen rotation. This is something I will test later today on my MacBook Pro.

Ok. Let me add the EDID data that gets injected:

00 ff ff ff ff ff ff 00 06 10 30 a0 00 00 00 00 26 19 01 04 b5 21 15 78 02 0f 55
ae 52 43 b0 26 0d 4f 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
7c 80 40 50 b0 08 34 70 08 20 68 08 4b cf 10 00 00 1a 00 00 00 10 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 fc 00 43 6f 6c 6f 72 20 4c 43 44 0a 20 20 20
00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe

And here the EDID data from the MacBookPro13,1

00 ff ff ff ff ff ff 00 06 10 34 a0 00 00 00 00 25 19 01 04 b5 1d 12 78 02 0f 41
ae 52 43 b0 26 0e 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
d9 65 00 50 a0 40 2e 60 08 20 08 08 1e b3 10 00 00 1a 7c 80 40 50 b0 08 34 70 08
20 68 08 1e b3 10 00 00 1a 00 00 00 fc 00 43 6f 6c 6f 72 20 4c 43 44 0a 20 20 20
00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3e

I also used SwitchResX to dump the EDID and one particular part of that output is this:

EDID Detailed mode

Clock 328.920 MHz, 331 mm x 207 mm
2880 2888 2920 2960 hborder 0
1800 1838 1846 1852 vborder 0
+hsync -vsync

I also used DarwinDumper and this is what I got:

Mode = 2880 x 1800 @ 60.001Hz
Pixel Clock............. 328.92 MHz Non-Interlaced

Horizontal Vertical
Active.................. 2880 pixels 1800 lines
Front Porch............. 8 pixels 38 lines
Sync Width.............. 32 pixels 8 lines
Back Porch.............. 40 pixels 6 lines
Blanking................ 80 pixels 52 lines
Total................... 2960 pixels 1852 lines
Scan Rate............... 111.122 kHz 60.001 Hz

Image Size.............. 331 mm 207 mm
Border.................. 0 pixels 0 lines

Sync: Digital separate with
* Negative vertical polarity
* Positive horizontal polarity

The above data is the technical description of the 15-inch display panel. And I used it, along with the saved-config data, to get this:

First column

2880 = horizontalActive
1800 = verticalActive

Second column

2880 = 2880 (horizontalActive) + 8 (horizontalSyncOffset)
1838 = 1800 (verticalActive) + 0x26/38 (verticalSyncOffset)

Third column

2920 = 2880 (horizontalActive) + 8 (horizontalSyncOffset) + 0x20/32 (horizontalSyncPulseWidth)
1846 = 1800 (verticalActive) + 0x26/38 (verticalSyncOffset) + 8 (verticalSyncPulseWidth)

Fourth column

2960 = 2880 (horizontalActive) + 0x50/80 (horizontalBlanking)
1852 = 1800 (verticalActive) + 0x34/52 (verticalBlanking)

Most of it can be extracted from IODisplayEDID, but I like to see it confirmed by others first. There is also unknown data. I have no idea, yet, what it may be. For example: 69 00 is 5a 00 on my MacBookPro13,1 and I have no idea what it is or how to get this value for my external monitor.

Injecting the wrong data is not what we want. I tried that and it failed to boot. The monitor of my hack went nuts, so the data obviously did something.

In short. We need a script or app that does most, if not all, of the work for us. We can use struct IODetailedTimingInformationV2 from IOGraphicsTypes.h to get (most of the) data. After that we can try to figure out what it does or if it helps us. Now the question is; who here is interested in this, and who can write that script and/or app?

Note: Some people may say that we don’t need it. Sure. We have been booting OS X for many years without this data. True. But now answer this question: Why does Apple inject the device-properties, when they don’t need it?

Does Apple load microcode for the IGPU?

Someone asked me if I knew if Apple loads Graphics micro code (Guc) for the IGPU and I can confirm that. Yes it does. Take a look at the following log data from my Apple MacBookPro13,3:

kernel: (AppleIntelSKLGraphics) [IGPU] Will fallback to host-side scheduling if graphics firmware fails to load
kernel: (AppleIntelSKLGraphics) [IGPU] Chose to use graphics firmware based on platform
kernel: (AppleIntelSKLGraphics) [IGPU] Graphics accelerator is using scheduler interface revision 3: Apple Firmware
kernel: (AppleIntelSKLGraphics) [IGPU] Scheduler: Multiple channel indexes per command streamer
kernel: (AppleIntelSKLGraphics) [IGPU] Scheduler: Process CSB using HWS.
kernel: (AppleIntelSKLGraphics) [IGPU] Scheduler: PM notify enabled
kernel: (AppleIntelSKLGraphics) [IGPU] Graphics Address: PPGTT, Separate Address Space
kernel: (AppleIntelSKLGraphics) [IGPU] MultiForceWake Enabled: Using 3D Driver
kernel: (AppleIntelSKLGraphics) [IGPU] Begin GuC load process
kernel: (AppleIntelSKLGraphics) [IGPU] Begin GuC load process
kernel: (AppleIntelSKLGraphics) [IGPU] ForceWake Multithread = 0x20002
kernel: (AppleIntelSKLGraphics) [IGPU] ForceWake Multithread = 0x20002
kernel: (AppleIntelSKLGraphics) [IGPU] CONFIG0 (0xD00) = 0x80000000
kernel: (AppleIntelSKLGraphics) [IGPU] CONFIG0 (0xD00) = 0x80000000
kernel: (AppleIntelSKLGraphics) [IGPU] GT_THREAD_STATUS = 0x400b0000
kernel: (AppleIntelSKLGraphics) [IGPU] GT_THREAD_STATUS = 0x400b0000
kernel: (AppleIntelSKLGraphics) [IGPU] Doing retry #0
kernel: (AppleIntelSKLGraphics) [IGPU] Doing retry #0

Debugging sleep issues…

A lot of people are still facing sleep/wake related issues and I like to figure out why so please check:

IOService:/AppleACPIPlatformExpert/IOPMrootDomain/PMStatusCode

1.) Is that number a zero or some other value?
2.) Do you have a property with the name: IOPMDeepIdleSupported?
3.) Do you have a property with the name: IOPMSystemSleepType?

If the answer for the first question is zero, then I would like to know if you are using a dGPU or IGPU only.

The second question can be solved by adding the following code to your ACPI tables:

Scope (\_SB)
{
    Method (LPS0, 0, NotSerialized)
    {
        Store ("Method \\_SB._LPS0 Called", Debug)
        Return (One)
    }
}

Scope (\_GPE)
{
    Method (LXEN, 0, NotSerialized)
    {
        Store ("Method \\_GPE.LXEN Called", Debug)
        Return (One)
    }
}

If the answer for the last question is yes, then what value is it, and what SMBIOS are you using? Please note that this specific property is not part of Yosemite. The value represents the lowest possible sleep state and is checked by the following kexts:

AppleACPIPlatform.kext
AppleIntelBDWGraphicsFramebuffer.kext
AppleIntelFramebufferAzul.kext
AppleIntelSKLGraphicsFramebuffer.kext
AppleSDXC.kext
AppleStorageDrivers.kext
IO80211Family.kext
IOBluetoothFamily.kext
IONVMeFamily.kext
IOUSBAttachedSCSI.kext
IOUSBMassStorageDriver.kext

That should be enough reasons for you to want that property.

I also added the following code to my ACPI tables:

Scope (\)
{
   Name (SLTP, Zero)

   Method (_TTS, 1, NotSerialized)
   {
       Store ("Method \\__TTS Called", Debug)
       Store (Arg0, SLTP)
   }
}

This, with additional checks, is used by Apple to skip parts for the NVMe SSD (RP01/IOPP/SSD0@0), AirPort (RP09/IOPP/ARP@0) and camera (RP10@1D,1/IOPP/CMRA) devices

NVRAM

There are two interesting NVRAM properties:

#define kIOSleepWakeDebugKey        "Persistent-memory-note"
#define kIOEFIBootRomFailureKey     "wake-failure"

That has to be it for now. Maybe later more…

Edit:

Ok. Jaybee asked (see comments) how he should validate the values. That is a good question. Let’s start with PMStatusCode. This should be 0x0 (success).

IOPMDeepIdleSupported. This should be there with a value of true.

IOPMSystemSleepType is the lowest possible sleep state and this is set to 7 on my MacBook Pro. This will also issue a sleep request for the iGPU.

Some people said that this property wasn’t there on their setup. For some not until after a sleep/wake cycle, and then it was set to 2.

I have yet to figure out how important this value is and if that can cause any trouble.

AppleIntelSKLGraphicsFramebuffer.kext

Here is the first data from the AppleIntelSKLGraphicsFramebuffer.kext binary that I like to share with you:

06 00 1B 19 00 00 00 00 91 09 08 00 00 00 00 00
01 01 01 01 00 00 60 02 00 00 00 00 00 00 00 60
6C 05 00 00 6C 05 00 00 00 00 00 00 00 00 00 00
00 00 08 00 02 00 00 00 98 04 00 00 FF 00 00 00
01 00 00 00 20 00 00 00 FF 00 00 00 01 00 00 00
20 00 00 00 FF 00 00 00 01 00 00 00 20 00 00 00
02 13 13 00 00 00 06 00 03 00 00 00 04 00 00 00
80 DF 17 10 00 00 00 00 78 05 00 00 D2 05 00 00
40 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 23 1B 00 00 00 00 00 60 24 1B 00 00 00 00 00
60 24 1B 00 00 00 00 00 01 00 00 00 08 00 00 00
00 00 00 00 00 00 00 00

The above example will activate/support only one display, and some of the data is well known by now so I am going to skip stuff like the black value, which is (still) the platformID.

Unused/disabled frame buffer data (see orange values) have also changed.

New are the red values, all represent a different kinds of version information.

New is the blue value, representing the number of Slices (Slice Count).

New is the green value, representing the number of Execution Unit (EU Count).

The purple data is used for the TCON configuration and this is what I found in the log file of my MacBookPro13,3:

kernel: (AppleIntelSKLGraphicsFramebuffer) IG: TCON:
kernel: (AppleIntelSKLGraphicsFramebuffer) Aux not ready at HW
kernel: (AppleIntelSKLGraphicsFramebuffer) IG: TCON:
kernel: (AppleIntelSKLGraphicsFramebuffer) BAN_DPCD_0x0_EXPECTED failed, got deadbeef

See also:

AppleIntelFramebufferAzul.kext (Part I)
AppleIntelFramebufferAzul.kext (Part II)
AppleIntelFramebufferAzul.kext (Part III)

Black screen with movable cursor…

I received a couple of question this month and one of them jumps out; Stuck on a black screen with a movable cursor.

Ok. I think I know what you mean and this is my work around for it (mentioned before in one of my replies in a blog post):

1.) Press enter (background image flashes shortly).

2.) Enter you password (screen is still black).

3.) There is your desktop.

Well. That’s it. Works every time for me. No matter what display connector that I use (HDMI, DVI or VGA).

p.s. You may run into this black screen with movable cursor if your PC failed to wake up, after you’ve used the on/off switch to boot again.

Update: Apple change something in 10.12.3 Beta (16D30a) and as a result the screen is no longer black.

Booting without monitor (cable) attached…

I tried to boot my Skylake setup without a monitor (cable) attached and it failed, up until the moment that I connect the monitor cable. It didn’t even (try to) load the boot loader from the M2 SSD. What I noticed was a flashing cursor at the top left corner, and only then did it load the boot loader from the M2 SSD. This is a serious BIOS bug.

Three questions:

1.) Can you boot (your Skylake setup) without a monitor attached?

2.) If yes, is that with an NVIDIA (or AMD) dGPU or the IGPU?

3.) Do you happen to know a work around for this problem?

Edit: It boots up with the monitor cable attached, even if the monitor is switched off – the BIOS may want to read the EDID and use the power from the DVI cable.