Jump to content

Clover Problems and Solutions


ErmaC
3,206 posts in this topic

Recommended Posts

Slice:

 

The crash experienced by calibre comes from GetTagCount() in rEFIt_UEFI/Platform/plist.c...

INTN GetTagCount( TagPtr dict )
{
	INTN count = 0;
	TagPtr tagList, tag;
  
  if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) {
    return 0;
  }
	tag = 0;
  tagList = dict->tag;
The value in ESI 0xFFFFFFFF is dict->tag. I've searched the code in plist.c, and I see it using NULL to mark this field as having no value - but I don't see how it could possibly get assigned the value 0xFFFFFFFF. So I'm not sure what to do about it.

 

[Note: the instruction that crashes "cmp dword [esi], 2" is the comparison tag->type != kTagTypeKey down the code]

Link to comment
Share on other sites

What I can't see is the check if dict exists or not

if ( dict->type != kTagTypeDict && dict->type != kTagTypeArray) {
    return 0;
  }

ie before any "->" operator, but offcourse if does not exist is not an array anyway

 

EDIT

ESI...Is a bad string! like the case contains special characters that xml.c can't handle or is null. :puppeh:

  • Like 1
Link to comment
Share on other sites

I am not sure if this is the case but I commit initializing local variables. (3531)

It will be better to have such problem on own computer to reproduce the crash and debug it.

 

 

For Zenith432/Mickey1979

 

attachicon.gifx32.png

upload, please, your quirky config.plist.

  • Like 1
Link to comment
Share on other sites

Can you show that Windows booted by Clover shows other hardware information then booted directly from BIOS?

I mentioned it earlier, but I'll say it again, what you have done is quite enough and I said, thank you, as well.

 

After some research I found that the Unknown memory type is a windows' issue not clover's, to be more specific not UEFI firmware's that starts windows.

 

You asked for differences in hardware information. I found one, not significant. If windows is booted from bios screen, so to speak, the hardware reserved memory is 1.5MB. However, if I boot windows from clover's GUI, the hardware reserved memory is 6.9MB.

 

Below are 2 screenshots. 

 

Best regards.

post-1378824-0-03167100-1463498559_thumb.png

post-1378824-0-18908100-1463498563_thumb.png

Link to comment
Share on other sites

Hi fellas,

I use R3251 for a while and it goes along with my GTX 690.

 

Today, i wanted to test newer revisions of clover but unfortunately with R3526 and R3424, graphics drivers are loaded but black screen on desktop. Switch back to R3251, all is fine. Any idea? I wasn't there for a long time.

 

 

EDIT : R3526 with my 8400 GS all ok.

Link to comment
Share on other sites

Hi fellas,

I use R3251 for a while and it goes along with my GTX 690.

 

Today, i wanted to test newer revisions of clover but unfortunately with R3526 and R3424, graphics drivers are loaded but black screen on desktop. Switch back to R3251, all is fine. Any idea? I wasn't there for a long time.

 

 

EDIT : R3526 with my 8400 GS all ok.

See changes explained here             #18            

Link to comment
Share on other sites

It will be better to have such problem on own computer to reproduce the crash and debug it.

Calibre sent me the binary for CLOVERIA32.efi that is crashing in post #824. I traced the return address on the stack,

and the call to GetTagCount is coming from

