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?

13 thoughts on “Apple IGPU saved-config data

  1. Thanks for the great info, I think Apple uses this information to check if the monitor is an Apple monitor,
    this may explain the fact that some Laptop users have to use an EDID custom so that they can fix “Error in preferences: Can’t load display preferences panel”, or I’ve been talking a lot of bullshit.

    Another thing to ask is why on external monitors
    using dGPU, the screen flashes before the start of the second stage of the boot, will be a check to see which port the monitor is connected? on Laptops doesn’t happen.

    • Hi Mirone,

      I managed to setup the data for my external monitor, no hangs, and everything looks fine thus far. I’ll see if I can figure out why it would be needed, but I am keeping it.

  2. Sorry off topic but it is really driving me mad , and after search alot without a clue i decide to bother you .
    i`m having bad performance scrolling images in OSIRIX and also HOROS in my skylake (i6700k and z170N-gaming 5) rig with gtx970 and nvidia drivers in sierra 10.12.3 (also with other sierra versions) with terminal showing kernel faults during scroll:

    static IOAccelResource2 *IOAccelResource2::newResourceWithClientBuffer(IOGraphicsAccelerator2 *, IOAccelShared2 *, enum eIOAccelResType, IOByteCount, mach_vm_address_t, mach_vm_address_t, IOByteCount, mach_vm_address_t *, uint32_t): fSysMemory is NULL.

    static IOAccelSysMemory *IOAccelSysMemory::withClientBuffer(IOGraphicsAccelerator2 *, task_t, IOAccelShared2 *, mach_vm_address_t, uint64_t): failed to get the memory descriptor.

    IOAccelSysMemory *IOAccelShared2::memory_with_client_buffer(mach_vm_address_t, uint64_t): withClientBuffer failed.

    A lot of faults only during scroll.

    Any Clue to fix it?

    Really thanks and grateful for all your work.

  3. Hi Pike,
    This is slightly off topic, but related to IGPU configuration. I’m interested in using an AMD RX 4xx family or Fiji GPU with an X99 system (which, of course, does not have an IGPU) — my understanding is that in order to load the graphics drivers for these correctly an IGPU needs to be loaded as the primary graphics device. Can you think of any way around this?

    Thanks!

    • Hi Jon,

      I’m aware of this issue, but I no longer own X99 hardware and thus working on stuff like this is rather difficult. Not to mention lack of time due to all other things that I am already working on. The problem is also far more complicated than people think. In short. Sorry. No. I don’t have a solution/workaround for this problem.

      • Hi Pike,
        No problem at — I naively assumed there might be a simple/elegant solution that you might know how to implement.

        All the best!
        Jon

Leave a comment