FillinCustomEntry()
...
  Prop = GetProperty (DictPointer, "VolumeType");
  if (Prop != NULL && (Prop->type == kTagTypeString)) {
    if (AsciiStriCmp (Prop->string, "Internal") == 0) {
      Entry->VolumeType = VOLTYPE_INTERNAL;
    } else if (AsciiStriCmp (Prop->string, "External") == 0) {
      Entry->VolumeType = VOLTYPE_EXTERNAL;
    } else if (AsciiStriCmp (Prop->string, "Optical") == 0) {
      Entry->VolumeType = VOLTYPE_OPTICAL;
    } else if (AsciiStriCmp (Prop->string, "FireWire") == 0) {
      Entry->VolumeType = VOLTYPE_FIREWIRE;
    }
  } else {
    INTN   i, Count = GetTagCount (Prop); <<<<<--------
    if (Count > 0) {
      TagPtr Prop2 = NULL;
      for (i = 0; i < Count; i++) {
...
The config.plist in post #833 doesn't have any custom entries. So it's loading the config.plist from somewhere else.

 

PS: It doesn't crash on my system when I use Calibre's CLOVERIA32.efi and config.plist.

Link to comment
Share on other sites

Calibre sent me the binary for CLOVERIA32.efi that is crashing in post #824. I traced the return address on the stack,

and the call to GetTagCount is coming from

FillinCustomEntry()
...
  Prop = GetProperty (DictPointer, "VolumeType");
  if (Prop != NULL && (Prop->type == kTagTypeString)) {
    if (AsciiStriCmp (Prop->string, "Internal") == 0) {
      Entry->VolumeType = VOLTYPE_INTERNAL;
    } else if (AsciiStriCmp (Prop->string, "External") == 0) {
      Entry->VolumeType = VOLTYPE_EXTERNAL;
    } else if (AsciiStriCmp (Prop->string, "Optical") == 0) {
      Entry->VolumeType = VOLTYPE_OPTICAL;
    } else if (AsciiStriCmp (Prop->string, "FireWire") == 0) {
      Entry->VolumeType = VOLTYPE_FIREWIRE;
    }
  } else {
    INTN   i, Count = GetTagCount (Prop); <<<<<--------
    if (Count > 0) {
      TagPtr Prop2 = NULL;
      for (i = 0; i < Count; i++) {
...
The config.plist in post #833 doesn't have any custom entries. So it's loading the config.plist from somewhere else.

 

PS: It doesn't crash on my system when I use Calibre's CLOVERIA32.efi and config.plist.

 

Weird!!!!

  Prop = GetProperty (DictPointer, "VolumeType");
  if (Prop != NULL && (Prop->type == kTagTypeString)) {
 ...
  } else {
    INTN   i, Count = GetTagCount (Prop); <<<<<--------

See! If Prop == NULL then GetTagCount (Prop) 

->

INTN GetTagCount( TagPtr dict )

{

INTN count = 0;

TagPtr tagList, tag;

  

  if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) {

Null pointer dereference!
I will correct immediately. Thanks for find!
  • Like 1
Link to comment
Share on other sites

Slice,

 

You're right (and Micky1979 too in post #831).  The bug is that argument TagPtr dict to GetTagCount is NULL.

I got confused about this.

Because the parameter dict is passed in ECX, and ECX in the dump is 0x3C8CF0 - looking valid.

So I mistook this pointer for dict.

But now I look at the disassembly again.

At the crash point

ESI holds the value of dict->tag, which was taken from NULL->tag,

and ECX holds  the value of ESI->tagNext, which corresponds to statement tagList = tag->tagNext.

So value of parameter dict is not in a register anymore at the crash point.  dict is forgotten.  The only

place it's used later in the func is dict->type, which is remembered in register EDX (it's kTagTypeArray,

but really taken from NULL parameter....)  It's a freak accident that NULL->type ended up as kTagTypeArray.

Otherwise GetTagCount would be exited with 0 as it should.

  • Like 2
Link to comment
Share on other sites

I'm f******** lost. What was the problem with old way? No matter how i struggle, clover beats me.

Give me your config.plist I will look what was conflict with new Clover.

Or you have too smart DSDT?

Link to comment
Share on other sites

I compiled and edk2 updated itself and prompted me for a conflict. Which one is correct to select, TC or MC?

The choices are documented at

http://www.tutorialspoint.com/svn/svn_resolve_conflicts.htm

 

I would choose TC or TF if I know I didn't change that file. But before that I would go to the Finder and duplicate the Clover folder and manually compare after the update is complete to make sure something weird didn't happen and to see what everyone else was changing.

 

May be timeouts?

There is a check

next cycle no such check.

We can change 1000 -> 200 to test.

The divide by 1000 is for converting Hz to kHz so that t is milliseconds instead of seconds. It would be faster and more accurate to multiply cycles by 1000 instead. Changing (t > 5) to (t > 200) would be the best way to increase the time out.

 

I would replace the smb_read_byte routine with the following test version to see how the status changes (the long timeout will increase Clover startup time by several seconds so use this only for checking the behavior of the SMBus spd read routine):

 

 

UINT8 smb_read_byte(UINT32 base, UINT8 adr, UINT16 cmd)
{
  //   INTN l1, h1, l2, h2;
  UINT64 t, t1, t2;
  UINT8 page;
  UINT8 c;
  UINT8 p;

  if (smbIntel) {
    p = 0xFF;
    t1 = AsmReadTsc(); //rdtsc(l1, h1);

    //IoWrite8(base + SMBHSTDAT, 0xFF);
    IoWrite8(base + SMBHSTSTS, 0xFF);       // reset SMBus Controller (set busy)
    while (1) {  // wait until host is not busy
      c = IoRead8(base + SMBHSTSTS);
      t2 = AsmReadTsc(); //rdtsc(l2, h2);
      t = DivU64x64Remainder(MultU64x32(t2 - t1, 1000), gCPUStructure.TSCFrequency, NULL);
      if (c != p) {
        DBG("t=%d adr=%02X cmd=%X host busy status %02X\n", (INTN)t, adr, cmd, c);
        p = c;
      }
      /*
      // This must be wrong. Bit 0 always appears to start as 0.
      if (~c & 1) {
        break;
      }
      */
      if (t > 300) {
        if (~c & 1)
          break;
        DBG("t=%d adr=%02X cmd=%X host is busy for too long!\n", (INTN)t, adr, cmd);
        return 0xFF;                  // break
      }
    }

    page = (cmd >> 8) & 1;
    if (page != smbPage) {
      IoWrite8(base + SMBHSTCMD, 0x00);
      IoWrite8(base + SMBHSTADD, 0x6C + (page << 1)); // Set SPD Page Address
#if 0
      IoWrite8(base + SMBHSTCNT, 0x48); // Start + Byte Data Write
      // Don't use "Byte Data Write" because status goes from 0x41 (Busy) -> 0x44 (Error)
#else
      IoWrite8(base + SMBHSTCNT, 0x40); // Start + Quick Write
      // status goes from 0x41 (Busy) -> 0x42 (Completed)
#endif
      smbPage = page;

      p = 0xFF;
      t1 = AsmReadTsc();
      while (1) {  // wait until command finished
        c = IoRead8(base + SMBHSTSTS);
        t2 = AsmReadTsc();
        t = DivU64x64Remainder(MultU64x32(t2 - t1, 1000), gCPUStructure.TSCFrequency, NULL);
        if (c != p) {
          DBG("t=%d adr=%02X cmd=%X spd page change status %02X\n", (INTN)t, adr, cmd, c);
          p = c;
        }
        if (c & 2) {
          break;
        }
        if (c & 4) {
          DBG("t=%d adr=%02X cmd=%X spd page change error!\n", (INTN)t, adr, cmd);
          break;
        }
        if (t > 5) {
          DBG("t=%d adr=%02X cmd=%X spd page change taking too long!\n", (INTN)t, adr, cmd);
          break;                  // break after 5ms
        }
      }
      return smb_read_byte(base, adr, cmd);
    }

    IoWrite8(base + SMBHSTSTS, 0xBF);
    IoWrite8(base + SMBHSTADD, (adr << 1) | 1); // read from spd
    IoWrite8(base + SMBHSTCMD, (UINT8)(cmd & 0xFF)); // SMBus uses 8 bit commands
    IoWrite8(base + SMBHSTCNT, 0x48); // Start + Byte Data Read
    // status goes from 0x41 (Busy) -> 0x42 (Completed) or 0x44 (Error)
   
   	p = 0xFF;
    t1 = AsmReadTsc();
    while (1) {  // wait until command finished
    	c = IoRead8(base + SMBHSTSTS);
      t2 = AsmReadTsc();
      t = DivU64x64Remainder(MultU64x32(t2 - t1, 1000), gCPUStructure.TSCFrequency, NULL);
      if (c != p) {
        DBG("t=%d adr=%02X cmd=%X spd read status %02X\n", (INTN)t, adr, cmd, c);
        p = c;
      }
      if (c & 2) {
        break;
      }
      /*
      if (c & 4) {
        // This alway happens when trying to read the memory type (cmd 2) of an empty slot
        DBG("t=%d adr=%02X cmd=%X spd byte read error!\n", (INTN)t, adr, cmd);
        break;
      }
      */
      if (t > 200) {
        // if (cmd != 2)
        DBG("t=%d adr=%02X cmd=%X spd byte read taking too long!\n", (INTN)t, adr, cmd);
        IoWrite8(base + SMBHSTCNT, IoRead8(base + SMBHSTCNT) | 2);
        return 0xFF;      // break after 5ms
      }
    }
    return IoRead8(base + SMBHSTDAT);
  }
  else {
    IoWrite8(base + SMBHSTSTS_NV, 0x1f);      // reset SMBus Controller
    IoWrite8(base + SMBHSTDAT_NV, 0xff);

    t1 = AsmReadTsc(); //rdtsc(l1, h1);
    while ( IoRead8(base + SMBHSTSTS_NV) & 0x01) {    // wait until read
      t2 = AsmReadTsc(); //rdtsc(l2, h2);
      t = DivU64x64Remainder((t2 - t1),
                             DivU64x32(gCPUStructure.TSCFrequency, 1000),
                             0);
      if (t > 5)
        return 0xFF;                  // break
    }

    IoWrite8(base + SMBHSTSTS_NV, 0x00); // clear status register
    IoWrite16(base + SMBHSTCMD_NV, cmd);
    IoWrite8(base + SMBHSTADD_NV, (adr << 1) | 0x01 );
    IoWrite8(base + SMBHPRTCL_NV, 0x07 );
    t1 = AsmReadTsc();

    while (!( IoRead8(base + SMBHSTSTS_NV) & 0x9F)) {   // wait till command finished
      t2 = AsmReadTsc();
      t = DivU64x64Remainder((t2 - t1),
                             DivU64x32(gCPUStructure.TSCFrequency, 1000),
                             0);
      if (t > 5)
        break; // break after 5ms
    }
    return IoRead8(base + SMBHSTDAT_NV);
  }
}

 

  • Like 1
Link to comment
Share on other sites

The choices are documented at

http://www.tutorialspoint.com/svn/svn_resolve_conflicts.htm

 

I would choose TC or TF if I know I didn't change that file. But before that I would go to the Finder and duplicate the Clover folder and manually compare after the update is complete to make sure something weird didn't happen and to see what everyone else was changing.

 

The divide by 1000 is for converting Hz to kHz so that t is milliseconds instead of seconds. It would be faster and more accurate to multiply cycles by 1000 instead. Changing (t > 5) to (t > 200) would be the best way to increase the time out.

 

I would replace the smb_read_byte routine with the following test version to see how the status changes (the long timeout will increase Clover startup time by several seconds so use this only for checking the behavior of the SMBus spd read routine):

 

@joevt,

Here's the output from your revised code. I've tried increasing the timeout further but still the same result, status appears to be read error. Could it be that the device is always busy so can't be read?

0:123  0:000  ScanSPD() start
0:124  0:000  SMBus device : 8086 8D22 class=0C0500 status=Success
0:124  0:000  SMBus CmdReg: 0x1
0:124  0:000  Scanning SMBus [8086:8D22], mmio: 0xFB135004, ioport: 0x580, hostc: 0x1
0:124  0:000  Slots to scan [8]...
0:124  0:000  t=0 adr=50 cmd=2 host busy status 00
0:124  0:000  t=0 adr=50 cmd=2 host busy status 40
0:364  0:240  t=0 adr=50 cmd=2 spd read status 41
0:365  0:000  t=0 adr=50 cmd=2 spd read status 44
0:525  0:160  t=201 adr=50 cmd=2 spd byte read taking too long!
0:525  0:000  t=0 adr=51 cmd=2 host busy status 00
0:525  0:000  t=0 adr=51 cmd=2 host busy status 40
0:766  0:240  t=0 adr=51 cmd=2 spd read status 41
0:766  0:000  t=0 adr=51 cmd=2 spd read status 45
0:766  0:000  t=0 adr=51 cmd=2 spd read status 44
0:927  0:160  t=201 adr=51 cmd=2 spd byte read taking too long!
0:927  0:000  t=0 adr=52 cmd=2 host busy status 00
0:927  0:000  t=0 adr=52 cmd=2 host busy status 40
1:168  0:240  t=0 adr=52 cmd=2 spd read status 41
1:168  0:000  t=0 adr=52 cmd=2 spd read status 44
1:328  0:160  t=201 adr=52 cmd=2 spd byte read taking too long!
1:328  0:000  t=0 adr=53 cmd=2 host busy status 00
1:328  0:000  t=0 adr=53 cmd=2 host busy status 40
1:569  0:240  t=0 adr=53 cmd=2 spd read status 41
1:569  0:000  t=0 adr=53 cmd=2 spd read status 44
1:730  0:160  t=201 adr=53 cmd=2 spd byte read taking too long!
1:730  0:000  t=0 adr=54 cmd=2 host busy status 00
1:730  0:000  t=0 adr=54 cmd=2 host busy status 40
1:971  0:240  t=0 adr=54 cmd=2 spd read status 41
1:971  0:000  t=0 adr=54 cmd=2 spd read status 44
2:132  0:160  t=201 adr=54 cmd=2 spd byte read taking too long!
2:132  0:000  t=0 adr=55 cmd=2 host busy status 00
2:132  0:000  t=0 adr=55 cmd=2 host busy status 40
2:372  0:240  t=0 adr=55 cmd=2 spd read status 41
2:373  0:000  t=0 adr=55 cmd=2 spd read status 44
2:533  0:160  t=201 adr=55 cmd=2 spd byte read taking too long!
2:533  0:000  t=0 adr=56 cmd=2 host busy status 00
2:533  0:000  t=0 adr=56 cmd=2 host busy status 40
2:774  0:240  t=0 adr=56 cmd=2 spd read status 41
2:774  0:000  t=0 adr=56 cmd=2 spd read status 44
2:935  0:160  t=201 adr=56 cmd=2 spd byte read taking too long!
2:935  0:000  t=0 adr=57 cmd=2 host busy status 00
2:935  0:000  t=0 adr=57 cmd=2 host busy status 40
3:176  0:240  t=0 adr=57 cmd=2 spd read status 41
3:176  0:000  t=0 adr=57 cmd=2 spd read status 44
3:336  0:160  t=201 adr=57 cmd=2 spd byte read taking too long!
3:336  0:000  ScanSPD() end
Link to comment
Share on other sites

@joevt,

Here's the output from your revised code. I've tried increasing the timeout further but still the same result, status appears to be read error. Could it be that the device is always busy so can't be read?

0:123  0:000  ScanSPD() start
0:124  0:000  SMBus device : 8086 8D22 class=0C0500 status=Success
0:124  0:000  SMBus CmdReg: 0x1
0:124  0:000  Scanning SMBus [8086:8D22], mmio: 0xFB135004, ioport: 0x580, hostc: 0x1
0:124  0:000  Slots to scan [8]...
0:124  0:000  t=0 adr=50 cmd=2 host busy status 00
0:124  0:000  t=0 adr=50 cmd=2 host busy status 40
0:364  0:240  t=0 adr=50 cmd=2 spd read status 41
0:365  0:000  t=0 adr=50 cmd=2 spd read status 44
0:525  0:160  t=201 adr=50 cmd=2 spd byte read taking too long!
0:525  0:000  t=0 adr=51 cmd=2 host busy status 00
0:525  0:000  t=0 adr=51 cmd=2 host busy status 40
0:766  0:240  t=0 adr=51 cmd=2 spd read status 41
0:766  0:000  t=0 adr=51 cmd=2 spd read status 45
0:766  0:000  t=0 adr=51 cmd=2 spd read status 44
0:927  0:160  t=201 adr=51 cmd=2 spd byte read taking too long!
0:927  0:000  t=0 adr=52 cmd=2 host busy status 00
0:927  0:000  t=0 adr=52 cmd=2 host busy status 40
1:168  0:240  t=0 adr=52 cmd=2 spd read status 41
1:168  0:000  t=0 adr=52 cmd=2 spd read status 44
1:328  0:160  t=201 adr=52 cmd=2 spd byte read taking too long!
...
3:336  0:000  ScanSPD() end

Those look like status bytes that you would expect from the SMBus when no device is connected at the adr. The first mystery is why it doesn't see a device in your machine so the status byte should start as 0x41 then change to 0x42 instead of 0x44.

 

I'm not sure that the host busy check is working correctly. Yours is the same as mine but it seems to be different than what my SBUS DSDT methods expect. I'll add comments about that in the next test.

 

It's strange that t=0 twice in a row. I'll change the output to use microseconds in the next test so we can see the change in time.

 

The read is reporting an error (status & 0x4) but I wonder if there is a valid byte in the DAT register at that time, so I'll add that to the output in the next test.

 

Here's a new testing replacement for smb_read_byte. I've moved the wait loop into a new function. Change DEBUGSPD to 0 to get a non-test version that will not wait for timeout, and will not spam output to the log.

 

#define DEBUGSPD 1

const CHAR8* SMBHOST = "host busy";
const CHAR8* SPDPAGE = "spd page change";
const CHAR8* SPDREAD = "spd read";

UINT8 smb_wait_transaction_complete(UINT32 base, UINT8 adr, UINT16 cmd, INTN timeout_us, const CHAR8* process)
{
  UINT8 c;
  UINT8 p;

  UINT64 t, t1, t2;

  p = 0xFF;
  t1 = AsmReadTsc(); //rdtsc(l1, h1);

  if (smbIntel) {
    while (1) { // wait until command finished
      c = IoRead8(base + SMBHSTSTS);
      t2 = AsmReadTsc(); //rdtsc(l2, h2);
      t = DivU64x64Remainder(MultU64x32(t2 - t1, 1000000), gCPUStructure.TSCFrequency, NULL);
#if DEBUGSPD
      if (c != p) {
        DBG("t=%d adr=%02X cmd=%X %a status %02X\n", t, adr, cmd, process, c);
        p = c;
      }
#endif
      // This must be wrong - bit 0 always appears to start as 0?
      if (process == SMBHOST && ~c & 1) {
        // the SMBHOST process isn't a control command so don't expect the host status to return a control command result (status & 0x1E != 0)
        // but it doesn't seem to return any result - the status will goes quickly from 0x00 to 0x40 (I don't know what the means) and remains at 0x40.
        // My DSDT says an SMBus control call is supposed to wait for status & 0x40 == 0, then wait for status & 0x01 == 0 which is almost the reverse of what we're seeing.
#if DEBUGSPD
        // if we're debugging, then let the first one timeout, to see if the status changes
        if (cmd != 2)
#endif
          break;
      }

      if (c & 2) {
        break;
      }

      if (c & 4) {
        if (process != SPDREAD) {
          // This alway happens when trying to read the memory type (cmd 2) of an empty slot so don't report the error
          DBG("t=%d adr=%02X cmd=%X %a error!\n", t, adr, cmd, process);
        }
#if !DEBUGSPD
        break;
#endif
      }

      if (t > timeout_us) {
        if (process == SMBHOST && ~c & 1) {
          // for SMBHOST, we don't know there's an error.
          break;
        }
        DBG("t=%d adr=%02X cmd=%X %a (%02X) timeout!\n", t, adr, cmd, process, IoRead8(base + SMBHSTDAT));
        return FALSE; // fail, stop!
      }
    }
  }
  else {
    t1 = AsmReadTsc(); //rdtsc(l1, h1);
    while (1) {
      c = IoRead8(base + SMBHSTSTS_NV);

      if (process == SMBHOST) {
        if (~c && 1) { // wait until read
          return TRUE;
        }
      }
      else {
        if (c & 0x9F) { // wait till command finished
          return TRUE;
        }
      }
        
      t2 = AsmReadTsc(); //rdtsc(l2, h2);
      t = DivU64x64Remainder(MultU64x32(t2 - t1, 1000000), gCPUStructure.TSCFrequency, NULL);
      if (t > timeout_us) {
        if (process == SMBHOST) {
          return FALSE;
        }
        break;
      }
    }
  }
  
  return TRUE; // success, keep going!
}

UINT8 smb_read_byte(UINT32 base, UINT8 adr, UINT16 cmd)
{
  UINT8 page = (cmd >> 8) & 1;

  if (smbIntel) {
//  IoWrite8(base + SMBHSTSTS, 0xFF); // reset SMBus Controller (set busy)
    smb_wait_transaction_complete(base, adr, cmd, 300000, SMBHOST);

    if (page != smbPage) {
      //IoWrite8(base + SMBHSTCMD, 0x00);
      IoWrite8(base + SMBHSTADD, 0x6C + (page << 1)); // Set SPD Page Address
      IoWrite8(base + SMBHSTCNT, 0x40); // Start + Quick Write ; don't use 0x48 because that gets status 0x44 (Error)
      // status goes from 0x41 (Busy) -> 0x42 (Completed)
      smbPage = page;
      smb_wait_transaction_complete(base, adr, cmd, 5000, SPDPAGE);
      IoWrite8(base + SMBHSTSTS, 0xFF); // reset SMBus Controller (set busy)
      return smb_read_byte(base, adr, cmd);
    }

    IoWrite8(base + SMBHSTSTS, 0xBF);
    IoWrite8(base + SMBHSTDAT, 0xFF);
    IoWrite8(base + SMBHSTADD, (adr << 1) | 0x01); // read from spd
    IoWrite8(base + SMBHSTCMD, (UINT8)(cmd & 0xFF)); // SMBus uses 8 bit commands
    IoWrite8(base + SMBHSTCNT, 0x48); // Start + Byte Data Read
    // status goes from 0x41 (Busy) -> 0x42 (Completed) or 0x44 (Error)
    if (smb_wait_transaction_complete(base, adr, cmd, 200000, SPDREAD))
    {
      IoWrite8(base + SMBHSTSTS, 0xFF); // reset SMBus Controller (set busy)
      return IoRead8(base + SMBHSTDAT);
    }
    else {
      IoWrite8(base + SMBHSTCNT, IoRead8(base + SMBHSTCNT) | 2); // kill
      IoWrite8(base + SMBHSTSTS, 0xFF); // reset SMBus Controller (set busy)
    }
    return 0xFF;
  }
  else {
    IoWrite8(base + SMBHSTSTS_NV, 0x1F); // reset SMBus Controller
    IoWrite8(base + SMBHSTDAT_NV, 0xFF);
    if (!smb_wait_transaction_complete(base, adr, cmd, 5000, SMBHOST))
      return 0xFF;

    IoWrite8(base + SMBHSTSTS_NV, 0x00); // clear status register
    IoWrite16(base + SMBHSTCMD_NV, cmd);
    IoWrite8(base + SMBHSTADD_NV, (adr << 1) | 0x01); // read from spd
    IoWrite8(base + SMBHPRTCL_NV, 0x07);
    smb_wait_transaction_complete(base, adr, cmd, 5000, SPDREAD);

    return IoRead8(base + SMBHSTDAT_NV);
  }
}

I wonder if it's possible to get a copy of the BIOS, disassemble it, and see how it populates the SMBIOS type 17 table? The ASUS website has firmware files in .cap format but I don't know anything about that. Finding the correct piece of code seems like searching for a needle in a haystack so I won't try that. I am able to extract the DSDT using the following commands (which isn't useful unless you don't have a computer with the firmware that you want to look at):

thecap=~/Downloads/X99-A-ASUS-3101.CAP

# Find possible DSDT aml header
strings -a -t d ${thecap} | grep DSDT

5423524 DSDTv_
7949521 _DSDT

# Check each result
dd if=${thecap} of=/tmp/dsdt.aml bs=1 skip=$((5423524)) count=0x24 2> /dev/null
xxd < /tmp/dsdt.aml

0000000: 4453 4454 765f 0300 02e4 414c 4153 4b41  DSDTv_....ALASKA
0000010: 4120 4d20 4920 0000 0920 0701 494e 544c  A M I ... ..INTL
0000020: 1309 1220                                ... 

# That looks like an aml header. Get the size of the DSDT and dump those bytes to an aml file.
dd if=${thecap} of=/tmp/dsdt.aml bs=1 skip=$((5423524+4)) count=4 2> /dev/null
dsdtsize=$(rev < /tmp/dsdt.aml | xxd -p)
dsdtsize=$((0x${dsdtsize:1:8}))
dd if=${thecap} of=/tmp/dsdt.aml bs=1 skip=5423524 count=${dsdtsize} 2> /dev/null

# Open the file in MaciASL.app
open /tmp/dsdt.aml

xxd < ${thecap} > /tmp/cap.txt

I wonder if the SMBus has devices on different addresses besides the ones we're looking at (50-57). Run Thaiphoon Burner and take a screenshot of the SMBus menu after doing a "Search for SMB Devices". You may need to set the delay option if you're using Snipping Tool. Mine looks like the attached image.

 

post-623141-0-74092600-1463721295_thumb.png

Link to comment
Share on other sites

@joevt

Thanks for working on this! Attached is a screenshot from Thaiphoon plus output of revised code plus native DSDT extracted from bios:

0:124  0:000  ScanSPD() start
0:124  0:000  SMBus device : 8086 8D22 class=0C0500 status=Success
0:124  0:000  SMBus CmdReg: 0x1
0:124  0:000  Scanning SMBus [8086:8D22], mmio: 0xFB135004, ioport: 0x580, hostc: 0x1
0:124  0:000  Slots to scan [8]...
0:124  0:000  t=1 adr=50 cmd=2 host busy status 00
0:124  0:000  t=4 adr=50 cmd=2 host busy status 40
0:424  0:300  t=1 adr=50 cmd=2 spd read status 41
0:424  0:000  t=118 adr=50 cmd=2 spd read status 44
0:624  0:199  t=200002 adr=50 cmd=2 spd read (FF) timeout!
0:624  0:000  t=1 adr=51 cmd=2 host busy status 00
0:624  0:000  t=3 adr=51 cmd=2 host busy status 40
0:924  0:300  t=1 adr=51 cmd=2 spd read status 41
0:924  0:000  t=118 adr=51 cmd=2 spd read status 44
1:124  0:199  t=200002 adr=51 cmd=2 spd read (FF) timeout!
1:124  0:000  t=1 adr=52 cmd=2 host busy status 00
1:124  0:000  t=3 adr=52 cmd=2 host busy status 40
1:424  0:300  t=1 adr=52 cmd=2 spd read status 41
1:424  0:000  t=117 adr=52 cmd=2 spd read status 44
1:624  0:199  t=200002 adr=52 cmd=2 spd read (FF) timeout!
1:624  0:000  t=1 adr=53 cmd=2 host busy status 00
1:624  0:000  t=3 adr=53 cmd=2 host busy status 40
1:924  0:300  t=1 adr=53 cmd=2 spd read status 41
1:924  0:000  t=117 adr=53 cmd=2 spd read status 44
2:124  0:199  t=200002 adr=53 cmd=2 spd read (FF) timeout!
2:124  0:000  t=1 adr=54 cmd=2 host busy status 00
2:124  0:000  t=3 adr=54 cmd=2 host busy status 40
2:424  0:300  t=1 adr=54 cmd=2 spd read status 41
2:424  0:000  t=119 adr=54 cmd=2 spd read status 44
2:624  0:199  t=200002 adr=54 cmd=2 spd read (FF) timeout!
2:624  0:000  t=1 adr=55 cmd=2 host busy status 00
2:624  0:000  t=3 adr=55 cmd=2 host busy status 40
2:924  0:300  t=1 adr=55 cmd=2 spd read status 41
2:924  0:000  t=119 adr=55 cmd=2 spd read status 44
3:124  0:199  t=200001 adr=55 cmd=2 spd read (FF) timeout!
3:124  0:000  t=1 adr=56 cmd=2 host busy status 00
3:124  0:000  t=3 adr=56 cmd=2 host busy status 40
3:424  0:300  t=1 adr=56 cmd=2 spd read status 41
3:424  0:000  t=118 adr=56 cmd=2 spd read status 44
3:624  0:199  t=200001 adr=56 cmd=2 spd read (FF) timeout!
3:624  0:000  t=1 adr=57 cmd=2 host busy status 00
3:624  0:000  t=3 adr=57 cmd=2 host busy status 40
3:924  0:300  t=1 adr=57 cmd=2 spd read status 41
3:924  0:000  t=117 adr=57 cmd=2 spd read status 44
4:124  0:199  t=200001 adr=57 cmd=2 spd read (FF) timeout!
4:124  0:000  ScanSPD() end

 

post-11298-0-68712600-1463729729_thumb.png

DSDT.dsl.zip

Link to comment
Share on other sites

@joevt

Thanks for working on this! Attached is a screenshot from Thaiphoon plus output of revised code plus native DSDT extracted from bios:

0:124  0:000  ScanSPD() start
0:124  0:000  SMBus device : 8086 8D22 class=0C0500 status=Success
0:124  0:000  SMBus CmdReg: 0x1
0:124  0:000  Scanning SMBus [8086:8D22], mmio: 0xFB135004, ioport: 0x580, hostc: 0x1
0:124  0:000  Slots to scan [8]...
0:124  0:000  t=1 adr=50 cmd=2 host busy status 00
0:124  0:000  t=4 adr=50 cmd=2 host busy status 40
0:424  0:300  t=1 adr=50 cmd=2 spd read status 41
0:424  0:000  t=118 adr=50 cmd=2 spd read status 44
0:624  0:199  t=200002 adr=50 cmd=2 spd read (FF) timeout!
...
3:624  0:000  t=1 adr=57 cmd=2 host busy status 00
3:624  0:000  t=3 adr=57 cmd=2 host busy status 40
3:924  0:300  t=1 adr=57 cmd=2 spd read status 41
3:924  0:000  t=117 adr=57 cmd=2 spd read status 44
4:124  0:199  t=200001 adr=57 cmd=2 spd read (FF) timeout!
4:124  0:000  ScanSPD() end

 

Nothing unexpected in that new output.

 

After reading the "Intel® C610 Series Chipset and Intel® X99 Chipset Platform Controller Hub (PCH) Datasheet", I now understand why status starts at 00 and immediately goes to 40. 00 means the host is not in use. Reading that value makes the host in use by us. We relinquish ownership when we write FF to the status. That clears the in-use flag and some other stuff.

 

The screenshot is interesting. Yours says SMBus#1 while mine says SMBus#0. Did Thaiphoon Burner say anything about reading the buses? Can you send a screen shot of the entire menu? If there are other buses, then I would like to know what SMBus addresses are used on each bus. I think the next step is to create an SMBus scanner to find devices, then we can compare the results with the Thaiphoon Burner result. That could confirm that we're reading the wrong bus.

 

The datasheet mentions 3 other buses, MS SMBus0,1,2 that are usually hidden. I don't know how to access those. They are hidden by the SPSR (device 17, function 0 (0x11:0) and would be function 1,2,3 of device 17 (0x11:1,0x11:2,0x11:3). There may be other things affecting that such as TCO and EVA. I'm not sure.

  • Like 4
Link to comment
Share on other sites

Nothing unexpected in that new output.

 

After reading the "Intel® C610 Series Chipset and Intel® X99 Chipset Platform Controller Hub (PCH) Datasheet", I now understand why status starts at 00 and immediately goes to 40. 00 means the host is not in use. Reading that value makes the host in use by us. We relinquish ownership when we write FF to the status. That clears the in-use flag and some other stuff.

 

The screenshot is interesting. Yours says SMBus#1 while mine says SMBus#0. Did Thaiphoon Burner say anything about reading the buses? Can you send a screen shot of the entire menu? If there are other buses, then I would like to know what SMBus addresses are used on each bus. I think the next step is to create an SMBus scanner to find devices, then we can compare the results with the Thaiphoon Burner result. That could confirm that we're reading the wrong bus.

 

The datasheet mentions 3 other buses, MS SMBus0,1,2 that are usually hidden. I don't know how to access those. They are hidden by the SPSR (device 17, function 0 (0x11:0) and would be function 1,2,3 of device 17 (0x11:1,0x11:2,0x11:3). There may be other things affecting that such as TCO and EVA. I'm not sure.

Think we might be getting somewhere, looks like Clover might be looking in the wrong place for SPD on X99 chipsets. Thaiphoon shows there is indeed an SMBus#0 at 44h marked as an unknown device. When you scan it it comes up with nothing.  Could the code be looking there by default and so not find anything? I have also noticed that in my ioreg the IODeviceMemory address for SBUS is 0xfb135000, whereas the boot log shows mmio as 0xfb135004...

post-11298-0-91879100-1463905283_thumb.png

post-11298-0-39067000-1463905570_thumb.png

Link to comment
Share on other sites

Think we might be getting somewhere, looks like Clover might be looking in the wrong place for SPD on X99 chipsets. Thaiphoon shows there is indeed an SMBus#0 at 44h marked as an unknown device. When you scan it it comes up with nothing.  Could the code be looking there by default and so not find anything? I have also noticed that in my ioreg the IODeviceMemory address for SBUS is 0xfb135000, whereas the boot log shows mmio as 0xfb135004...

I'm adding a couple other methods for finding/accessing SMBus devices. Maybe one of them will work. I've also added an SMBus scanner to get a list of slaves on an SMBus.

 

Bit 0-7 of mmio are not part of the address and Clover uses the ioport address instead of that memory mapped address anyway.

Link to comment
Share on other sites

×
×
  • Create New...